C# 中SharpMap的简单使用实例详解
程序员文章站
2023-12-15 21:01:10
本文是利用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知识结构图:
效果图如下:
(一)车辆轨迹图:数据源:excel数据
(二)定点数据(数据源:excel)将河南省十七个城市,全部插上小红旗
(三)使用mapinfo做背景文件(此处通过程序调整了比例尺)
(四)使用shapfile做背景图
核心代码
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的简单使用实例详解,希望对大家有所帮助