目录
- 添加GMap引用
- 下载GMap demo
- 尝试一个测试程序
- 下载离线地图
- 使用离线模式读取地图
- 加载高德地图
- 获取WMTS
- 坐标系转化
- GMap常用地图操作
- 自建地图服务器
添加GMap引用
下载GMap demo
包含GMap源码以及地图下载器(用于生成GMDB格式离线地图文件)
下载地址:https://archive.codeplex.com/?p=greatmaps
PS:部分网络下载速度较慢,稍后提供下载链接。
尝试一个测试程序
新建用户控件继承GMapControl
重新生成解决方案,拖控件。
只需要几行代码就可以加载谷歌地图
下载离线地图
适合内网环境,程序拷贝到另外的设备也可以直接使用,方便部署;后面还会给出自建地图服务器的方法,以便更高要求的开发需要。
打开官方的demo,运行Demo.WinfowsForms.exe下载地图;低配电脑打开较慢,请耐心等待。
选择谷歌中国地图;右键拖拽,滚轮放大缩小;
按住alt,鼠标左键框选需要下载的地图
右侧点击cache->prefretch selected area;
确认是否截取Zoom级别12的地图;点击是。
一般截取到16或17就够用了;不需要截取的zoom点击否;
prefetch完毕后点击Export导出gmdb文件,也就是离线地图。
使用离线模式读取地图
修改我们的代码
运行程序,可以看到未下载的地图区域是无法显示的,而下载的地图区域已经成功从本地读取了缓存。
加载高德地图
打开GMap源码,可以看到已经有很多MapProvider;可是没有高德,百度等国内地图的Provider;需要我们自己实现MapProvider。
查看源码,看不懂怎么办?没有关系,依葫芦画瓢;首先创建一个AMapProviderBase继承GMapProvider
然后创建AMapProvider继承AMapProviderBase
我们可以观察到这些Provider的实现类都很类似,最大的区别就是UrlFormat不一样;
这个UrlFormat代表什么?
我们复制一个UrlFormat到浏览器看一看:
static readonly string UrlFormat = “http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer/tile/{0}/{1}/{2}”;
观察代码发现{0},{1},{2}分包表示zoom,Y坐标和X坐标;
于是我们修改一下URL:
http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer/tile/1/1/2
这不就是我们要找的瓦片地图吗?
对没错!这个URL就是地图提供商提供的WMTS接口!也就是地图瓦片服务。如果我们拿到了WMTS接口,就意味着我们可以通过GMap访问市面上大部分地图服务器。
这里提供高德的WMTS接口,修改style可以调用不同的地图样式。(在网路上找了很多,这个版本的WMTS貌似是最新的,不过好像没有只显示路名的简图)
完成AMapProvider的编写后,打开GMapProviders类,新增一个高德地图的实例
运行一下,可以看到已经有了高德地图的选项。
下面就可以尽情下载高德地图了
应用程序使用离线地图也需要修改MapProvider
获取WMTS
有了WMTS接口就可以加载任意的地图
捷泰地图暗黑版
捷泰地图暖色版
注意部分地图提供商的服务需要注册申请key
坐标系转化
注意地图使用的坐标系,不同坐标系经纬度会有偏移:
名称 | 解释 |
---|---|
WGS84 | 地心坐标系,国际通用坐标系 |
GCJ02 | 国测局坐标(火星坐标系),WGS84加密后的坐标系;GoogleChina地图、高德地图等国内地图使用 |
BD09 | 百度坐标系,GCJ02再次加密后的坐标系 |
网路上可以搜索到坐标原理以及不同坐标转换的工具类,在此不再赘述。
GMap常用地图操作
GMap地图控件结构:
底图
↓
图层1→markers、routes…
↓
图层2→markers、routes…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | //图层 GMapOverlay bgLayer = new GMapOverlay("bgLayer"); mapControl1.Overlays.Add(bgLayer); mapControl1.Overlays.Remove(bgLayer); //marker Bitmap markerGreen = Image.FromFile("path") as Bitmap; PointLatLng point = new PointLatLng(32.261551, 118.339794); GMapMarker marker = new GMarkerGoogle(point, markerGreen); //tooltip MarkerTooltipMode mode = MarkerTooltipMode.Always;//标注一直显示 Brush tooltipBackColor = new SolidBrush(Color.Transparent); marker.ToolTip = new GMapToolTip(marker); marker.ToolTipMode = mode; marker.ToolTipText = "xx路与xx路"; //tooltip样式 marker.ToolTip.Font = new Font("微软雅黑", 11); marker.ToolTip.Fill = tooltipBackColor; marker.ToolTip.Foreground = Brushes.Gray; marker.ToolTip.Stroke.Brush = tooltipBackColor; marker.ToolTip.Offset = new System.Drawing.Point(marker.Offset.X - (int)((float)marker.ToolTipText.Length / 2) * 15, marker.Offset.Y + 28); //marker加到图层 bgLayer.Markers.Add(marker); //marker点击事件 mapControl1.OnMarkerClick += new MarkerClick(Marker_Click_Event); //Route线路 List<PointLatLng> points = new List<PointLatLng>(); GMapRoute r = new GMapRoute(points, null); bgLayer.Routes.Add(r); |
自定义Marker,实现图标实时切换,图标闪烁等功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | public class GMapMarkerImage : GMapMarker { private Image image; public Image Image { get { return image; } set { image = value; if (image != null) { this.Size = new Size(image.Width, image.Height); } } } public Pen Pen { get; set; } public Pen OutPen { get; set; } public GMapMarkerImage(PointLatLng point, Image image) : base(point) { Size = new Size(image.Width, image.Height); Offset = new Point(-Size.Width / 2, -Size.Height / 2); this.image = image; Pen = null; OutPen = null; } public override void OnRender(Graphics g) { if (image == null) { return; } Rectangle rect = new Rectangle(LocalPosition.X, LocalPosition.Y, Size.Width, Size.Height); Rectangle rectBlink = new Rectangle(LocalPosition.X-3, LocalPosition.Y -3, Size.Width+5, Size.Height+5); g.DrawImage(image, rect); if (Pen != null) { g.DrawRectangle(Pen, rect); } if (OutPen != null) { g.DrawEllipse(OutPen, rectBlink); } } public void UpdateImage(Image image) { this.image = image; } public override void Dispose() { if (Pen != null) { Pen.Dispose(); Pen = null; } if (OutPen != null) { OutPen.Dispose(); OutPen = null; } base.Dispose(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 | //切换图片 marker.UpdateImage(bitmapGreen); //闪烁 用定时器刷新 if (marker.OutPen == null) { marker.OutPen = new Pen(Brushes.DeepSkyBlue, 5); } else { marker.OutPen.Dispose(); marker.OutPen = null; } |
可以实现的效果
自建地图服务器
通过自建地图服务器,可以实现自定义地图边界,手动绘制新增道路,随意调整地图样式,去除不必要的标注等功能。
GeoServer 是 OpenGIS Web 服务器规范的 J2EE 实现,利用 GeoServer 可以方便的发布地图数据,允许用户对特征数据进行更新、删除、插入操作,通过 GeoServer 可以比较容易的在用户之间迅速共享空间地理信息。GeoServer是社区开源项目,可以直接通过社区网站下载。
WEB开发可以通过OpenLayers访问地图服务器。OpenLayers 是一个专为Web GIS 客户端开发提供的JavaScript 类库包,用于实现标准格式发布的地图数据访问。可以在 Web 上创建交互式地图,显示从任何来源加载的地图图块、矢量数据和标记。
安装GeoServer(需要JDK)
浏览器输入http://localhost:8089/geoserver/web/进入管理页面
GeoServer支持多种格式的地图,可以从网路上下载或购买。
推荐地图编辑软件:ArcMap、MapInfo
发布图层
自定义地图样式
WMTS服务
地图预览,比第三方地图服务器简洁了很多,多余的区域不显示,没有杂乱的标注和图标,可以充分个性化。
WMS接口
WMTS接口
“http://{your ip&port}/geoserver/gwc/service/wmts?layer={your mapName}&tilematrixset=EPSG:4326&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image/png&TileMatrix=EPSG:4326:{zoom}&TileCol={X}&TileRow={Y}”;
程序展示