0% found this document useful (0 votes)
8 views

DotSpatial Tutorials_DotSpatial_Tutorial_6

This tutorial provides a step-by-step guide for analyzing hiking paths using the DotSpatial class library, focusing on finding elevation profiles from Digital Elevation Models (DEMs). It outlines six key steps including downloading the library, setting up the Visual Studio environment, designing the GUI, and implementing the necessary code for map operations. The tutorial emphasizes the creation of a graphical user interface and coding for path drawing and elevation extraction functionalities.

Uploaded by

iwgss2024
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views

DotSpatial Tutorials_DotSpatial_Tutorial_6

This tutorial provides a step-by-step guide for analyzing hiking paths using the DotSpatial class library, focusing on finding elevation profiles from Digital Elevation Models (DEMs). It outlines six key steps including downloading the library, setting up the Visual Studio environment, designing the GUI, and implementing the necessary code for map operations. The tutorial emphasizes the creation of a graphical user interface and coding for path drawing and elevation extraction functionalities.

Uploaded by

iwgss2024
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 18

Introduction to Programming with DotSpatial

Raster Vector Data Analysis ~ Hiking


Path Finder
Tutorial (6)

Purpose of this tutorial: Finding an elevation distance profile for any hiking path on any DEM.

This tutorial has 5 important steps.

Step 1: Download the DotSpatial class library

Step 2: Add the DotSpatial reference and change the compile option.

Step 3: Add the DotSpatial Controls into the Visual Studio Toolbox.

Step 4: Copy the Data Extensions folder to the debugs folder of the current project

Step 5: Design the GUI. (GUI - Graphical User Interface)

Step 6: Write the code for implementing the map operations.

Step 1: Download the DotSpatial class library

This step is similar to the Tutorial #1 step 1.

Step 2: Add the DotSpatial reference and change the compile option.

1.1) Adding the references.

DotSpatial.Data.Forms.dll, DotSpatial.Symbology.dll, DotSpatial.Controls.dll, DotSpatial.Projections.dll,


DotSpatial.Data.dll, DotSpatial.Topology.dll

2nd International MapWindow GIS and DotSpatial Conference 2011 Page 1


Introduction to Programming with DotSpatial

Fig. 1 Required references.

2.2) Change the compile option.

Change the compile option from .Net Framework 4 Client Profile to .Net Framework4. This step is as
same as the Tutorial # 1 step 2.2.

Step 2: Add the DotSpatial controls on the Visual Studio Toolbox window.

Create a new tab on the toolbox and add the DotSpatial controls on it, the same as tutorial (1) step 1.

Step 3: Add the DotSpatial Controls into the Visual Studio Toolbox.

This step is as same as the Tutorial # 1 step 3.

Step 4: Copy the Data Extension folder from your downloaded folder to your current project debug
folder. The .dlls from this folder is necessary for GDAL data provider access.

Fig. 2 Data Extensions folder from DotSpatial downloaded unzip folder

2nd International MapWindow GIS and DotSpatial Conference 2011 Page 2


Introduction to Programming with DotSpatial

Step 5: Design the GUI : GUI has 2 different parts such as Main interface form and Graph interface
form.

5.1 ) Design the main interface form.

Fig. 2 Final GUI. (frmMain form)

Interface design considerations.

1. Add three panel controls. Panel control's properties should be as follows:

Properties Panel1 Panel2 Panel3


Name pnlOperation pnlLegend pnlMap
s
Dock Top Left Fill
Optional step : Panel 1 background color : ActiveCaption

2. Add three buttons. Button properties should be as follows:

Properties Button1 Button2 Button3


Name btnLoadDEM btnDrawPath btnViewElevation
Text &Load DEM &Draw Hiking &View Elevation

2nd International MapWindow GIS and DotSpatial Conference 2011 Page 3


Introduction to Programming with DotSpatial

Path

3. Add a label control and set its property as follows:

Name : lbltile Text: Hiking Path Finder.

4. Drag a “Legend” control from the DotSpatial tab under toolbox and drop it on pnlLegend. Legend
properties should be as follows:

Name: Legend1 Dock: Fill

5. Drag a “Map” control from the DotSpatial tab under toolbox and drop it on pnlMap. Map properties
should be as follows:

Name: Map1, Dock: Fill, Legend: Legend1 , Back color: Silver , ProjectionModeDefine: Never
ProjectionModeReproject: Never

6. 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.

Fig. 3 AppManager.

7. Set the properties of AppManager1 as follows:

Map: Map1 Legend: Legend1

2nd International MapWindow GIS and DotSpatial Conference 2011 Page 4


Introduction to Programming with DotSpatial

9. Rename the form1 as frmTutorial6.

5.2 ) Design the graph interface form.

1. Download the ZedGraph.dll from the class form website or from the following URL:
http://sourceforge.net/projects/zedgraph/files/

2. from the tool box, right click on the DotSpatial tab OR all windows forms tab and select the choose
items from the context menu.

Fig. 6 Choose Item context menu.

Select the ZedGraph.dll from the downloaded folder.

3. Design the interface as follows:

4. Add a second form and name it as frmGraph.

2nd International MapWindow GIS and DotSpatial Conference 2011 Page 5


Introduction to Programming with DotSpatial

Fig. 7 frmGraph form.

5. Add a panel control and set its properties as follows:

name : pnlGraph Dock= fill

6. Drag the ZedGraph control from the toolbox and drop into the pnlGraph control. Set its properties as
follows:

Dock : fill

Step 6: Code implementation

6.1) Following code is related to frmMain form.

Import the following namespaces

2nd International MapWindow GIS and DotSpatial Conference 2011 Page 6


Introduction to Programming with DotSpatial

VB
#Region "NameSpaces"
Imports DotSpatial.Controls
Imports DotSpatial.Data
Imports DotSpatial.Symbology
Imports DotSpatial.Topology
Imports System.Collections.Generic
#End Region

C#
#region "NameSpaces"
using DotSpatial.Controls;
using DotSpatial.Data;
using DotSpatial.Symbology;
using DotSpatial.Topology;
#endregion

Declare the following class level variables.

VB

#Region "Class level varibales"

'the line layer


Dim lineLayer As MapLineLayer

'the line feature set


Dim lineF As New FeatureSet(FeatureType.Line)

Dim lineID As Integer = 0

'boolean variable for first time mouse click


Dim firstClick As Boolean = False

'boolean variable for ski path drawing finished


Dim hikingpathPathFinished As Boolean = False

#End Region

C#

#region "Class level varibales"


//the line layer
MapLineLayer lineLayer = default(MapLineLayer);
//the line feature set
FeatureSet lineF = new FeatureSet(FeatureType.Line);
int lineID = 0;
//boolean variable for first time mouse click
bool firstClick = false;
//boolean variable for ski path drawing finished
bool hikingpathPathFinished = false;
#endregion

Create a PathPoint class as follows below the frmTutorial6 class.

2nd International MapWindow GIS and DotSpatial Conference 2011 Page 7


Introduction to Programming with DotSpatial

VB
Public Class PathPoint
Public X As Double
Public Y As Double
Public Distance As Double
Public Elevation As Double
End Class

C#
public class PathPoint
{
public double X;
public double Y;
public double Distance;
public double Elevation;
}

Crate an ExtractElevation function as follows: This function is used to get the elevation from the DEM
along with the line segment.

VB

