FGMap默认支持Web墨卡托投影后的瓦片地图数据,也就是现在我们看到的Google Map、Bing Map、百度地图这样的瓦片数据,只要解析所对应的请求地址路径就可以,这个方法在之前的文章中介绍过。今天我们加载一个“经纬度直投”的地图数据类型--天地图数据,因为投影的方式不一样,所以加载的方式可能会不一样些。“经纬度等间隔直投”和“Web墨卡托”之间的区别大家可以参考一下《天地图-地图投影技术剖析与思考》

需要加载不同投影下的地图数据,我们需要自己来定义一个投影计算的方式,可以继承IProjection类,IProjection中有两个关键的方法:

fromPixelToLatLng:将像素点转换成对应的经纬度坐标。

fromLatLngToPixel:将经纬度坐标转换成对应的像素。

因为天地图使用的是“经纬度直投”的方式进行投影,所以换算方式比较简单:

 1         public function fromPixelToLatLng(pixel:Point, zoom:Number, nowrap:Boolean = false) : LatLng
2 {
3 var x:Number = 0;
4 var y:Number = 0;
5
6 x = pixel.x / (Math.pow(2,zoom) * titeSize) * 360 - 180;
7 y = 90 - pixel.y / (Math.pow(2,zoom-1) * titeSize) * 180;
8
9 var latlng:LatLng = new LatLng(y, x, nowrap);
10 return latlng;
11 }
12
13 public function fromLatLngToPixel(latLng:LatLng, zoom:Number) : Point
14 {
15 var point:Point = new Point(0,0);
16 var x:Number = 0;
17 var y:Number = 0;
18
19 latLng = new LatLng(latLng.lat(),latLng.lng());
20
21 point.x = (latLng.lng() + 180) / 360 * (Math.pow(2,zoom) * titeSize);
22 point.y = (90 - latLng.lat()) / 180 * (Math.pow(2,zoom-1) * titeSize);
23
24 return point;
25 }

 

大家也可以参考一下这篇文章:http://lt.cjdby.net/thread-1003128-1-1.html

有了这个方法后,我们可以自己定义一个投影,具体代码如下:

TiandituProjection
  1 package com.fgmap.expand.core
2 {
3 import com.fgmap.expand.*;
4 import com.fgmap.maps.LatLng;
5 import com.fgmap.maps.interfaces.IProjection;
6
7 import flash.geom.Point;
8
9 public class TiandituProjection implements IProjection
10 {
11 private var _wrapper:Object;
12 private var pixelRange:Array;
13 private var pixelsPerLonDegree:Array;
14 private var pixelOrigo:Array;
15 private var pixelsPerLonRadian:Array;
16 public static const MERCATOR_ZOOM_LEVEL_ZERO_RANGE:Number = 256;
17 private var titeSize:int = 256;
18
19 public function TiandituProjection(zoom:int)
20 {
21 var mapSize:Number = MERCATOR_ZOOM_LEVEL_ZERO_RANGE;
22 var i:int = 0;
23 var mapOrigo:Number = 0;
24 pixelsPerLonDegree = [];
25 pixelsPerLonRadian = [];
26 pixelOrigo = [];
27 pixelRange = [];
28 while (i < zoom)
29 {
30 mapOrigo = mapSize / 2;
31 pixelsPerLonDegree.push(mapSize / 360);
32 pixelsPerLonRadian.push(mapSize / (2 * Math.PI));
33 pixelOrigo.push(new Point(mapOrigo, mapOrigo));
34 pixelRange.push(mapSize);
35 mapSize = mapSize * 2;
36 i++;
37 }
38 }
39
40 public function fromPixelToLatLng(pixel:Point, zoom:Number, nowrap:Boolean = false) : LatLng
41 {
42 var x:Number = 0;
43 var y:Number = 0;
44
45 x = pixel.x / (Math.pow(2,zoom) * titeSize) * 360 - 180;
46 y = 90 - pixel.y / (Math.pow(2,zoom-1) * titeSize) * 180;
47
48 var latlng:LatLng = new LatLng(y, x, nowrap);
49 return latlng;
50 }
51
52 public function fromLatLngToPixel(latLng:LatLng, zoom:Number) : Point
53 {
54 var point:Point = new Point(0,0);
55 var x:Number = 0;
56 var y:Number = 0;
57
58 latLng = new LatLng(latLng.lat(),latLng.lng());
59
60 point.x = (latLng.lng() + 180) / 360 * (Math.pow(2,zoom) * titeSize);
61 point.y = (90 - latLng.lat()) / 180 * (Math.pow(2,zoom-1) * titeSize);
62
63 return point;
64 }
65
66 public function get interfaceChain() : Array
67 {
68 return ["IProjection"];
69 }
70
71 public function get wrapper() : Object
72 {
73 return this._wrapper;
74 }
75
76 public function tileCheckRange(param1:Point, param2:Number, param3:Number) : Boolean
77 {
78 var x:Number = 0;
79 var y:Number = 0;
80 x = pixelRange[param2];
81 if (param1.y < 0 || param1.y * param3 >= x)
82 {
83 return false;
84 }
85 if (param1.x < 0 || param1.x * param3 >= x)
86 {
87 y = Math.floor(x / param3);
88 param1.x = param1.x % y;
89 if (param1.x < 0)
90 {
91 param1.x = param1.x + y;
92 }
93 }
94 return true;
95 }
96
97 public function getWrapWidth(param1:Number) : Number
98 {
99 return pixelRange[param1];
100 }
101
102 public function set wrapper(param1:Object) : void
103 {
104 this._wrapper = param1;
105 return;
106 }
107
108 }
109 }

