欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C# 中SharpMap的简单使用实例详解

程序员文章站 2023-12-09 17:30:03
本文是利用shapmap实现gis的简单应用的小例子,以供学习分享使用。关于sharpmap的说明,网上大多是以shapefile为例进行简单的说明,就连官网上的例子也不多...

本文是利用shapmap实现gis的简单应用的小例子,以供学习分享使用。关于sharpmap的说明,网上大多是以shapefile为例进行简单的说明,就连官网上的例子也不多。本文是自己参考了源代码进行整理的,主要是winform的例子。原理方面本文也不过多论述,主要是实例演示,需要的朋友还是以sharpmap源码进行深入研究。

什么是sharpmap ?

sharpmap是一个基于.net 2.0使用c#开发的map渲染类库,可以渲染各类gis数据(目前支持esri shape和postgis格式),可应用于桌面和web程序。代码行数近10000行,可以算是一个实现了最基本功能的gis系统,有利于研究学习使用。

涉及知识点:

  • sharpmap的基本概念:layer(图层,常用图层:vectorlayer,labellayer) , iprovider(数据提供者,常用数据源:ogr(对应mapinfo),shapfile,datatablepoint(对应dataset))
  • 坐标转换:主要用于经纬度和地图坐标的转换。

sharpmap知识结构图:

C# 中SharpMap的简单使用实例详解

效果图如下:

(一)车辆轨迹图:数据源:excel数据

C# 中SharpMap的简单使用实例详解

(二)定点数据(数据源:excel)将河南省十七个城市,全部插上小红旗

C# 中SharpMap的简单使用实例详解

(三)使用mapinfo做背景文件(此处通过程序调整了比例尺)

C# 中SharpMap的简单使用实例详解

(四)使用shapfile做背景图

C# 中SharpMap的简单使用实例详解

核心代码

