Raster Vector Data Analysis in DotSpatial
Raster Vector Data Analysis in DotSpatial
What is a DotSpatial class library? DotSpatial aims to provide a free, open source, consistent and dependable set of libraries for the .NET, Silverlight and Mono platforms, enabling developers to easily incorporate spatial data, analysis, and mapping into their applications thereby unleashing the massive potential of GIS in solutions for organizations and communities of all types in a nonrestrictive way. It is being developed by members of the MapWindow geographic information system (GIS) open source team, and the broader OSGeo .NET developer community. This tutorial utilizes the following four major steps: Step 1: Configure the DotSpatial class library in Visual C# Step 2: Configure the GDAL access in the application Step 3: Graphical User Interface design Step 4: Code implementation.
Step 1: Configure the DotSpatial class library in Visual C# Download the DotSpatial class library from the following website. http:// www. DotSpatial.org Start a new Windows Forms application project in visual studio. Add the following DotSpatial references in the development environment: DotSpatial.Controls.dll, DotSpatial.Data.dll, DotSpatial.Data.Forms.dll, DotSpatial.Projections.dll, DotSpatial.Symbology.dll, DotSpatial.Topology.dll Change the target framework in C# development environment, from .Net Framework 4 Client Profile to .Net Framework 4. This property should be under the properties of the application. Add the DotSpatial control into the Visual Studio Toolbox. Create a new tab with the name DotSpatial on the toolbox and add the DotSpatial controls on it. To add the DotSpatial controls, right click on the DotSpatial tab and select the choose items on the context menu; then select the DotSpatial.Controls.dll from the downloaded folder.
Page 1
Fig. 1 Data Extensions folder from DotSpatial downloaded unzip folder Step 3: Graphical User Interface design. Design the main user interface as follows:
Page 2
Add a label control and set its property as follows: Name: lbltitle Text: Hiking Path Finder. Drag a Legend control from the DotSpatial tab under toolbox and drop it on the pnlLegend. Legend properties should be set as follows: Name: Legend1 Dock: Fill Drag a Map control from the DotSpatial tab under toolbox and drop it on pnlMap. Map properties should be set as follows: Name: Map1, Dock: Fill, Legend: Legend1, Back color: Silver, ProjectionModeDefine: Never, ProjectionModeReproject: Never Drag an "AppManager" control from DotSpatial tab under toolbox and drop it on the form. Note: This control is necessary for loading different formats of raster data. Set the properties of AppManager1 as follows: Map: Map1 Legend: Legend1 Name: appManager1 Design the Graph user interface: Add a second windows form and design it as follows: Fig. 3 shows the graph form. Set the properties of the form as follows: Name: frmGraph, Text: Elevation-Distance
Page 3
Fig.3. frmGraph form Download the ZedGraph.dll from the class form website or from the following URL: http://sourceforge.net/projects/zedgraph/files/ Add a reference called the ZedGraph.dll from the downloaded folder. Add a panel control and set its properties as follows: name : pnlGraph Dock= fill Add the Zedgraph control to toolbox: Create a new tab on the toolbox and add the Zedgraph control on it. To add the Zedgraph control, right click on the zedgraph tab and select chooseitems on the context menu then select ZedGraph.dll from the downloaded folder. Drag the ZedGraph control from the toolbox and drop into the pnlGraph control. Set its properties as follows: Dock :fill
Step 4: Implementation of code. First, load a raster file on the map control; then on the map control, based on any drawn polyline, the elevation distance profile on the graph control is visualized. Thus, in the code implementation the following sequence must be maintained. 1. Load raster data. 2. Draw a polyline/ hiking path. 3. Obtain the elevation of the DEM along the hiking path (polyline).
FOSS4G DENVER 2011 Page 4
Start drawing a path in the following manner. First, click on the draw path button. Now, start drawing a polyline using a left mouse clicking on the map control.
Create a polyline by left clicking more than once on the map control in different locations and finally a right mouse click to finish the polyline. Initialize a line layer: The first step in creating a polyline is the creation of an instance of the line FeatureSet and an initialization of a line layer. The following code is used to initialize the line layer and instantiate the line feature. FeatureSet lineF=new FeatureSet(FeatureType.Line); //Instantiate the line feature lineF.Projection = map1.Projection; //Set the projection to the line feature as same as map projection. lineLayer = (MapLineLayer lineLayer) map1. Layers.add(lineF) ; //Initialize the line layer
Mouse click: After the initialization of the polyline, left mouse click event is used to add the map coordinates to the polyline. The following code is used to get the map coordinates of the map based on the mouse click location. Coordinate coord = map1.PixelToProj(e.Location); Add point to line layer: After the mouse coordinates are obtained, the following code is used to add the map mouse coordinates into the line feature. lineFeature.Coordinates.Add(coord); LineGeometry is an instance of the line string, which is used to store the list of line coordinates. Assign the line feature to the IFeature to handle the attribute column values of the polyline shape file. Dim lineFeature As IFeature = lineF.AddFeature(lineGeometry) Create an attribute column called ID and store numeric data in the attribute column. lineFeature.DataRow("ID") = lineID // Here lineID is an inter variable. Left mouse click: Left mouse click to collect the mouse click map coordinates and add them to the polyline feature.
Page 6
Get the elevation of the DEM along the polyline: To calculate the elevation along the polyline, various line segment coordinates will be collected and those divided by a constant number.
The following code is used to access the polyline layer from the map control, obtain the coordinates from the line segments and access the raster layer from the map control.
FOSS4G DENVER 2011 Page 9
IMapLineLayer pathLayer = default(IMapLineLayer); //declare the maplinelayer pathLayer = map1.GetLineLayers()[0]; //get the polyline layer from the map control IFeatureSet featureSet = pathLayer.DataSet; //get the data set of the polyline IList<Coordinate> coordinateList = featureSet.Features[0].Coordinates; //get the polylines line segment coordinates from the data set.
Accessing the raster layer from the map control IMapRasterLayer rasterLayer = default(IMapRasterLayer); //Declare an ImapRasterLayer rasterLayer = map1.GetRasterLayers()[0]; //Get the first raster layer. The following flowchart shows how to obtain the elevation based on the line segments coordinate and the raster layer.
Get map coordinates: First, obtain the various line segments of the polyline. Second, from each line segment, obtain their coordinates and convert them to map coordinates. IList<Coordinate> coordinateList = featureSet.Features[0].Coordinates; //Get the coordinates of the polylines point feature. Coordinate startCoord = coordinateList[i]; //get the start point coordinate from the polylines line segment Coordinate endCoord = coordinateList[i + 1]; //get the end point coordinate from the polylines line segment Coordinate coordinate = new Coordinate(curX, curY); //Get the map coordinate based on the maps x, y coordinate Calculate raster cell coordinates: Based on each points map coordinate, the coordinate in each raster cell is calculated as the following manner: RcIndex rowColumn = raster.DataSet.Bounds.ProjToCell(coordinate); //Get the raster column index based on the coordinate Extract the elevation from the raster cell. Based on the rasters row and column value, the following code is used to get the elevation value from the raster data layer. curElevation = raster.DataSet.Value[rowColumn.Row, rowColumn.Column]; Calculate distance from the following points: Based on the following points X, Y values, the Pythagorean Theorem is used to find the distance. Steps for calculating the total distance: Given 2 points (PSTART, PEND) and a step . 1) Calculate the Distance (PSTART, PEND) PSTART = X Start, Y Start PEND= X End, Y End 2) Calculate the constant Xdiff, Ydiff Constant Xdiff = ( [Xend Xstart] / N ) Constant Ydiff = ( [Yend Ystart] / N ) N is the number of steps. 3) X i = X (i-1) + Constant Xdiff 4) Y i = Y (i-1) + Constant Ydiff 5) Distance di = (X i 2 + Y i 2 ) ^ () 6) Add the distance di to the distance array as follows: di =+ di
Page 11
Create an ExtractElevation function as follows: This function is used to get the elevation from the DEM along with the line segment. /// <summary> /// This function is used to get the elevation. /// Based on the given line segment's start and endpoint, 100 points will be divided and based on the points elevation will be claculated. /// </summary> /// <param name="startX">Line segement's start X point</param> /// <param name="startY">Line segement's start Y point</param> /// <param name="endX">Line segement's end X point</param> /// <param name="endY">Line segement's end Y point</param> /// <param name="raster">Raster DEM</param> /// <returns>List of elevation</returns> /// <remarks></remarks> public List<PathPoint> ExtractElevation(double startX, double startY, double endX, double endY, IMapRasterLayer raster) { double curX = startX; double curY = startY; double curElevation = 0; List<PathPoint> pathPointList = new List<PathPoint>(); int numberofpoints = 100; double constXdif = ((endX - startX) / numberofpoints); double constYdif = ((endY - startY) / numberofpoints); for (int i = 0; i <= numberofpoints; i++) { PathPoint newPathPoint = new PathPoint(); if ((i == 0)) { curX = startX; curY = startY; } else
FOSS4G DENVER 2011 Page 14
} return pathPointList; }
Add the following code in the frmGraph.cs form. Based on the elevation and distance, Zed graph control is used to draw an elevation profile graph. Zed graph control is an open source graph control. The following line of code is used to add the X, Y, caption to the zed graph control. public frmGraph(List<PathPoint> pathList) { InitializeComponent(); //populate the graph //create the distance and elevation arrays.. double[] distanceArray = new double[pathList.Count]; double[] elevationArray = new double[pathList.Count]; for (int i = 0; i <= pathList.Count - 1; i++) { distanceArray[i] = pathList[i].Distance; elevationArray[i] = pathList[i].Elevation; } zedGraphControl1.GraphPane.CurveList.Clear(); ZedGraph.LineItem myCurve = zedGraphControl1.GraphPane.AddCurve("Elevation Profile", distanceArray, elevationArray, Color.Blue);
Page 15
Output Screen shots of the project: Figure 6, 7 shows the elevation distance profile.
Page 17