当然,这里会做一些处理,因为天地图的图数据分为“线划地图”和“影像地图”两种,而每一类中,又分为底图和标注,所以我们需要在程序中加以区分,天地图资源的分类可以参见:http://www.tianditu.com/guide/resource.jsp

有了这些信息后,,我们在自定义一个地图类型对数据进行处理:

TiandituTileLayer
  1 package com.fgmap.expand.core 
2 {
3 import com.fgmap.maps.Copyright;
4 import com.fgmap.maps.CopyrightCollection;
5 import com.fgmap.maps.LatLng;
6 import com.fgmap.maps.LatLngBounds;
7 import com.fgmap.maps.TileLayerBase;
8 import com.fgmap.maps.interfaces.ICopyrightCollection;
9
10 import flash.display.DisplayObject;
11 import flash.display.Loader;
12 import flash.events.IOErrorEvent;
13 import flash.geom.Point;
14 import flash.net.URLRequest;
15
16 public class TiandituTileLayer extends TileLayerBase
17 {
18 public static const EMAP:String = "EMap";//矢量地图
19 public static const ANNO:String = "Anno";//矢量标注
20 public static const IMGANNO:String = "ImgAnno";//影像标注
21 public static const IMG:String = "Img";//影像地图
22
23 private var mapMinZoom:int = 1; //最小显示等级
24 private var mapMaxZoom:int = 18;//最大显示等级
25 private var _mapType:String = EMAP;
26
27 public function TiandituTileLayer(tileSize:Number,mapMinZoom:Number,mapMaxZoom:Number,alpha:Number)
28 {
29 var copyrightCollection:CopyrightCollection = new CopyrightCollection();
30 //创建一个自己的版权说明
31 copyrightCollection.addCopyright(
32 new Copyright("TiandituData" + MapType,
33 new LatLngBounds(new LatLng(-180, -90),
34 new LatLng(180, 90)), 0,
35 "天地图数据",18));
36
37 super(copyrightCollection, mapMinZoom, mapMaxZoom, alpha); //调用父类的方法
38 }
39
40 public function get MapType():String
41 {
42 return _mapType;
43 }
44
45 public function set MapType(value:String):void
46 {
47 _mapType = value;
48 }
49
50 //覆盖加载地图数据的方法,这个很重要,地图数据从这里读取
51 override public function loadTile(tilePos:Point, zoom:Number):DisplayObject {
52 var testLoader:Loader = new Loader();
53
54 var z:Number = Math.pow(2,zoom - 1) - Math.pow(2,zoom - 2) - 1;
55 var x:Number = tilePos.x;
56 z = Math.pow(2,zoom - 2);
57 var y:Number = tilePos.y;
58
59 var layerName:String = "";
60 var strURL:String = "";
61 switch(_mapType){
62 case EMAP:
63 if (zoom <= 10) {
64 layerName = "A0512_EMap";
65 } else if (zoom == 11 || zoom == 12) {
66 layerName = "B0627_EMap1112";
67 } else if (zoom >= 13 && zoom <= 18) {
68 layerName = "siwei0608";
69 }
70 break;
71 case IMG:
72 if (zoom <= 10) {
73 layerName = "sbsm0210";
74 } else if (zoom == 11) {
75 layerName = "e11";
76 } else if (zoom == 12) {
77 layerName = "e12";
78 } else if (zoom == 13) {
79 layerName = "e13";
80 } else if (zoom == 14) {
81 layerName = "eastdawnall";
82 } else if (zoom >= 15 && zoom <= 18) {
83 layerName = "sbsm1518";
84 }
85 break;
86 case ANNO:
87 if (zoom <= 10) {
88 layerName = "AB0512_Anno";
89 } else {
90 strURL = "http://www.tianditu.com/js/GeoSurfJSAPI/img/blank.gif";
91 }
92 break;
93 case IMGANNO:
94 if (zoom <= 10) {
95 layerName = "A0610_ImgAnno";
96 } else if(zoom >= 11 && zoom <= 14){
97 layerName = "B0530_eImgAnno";
98 } else if(zoom > 14 && zoom < 19){
99 layerName = "siweiAnno68";
100 } else {
101 strURL = "http://www.tianditu.com/js/GeoSurfJSAPI/img/blank.gif";
102 }
103 break;
104 }
105
106 var num:int = Math.random()* 3;
107 if(strURL == ""){
108 strURL = encodeURI("http://tile" + num + ".tianditu.com/DataServer?" +
109 "T=" + layerName +
110 "&X=" + x +
111 "&Y=" + y +
112 "&L=" + zoom +
113 "&d=2009-10-22T20:25:15&cd=9999-12-31T00:00:00");
114 }
115 var urlRequest:URLRequest;
116 urlRequest = new URLRequest(strURL); //没有地图时显示的内容
117
118 testLoader.load(urlRequest);
119 testLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
120
121 return testLoader;
122 }
123
124 //出错处理
125 private function ioErrorHandler(event:IOErrorEvent):void {
126 trace("ioErrorHandler: " + event);
127 }
128 }
129 }


