一、DotSpatial是什么
DotSpatial是一个基于.Net Framework 4.0 版本编写的一个地理信息系统(GIS)库,以UserControl的形式提供地图控件。它可帮助开发人员把空间数据、空间分析的功能加入到他们的应用程序中,还可以帮助开发人员把地理信息系统功能扩展到社区。目前Dans Ames是DotSpatial的项目经理。
DotSpatial可以帮助您:
- 在WinForm或者ASP.NET中打开地图
- 打开用Shapefile格式存储的矢量图以及栅格、位图等形式表示的地图
- 渲染符号,不重叠的标签
- 简单的坐标系统转换,包括大地坐标系与投影坐标系之间的转换,内置支持北京54、西安80、国家CGCS2000等等投影坐标系
- 操作和显示属性数据
- 科学分析
- 读取GPS数据
官方提供的源代码目前还不能:
- 地图绘图系统绘制除点、线、多边形以外的几何图形,包括椭圆形、扇形、弧形
- 以谷歌的900913坐标系为代表的WebMecator系列投影坐标系与其它坐标系之间的互相转换
- 多次空间测量,圆形、扇形等多种图形的面积测量
- DotSpatial绘图消息外部单独刷新某一个图层,不支持异步加载地图数据后展示
下面我以加载地图开始,以逐步扩展DotSpatial功能的方式为详细介绍DotSpatial。
二、准备工作
1、开发工具
开发WinForm程序当然得VisualStudio,我用的是VS2013Update5。
2、地图控件库
下载DotSpatial库进行引用或者源代码进行编译。DotSpatial的下载地址是:http://dotspatial.codeplex.com/。还可以在这里下载:https://github.com/DotSpatial/DotSpatial。我直接下载的是库,如下图所示:
3、数据
进行地图控件开发当然得要必须的GIS数据。如果您不想到处找资源,我上传了一个资源,可供开发测试使用。这个地图数据也是我这个代码示例使用的地图数据。下载链接如下:http://download.youkuaiyun.com/detail/caoshiying/9602626。您还可以自己上网搜索。
三、加载一个Shapefile
1、开始
好的编程习惯始于合理的代码目录结构。我新建的代码目录结构如下:
其中data目录存储的软件需要的存放在本地电脑的外部数据,demo是解决方案名称,lib是解决方案引用的外部库,release用于存放经过冒烟测试确认稳定的版本,test存放的是测试工程。
2、新建项目
用VS自带的模板新建一个简单的Winform应用程序,如下图所示:
3、引入DosSpatial的控件库
我选择全部引用,如下图所示:
4、输出地图数据
用VS编译设置帮助复制地图文件到软件运行目录下,如下图所示:
5、加入DotSpatial的地图控件
加载一个Shapefile,代码如下:
public partial class MainForm : Form
{
private Map mapCtrl = null;
public MainForm()
{
InitializeComponent();
InitMapControl();
}
private void InitMapControl()
{
mapCtrl = new Map()
{
Name = "mapCtrl",
Dock = DockStyle.Fill
};
var shp = Shapefile.OpenFile("Shapefiles\\bou2_4l.shp");
shp.Projection = KnownCoordinateSystems.Geographic.World.WGS1984;
var layer = mapCtrl.Layers.Add(shp) as MapLineLayer;
layer.Symbolizer = new DotSpatial.Symbology.LineSymbolizer(Color.FromArgb(0x33, 0x33, 0x33), 1);
Controls.Add(mapCtrl);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
mapCtrl.ViewExtents = mapCtrl.ViewExtents;
}
}
6、运行效果
四、实时坐标
一张突突的地图啥都没有确实不自在。下面,我将用一个简单的方法实现在左下角显示实时坐标。
1、增加一个Label控件
把背景设为透明色,代码如下:
private void InitCoordinateLabel()
{
coordLabelCtrl = new Label()
{
Name = "coordLabelCtrl",
Text = "X:00.0000,Y:00.0000",
Width=200,
BackColor = Color.Transparent
};
mapCtrl.Controls.Add(coordLabelCtrl);
}
2、显示Label控件
把显示位置的Label控件加入到地图控件,并监听地图控件的地理坐标位置改变事件:
private Label coordLabelCtrl = null;
void mapCtrl_GeoMouseMove(object sender, GeoMouseArgs e)
{
string locStr = "X:" + e.GeographicLocation.X.ToString("F6");
locStr += "Y:" + e.GeographicLocation.Y.ToString("F6");
coordLabelCtrl.Text = locStr;
}
3、运行效果