''' <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 Function ExtractElevation(ByVal startX As Double, ByVal startY As Double, ByVal endX As
Double, ByVal endY As Double, ByVal raster As IMapRasterLayer) As List(Of PathPoint)
Dim curX As Double = startX

2nd International MapWindow GIS and DotSpatial Conference 2011 Page 8


Introduction to Programming with DotSpatial

Dim curY As Double = startY


Dim curElevation As Double = 0
Dim pathPointList As New List(Of PathPoint)
Dim numberofpoints As Integer = 100
Dim constXdif = ((endX - startX) / numberofpoints)
Dim constYdif = ((endY - startY) / numberofpoints)
For i As Integer = 0 To numberofpoints
Dim newPathPoint As New PathPoint
If (i = 0) Then
curX = startX
curY = startY
Else
curX = curX + constXdif
curY = curY + constYdif
End If
Dim coordinate As New Coordinate(curX, curY)
Dim rowColumn As RcIndex = raster.DataSet.Bounds.ProjToCell(coordinate)
curElevation = raster.DataSet.Value(rowColumn.Row, rowColumn.Column)
'set the properties of new PathPoint
newPathPoint.X = curX
newPathPoint.Y = curY
newPathPoint.Elevation = curElevation
pathPointList.Add(newPathPoint)
Next
Return pathPointList
End Function

C#

/// <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

2nd International MapWindow GIS and DotSpatial Conference 2011 Page 9


Introduction to Programming with DotSpatial

{
curX = curX + constXdif;
curY = curY + constYdif;
}
Coordinate coordinate = new Coordinate(curX, curY);
RcIndex rowColumn = raster.DataSet.Bounds.ProjToCell(coordinate);
curElevation = raster.DataSet.Value[rowColumn.Row, rowColumn.Column];
//set the properties of new PathPoint
newPathPoint.X = curX;
newPathPoint.Y = curY;
newPathPoint.Elevation = curElevation;
pathPointList.Add(newPathPoint);
}
return pathPointList;
}

Add the following code in the Load DEM button click event.

VB

Private Sub btnLoadDEM_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles


btnLoadDEM.Click
Map1.AddRasterLayer()
Map1.ZoomToMaxExtent()
End Sub

C#

private void btnLoadDEM_Click(object sender, EventArgs e)


{
map1.AddRasterLayer();
map1.ZoomToMaxExtent();
}

Add the following code in the Drawing hiking path button click event.

VB
Private Sub btnDrawPath_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
btnDrawPath.Click
'remove any existing path
Dim existingPathList = Map1.GetLineLayers()
For Each existingPath As IMapLineLayer In existingPathList
Map1.Layers.Remove(existingPath)
Next
lineF = New FeatureSet(FeatureType.Line)

'ski path is not finished


hikingpathPathFinished = False

'initialize polyline feature set


Map1.Cursor = Cursors.Cross

'set projection
lineF.Projection = Map1.Projection
'initialize the featureSet attribute table
Dim column As New DataColumn("ID")
lineF.DataTable.Columns.Add(column)
'add the featureSet as map layer

2nd International MapWindow GIS and DotSpatial Conference 2011 Page 10


Introduction to Programming with DotSpatial

lineLayer = Map1.Layers.Add(lineF)
Dim symbol As New LineSymbolizer(Color.Blue, 2)
lineLayer.Symbolizer = symbol
lineLayer.LegendText = "Hiking path"
firstClick = True
End Sub

C#

private void btnDrawPath_Click(System.Object sender, System.EventArgs e)


{
//remove any existing path
foreach (IMapLineLayer existingPath in map1.GetLineLayers())
{
map1.Layers.Remove(existingPath);
}
lineF = new FeatureSet(FeatureType.Line);

//ski path is not finished


hikingpathPathFinished = false;

//initialize polyline feature set


map1.Cursor = Cursors.Cross;

//set projection
lineF.Projection = map1.Projection;
//initialize the featureSet attribute table
DataColumn column = new DataColumn("ID");
lineF.DataTable.Columns.Add(column);
//add the featureSet as map layer
lineLayer = (MapLineLayer)map1.Layers.Add(lineF);
LineSymbolizer symbol = new LineSymbolizer(Color.Blue, 2);
lineLayer.Symbolizer = symbol;
lineLayer.LegendText = "Hiking path";
firstClick = true;
}

Add the following code in the Map1_MouseDown event.

VB

Private Sub Map1_MouseDown(ByVal sender As System.Object, ByVal e As


System.Windows.Forms.MouseEventArgs) Handles Map1.MouseDown
'if ski path is fininshed, don't draw any line
If hikingpathPathFinished = True Then Exit Sub
If e.Button = MouseButtons.Left Then
'left click - fill array of coordinates
'coordinate of clicked point
Dim coord As Coordinate = Map1.PixelToProj(e.Location)
'first time left click - create empty line feature
If firstClick Then
'Create a new List called lineArray.
'In List we need not define the size and also
'Here this list will store the Coordinates
'We are going to store the mouse click coordinates into this array.
Dim lineArray As New List(Of Coordinate)

2nd International MapWindow GIS and DotSpatial Conference 2011 Page 11


Introduction to Programming with DotSpatial

'Create an instance for LineString class.


'We need to pass collection of list coordinates
Dim lineGeometry As New LineString(lineArray)

'Add the linegeometry to line feature


Dim lineFeature As IFeature = lineF.AddFeature(lineGeometry)

'add first coordinate to the line feature


lineFeature.Coordinates.Add(coord)
'set the line feature attribute
lineID = lineID + 1
lineFeature.DataRow("ID") = lineID
firstClick = False
Else
'second or more clicks - add points to the existing feature
Dim existingFeature As IFeature = lineF.Features(lineF.Features.Count - 1)
existingFeature.Coordinates.Add(coord)
'refresh the map if line has 2 or more points
If existingFeature.Coordinates.Count >= 2 Then
lineF.InitializeVertices()
Map1.ResetBuffer()
End If
End If
Else
'right click - reset first mouse click
firstClick = True
Map1.ResetBuffer()
lineF.SaveAs("c:\2009 Falls\linepath.shp", True)
MsgBox("The line shapefile has been saved.")
Map1.Cursor = Cursors.Arrow
'the ski path is finished
hikingpathPathFinished = True
End If
End Sub

C#

private void map1_MouseDown(object sender, MouseEventArgs e)


{

//if ski path is fininshed, don't draw any line


if (hikingpathPathFinished == true)
return;
if (e.Button == MouseButtons.Left)
{
//left click - fill array of coordinates
//coordinate of clicked point
Coordinate coord = map1.PixelToProj(e.Location);
//first time left click - create empty line feature
if (firstClick)
{
//Create a new List called lineArray.
//In List we need not define the size and also
//Here this list will store the Coordinates
//We are going to store the mouse click coordinates into this array.
List<Coordinate> lineArray = new List<Coordinate>();

//Create an instance for LineString class.


//We need to pass collection of list coordinates

2nd International MapWindow GIS and DotSpatial Conference 2011 Page 12


Introduction to Programming with DotSpatial

LineString lineGeometry = new LineString(lineArray);

//Add the linegeometry to line feature


IFeature lineFeature = lineF.AddFeature(lineGeometry);

//add first coordinate to the line feature


lineFeature.Coordinates.Add(coord);
//set the line feature attribute
lineID = lineID + 1;
lineFeature.DataRow["ID"] = lineID;
firstClick = false;
}
else
{
//second or more clicks - add points to the existing feature
IFeature existingFeature = lineF.Features[lineF.Features.Count - 1];
existingFeature.Coordinates.Add(coord);
//refresh the map if line has 2 or more points
if (existingFeature.Coordinates.Count >= 2)
{
lineF.InitializeVertices();
map1.ResetBuffer();
}
}
}
else
{
//right click - reset first mouse click
firstClick = true;
map1.ResetBuffer();
lineF.SaveAs("c:\\2009 Falls\\linepath.shp", true);
MessageBox.Show("The line shapefile has been saved.");
map1.Cursor = Cursors.Arrow;
//the ski path is finished
hikingpathPathFinished = true;
}
}

Add the following code in the frmGraph.vb form.

VB

Public Class frmGraph

Public Sub New(ByVal pathList As List(Of PathPoint))

InitializeComponent()

'populate the graph


'create the distance and elevation arrays..
Dim distanceArray(pathList.Count - 1) As Double
Dim elevationArray(pathList.Count - 1) As Double
For i As Integer = 0 To pathList.Count - 1
distanceArray(i) = pathList(i).Distance
elevationArray(i) = pathList(i).Elevation
Next

ZedGraphControl1.GraphPane.CurveList.Clear()

2nd International MapWindow GIS and DotSpatial Conference 2011 Page 13


Introduction to Programming with DotSpatial

Dim myCurve As ZedGraph.LineItem = ZedGraphControl1.GraphPane.AddCurve("Elevation


Profile", distanceArray, elevationArray, Color.Blue)
myCurve.Line.Width = 2.0F
myCurve.Symbol.Type = ZedGraph.SymbolType.None
myCurve.Line.Fill.Color = Color.LightBlue
myCurve.Line.Fill.Color = Color.FromArgb(100, 0, 0, 255)
myCurve.Line.Fill.IsVisible = True

ZedGraphControl1.GraphPane.XAxis.Title.Text = "Distance (meters)"


ZedGraphControl1.GraphPane.YAxis.Title.Text = "Elevation (meters)"

'refresh the graph


ZedGraphControl1.AxisChange()

'set the graph title


ZedGraphControl1.GraphPane.Title.Text = "Hiking Path Graph"

End Sub

End Class

C#
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);
myCurve.Line.Width = 2f;
myCurve.Symbol.Type = ZedGraph.SymbolType.None;
myCurve.Line.Fill.Color = Color.LightBlue;
myCurve.Line.Fill.Color = Color.FromArgb(100, 0, 0, 255);
myCurve.Line.Fill.IsVisible = true;

zedGraphControl1.GraphPane.XAxis.Title.Text = "Distance (meters)";


zedGraphControl1.GraphPane.YAxis.Title.Text = "Elevation (meters)";

//refresh the graph


zedGraphControl1.AxisChange();

//set the graph title


zedGraphControl1.GraphPane.Title.Text = "Hiking Path Graph";
}

Add the following code in the frmMain.vb form's btnViewElevation_Click event

2nd International MapWindow GIS and DotSpatial Conference 2011 Page 14


Introduction to Programming with DotSpatial

VB

Private Sub btnViewElevation_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)


Handles btnViewElevation.Click
Try

'extract the complete elevation


'get the raster layer
Dim rasterLayer As IMapRasterLayer
If Map1.GetRasterLayers().Count = 0 Then
MsgBox("Please add a raster layer")
Exit Sub
End If

'use the first raster layer in the map


rasterLayer = Map1.GetRasterLayers(0)

'get the ski path line layer


Dim pathLayer As IMapLineLayer
If Map1.GetLineLayers().Count = 0 Then
MsgBox("Please add the ski path")
Exit Sub
End If
pathLayer = Map1.GetLineLayers(0)

Dim featureSet As IFeatureSet = pathLayer.DataSet


'get the coordinates of the ski path. this is the first feature of
'the feature set.
Dim coordinateList = featureSet.Features(0).Coordinates

'get elevation of all segments of the path


Dim fullPathList As New List(Of PathPoint)

For i As Integer = 1 To coordinateList.Count - 1


'for each line segment
Dim startCoord = coordinateList(i - 1)
Dim endCoord = coordinateList(i)
Dim segmentPointList = ExtractElevation(startCoord.X, startCoord.Y, endCoord.X,
endCoord.Y, rasterLayer)
'add list of points from this line segment to the complete list
fullPathList.AddRange(segmentPointList)
Next

'calculate the distance


Dim distanceFromStart As Double = 0
For i As Integer = 1 To fullPathList.Count - 1
'distance between two neighbouring points
Dim x1 = fullPathList(i - 1).X
Dim y1 = fullPathList(i - 1).Y
Dim x2 = fullPathList(i).X
Dim y2 = fullPathList(i).Y
Dim distance12 = Math.Sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)))
distanceFromStart += distance12
fullPathList(i).Distance = distanceFromStart
Next

Dim graphForm As New frmGraph(fullPathList)


graphForm.Show()

2nd International MapWindow GIS and DotSpatial Conference 2011 Page 15


Introduction to Programming with DotSpatial

Catch ex As Exception
MessageBox.Show("Error calculating elevation. the whole path should be inside the DEM area")
End Try
End Sub

C#

private void btnViewElevation_Click(System.Object sender, System.EventArgs e)


{

try
{
//extract the complete elevation
//get the raster layer
IMapRasterLayer rasterLayer = default(IMapRasterLayer);
if (map1.GetRasterLayers().Count() == 0)
{
MessageBox.Show("Please add a raster layer");
return;
}

//use the first raster layer in the map


rasterLayer = map1.GetRasterLayers()[0];

//get the ski path line layer


IMapLineLayer pathLayer = default(IMapLineLayer);
if (map1.GetLineLayers().Count() == 0)
{
MessageBox.Show("Please add the ski path");
return;
}
pathLayer = map1.GetLineLayers()[0];

IFeatureSet featureSet = pathLayer.DataSet;


//get the coordinates of the ski path. this is the first feature of
//the feature set.
IList<Coordinate> coordinateList = featureSet.Features[0].Coordinates;

//get elevation of all segments of the path


List<PathPoint> fullPathList = new List<PathPoint>();

for (int i = 0; i < coordinateList.Count - 1; i++)


{
//for each line segment
Coordinate startCoord = coordinateList[i];
Coordinate endCoord = coordinateList[i + 1];
List<PathPoint> segmentPointList = ExtractElevation(startCoord.X,
startCoord.Y, endCoord.X, endCoord.Y, rasterLayer);
//add list of points from this line segment to the complete list
fullPathList.AddRange(segmentPointList);
}

//calculate the distance


double distanceFromStart = 0;
for (int i = 1; i <= fullPathList.Count - 1; i++)
{
//distance between two neighbouring points
double x1 = fullPathList[i - 1].X;
double y1 = fullPathList[i - 1].Y;
double x2 = fullPathList[i].X;

2nd International MapWindow GIS and DotSpatial Conference 2011 Page 16


Introduction to Programming with DotSpatial

double y2 = fullPathList[i].Y;
double distance12 = Math.Sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 -
y1)));
distanceFromStart += distance12;
fullPathList[i].Distance = distanceFromStart;
}

frmGraph graphForm = new frmGraph(fullPathList);


graphForm.Show();

}
catch (Exception ex)
{
MessageBox.Show("Error calculating elevation. the whole path should be inside
the DEM area");
}
}

Output screen shots

Fig. 8 HikingMain form output screen.

2nd International MapWindow GIS and DotSpatial Conference 2011 Page 17


Introduction to Programming with DotSpatial

Fig. 9 Elevation distance profile for the drawn path.

2nd International MapWindow GIS and DotSpatial Conference 2011 Page 18

You might also like