最后,我们将“线划地图”和“影像地图”加载到我们的地图中来:

FGMapTianditu
  1 <?xml version="1.0" encoding="utf-8"?>
2 <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
3 xmlns:s="library://ns.adobe.com/flex/spark"
4 xmlns:mx="library://ns.adobe.com/flex/mx"
5 xmlns:maps="com.fgmap.maps.*"
6 minWidth="955" minHeight="600">
7 <fx:Declarations>
8 <!-- 将非可视元素(例如服务、值对象)放在此处 -->
9 </fx:Declarations>
10 <s:Panel width="800" height="600" title="FGMap加载天地图数据">
11 <maps:Map >133 </s:Application>

下面就是我们看到的运行结果,线划地图:

FGMap加载天地图地图数据

影像地图:

FGMap加载天地图地图数据


到此,我们就可以完全的加载上天地图的数据了。

但是,细心的童鞋可能会发现同一个经纬度,在不同的地图下,位置不对,这是因为各地图厂商都对自己的地图数据进行了偏移,是人为加上去的,所以会有偏差,如果真实使用中,这个需要进行偏移纠正的,这是另一个话题了。

这里只给出一个加载的方式,如果正式使用各地图商的数据,请与他们联系!

完整的项目代码从这里下载:https://files.cnblogs.com/liongis/FGMapTianditu.zip

 

相关文章: