研发三维GIS系统笔记/实现wgs84投影-001
1. 工作内容,改造引擎,支持wgs84投影
改造原因:目前投影是墨卡托投影(与Google Map一致) 目前的GIS系统是二维的采用这个坐标系是没有问题的
但不支持wgs84瓦片数据以及高程数据,工作中很多数据是wgs84格式的,尤其很多三维GIS都是采用wgs84投影
wgs84 与mercator 从数据上看,就是跟节点是一个与两个的区别(长方形)
下图Mercator 投影(zhengfangxing)
2. 对现有接口进行抽象,目的是向下兼容原有的引擎(Mercator)投影
抽象类如下定义:
class CELLSpRef { public: /// <summary> /// 经纬度转化为世界坐标 /// </summary> virtual real2 longLatToWorld(const real2& longLatx) = 0; /// <summary> /// 世界坐标转化为经纬度 /// </summary> virtual real2 worldToLongLat(const real2& world) = 0; /// <summary> /// 给定经纬度返回对应的瓦片Id /// </summary> virtual int3 getKey(unsigned l,real rLong,real rLat) = 0; };
3. wgs84投影类实现如下:
1 class CELLWgs842d :public CELLSpRef 2 { 3 public: 4 /// <summary> 5 /// 经纬度转化为世界坐标 6 /// </summary> 7 virtual real2 longLatToWorld(const real2& longLatx) override 8 { 9 real2 world; 10 world.x = longLatx.x * WGS_84_RADIUS_EQUATOR; 11 world.y = longLatx.y * WGS_84_RADIUS_EQUATOR; 12 return world; 13 } 14 15 /// <summary> 16 /// 世界坐标转化为经纬度 17 /// </summary> 18 virtual real2 worldToLongLat(const real2& world) override 19 { 20 real2 lonlat; 21 lonlat.x = world.x / WGS_84_RADIUS_EQUATOR; 22 lonlat.y = world.y / WGS_84_RADIUS_EQUATOR; 23 return lonlat; 24 } 25 26 /// <summary> 27 /// 给定经纬度返回对应的瓦片Id 28 /// </summary> 29 virtual int3 getKey(unsigned level, real rLong,real rLat) override 30 { 31 /// 当下版本还在实现中 32 return int3(0,0,level); 33 } 34 };
4. 适配引擎代码
引擎中原来直接调用了Mercator投影,现在需要统一接口,在引擎类中增加一个获取投影接口的类
1 class CELLTerrainInterface 2 { 3 public: 4 virtual ~CELLTerrainInterface() 5 {} 6 /// <summary> 7 /// 创建纹理 8 /// </summary> 9 virtual uint createTexture(const TileId& id) = 0; 10 /// <summary> 11 /// 释放纹理 12 /// </summary> 13 virtual void request(CELLQuadTree* node) = 0; 14 15 /// <summary> 16 /// 释放纹理 17 /// </summary> 18 virtual void cancelRequest(CELLQuadTree* node) = 0; 19 20 /// <summary> 21 /// 释放纹理 22 /// </summary> 23 virtual void releaseTexture(uint texId) = 0; 24 25 /// <summary> 26 /// 获取统计信息 27 /// </summary> 28 29 virtual Counts& getCounts() = 0; 30 31 /// <summary> 32 /// 获取投影,具体使用什么类型的投影,由具体实现决定 33 /// </summary> 34 virtual CELLSpRef* spRef() = 0; 35 36 37 };
5. 改造调用了投影接口的代码
主要集中在四叉树部分,四叉树根据输入的世界坐标创建瓦片,同时根据也是子节点以及其他后代节点裂分的根据。
6. 改造引擎根节点
墨卡托投影下,四叉树的根节点只有一个,现在有两个(wgs84投影)
代码如下:
1 auto root0 = new CELLQuadTree( this 2 , 0 3 , real2(-PI * WGS_84_RADIUS_EQUATOR, -HALF_PI * WGS_84_RADIUS_EQUATOR) 4 , real2(0, +HALF_PI * WGS_84_RADIUS_EQUATOR) 5 , 0 6 , CELLQuadTree::CHILD_LT 7 ); 8 auto root1 = new CELLQuadTree( this 9 , 0 10 , real2(0, -HALF_PI * WGS_84_RADIUS_EQUATOR) 11 , real2(-PI * WGS_84_RADIUS_EQUATOR, +HALF_PI * WGS_84_RADIUS_EQUATOR) 12 , 0 13 , CELLQuadTree::CHILD_LT 14 ); 15 16 _roots.push_back(root0); 17 _roots.push_back(root1);