小言_互联网的博客

C# .NET winform地图开发GMap离线地图在线地图&自建地图服务器

657人阅读  评论(0)

添加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…

			//图层
            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,实现图标实时切换,图标闪烁等功能

 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();
        }
    }
//切换图片
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}”;

程序展示


转载:https://blog.csdn.net/cs5956/article/details/106158103
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场