zoukankan      html  css  js  c++  java
  • FGMap加载天地图地图数据

    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 id="map" width="100%" height="100%" mapevent_mapready="onMapreadyHandler(event)"/>
    12 </s:Panel>
    13
    14 <fx:Script>
    15 <![CDATA[
    16 import com.fgmap.expand.core.*;
    17 import com.fgmap.maps.*;
    18 import com.fgmap.maps.MapMouseEvent;
    19 import com.fgmap.maps.controls.MapTypeControl;
    20 import com.fgmap.maps.controls.NavigationControl;
    21 import com.fgmap.maps.controls.OverviewMapControl;
    22 import com.fgmap.maps.controls.ScaleControl;
    23 import com.fgmap.maps.interfaces.IMapType;
    24 import com.fgmap.maps.overlays.*;
    25
    26 private var marker:Marker;
    27
    28 private var centreLatlng:LatLng = new LatLng(39.90509127978099,116.39769769279956818);//人民英雄纪念碑。
    29
    30 private var tiandituAnno:TiandituTileLayer = null;
    31 private var TiandituAnno:TileLayerOverlay = null;
    32 //地图加载完成后执行的方法
    33 protected function onMapreadyHandler(event:MapEvent):void
    34 {
    35 map.enableContinuousZoom(); //启用连续平滑缩放。
    36 map.enableScrollWheelZoom(); //启用使用鼠标滚轮缩放。
    37 map.addControl(new MapTypeControl()); //供用户在地图类型之间进行切换的按钮。
    38 map.addControl(new NavigationControl());//供用户更改地图的各项导航参数,包括缩放级别、中心位置和空间方位角。
    39 map.addControl(new ScaleControl()); //比例控件是用于指示当前地图的分辨率和缩放级别的可视指示器。
    40
    41 var normalMapType:IMapType = MapType.NORMAL_MAP_TYPE; //定义一个地图类型
    42 var tileLayers:Array = new Array();
    43
    44 //天地图矢量
    45
    46 var tdtemaplTileLayer:TiandituTileLayer = new TiandituTileLayer(normalMapType.getTileSize(),1,18,1)
    47 tdtemaplTileLayer.MapType = TiandituTileLayer.EMAP;
    48 tileLayers.push(tdtemaplTileLayer); //地图类型
    49 var TdtEmapMapType:IMapType = new MapType(tileLayers,new TiandituProjection(18),"矢量");//创建自己的地图类型
    50 map.addMapType(TdtEmapMapType); //增加到地图上
    51
    52 tiandituAnno = new TiandituTileLayer(normalMapType.getTileSize(),1,10,1)
    53 tiandituAnno.MapType = TiandituTileLayer.ANNO;
    54 TiandituAnno = new TileLayerOverlay(tiandituAnno,256,new TiandituProjection(18));//创建自己的地图类型
    55 //tileLayers.push(tiandituAnno);
    56 //var TdtAnnoMapType:IMapType = new MapType(tileLayers,new TiandituProjection(18),"标注");//创建自己的地图类型
    57 //map.addMapType(TdtAnnoMapType); //增加到地图上
    58
    59 //天地图影像
    60 var tdtimgTileLayer:TiandituTileLayer = new TiandituTileLayer(normalMapType.getTileSize(),1,18,1)
    61 tdtimgTileLayer.MapType = TiandituTileLayer.IMG;
    62 tileLayers = new Array();
    63 tileLayers.push(tdtimgTileLayer); //地图类型
    64 var TdtImgMapType:IMapType = new MapType(tileLayers,new TiandituProjection(18),"影像");//创建自己的地图类型
    65 map.addMapType(TdtImgMapType); //增加到地图上
    66
    67 map.setMapType(TdtEmapMapType); //设置自己的地图可见
    68
    69 map.addEventListener(MapEvent.MAPTYPE_CHANGED,onMapTypeChanged);
    70
    71 map.addOverlay(TiandituAnno); //加载标注覆盖层
    72
    73 //移除原来的地图类型
    74 // for(var i:int=0;i < MapType.DEFAULT_MAP_TYPES.length;i++){
    75 // map.removeMapType(MapType.DEFAULT_MAP_TYPES[i]);
    76 // }
    77
    78 map.setCenter(centreLatlng,5); //设置地图的中心点。
    79 marker = new Marker(centreLatlng); //建立一个标注。
    80 //map.addOverlay(marker); //在地图上显示此标注。
    81 BindMarker(marker);
    82 }
    83
    84 private function onMapTypeChanged(e:MapEvent):void {
    85 map.removeOverlay(TiandituAnno);
    86 if(map.getCurrentMapType().getName() == "矢量"){
    87 tiandituAnno = new TiandituTileLayer(256,1,10,1)
    88 tiandituAnno.MapType = TiandituTileLayer.ANNO;
    89 TiandituAnno = new TileLayerOverlay(tiandituAnno,256,new TiandituProjection(18));
    90 map.addOverlay(TiandituAnno); //加载标注覆盖层
    91 }else if(map.getCurrentMapType().getName() == "影像"){
    92 tiandituAnno = new TiandituTileLayer(256,1,18,1)
    93 tiandituAnno.MapType = TiandituTileLayer.IMGANNO;
    94 TiandituAnno = new TileLayerOverlay(tiandituAnno,256,new TiandituProjection(18));
    95 map.addOverlay(TiandituAnno); //加载标注覆盖层
    96 }else{
    97 map.removeOverlay(TiandituAnno); //移除标注覆盖层
    98 }
    99 }
    100
    101 private function BindMarker(marker:Marker):void {
    102 var markerOptions:MarkerOptions = new MarkerOptions();
    103 markerOptions.draggable = true;//设置标注可以拖动
    104
    105 //定义一个标注
    106 //var marker:Marker = new Marker(map.getCenter(),markerOptions);
    107
    108 marker.setOptions(markerOptions);
    109
    110 var infoOptions:InfoWindowOptions = new InfoWindowOptions();
    111 infoOptions.title = "我的坐标是";
    112 infoOptions.content = marker.getLatLng().toString();
    113 //标注拖动时关闭提示框
    114 marker.addEventListener(MapMouseEvent.DRAG_START,function(e:Event):void{
    115 marker.closeInfoWindow();
    116 });
    117 //拖动接受时显示提示框
    118 marker.addEventListener(MapMouseEvent.DRAG_END,function(e:Event):void{
    119 infoOptions.content = marker.getLatLng().toString();
    120 marker.openInfoWindow(infoOptions);
    121 });
    122 //点击标注时显示提示框
    123 marker.addEventListener(MapMouseEvent.CLICK, function(e:Event):void {
    124 infoOptions.content = marker.getLatLng().toString();
    125 marker.openInfoWindow(infoOptions);
    126 });
    127
    128 map.addOverlay(marker);//在地图上显示这个标注
    129 marker.openInfoWindow(infoOptions);//打开对话框
    130 }
    131 ]]>
    132 </fx:Script>
    133 </s:Application>

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

    影像地图:


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

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

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

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

  • 相关阅读:
    MIT python 第二课第四十分钟 取最小值的例子
    Python IDLE快捷键 汇总
    5、Hibernate的延迟加载
    4、Hibernate三种状态的讲解
    3、Hibernate实现简单的CRUD操作
    1、hibernate的简单配置
    2、hibernate的 save 保存失败的解决方法
    JavaWeb开发中关于分页的实现
    常见的网页布局二
    常见的网页布局一
  • 原文地址:https://www.cnblogs.com/liongis/p/2417456.html
Copyright © 2011-2022 走看看