五、常见地图问题
1、地图拉伸变形问题
很多人添加地图后发现地图被拉伸变形了。其实原因在于MapCtrol控件监听窗口大小改变事件的同时会适当判断是否更新地图。在窗口显示之前地图控件的大小是默认的,DotSpatial按照此大小绘制地图。在窗口真正显示的时候只是简单拉伸图形,并没有重新。一个比较好的解决办法是在主窗口初始化之前把地图控件的事情做完,在主窗口加载的时机把地图控件显示出来,调整后的代码如下:
public partial class MainForm : Form
{
private Map mapCtrl = null;
public MainForm()
{
InitMapControl();
InitializeComponent();
}
private void InitMapControl()
{
mapCtrl = new Map()
{
Name = "mapCtrl",
Dock = DockStyle.Fill
};
var shp = Shapefile.OpenFile("Shapefiles\\bou2_4l.shp");
shp.Projection = KnownCoordinateSystems.Geographic.World.WGS1984;
var layer = mapCtrl.Layers.Add(shp) as MapLineLayer;
layer.Symbolizer = new DotSpatial.Symbology.LineSymbolizer(Color.FromArgb(0x33, 0x33, 0x33), 1);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Controls.Add(mapCtrl);
}
}
2、源代码
与VS模板相比较,所有发生变化的代码就一个主窗口。全文代码如下:
using DotSpatial.Controls;
using DotSpatial.Data;
using DotSpatial.Projections;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace demo
{
public partial class MainForm : Form
{
private Map mapCtrl = null;
private Label coordLabelCtrl = null;
public MainForm()
{
InitMapControl();
InitCoordinateLabel();
InitializeComponent();
}
private void InitMapControl()
{
mapCtrl = new Map()
{
Name = "mapCtrl",
Dock = DockStyle.Fill
};
var shp = Shapefile.OpenFile("Shapefiles\\bou2_4l.shp");
shp.Projection = KnownCoordinateSystems.Geographic.World.WGS1984;
var layer = mapCtrl.Layers.Add(shp) as MapLineLayer;
layer.Symbolizer = new DotSpatial.Symbology.LineSymbolizer(Color.FromArgb(0x33, 0x33, 0x33), 1);
mapCtrl.GeoMouseMove += mapCtrl_GeoMouseMove;
}
void mapCtrl_GeoMouseMove(object sender, GeoMouseArgs e)
{
string locStr = "X:" + e.GeographicLocation.X.ToString("F6");
locStr += "Y:" + e.GeographicLocation.Y.ToString("F6");
coordLabelCtrl.Text = locStr;
}
private void InitCoordinateLabel()
{
coordLabelCtrl = new Label()
{
Name = "coordLabelCtrl",
Text = "X:00.0000,Y:00.0000",
Width=200,
BackColor = Color.Transparent
};
mapCtrl.Controls.Add(coordLabelCtrl);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Controls.Add(mapCtrl);
coordLabelCtrl.Top = mapCtrl.Height - coordLabelCtrl.Height;
}
}
}
六、高级功能
关于比例尺,请参照:http://blog.youkuaiyun.com/caoshiying/article/details/51596005
关于空间测量,请参照:http://blog.youkuaiyun.com/caoshiying/article/details/51860026
http://blog.youkuaiyun.com/caoshiying/article/details/51820983
关于元素识别:http://blog.youkuaiyun.com/caoshiying/article/details/51981897
关于DotSpatial性能:http://blog.youkuaiyun.com/caoshiying/article/details/51831033
关于WMS地图:http://blog.youkuaiyun.com/caoshiying/article/details/51984796