青梅猪马

by LionGG, a GIS Major

 

2011年5月6日

百度地图Silverlight版和Flex版(via SuperMap iClient)

Demo演示:(小提示:点击左上角罗盘外环转动,地图可以旋转哦。双击它即可恢复正北指向。)
http://liongg.github.com/maps/bmsl.html (Silverlight)   http://liongg.github.com/maps/bmflex.html (Flex)

百度地图目前只有JavaScript版本,没有Flex、Silverlight等版本。SuperMap iClient系列产品,支持Google Maps、OSM、QQ 地图等等等等Web墨卡托投影及其Tile瓦片组织方式的地图自然不在话下,对于百度地图相对而言独树一帜的投影和瓦片组织方式,并没有提供已知的解决方案。出于“好奇”,俺试着把两者结合一下,搞个Mashup玩玩,非官方产品。

以下简单描述了两者结合的思路,语焉不详不是为了保留,而是没法详述。如果对两者都有一定程度的了解,则下面的思路即可转换为实际的代码。如果不了解,讲得再详细也没有用。另外,需要声明的是,这儿的思路都可以从两者公开的接口中拿到。当然有时候,你必须hack到一些在文档中没有,但实际上可以使用的接口。

按照SuperMap iClient提供的实现接口,需要知道百度地图的地图边界范围、尺度(分辨率或比例尺)数组、Tile瓦片组织方式。然后即可在SuperMap iClient系列产品中使用百度地图的数据。

尺度数组:在百度API技术交流群中,透漏过百度地图在18级是1px代表1m,也就是空间分辨率是1mpp。(同时还提到谷歌地图在18级是1px代表0.8m,但我认为此值不准确)如果你不凑巧错过上述有价值的信息,或者你貌似听到过但当了耳旁风,还可以从百度地图的比例尺控件中获取到这个值(思考题,怎么获取?),只是有稍许误差,但这并不影响。因此对于某缩放级别n而言,分辨率就是Math.pow(2,18-n) ppx。

边界范围:首先要勇于抛弃基本上没有什么价值的1-4级地图,除中国外,百度暂未提供其他地区的数据。也可以不抛弃,但抛弃会给后面的算法带来较大的简化。从第5级地图来分析,是有4行5列张瓦片组成。结合百度地图坐标拾取系统,可以获取地图左下角的经纬度值。通过百度地图API中hack到的坐标转换接口,可以将其转换为投影坐标。结合第一步得到尺度数据和刚才的瓦片数量,即可得出“右上角”的米坐标值。如此一来地图边界范围唾手而得。(思考题:为什么不直接用类似获取左下角坐标的方式来获取右上角的值呢?)

瓦片组织:经过对百度瓦片URL格式的简单分析,即可知道,它的起算点是(0,0),对于中国区而言,其实就是左下方向。SuperMap iClient的瓦片起算点在左上点,因此对二者进行相应的转换。悲催的是,每一级别的转换常量是不同的,必须分别计算。计算这一组常量差值,是整个过程中最复杂的步骤。
首先,有这么一个小程序,给定一个坐标值,即可计算出某确定级别时它所在的瓦片的行列号。(思考题,如何完成这个小工具?提示:需要hack到坐标转换接口)进而可得到该瓦片的精确范围,也即四边的经纬度值。
其次,有了上述工具,用地图坐标拾取系统得到第5级左上角的大概值,进而可确定第5级左上角的精确经纬度值。精确是必须的,因为在级别很大的时候,错1度都将差得很远。
第三,依次确定,在5级-18级时,左上角所在的行列号。该行列号,则是确定级别下,与SuperMap iClient瓦片组织的常量差值。
 
最后声明:此文仅作研究之用,非官方产品。尽管百度地图和SuperMap iClient都是免费产品,如果要商用,还请联系相关公司。

posted @ 2011-05-06 11:25 狮兄 阅读(2410) 评论(8) 编辑

2011年3月16日

MarkerCluster之百度地图版

在《Marker Cluster面面观》一文中我描述了Marker Cluster的用处:用来解决加载大量点要素到地图上产生覆盖现象的问题,并提高性能。文中列举了那时(2009年)的一些厂商解决方案,并给了图示和链接。在《BMSL:自定义Cluster》一文中,简述并图示了最简单的聚合算法,给了一套针对Bing MapC#算法简要版。在国内地图/GIS厂商中,超图软件和高德/MapABC都有自己类似的解决方案。

算法的原理还是老样子,打格子,计算,聚合。平移或缩放后,也即地图可视区域发生变化,重新计算。事实上,还可以有更复杂的处理方法,在计算距离聚合时采用不同的方案,就会有不同的结果。比如,可以根据每个点标记的某项属性信息,赋予该点一些权重,使得最终聚合起来的那个“大点”的落脚位置,依据权重有所不同。再比如,不纯粹以距离为标准来聚合,再附件一条标准,落在给定的省份范围内,(也即同时在一个省份的边界多边形内的点标记)才可以聚合到一块等等。SuperMap iClient提供了不少这样的参数来确定。

本文则主要把基于Google Maps的扩展库MarkerClusterer迁移到百度地图API上来,参考了v2v3的源码,但做了不少改动。比如抽象出来了ClusterMarker这个自定义覆盖物类,使其不依赖于MarkerClusterer的算法,可单独加以使用。删除了MarkerClustererOverlay的继承关系,因为根本不必要。最终结果图示如下,在线示例链接。(源码你找得到)

解释一下源码和重要接口。MarkerClusterer类,也即“标记聚合器”类,其实是个“管理器”,负责把根据一定的参数设置,把地图上的点标记,按照算法进行聚合,并加载到地图上呈现出来。ClusterMarker类,也即“聚合标记”类,是一种自定义覆盖物,一种复杂的标记,类似Marker,可参考前面铺垫的文章“自定义覆盖物”。而Cluster类,则联系二者,起一个桥梁的作用,一个Cluster含有多个聚合在一起的Marker,最终在地图上的表现形式就是一个ClusterMarker

构造函数:MarkerClusterer(map, opt_markers, opt_options): map的描述略。

opt_markers 就是往地图上添加的诸多点标记,之所以定位可选参数,是因为还提供了addMarkeraddMarkers等方法动态添加标记的接口。对应的,还有removeMarkerremoveMarkersclearMarkers等删除和清除点标记的接口。不管是动态的添加还是删除,会默认的重新进行Cluster的计算,除非对可算参数强制声明则不加以重新计算。还附件提供了getMarkersgetMarkersCount的方法方便使用。

Opt_options里有gridSize来控制点聚合的像素范围,默认是60maxZoom是控制聚合的最大缩放级别,也即到哪一级就全部散开了,默认是18,就是百度地图支持的最大级别。averageCenter则是控制聚合到一块的这些Marker,聚成一个后的位置,是否取所有点标记的位置的平均数,否的话直接取第一个的位置,默认falseminClusterSize控制最小Cluster包含的数量,也就是说小于这个数,就不能组成为一个Cluster,默认是2styles则是控制CluserMarker的样式外观。基本上都有对应的get/set方法来控制。但动态改变后,需调用刷新接口来自动重绘。

其他的还有getClustersCount来获取当前视图下的Cluster数量。由于为了提高性能,不在视图内的点标记,是不参与聚合计算的。因此这个ClustersCount不仅与缩放级别有关,就是在平移地图,改变地图视野的情况下,也会发生变化。(原文链接

posted @ 2011-03-16 13:11 狮兄 阅读(1381) 评论(1) 编辑

2011年3月14日

百度地图之自定义覆盖物(Overlay)

     百度地图提供了默认的Marker作为默认的点标记,或者叫图像标注。除了位置,还支持设置图像Icon,来达到自定义效果。但这个显然比较有限,我们需要更加负责的覆盖物(Overlay)来展示点要素。

本文提供了一种自定义覆盖物,命名为ClusterMarker,类似是一种较为复杂的标记。它除了支持常规的位置(Point),还可以设置文字(Text)和风格(Style),而在Text和Style之间会有一定的映射关系,不同的Text对应不同的Style。而映射关系的接口,同样予以开放,可自行设置。

 构造函数:

     ClusterMarker(point, text, opt_options):point表示位置信息;text表示文字信息;可选参数opt_options是个对象,形如{styles:myStyles,bounds:myBounds},其中styles可以设置自定义风格,如果不设置,则用默认风格(默认更个的图片取自这里);bounds是为了后面的ClusterMarkerer而设置的,比如这假设是几个点的一个聚合时,它可以表示这几个点的范围bounds。

方法接口:

    getPoint() 和 setPoint(point) 用来获取和设置显示的位置。

    getText()  和 setText(text) 用来获取和设置显示的文字。

    getBounds() 和 setBounds(bounds) 用来获取和设置聚合点的范围,如果有的话。

    getCalculator() 和 setCalculator(calculator) 用来获取和设置文字与风格之间映射关系。默认的映射关系是,把文字转换为数字,对10取整,作为对应的风格图片索引。比如text为9,对应index为0的风格;24则对应index为2的风格。

    支持通过addEventListener方法添加click事件的响应。

    关于ClusterMarker命名,首先体现是一种类似Marker的点标记,Cluster的意思主要是积聚,比如Text可以表示,该Point附近积聚了Text个标记等。其实,这是做百度地图版的MarkerCluster的中间产物。代码将会包含在下一篇文章“ClusterMarkerer百度地图版”中。

演示地址:简单示例   复杂示例(设置不同风格)

     怎么找源码,你懂的。原文链接

posted @ 2011-03-14 13:57 狮兄 阅读(1439) 评论(1) 编辑

2009年11月17日

BMSL:Map Mode解析

       和传统GIS客户端架构有所不同,BMSLMapMode的方式来控制Map的一些特征,比如更换地图瓦片数据,限定缩放级别,固定平移范围;甚至是控制鼠标键盘事件导航地图的方式,以及地理坐标与像素坐标的映射等。

         Map有属性曰Mode,类型为MapModeMapMode有子类FlatMapModeFlatMapMode有子类MercatorModeMercatorMode有两个子类RoadModeAerialMode。(关系简单,不再图示)

         MercatorMode设置了Web Mercator投影的相关投影,RoadModeAerialMode分别定了Bing Maps的数据类型,以及导航控件等。比如把MapMode设置为空的MercatorMode,即可清除Bing Maps数据,替换其中的TileSource,即可更换底图数据。

         若要限制显示范围,则要定制自己的MapMode,比如从RoadMode继承,覆盖GetZoomRange限制缩放级别,覆盖ConstrainView限制平移范围。


        下文的示例,大致限定在中国经纬度范围内,缩放级别限定在310之间,并把底图数据改变为Google卫星地图以及它的地图注记数据(即那些汉字标绘),如何自定义TileSource请参考《BMSL中使用Google 地图》。

    public class ChinaMode : RoadMode
    {
        private Range<double> validLatitudeRange = new Range<double>(3.92, 53.51);
        private Range<double> validLongitudeRange = new Range<double>(73.60, 135.01);

        public ChinaMode()
            : base()
        {
            var tileLayer = (MapTileLayer)this.Content;
            tileLayer.TileSources.Clear();
            tileLayer.TileSources.Add(new GoogleSatelliteTileSource());
            tileLayer.TileSources.Add(new GoogleLabelTileSource());
        }

        protected override Range<double> GetZoomRange(Location center)
        {
            return new Range<double>(3, 10);
        }

        public override bool ConstrainView(Location center, ref double zoomLevel, ref double heading, ref double pitch)
        {
            bool isChanged = base.ConstrainView(center, ref zoomLevel, ref heading, ref pitch);
            double newLatitude = center.Latitude;
            double newLongitude = center.Longitude;
            if (center.Longitude > validLongitudeRange.To)
            {
                newLongitude = validLongitudeRange.To;
            }
            else if (center.Longitude < validLongitudeRange.From)
            {
                newLongitude = validLongitudeRange.From;
            }

            if (center.Latitude > validLatitudeRange.To)
            {
                newLatitude = validLatitudeRange.To;
            }
            else if (center.Latitude < validLatitudeRange.From)
            {
                newLatitude = validLatitudeRange.From;
            }

            if (newLatitude != center.Latitude || newLongitude != center.Longitude)
            {
                center.Latitude = newLatitude;
                center.Longitude = newLongitude;
                isChanged = true;
            }

            Range<double> range = GetZoomRange(center);
            if (zoomLevel > range.To)
            {
                zoomLevel = range.To;
                isChanged = true;
            }
            else if (zoomLevel < range.From)
            {
                zoomLevel = range.From;
                isChanged = true;
            }

            return isChanged;
        }

    }

 

         定义好之后,调用起来很方便。

XAML<m:Map x:Name="myMap" CredentialsProvider="Your Key" /> C#

            myMap.Mode = new ChinaMode();

            myMap.SetView(new Location(37.5, 104.3), 4);

            myMap.MapForeground.TemplateApplied += (s, e) =>

            {

                myMap.MapForeground.NavigationBar.TemplateApplied += (sender, eventArgs) =>

                    {

                        myMap.MapForeground.NavigationBar.HorizontalPanel.Children.Clear();

                    };

            };

         限定显示范围内,导航条中的缩放条会自动根据所设置的级别变化,但需要手工屏蔽它自带的RoadAerial的按钮。上述C#后面的代码作用即此,请注意图中左上角的导航条变化。示例结果图示: http://hi.baidu.com/liongg/blog/item/5724d42a1d048291033bf620.html 

posted @ 2009-11-17 22:43 狮兄 阅读(1026) 评论(2) 编辑

2009年11月16日

BMSL V1新特性

       BMSL V1除包含CTP版的诸如DeepZoom等所有特性外,基于Silverlight3构建,支持OOBBlend设计时,并利用Bing Maps Key的方式授权。值得一提的新功能有:

       Map Mode的扩展性增强,比如新增的Fading Labels功能,即来源于此。

       内置PushpinBinding:原来没有默认的地理标记,最基本的添加个地理要素也需要自定义个形状,在Earthware等人的呼吁下,终于默认提供了,并提供MapItemsControl支持批量地物绑定,俺觉得后者有些多余。

       Bing Maps Web Service:对相关类,属性,方法进行一系列包装,可以更加方便的再BMSL中使用。

       国际支持:通过设置Mapculture属性,可以使用某地区本地的瓦片数据。

       可嵌入性:无需懂得编程,按照给定URL的参数规范,设定相应的值,嵌入到原来的程序中,即可显示地图。此功能目前有限,仅支持添加pushpin等简单用途。

 脚本API:对那些不愿意使用VS等开发工具的同学们来说是个顶级好消息,利用相关API的脚本接口,在JavaScript里完成相关开发程序。

      

       Embeddable MapsScriptable API其实是微软自己开发的在线应用程序,通过特定的URL参数和脚本接口,来让普通用户使用。在线程序网址,也即使用Embeddable Maps特性时的URL前缀:http://dev.virtualearth.net/embeddedMap/v1/silverlight ;其中的XAP,也即使用Scriptable API必需引用的XAP源:http://dev.virtualearth.net/silverlight/mapcontrol/v1/Microsoft.Maps.MapControl.xap

 

        把该XAP下载解压缩反编译,可以发现程序集Microsoft.Maps.MapControl.Scripting.dll中的ScriptableMapMap继承,ScriptableMapLayerMapLayer继承,开放相应接口,共同构成Scriptable API。而在App类的Application_Startup中,根据规范的URL参数,来载入相应的地图数据,从而支持了Embeddable Map功能。
      

 

       基本来说,新特性就上述这么点东西。对比EarthWaretop-10-wish-list还差得老远,比如模块的重新设计,KML/GeoRSS的内置支持,Clustering,绘制工具,导航控件自定义风格能够更容易等等。因此估计他们和我一样不免失望。

         但同时Embeddable MapsScriptable API功能的支持方法,也提醒我们,不要总想着依赖基础商给我们定制太多的东西,很多好玩的,我们自己,或者说更靠近用户的开发商,可以自己去玩玩。

 

    延伸阅读:图文版    在BMSL中使用Google 地图    Bing Maps Silverlight Control 1.0发布 

 

posted @ 2009-11-16 08:54 狮兄 阅读(961) 评论(0) 编辑

2009年11月14日

在BMSL中使用Google 地图

摘要: BMSL,即Bing MapsSilverlight Control的简称,入门请看帮助文档和iSDK,比如申请Key之类,否则会出现“InvalidateCredentials ”的警告。看题目貌似我又来砸场子了,其实不是。遥想当年,Google Maps刚刚诞生之时,并无相应的API。不久就有人Hack之,于是Google就顺势推出API,自此风靡…&he...阅读全文

posted @ 2009-11-14 11:02 狮兄 阅读(1306) 评论(8) 编辑

2009年11月11日

Bing Maps Silverlight Control 1.0发布

摘要: Bing Maps Silverlight Control自从3月发布CTP版后,8个月不见动静,甚至沦落到在论坛里已经有人问这个项目是不是死掉了。终于,跳过Beta直接就发布正式版。参见官方报道1,官方报道2,视频新闻等。同时,Bing Maps彻底翻新,增加了诸多新特性,比如:Draggable Routes,缩放条样式更新,和Silverlight Control一致,必应版(中国版)截至目...阅读全文

posted @ 2009-11-11 12:45 狮兄 阅读(1903) 评论(5) 编辑

2009年4月27日

猪流感疑似病例全球分布动态图

posted @ 2009-04-27 23:07 狮兄 阅读(244) 评论(1) 编辑

2009年4月20日

Google Maps地图投影全解析

posted @ 2009-04-20 20:17 狮兄 阅读(5299) 评论(7) 编辑

2009年3月20日

ArcGIS API for Silverlight 测试版发布

posted @ 2009-03-20 22:15 狮兄 阅读(625) 评论(1) 编辑

导航

统计

公告

昵称:狮兄
园龄:3年3个月
粉丝:20
关注:2

搜索

 

常用链接

我的标签

随笔档案

相册

积分与排名

最新评论

阅读排行榜

评论排行榜

推荐排行榜