using brutile.predefined;
using geoapi.coordinatesystems.transformations;
using projnet.coordinatesystems;
using projnet.coordinatesystems.transformations;
using sharpmap;
using sharpmap.data.providers;
using sharpmap.layers;
using sharpmap.rendering;
using sharpmap.rendering.thematics;
using sharpmap.styles;
using system;
using system.collections.generic;
using system.data;
using system.data.oledb;
using system.drawing;
using system.drawing.drawing2d;
using system.drawing.text;
using system.linq;
using system.text;
using point = geoapi.geometries.coordinate;
namespace demosharpmap
{
 public class sharpmaphelper
 {
 private const string xlsconnectionstring = "provider={2};data source={0}\\{1};extended properties=\"excel 8.0;hdr=yes;imex=1\"";
 public static map initializemap(maptype tt,float angle)
 {
  map map = null;
  switch (tt)
  {
  case maptype.runline:
   map = initializemaposmwithxls(angle);
   break;
  case maptype.mapinfo:
   map = initializemapinfo(angle);
   break;
  case maptype.shapefile:
   map = initializemaporig(angle);
   break;
  case maptype.static:
   map = initializemaposmwithxls2(angle);
   break;
  default:
   map = initializemaposmwithxls(angle);
   break;
  }
  return map;
 }
 /// <summary>
 /// mapinfo格式的地图文件
 /// </summary>
 /// <param name="angle"></param>
 /// <returns></returns>
 private static map initializemapinfo(float angle)
 {
  //initialize a new map of size 'imagesize'
  map map = new map();
  //set up the countries layer
  vectorlayer laycountries = new vectorlayer("countries");
  //set the datasource to a shapefile in the app_data folder
  try
  {
  laycountries.datasource = new ogr("geodata/mapinfo/countriesmapinfo.tab");
  }
  catch (typeinitializationexception ex)
  {
  if (ex.message == "the type initializer for 'osgeo.ogr.ogr' threw an exception.")
  {
   throw new exception(
   string.format(
    "the application threw a pinvoke exception. you probably need to copy the unmanaged dll's to your bin directory. they are a part of fwtools {0}. you can download it from: http://home.gdal.org/fwtools/",
    gdalrasterlayer.fwtoolsversion));
  }
  throw;
  }
  //set fill-style to green
  laycountries.style.fill = new solidbrush(color.green);
  //set the polygons to have a black outline
  laycountries.style.outline = pens.black;
  laycountries.style.enableoutline = true;
  laycountries.srid = 4326;
  //set up a river layer
  vectorlayer layrivers = new vectorlayer("rivers");
  //set the datasource to a shapefile in the app_data folder
  layrivers.datasource = new ogr("geodata/mapinfo/riversmapinfo.tab");
  //define a blue 1px wide pen
  layrivers.style.line = new pen(color.blue, 1);
  layrivers.srid = 4326;
  //set up a river layer
  vectorlayer laycities = new vectorlayer("cities");
  //set the datasource to a shapefile in the app_data folder
  laycities.datasource = new ogr("geodata/mapinfo/citiesmapinfo.tab");
  laycities.style.symbolscale = 0.8f;
  laycities.maxvisible = 40;
  laycities.srid = 4326;
  //set up a country label layer
  labellayer laylabel = new labellayer("country labels");
  laylabel.datasource = laycountries.datasource;
  laylabel.enabled = true;
  laylabel.labelcolumn = "name";
  laylabel.style = new labelstyle();
  laylabel.style.forecolor = color.white;
  laylabel.style.font = new font(fontfamily.genericserif, 12);
  laylabel.style.backcolor = new solidbrush(color.fromargb(128, 255, 0, 0));
  laylabel.maxvisible = 90;
  laylabel.minvisible = 30;
  laylabel.style.horizontalalignment = labelstyle.horizontalalignmentenum.center;
  laylabel.srid = 4326;
  laylabel.multipartgeometrybehaviour = labellayer.multipartgeometrybehaviourenum.largest;
  //set up a city label layer
  labellayer laycitylabel = new labellayer("city labels");
  laycitylabel.datasource = laycities.datasource;
  laycitylabel.enabled = true;
  laycitylabel.labelcolumn = "name";
  laycitylabel.style = new labelstyle();
  laycitylabel.style.forecolor = color.black;
  laycitylabel.style.font = new font(fontfamily.genericserif, 11);
  laycitylabel.maxvisible = laylabel.minvisible;
  laycitylabel.style.horizontalalignment = labelstyle.horizontalalignmentenum.left;
  laycitylabel.style.verticalalignment = labelstyle.verticalalignmentenum.bottom;
  laycitylabel.style.offset = new pointf(3, 3);
  laycitylabel.style.halo = new pen(color.yellow, 2);
  laycitylabel.textrenderinghint = textrenderinghint.antialias;
  laycitylabel.smoothingmode = smoothingmode.antialias;
  laycitylabel.srid = 4326;
  laycitylabel.labelfilter = labelcollisiondetection.thoroughcollisiondetection;
  laycitylabel.style.collisiondetection = true;
  //add the layers to the map object.
  //the order we add them in are the order they are drawn, so we add the rivers last to put them on top
  map.layers.add(laycountries);
  map.layers.add(layrivers);
  map.layers.add(laycities);
  map.layers.add(laylabel);
  map.layers.add(laycitylabel);
  //增加layers
  var xlspath = string.format(xlsconnectionstring, system.io.directory.getcurrentdirectory(), "geodata\\henan.xls", properties.settings.default.oledbprovider);
  var ds = getdatafromexcel(xlspath, "cities");
  //var ct = getcoordinatetransformation();
  //transcoordinate(ds, ct);
  string columename = "rotation";
  //add rotation column
  addcolumetodataset(ds, columename, -angle);
  var xlslayer = getlayerfromdataset2(ds, color.greenyellow);//set up provider
  map.layers.add(xlslayer); //add layer to map
  map.center = xlslayer.envelope.centre;// new point(0, 0);
  map.mapscale = 350;
  //map.center = new point(0, 0);
  //_ogrsampledataset = "mapinfo";
  //matrix mat = new matrix();
  //mat.rotateat(angle, map.worldtoimage(map.center));
  //map.maptransform = mat;
  //map.zoomtobox(xlslayer.envelope);
  return map;
 }
 /// <summary>
 /// shapefile
 /// </summary>
 /// <param name="angle"></param>
 /// <returns></returns>
 private static map initializemaporig(float angle)
 {
  //initialize a new map of size 'imagesize'
  map map = new map();
  //set up the countries layer
  vectorlayer laycountries = new vectorlayer("countries");
  //set the datasource to a shapefile in the app_data folder
  laycountries.datasource = new shapefile("geodata/world/countries.shp", true);
  //set fill-style to green
  laycountries.style.fill = new solidbrush(color.fromargb(64, color.green));
  //set the polygons to have a black outline
  laycountries.style.outline = pens.black;
  laycountries.style.enableoutline = true;
  laycountries.srid = 4326;
  //set up a river layer
  vectorlayer layrivers = new vectorlayer("rivers");
  //set the datasource to a shapefile in the app_data folder
  layrivers.datasource = new shapefile("geodata/world/rivers.shp", true);
  //define a blue 1px wide pen
  layrivers.style.line = new pen(color.blue, 1);
  layrivers.srid = 4326;
  //set up a cities layer
  vectorlayer laycities = new vectorlayer("cities");
  //set the datasource to a shapefile in the app_data folder
  laycities.datasource = new shapefile("geodata/world/cities.shp", true);
  laycities.style.symbolscale = 0.8f;
  laycities.maxvisible = 40;
  laycities.srid = 4326;
  //set up a country label layer
  labellayer laylabel = new labellayer("country labels");
  laylabel.datasource = laycountries.datasource;
  laylabel.enabled = true;
  laylabel.labelcolumn = "name";
  laylabel.style = new labelstyle();
  laylabel.style.forecolor = color.white;
  laylabel.style.font = new font(fontfamily.genericserif, 12);
  laylabel.style.backcolor = new solidbrush(color.fromargb(128, 255, 0, 0));
  laylabel.maxvisible = 90;
  laylabel.minvisible = 30;
  laylabel.style.horizontalalignment = labelstyle.horizontalalignmentenum.center;
  laylabel.srid = 4326;
  laylabel.multipartgeometrybehaviour = labellayer.multipartgeometrybehaviourenum.largest;
  laylabel.labelfilter = labelcollisiondetection.thoroughcollisiondetection;
  laylabel.style.collisiondetection = true;
  laylabel.labelpositiondelegate = fdr => fdr.geometry.interiorpoint.coordinate;
  laylabel.prioritycolumn = "popdens";
  //set up a city label layer
  labellayer laycitylabel = new labellayer("city labels");
  laycitylabel.datasource = laycities.datasource;
  laycitylabel.enabled = true;
  laycitylabel.labelcolumn = "name";
  laycitylabel.style = new labelstyle();
  laycitylabel.style.forecolor = color.black;
  laycitylabel.style.font = new font(fontfamily.genericserif, 11);
  laycitylabel.maxvisible = laylabel.minvisible;
  laycitylabel.style.horizontalalignment = labelstyle.horizontalalignmentenum.left;
  laycitylabel.style.verticalalignment = labelstyle.verticalalignmentenum.bottom;
  laycitylabel.style.offset = new pointf(3, 3);
  laycitylabel.style.halo = new pen(color.yellow, 2);
  laycitylabel.textrenderinghint = textrenderinghint.antialias;
  laycitylabel.smoothingmode = smoothingmode.antialias;
  laycitylabel.srid = 4326;
  laycitylabel.labelfilter = labelcollisiondetection.thoroughcollisiondetection;
  laycitylabel.style.collisiondetection = true;
  laycitylabel.prioritycolumn = "population";
  laycitylabel.theme = new gradienttheme(laycitylabel.prioritycolumn, 250000, 5000000,
  new labelstyle
  {
   maxvisible = 10,
   collisionbuffer = new size(0, 0),
   collisiondetection = true,
   enabled = true,
   forecolor = color.lightslategray,
   halo = new pen(color.silver, 1),
   horizontalalignment = labelstyle.horizontalalignmentenum.center,
   verticalalignment = labelstyle.verticalalignmentenum.middle,
   font = new font(genericfontfamilies.sansserif.tostring(), 8f, fontstyle.regular)
  },
  new labelstyle
  {
   maxvisible = laylabel.minvisible,
   collisionbuffer = new size(3, 3),
   collisiondetection = true,
   enabled = true,
   forecolor = color.lightslategray,
   halo = new pen(color.silver, 5),
   horizontalalignment = labelstyle.horizontalalignmentenum.center,
   verticalalignment = labelstyle.verticalalignmentenum.middle,
   font = new font(genericfontfamilies.sansserif.tostring(), 16f, fontstyle.bold)
  });
  bool ignorelength = false;
  var layriverlabel = new labellayer("river labels")
  {
  datasource = layrivers.datasource,
  enabled = true,
  labelcolumn = "name",
  textrenderinghint = textrenderinghint.antialias,
  smoothingmode = smoothingmode.antialias,
  srid = 4326,
  labelfilter = labelcollisiondetection.thoroughcollisiondetection,
  multipartgeometrybehaviour = labellayer.multipartgeometrybehaviourenum.commoncenter,
  style =
      new labelstyle
      {
      forecolor = color.darkblue,
      font = new font(fontfamily.genericsansserif, 11),
      horizontalalignment = labelstyle.horizontalalignmentenum.center,
      verticalalignment = labelstyle.verticalalignmentenum.middle,
      //collisiondetection = true,
      halo = new pen(color.azure, 2),
      ignorelength = ignorelength,
      offset = new pointf(0, -10)
      },
  };
  //add the layers to the map object.
  //the order we add them in are the order they are drawn, so we add the rivers last to put them on top
  //map.backgroundlayer.add(asynclayerproxylayer.create(laycountries));
  map.layers.add(laycountries);
  map.layers.add(layrivers);
  map.layers.add(laycities);
  map.layers.add(laylabel);
  map.layers.add(laycitylabel);
  map.layers.add(layriverlabel);
  //增加layers
  var xlspath = string.format(xlsconnectionstring, system.io.directory.getcurrentdirectory(), "geodata\\henan.xls", properties.settings.default.oledbprovider);
  var ds = getdatafromexcel(xlspath, "cities");
  //var ct = getcoordinatetransformation();
  //transcoordinate(ds, ct);
  string columename = "rotation";
  //add rotation column
  addcolumetodataset(ds, columename, -angle);
  var xlslayer = getlayerfromdataset2(ds, color.greenyellow);//set up provider
  map.layers.add(xlslayer); //add layer to map
     //limit the zoom to 360 degrees width
     //map.maximumzoom = 360;
     //map.backcolor = color.lightblue;
  //map.zoom = 360;
  map.center = xlslayer.envelope.centre;// new point(0, 0);
  map.mapscale = 350;
  //matrix mat = new matrix();
  //mat.rotateat(angle, map.worldtoimage(map.center));
  //map.maptransform = mat;
  //map.zoomtobox(xlslayer.envelope);
  return map;
 }
 /// <summary>
 /// 在线显示,圆点显示轨迹
 /// </summary>
 /// <param name="angle"></param>
 /// <returns></returns>
 private static map initializemaposmwithxls(float angle)
 {
  var map = new map();
  var tilelayer = new tileasynclayer(
  knowntilesources.create(knowntilesource.openstreetmap), "tilelayer - osm with xls");
  tilelayer.srid = 4326;
  map.backgroundlayer.add(tilelayer);
  //get data from excel
  var xlspath = string.format(xlsconnectionstring, system.io.directory.getcurrentdirectory(), "geodata\\cities.xls", properties.settings.default.oledbprovider);
  var ds = getdatafromexcel(xlspath, "cities");
  var ds1 = getdatafromexcel(xlspath, "cities2");
  var ct = getcoordinatetransformation();
  transcoordinate(ds, ct);
  transcoordinate(ds1, ct);
  string columename = "rotation";
  //add rotation column
  addcolumetodataset(ds, columename, -angle);
  addcolumetodataset(ds1, columename, -angle);
  var xlslayer = getlayerfromdataset(ds, color.greenyellow);//set up provider
  map.layers.add(xlslayer); //add layer to map
  var xlslayer1 = getlayerfromdataset(ds1, color.red);
  map.layers.add(xlslayer1);
  var xlslabellayer = getlabellayerbyvectorlayer(xlslayer, "xlslabel");
  xlslabellayer.theme = new sharpmap.rendering.thematics.fontsizetheme(xlslabellayer, map) { fontsizescale = 1000f };
  map.layers.add(xlslabellayer);
  map.zoomtobox(xlslayer.envelope.expandedby(xlslayer1.envelope));
  return map;
 }
 /// <summary>
 /// 在线显示,图标显示轨迹
 /// </summary>
 /// <param name="angle"></param>
 /// <returns></returns>
 private static map initializemaposmwithxls2(float angle)
 {
  var map = new map();
  var tilelayer = new tileasynclayer(
  knowntilesources.create(knowntilesource.openstreetmap), "tilelayer - osm with xls");
  tilelayer.srid = 4326;
  map.backgroundlayer.add(tilelayer);
  //get data from excel
  var xlspath = string.format(xlsconnectionstring, system.io.directory.getcurrentdirectory(), "geodata\\henan.xls", properties.settings.default.oledbprovider);
  var ds = getdatafromexcel(xlspath, "cities");
  var ct = getcoordinatetransformation();
  transcoordinate(ds, ct);
  string columename = "rotation";
  //add rotation column
  addcolumetodataset(ds, columename, -angle);
  var xlslayer = getlayerfromdataset2(ds, color.greenyellow);//set up provider
  map.layers.add(xlslayer); //add layer to map
  var xlslabellayer = getlabellayerbyvectorlayer(xlslayer, "xlslabel");
  xlslabellayer.theme = new fontsizetheme(xlslabellayer, map) { fontsizescale = 1000f };
  map.layers.add(xlslabellayer);
  map.zoomtobox(xlslayer.envelope);
  return map;
 }
 /// <summary>
 /// 从excel中读取数据
 /// </summary>
 private static dataset getdatafromexcel(string xlspath, string sheetname)
 {
  dataset ds = new dataset("xls");
  string sql = string.format("select * from [{0}$];", sheetname);
  using (var cn = new oledbconnection(xlspath))
  {
  cn.open();
  using (var da = new oledbdataadapter(new oledbcommand(sql, cn)))
  {
   da.fill(ds);
  }
  }
  return ds;
 }
 /// <summary>
 /// 获取坐标转换对象
 /// </summary>
 /// <returns></returns>
 private static icoordinatetransformation getcoordinatetransformation()
 {
  //the srs for this datasource is epsg:4326, therefore we need to transfrom it to osm projection
  var ctf = new coordinatetransformationfactory();
  var cf = new coordinatesystemfactory();
  var epsg4326 = cf.createfromwkt("geogcs[\"wgs 84\",datum[\"wgs_1984\",spheroid[\"wgs 84\",6378137,298.257223563,authority[\"epsg\",\"7030\"]],authority[\"epsg\",\"6326\"]],primem[\"greenwich\",0,authority[\"epsg\",\"8901\"]],unit[\"degree\",0.01745329251994328,authority[\"epsg\",\"9122\"]],authority[\"epsg\",\"4326\"]]");
  var epsg3857 = cf.createfromwkt("projcs[\"popular visualisation crs / mercator\", geogcs[\"popular visualisation crs\", datum[\"popular visualisation datum\", spheroid[\"popular visualisation sphere\", 6378137, 0, authority[\"epsg\",\"7059\"]], towgs84[0, 0, 0, 0, 0, 0, 0], authority[\"epsg\",\"6055\"]],primem[\"greenwich\", 0, authority[\"epsg\", \"8901\"]], unit[\"degree\", 0.0174532925199433, authority[\"epsg\", \"9102\"]], axis[\"e\", east], axis[\"n\", north], authority[\"epsg\",\"4055\"]], projection[\"mercator\"], parameter[\"false_easting\", 0], parameter[\"false_northing\", 0], parameter[\"central_meridian\", 0], parameter[\"latitude_of_origin\", 0], unit[\"metre\", 1, authority[\"epsg\", \"9001\"]], axis[\"east\", east], axis[\"north\", north], authority[\"epsg\",\"3857\"]]");
  var ct = ctf.createfromcoordinatesystems(epsg4326, epsg3857);
  return ct;
 }
 /// <summary>
 /// 转换地球经纬度到坐标
 /// </summary>
 /// <param name="ds"></param>
 /// <param name="ct"></param>
 private static void transcoordinate(dataset ds, icoordinatetransformation ct)
 {
  foreach (system.data.datarow row in ds.tables[0].rows)
  {
  if (row["x"] == dbnull.value || row["y"] == dbnull.value) continue;
  var coords = new[] { convert.todouble(row["x"]), convert.todouble(row["y"]) };
  coords = ct.mathtransform.transform(coords);
  row["x"] = coords[0];
  row["y"] = coords[1];
  }
 }
 /// <summary>
 /// 增加列
 /// </summary>
 /// <param name="ds"></param>
 /// <param name="columename"></param>
 /// <param name="columevalue"></param>
 private static void addcolumetodataset(dataset ds, string columename, float columevalue)
 {
  ds.tables[0].columns.add(columename, typeof(float));
  foreach (system.data.datarow row in ds.tables[0].rows)
  {
  row["rotation"] = -columevalue;
  }
 }
 /// <summary>
 /// 轨迹用点表示
 /// </summary>
 /// <param name="ds"></param>
 /// <param name="c"></param>
 /// <returns></returns>
 private static vectorlayer getlayerfromdataset(dataset ds, color c)
 {
  var xlsprovider = new datatablepoint(ds.tables[0], "oid", "x", "y");
  var xlslayer = new vectorlayer("xls", xlsprovider)
  { style = new vectorstyle() { pointcolor = new solidbrush(c) } };
  return xlslayer;
 }
 /// <summary>
 /// 获取带图标的图层
 /// </summary>
 /// <param name="ds"></param>
 /// <param name="c"></param>
 /// <returns></returns>
 private static vectorlayer getlayerfromdataset2(dataset ds, color c)
 {
  var xlsprovider = new datatablepoint(ds.tables[0], "oid", "x", "y");
  var xlslayer = new vectorlayer("xls", xlsprovider)
  { style = { symbol=properties.resources.redflag} };
  return xlslayer;
 }
 private static labellayer getlabellayerbyvectorlayer(vectorlayer xlslayer, string layername)
 {
  var xlslabellayer = new labellayer(layername)
  {
  datasource = xlslayer.datasource,
  labelcolumn = "name",
  //prioritycolumn = "population",
  style =
   {
   collisionbuffer = new system.drawing.sizef(2f, 2f),
   collisiondetection = true
   },
  labelfilter = labelcollisiondetection.thoroughcollisiondetection
  };
  return xlslabellayer;
 }
 }
 public enum maptype {
 shapefile = 0,
 mapinfo = 1,
 runline = 2,//运行轨迹
 static = 3 //定点数据
 }
}

备注:

1. 因用的mapinfo和shape源文件为源码里面的,所有为英文显示。

源码下载:http://xiazai.jb51.net/201707/yuanma/demosharpmap_jb51.rar

总结

以上所述是小编给大家介绍的c# 中sharpmap的简单使用实例详解,希望对大家有所帮助