C# SharpMap的简单使用
本文是利用ShapMap实现GIS的简单应用的小例子,以供学习分享使用。关于SharpMap的说明,网上大多是以ShapeFile为例进行简单的说明,就连官网上的例子也不多。本文是自己参考了源代码进行整理的,主要是WinForm的例子。原理方面本文也不过多论述,主要是实例演示,需要的朋友还是以SharpMap源码进行深入研究。 什么是SharpMap ? SharpMap是一个基于.net 2.0使用C#开发的Map渲染类库,可以渲染各类GIS数据(目前支持ESRI Shape和PostGIS格式),可应用于桌面和Web程序。代码行数近10000行,可以算是一个实现了最基本功能的GIS系统,有利于研究学习使用。 涉及知识点:
SharpMap知识结构图: 效果图如下: (一)车辆轨迹图:数据源:Excel数据 (二)定点数据(数据源:Excel)将河南省十七个城市,全部插上小红旗 (三)使用MapInfo做背景文件(此处通过程序调整了比例尺) (四)使用ShapFile做背景图 ? 核心代码 1 using BruTile.Predefined; 2 GeoAPI.CoordinateSystems.Transformations; 3 ProjNet.CoordinateSystems; 4 ProjNet.CoordinateSystems.Transformations; 5 SharpMap; 6 SharpMap.Data.Providers; 7 SharpMap.Layers; 8 SharpMap.Rendering; 9 SharpMap.Rendering.Thematics; 10 SharpMap.Styles; 11 System; 12 System.Collections.Generic; 13 System.Data; 14 System.Data.OleDb; 15 System.Drawing; 16 System.Drawing.Drawing2D; 17 System.Drawing.Text; 18 System.Linq; 19 System.Text; 20 using Point = GeoAPI.Geometries.Coordinate; 21 namespace DemoSharpMap 22 { 23 public class SharpMapHelper 24 { 25 26 private const string XlsConnectionString = "Provider={2};Data Source={0}{1};Extended Properties="Excel 8.0;HDR=Yes;IMEX=1""; 27 28 static Map InitializeMap(MapType tt,float angle) 29 { 30 Map map = null 31 switch (tt) 32 { 33 case MapType.RunLine: 34 map = InitializeMapOsmWithXls(angle); 35 break 36 MapType.MapInfo: 37 map = InitializeMapinfo(angle); 38 39 MapType.ShapeFile: 40 map = InitializeMapOrig(angle); 41 42 MapType.Static: 43 map = InitializeMapOsmWithXls2(angle); 44 45 default: 46 map = 47 48 } 49 return map; 50 } 51 52 /// <summary> 53 /// MapInfo格式的地图文件 54 </summary> 55 <param name="angle"></param> 56 <returns></returns> 57 static Map InitializeMapinfo( 58 59 //Initialize a new map of size 'imagesize' 60 Map map = new Map(); 61 62 Set up the countries layer 63 VectorLayer layCountries = new VectorLayer(Countries); 64 Set the datasource to a shapefile in the App_data folder 65 try 66 67 layCountries.DataSource = new Ogr(GeoData/MapInfo/countriesMapInfo.tab 68 69 catch (TypeInitializationException ex) 70 71 if (ex.Message == The type initializer for 'OSGeo.OGR.Ogr' threw an exception.) 72 { 73 throw Exception( 74 String.Format( 75 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/, 76 GdalRasterLayer.FWToolsVersion)); 77 } 78 throw 79 80 81 Set fill-style to green 82 layCountries.Style.Fill = SolidBrush(Color.Green); 83 Set the polygons to have a black outline 84 layCountries.Style.Outline = Pens.Black; 85 layCountries.Style.EnableOutline = true 86 layCountries.SRID = 4326 87 88 Set up a river layer 89 VectorLayer layRivers = Rivers 90 91 layRivers.DataSource = GeoData/MapInfo/riversMapInfo.tab 92 Define a blue 1px wide pen 93 layRivers.Style.Line = new Pen(Color.Blue,1 94 layRivers.SRID = 95 96 97 VectorLayer layCities = Cities 98 99 layCities.DataSource = GeoData/MapInfo/citiesMapInfo.tab100 layCities.Style.SymbolScale = 0.8f101 layCities.MaxVisible = 40102 layCities.SRID = 103 104 Set up a country label layer 105 LabelLayer layLabel = new LabelLayer(Country labels106 layLabel.DataSource = layCountries.DataSource; 107 layLabel.Enabled = 108 layLabel.LabelColumn = Name109 layLabel.Style = LabelStyle(); 110 layLabel.Style.ForeColor = Color.White; 111 layLabel.Style.Font = new Font(FontFamily.GenericSerif,1)">12112 layLabel.Style.BackColor = new SolidBrush(Color.FromArgb(128,1)">255,1)">0,1)">0)); 113 layLabel.MaxVisible = 90114 layLabel.MinVisible = 30115 layLabel.Style.HorizontalAlignment = LabelStyle.HorizontalAlignmentEnum.Center; 116 layLabel.SRID = 117 layLabel.MultipartGeometryBehaviour = LabelLayer.MultipartGeometryBehaviourEnum.Largest; 118 119 Set up a city label layer 120 LabelLayer layCityLabel = City labels121 layCityLabel.DataSource = layCities.DataSource; 122 layCityLabel.Enabled = 123 layCityLabel.LabelColumn = 124 layCityLabel.Style = 125 layCityLabel.Style.ForeColor = Color.Black; 126 layCityLabel.Style.Font = 11127 layCityLabel.MaxVisible = layLabel.MinVisible; 128 layCityLabel.Style.HorizontalAlignment = LabelStyle.HorizontalAlignmentEnum.Left; 129 layCityLabel.Style.VerticalAlignment = LabelStyle.VerticalAlignmentEnum.Bottom; 130 layCityLabel.Style.Offset = new PointF(3,1)">3131 layCityLabel.Style.Halo = new Pen(Color.Yellow,1)">2132 layCityLabel.TextRenderingHint = TextRenderingHint.AntiAlias; 133 layCityLabel.SmoothingMode = SmoothingMode.AntiAlias; 134 layCityLabel.SRID = 135 layCityLabel.LabelFilter = LabelCollisionDetection.ThoroughCollisionDetection; 136 layCityLabel.Style.CollisionDetection = 137 138 Add the layers to the map object. 139 The order we add them in are the order they are drawn,so we add the rivers last to put them on top 140 map.Layers.Add(layCountries); 141 map.Layers.Add(layRivers); 142 map.Layers.Add(layCities); 143 map.Layers.Add(layLabel); 144 map.Layers.Add(layCityLabel); 145 增加Layers 146 var xlsPath = string.Format(XlsConnectionString,System.IO.Directory.GetCurrentDirectory(),1)">GeoDataHenan.xls147 var ds = GetDataFromExcel(xlsPath,1)">148 var ct = GetCoordinateTransformation(); 149 TransCoordinate(ds,ct); 150 string columeName = Rotation151 Add Rotation Column 152 AddColumeToDataSet(ds,columeName,-angle); 153 154 var xlsLayer = GetLayerFromDataSet2(ds,Color.GreenYellow);Set up provider 155 156 map.Layers.Add(xlsLayer); Add layer to map 157 map.Center = xlsLayer.Envelope.Centre; new Point(0,0); 158 map.MapScale = 350159 map.Center = new Point(0,0); 160 161 _ogrSampleDataset = "MapInfo"; 162 163 Matrix mat = new Matrix(); 164 mat.RotateAt(angle,map.WorldToImage(map.Center)); 165 map.MapTransform = mat; 166 167 map.ZoomToBox(xlsLayer.Envelope); 168 169 170 171 172 ShapeFile 173 174 175 176 static Map InitializeMapOrig(177 178 179 Map map = 180 181 182 VectorLayer layCountries = 183 184 layCountries.DataSource = new ShapeFile(GeoData/World/countries.shp",1)">185 186 layCountries.Style.Fill = 64187 188 layCountries.Style.Outline =189 layCountries.Style.EnableOutline = 190 layCountries.SRID = 191 192 193 VectorLayer layRivers = 194 195 layRivers.DataSource = GeoData/World/rivers.shp196 197 layRivers.Style.Line = 198 layRivers.SRID = 199 200 Set up a cities layer 201 VectorLayer layCities = 202 203 layCities.DataSource = GeoData/World/cities.shp204 layCities.Style.SymbolScale = 205 layCities.MaxVisible = 206 layCities.SRID = 207 208 209 LabelLayer layLabel = 210 layLabel.DataSource =211 layLabel.Enabled = 212 layLabel.LabelColumn = 213 layLabel.Style = 214 layLabel.Style.ForeColor =215 layLabel.Style.Font = 216 layLabel.Style.BackColor = 217 layLabel.MaxVisible = 218 layLabel.MinVisible = 219 layLabel.Style.HorizontalAlignment =220 layLabel.SRID = 221 layLabel.MultipartGeometryBehaviour =222 layLabel.LabelFilter =223 layLabel.Style.CollisionDetection = 224 layLabel.LabelPositionDelegate = fdr => fdr.Geometry.InteriorPoint.Coordinate; 225 layLabel.PriorityColumn = POPDENS226 227 228 LabelLayer layCityLabel = 229 layCityLabel.DataSource =230 layCityLabel.Enabled = 231 layCityLabel.LabelColumn = 232 layCityLabel.Style = 233 layCityLabel.Style.ForeColor =234 layCityLabel.Style.Font = 235 layCityLabel.MaxVisible =236 layCityLabel.Style.HorizontalAlignment =237 layCityLabel.Style.VerticalAlignment =238 layCityLabel.Style.Offset = 239 layCityLabel.Style.Halo = 240 layCityLabel.TextRenderingHint =241 layCityLabel.SmoothingMode =242 layCityLabel.SRID = 243 layCityLabel.LabelFilter =244 layCityLabel.Style.CollisionDetection = 245 layCityLabel.PriorityColumn = POPULATION246 layCityLabel.Theme = new GradientTheme(layCityLabel.PriorityColumn,1)">250000,1)">5000000247 LabelStyle 248 249 MaxVisible = 10250 CollisionBuffer = new Size(),1)">251 CollisionDetection = 252 Enabled = 253 ForeColor = Color.LightSlateGray,1)">254 Halo = new Pen(Color.Silver,1)">255 HorizontalAlignment = LabelStyle.HorizontalAlignmentEnum.Center,1)">256 VerticalAlignment = LabelStyle.VerticalAlignmentEnum.Middle,1)">257 Font = Font(GenericFontFamilies.SansSerif.ToString(),8f,FontStyle.Regular) 258 },1)">259 260 261 MaxVisible = layLabel.MinVisible,1)">262 CollisionBuffer = 263 CollisionDetection = 264 Enabled = 265 ForeColor =266 Halo = 5267 HorizontalAlignment =268 VerticalAlignment =269 Font = 270 }); 271 272 bool ignoreLength = false273 274 var layRiverLabel = River labels275 276 DataSource = layRivers.DataSource,1)">277 Enabled = 278 LabelColumn = 279 TextRenderingHint = TextRenderingHint.AntiAlias,1)">280 SmoothingMode = SmoothingMode.AntiAlias,1)">281 SRID = 282 LabelFilter = LabelCollisionDetection.ThoroughCollisionDetection,1)">283 MultipartGeometryBehaviour = LabelLayer.MultipartGeometryBehaviourEnum.CommonCenter,1)">284 Style = 285 286 { 287 ForeColor = Color.DarkBlue,1)">288 Font = new Font(FontFamily.GenericSansSerif,1)">289 HorizontalAlignment =290 VerticalAlignment =291 CollisionDetection = true, 292 Halo = new Pen(Color.Azure,1)">293 IgnoreLength = ignoreLength,1)">294 Offset = 295 296 },1)">297 }; 298 299 300 301 map.BackgroundLayer.Add(AsyncLayerProxyLayer.Create(layCountries)); 302 303 304 305 306 307 map.Layers.Add(layRiverLabel); 308 309 310 311 312 313 314 315 316 AddColumeToDataSet(ds,1)">317 318 319 320 map.Layers.Add(xlsLayer); Add layer to map 321 limit the zoom to 360 degrees width 322 map.MaximumZoom = 360; 323 map.BackColor = Color.LightBlue; 324 325 map.Zoom = 360; 326 map.Center = xlsLayer.Envelope.Centre;327 map.MapScale = 328 329 330 331 332 333 334 335 336 在线显示,圆点显示轨迹 337 338 339 340 static Map InitializeMapOsmWithXls(341 342 var map = 343 344 var tileLayer = TileAsyncLayer( 345 KnownTileSources.Create(KnownTileSource.OpenStreetMap),1)">TileLayer - OSM with XLS346 tileLayer.SRID = 347 map.BackgroundLayer.Add(tileLayer); 348 349 Get data from excel 350 GeoDataCities.xls351 352 var ds1 = GetDataFromExcel(xlsPath,1)">Cities2353 var ct = GetCoordinateTransformation(); 354 TransCoordinate(ds,ct); 355 TransCoordinate(ds1,1)">356 357 358 AddColumeToDataSet(ds,1)">359 AddColumeToDataSet(ds1,1)">360 361 var xlsLayer = GetLayerFromDataSet(ds,1)">362 map.Layers.Add(xlsLayer); 363 364 var xlsLayer1 = GetLayerFromDataSet(ds1,Color.Red); 365 map.Layers.Add(xlsLayer1); 366 367 var xlsLabelLayer = GetLabelLayerByVectorLayer(xlsLayer,1)">XLSLabel368 369 xlsLabelLayer.Theme = new SharpMap.Rendering.Thematics.FontSizeTheme(xlsLabelLayer,map) { FontSizeScale = 1000f }; 370 map.Layers.Add(xlsLabelLayer); 371 map.ZoomToBox(xlsLayer.Envelope.ExpandedBy(xlsLayer1.Envelope)); 372 373 374 375 376 在线显示,图标显示轨迹 377 378 379 380 static Map InitializeMapOsmWithXls2(381 382 383 384 385 KnownTileSources.Create(KnownTileSource.OpenStreetMap),1)">386 tileLayer.SRID = 387 388 389 390 391 392 393 394 395 396 AddColumeToDataSet(ds,1)">397 398 399 map.Layers.Add(xlsLayer); 400 401 402 403 xlsLabelLayer.Theme = new FontSizeTheme(xlsLabelLayer,1)">404 405 map.ZoomToBox(xlsLayer.Envelope); 406 407 408 409 410 从Excel中读取数据 411 412 static DataSet GetDataFromExcel(string xlsPath,1)">string sheetName) 413 414 DataSet ds = new DataSet(XLS415 string sql = string.Format(SELECT * FROM [{0}$];416 using (var cn = OleDbConnection(xlsPath)) 417 418 cn.Open(); 419 var da = new OleDbDataAdapter( OleDbCommand(sql,cn))) 420 421 da.Fill(ds); 422 423 424 ds; 425 426 427 428 获取坐标转换对象 429 430 431 static ICoordinateTransformation GetCoordinateTransformation() 432 433 The SRS for this datasource is EPSG:4326,therefore we need to transfrom it to OSM projection 434 var ctf = CoordinateTransformationFactory(); 435 var cf = CoordinateSystemFactory(); 436 var epsg4326 = cf.CreateFromWkt(GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],"6326"]],PRIMEM["Greenwich","8901"]],UNIT["degree",0.01745329251994328,"9122"]],"4326"]]437 var epsg3857 = cf.CreateFromWkt(PROJCS["Popular Visualisation CRS / Mercator",GEOGCS["Popular Visualisation CRS",DATUM["Popular Visualisation Datum",SPHEROID["Popular Visualisation Sphere","7059"]],TOWGS84[0,0],"6055"]],0.0174532925199433,"9102"]],AXIS["E",EAST],AXIS["N",NORTH],"4055"]],PROJECTION["Mercator"],PARAMETER["False_Easting",PARAMETER["False_Northing",PARAMETER["Central_Meridian",PARAMETER["Latitude_of_origin",UNIT["metre",1,"9001"]],AXIS["East",AXIS["North","3857"]]438 ctf.CreateFromCoordinateSystems(epsg4326,epsg3857); 439 ct; 440 441 442 443 转换地球经纬度到坐标 444 445 <param name="ds"></param> 446 <param name="ct"></param> 447 static void TransCoordinate(DataSet ds,ICoordinateTransformation ct) 448 449 foreach (System.Data.DataRow row in ds.Tables[].Rows) 450 451 if (row[X"] == DBNull.Value || row[Y"] == DBNull.Value) continue452 var coords = new[] { Convert.ToDouble(row["]),Convert.ToDouble(row[]) }; 453 coords = ct.MathTransform.Transform(coords); 454 row["] = coords[]; 455 row[456 457 458 459 460 增加列 461 462 463 <param name="columeName"></param> 464 <param name="columeValue"></param> 465 void AddColumeToDataSet(DataSet ds,1)">string columeName,1)"> columeValue) 466 467 ds.Tables[0].Columns.Add(columeName,1)">typeof(468 469 470 row["] = -columeValue; 471 472 473 474 475 轨迹用点表示 476 477 478 <param name="c"></param> 479 480 VectorLayer GetLayerFromDataSet(DataSet ds,Color c) 481 482 var xlsProvider = new DataTablePoint(ds.Tables[0],1)">OID483 var xlsLayer = 484 { Style = new VectorStyle() { PointColor = SolidBrush(c) } }; 485 xlsLayer; 486 487 488 489 获取带图标的图层 490 491 492 493 494 VectorLayer GetLayerFromDataSet2(DataSet ds,1)">495 496 497 498 { Style = { Symbol=Properties.Resources.redflag} }; 499 500 501 502 static LabelLayer GetLabelLayerByVectorLayer(VectorLayer xlsLayer,1)"> layerName) 503 504 var xlsLabelLayer = LabelLayer(layerName) 505 506 DataSource = xlsLayer.DataSource,1)">507 LabelColumn = NAME508 PriorityColumn = "Population",1)">509 Style = 510 { 511 CollisionBuffer = System.Drawing.SizeF(2f,2f),1)">512 CollisionDetection = true 513 },1)">514 LabelFilter = LabelCollisionDetection.ThoroughCollisionDetection 515 516 xlsLabelLayer; 517 518 } 519 520 enum MapType { 521 ShapeFile = 522 MapInfo = 523 RunLine = 2,1)">运行轨迹 524 Static = 3 定点数据 525 526 527 } ? 源码下载链接 ? 备注: 1. 因用的MapInfo和Shape源文件为源码里面的,所有为英文显示。 ? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |