6基于Wms协议的Map开发(六:通讯模块).doc_第1页
6基于Wms协议的Map开发(六:通讯模块).doc_第2页
6基于Wms协议的Map开发(六:通讯模块).doc_第3页
6基于Wms协议的Map开发(六:通讯模块).doc_第4页
6基于Wms协议的Map开发(六:通讯模块).doc_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

声明:此系列文章,不是说教,不是告诉任何人如何利用C+开发电子地图的教程,而且本人水平有限,也达不到教程的地步。只是利用此系列的文章,来记录开发基于C+应用在Windows下开发电子地图的过程。愿对C+开发感兴趣的朋友,熟知Gis开发的朋友,了解Wms、WFS协议的朋友,亦或是对GoogleMap之类感兴趣的朋友,共同讨论。(废话到此结束)。通讯模块此通讯模块目的在于根据输入,下载指定URL的内容。由于本人很少从事网络方面的编码,这部分很不擅长,当初,设计时,欲寻找一套简单易用的库,所以选择了WinInet实现此部分逻辑,但是随着知识的增长,了解到WinINet是极不稳定的,所以对网络编程熟悉的朋友可自行实现此部分功能。例如:可以使用Socket来完成此功能。重中之重GetCapabilitybool BStarWmsPostMan:SaveCapFile(char * strAddr,char buf, int& buflen)char* temp = SERVICE=WMS&VERSION=1.1.1&REQUEST=GetCapabilities;char url512;memcpy_s(url,512, strAddr,256);strcat_s(url,512,temp);if (!ReciveBuffer(url,buf, buflen)delete buf;buf = NULL;return false;解释:strAddr:是你服务器的地址字符串char buf:接收到的字符串。int& buflen:接收到的字符串的长度。GetMap我给出一个如何拼接GetMap命令的函数,主要目的是让大家了解GetMap字符串如何拼接的,这样有利于大家自己实现下载功能。bool BStarWmsPostMan:GetMap(LATLONBB maparea, char buf, int& buflen)char strTemp1280;char url2560;memcpy_s(url,2560,m_strAddr,256);sprintf_s(strTemp,1280,BBOX=%f,%f,%f,%f&SRS=EPSG:%s&WIDTH=%d&HEIGHT=%d&LAYERS=%s&STYLES=&FORMAT=%s&DPI=96,maparea.minx,maparea.miny,maparea.maxx,maparea.maxy,m_layerProperty.Srs,m_layerProperty.Width,m_layerProperty.Height,m_layerProperty.Name,m_layerProperty.ImageType);strcat_s(url ,2560, SERVICE=WMS&version=1.0.0&request=getmap&);strcat_s(url , 2560, strTemp);if(!ReciveBuffer(url,buf,buflen)return false;return true;解释:LATLONBB maparea:这个数据结构大家看过前文的,应该记得,由四个double组成,代表左右上下四个边界的经纬度值。char buf:接收到的字符串。int& buflen:接收到的字符串的长度。如果你看明白了,而且想做个稳定的通讯模块,好的,就别再往下看了,自己实现吧。主要工作就是用你自己的方法实现ReciveBuffer()这个函数。模块功能先让我们来看看此功能模块是做什么用的,有哪些事情是要处理的。流程图如下:再让我们用文字描述一下这个流程:明确任务首先明确,通讯模块需要得到什么样的数据呢?(1) 还记得Wms协议中的GetCapability吗?对了,得到服务器属性的功能,我们需要通过GetCapability来得到一个关于当前地图服务器描述的XML表。从而得到很多我们需要的信息,例如当前服务器上存在的地图图层有哪一些,每个图层的经纬度范围是什么,每个图层的名称是什么,投影系是什么等等。(2) 重点当然是我们要通过GetMap来获取我们指定图层、指定坐标范围内的图片了。此模块当然还要能下载这些指定的图片。其次,我们通过GetCapability得到的关于服务器属性的XML描述,要经过分析得到我们关心的数据集合了。我这里采用了一个轻量级的XML库来做到这一点。选择了TinyXML(上网看一下关于此的简介吧)。由于我希望透视XML分析过程,所以这里没有采用他的库文件,而是直接使用了他的源代码(TinyXML是开源的)。经过分析、确认的数据会被我存到我定义好的数据结构中。再回首明确了功能后,回过头来,再来看一下流程图。(1)其中“设置服务器”是一个拼接命令给GetCapability作为输入的过程。简单的说来,比如你的服务器地址是/lizardtech/iserv/ows如果你使用的是一个1.1.1版本的WMS服务器 ,那么如果加上“?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetCapabilities”这个字符串之后,就相当于设置完成GetCapability命令的拼接。只需要打开“/lizardtech/iserv/ows?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetCapabilities”这个URL,那么你就会得到一个XML文件。(2)接下来,“获取服务器属性”以及“得到服务器相关属性”的两个步骤,就是我要通过TinyXML分析这个XML文件,并将我们关心的数据存入我们自定义的数据结构中。(3)随后,“工作对象的相关属性”,应为我们是要针对对象开发的,意思就是我可以建立多个独立的地图对象,所以,每个独立的地图对象要拥有各自独立的通讯模块,所以,通讯模块的实现要通过建立类,用类的实例来实现,所以工作对象的属性,就是指每个类实例中的一些私有化成员变量将得到赋值。(4)最后,每个通讯对象的实例,要根据自己的输入去下载数据到本地保存,我的是现实是用WinINet,强烈建议大家用socket实现,这里要说的是,XML下载每个通讯实例只需要完成一次,而图片的下载要完成多次。(这里是根据上层模块的多线程安排下载的,之后会在文件模块的说明中介绍)。(5)补充说明,这里有个问题,不知道大家注意到没有,下载文件的过程相对于其他操作是耗时的工作,如果用户没耐心看完当前的地图,或者不关心当前地图,从而又开始了新的操作,我们需要一种中断机制,让正在下载的工作停止。这是很重要的,个人在工作中感觉到,好的功能代码要做到全代码调用的可控。相当于开线程,不能让线程成为脱缰野马的道理一样。模块接口及数据结构数据结构/经纬度范围typedef struct tagLATLONBB double minx;/最小xdouble miny;/最小ydouble maxx;/最大xdouble maxy;/最大yLATLONBB, *PLATLONBB;#endif/wms标准协议中包含数据typedef struct tagCAPABILITYDATAS int Width;/图片像素宽度int Height;/图片像素高度char ImageTypeBUFFER_SIZE_COMMON; /图片类型char SrsBUFFER_SIZE_COMMON;/投影类型char NameBUFFER_SIZE_SPECIAL;/层名(用于拼接)char TitleBUFFER_SIZE_SPECIAL;/层名(用于显示)LATLONBB BoundBox;/层范围(该层最大范围)CAPABILITYDATAS,*PCAPABILITYDATAS;对外接口/登录服务器DLL_API int LogIn(const char* strAddr);/ 2次调用,1次确定buflen,2次真正的操作DLL_API bool GetCapability(int index, CAPABILITYDATAS itemsName, int& count);/ 设置用户关心的层DLL_API LATLONBB SetCapability(int index, CAPABILITYDATAS itemsName,const int count);/ 获取图层2次获取,1次确定buflen,2次真正的操作DLL_API bool GetMap(int index, LATLONBB maparea, char buf, int& buflen);/ 中断操作,舍弃当前下载的工作DLL_API void AbortMap(int index, BOOL IsAbort);/登出服务器DLL_API void LogOut(int index);/复制服务器信息DLL_API void CopyServerData(int indexSrs, int indexDes);TinyXML我们看一下针对我们的应用,TinyXML的使用。(这只是个建议,可以使用其他XML操作的库),其实使用起来还是很简单的,至少是读取很简单吧。bool BStarWmsPostMan:GetCapItems(CAPABILITYDATAS items, int& count)LATLONBB tempLatlon;TiXmlDocument* myDocument = new TiXmlDocument();BOOL bHaveLatlon = FALSE;char filename64;sprintf_s(filename,%s-%d,GetCapability,m_Index);if (!myDocument-LoadFile(filename,TIXML_ENCODING_UNKNOWN)return FALSE;TiXmlElement* rootElement = myDocument-RootElement();/classTiXmlElement* CapabilityElement = rootElement-FirstChildElement(Capability);TiXmlElement* LayersElement = CapabilityElement-FirstChildElement(Layer); TiXmlElement* allName = LayersElement-FirstChildElement(Name);TiXmlElement* LayersTitleElement = LayersElement-FirstChildElement(Title);TiXmlElement* LayerElement = LayersElement-FirstChildElement(Layer);TiXmlElement* LayerTitleElement = LayerElement-FirstChildElement(Title);while (LayerElement) indextemp+;TiXmlElement* LayerSrsElement = LayerElement-FirstChildElement(SRS);TiXmlElement* LayerTitleElement = LayerElement-FirstChildElement(Title);TiXmlElement* LayerNameElement = LayerElement-FirstChildElement(Name);TiXmlElement* LayerLatLonBoundingBox = LayerElement-FirstChildElement(LatLonBoundingBox);TiXmlElement* LayerBoundingBox = LayerElement-FirstChildElement(BoundingBox);TiXmlElement* LayerSrs = LayerElement-FirstChildElement(SRS);TiXmlAttribute* RectofLayerLatLonBoundingBox = LayerLatLonBoundingBox-FirstAttribute();Datasindextemp.BoundBox.minx = atof(RectofLayerLatLonBoundingBox-Value();RectofLayerLatLonBoundingBox=RectofLayerLatLonBoundingBox-Next();Datasindextemp.BoundBox.miny = atof(RectofLayerLatLonBoundingBox-Value();RectofLayerLatLonBoundingBox=RectofLayerLatLonBoundingBox-Next();Datasindextemp.BoundBox.maxx = atof(RectofLayerLatLonBoundingBox-Value();RectofLayerLatLonBoundingBox=RectofLayerLatLonBoundingBox-Next();Datasindextemp.BoundBox.maxy = atof(RectofLayerLatLonBoundingBox-Value();LATLONBB tempsort;tempsort = Datasindextemp.BoundBox;if (tempsort.minx tempsort.maxx)Datasindextemp.BoundBox.minx = tempsort.maxx;Datasindextemp.BoundBox.maxx = tempsort.minx;if (tempsort.miny tempsort.maxy)Datasindextemp.BoundBox.miny = tempsort.maxy;Datasindextemp.BoundBox.maxy = tempsort.miny;memcpy(Datasindextemp.Name,(char*)LayerNameElement-GetText(),128);memcpy(Datasindextemp.Srs , 4326,sizeof( 4326);memcpy_s(Datasindextemp.Title, BUFFER_SIZE_SPECIAL,(char*) LayerTitleElement-GetText(),128);memcpy_s(Datasindextemp.ImageType, BUFFER_SIZE_COMMON, image/jpeg ,sizeof(image/jpeg);Datasindextemp.Width = 256;Datasindextemp.Height = 256;if (items != NULL)memcpy_s(itemsindextemp.Name,BUFFER_SIZE_SPECIAL,Datasindextemp.Name,BUFFER_SIZE_SPECIAL);itemsindextemp.BoundBox = Datasindextemp.BoundBox;memcpy_s(itemsindextemp.Title,BUFFER_SIZE_SPECIAL, Datasindextemp.Title,BUFFER_SIZE_SPECIAL);memcpy_s(itemsindextemp.ImageType,BUFFER_SIZE_COMMON,Datasindextemp.ImageType,BUFFER_SIZE_COMMON);itemsindextemp.Width = Datasindextemp.Width;itemsindextemp.Height = Datasindextemp.Height;memcpy_s(itemsindextemp.Srs,BUFFER_SIZE_COMMON, Datasindextemp.Srs,BUFFER_SIZE_COMMON);LayerElement = LayerElement-NextSiblingElement(Layer);count = indextemp + 1;delete myDocument;myDocument = NULL;return true;GetMap下载过程虽然强烈建议大家用socket开发图片下载这部分,不过还是给出WinInet的实现吧。我定义了一个类头文件#ifndef _CVodStreamCache_H#define _CVodStreamCache_H#include #include #include #include #include using namespace std;#pragma comment(lib, wininet.lib)class CVodStreamCachepublic:CVodStreamCache();CVodStreamCache();bool Create(char token, char url);int ReadBlock(long offset, int len, char *buffer);bool Recive(char buf, int& buflen);void Destory();void CacheInfo();void Abort(BOOL IsAbort);private:HINTERNET internetOpen;HINTERNET internetOpenUrl;DWORD dwStatusCode;DWORD dwContentLength;HANDLE createFile;static const int BUFFERSIZE = 9216;BOOL m_IsAbort;#endif /_CVodStreamCache_HCPP文件#include stdafx.h#include #include CVodStreamCache.hCVodStreamCache:CVodStreamCache()internetOpen = NULL;internetOpenUrl= NULL;m_IsAbort = false;CVodStreamCache:CVodStreamCache()bool CVodStreamCache:Create(char token, char url)internetOpen = InternetOpen(NULL, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);if (internetOpen = NULL)cout Internet open failed! endl;return false; if (m_IsAbort) InternetCloseHandle(internetOpen); return false; if (internetOpen = NULL)cout Internet open failed! endl;return false;internetOpenUrl = InternetOpenUrlA(internetOpen, url,NULL, 0, INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_PRAGMA_NOCACHE, 0);if (internetOpenUrl = NULL)cout Internet open url failed! Error code = GetLastError() endl;InternetCloseHandle(internetOpen);return false;return true;int CVodStreamCache:ReadBlock(l

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论