DotSpatial

Innen: GIS Wiki
A lap korábbi változatát látod, amilyen Roberto (vitalap | szerkesztései) 2016. június 1., 19:24-kor történt szerkesztése után volt.

A DotSpatial egy nyílt forráskódú térinformatikai programkönyvtár, amely különböző funkcionalitásokat biztosít téradat kezelés, betöltés és mentés, valamint elemzési feladatokra. A programkönyvtár C#-ban íródott és a .NET 4.0 keretrendszeren alapszik. Elsősorban asztali alkalmazások elkészítését segíti elő, amely a Windows Forms platformra épülnek. A programcsomag GNU LGPL licensz alatt használható.


Története

A könyvtár létrehozását az Idaho állami egyetemen (Idaho State University) fejlesztett MapWindow alkalmazás ihlette. Kezdetben csak a saját belső fejlesztésüket szerették volna megkönnyíteni különféle központi funkciók kiszervezésével, idővel azonban a felhalmozott szolgáltatások száma elérte azt a méretet, hogy a fejlesztők úgy érezték, érdemes kiadni a nagyközönség számára is. Sajnos a folyamatosan rétegződő, és központi koncepció nélküli fejlesztés rányomta a bélyegét a kódbázisra. Ennek megfelelően modulonként, vagy akár azokon belül is erősen eltérő megközelítéseket láthatunk a forráskódban.

Szolgáltatások

  • Térinformatikai adatok megjelenítése .Net Windows Form, vagy Web alkalmazásokban
  • Shapefájlok, rácshálók valamint raszter felvételek olvasása.
  • Menet közbeni projektálás
  • Tudományos analízis
  • GPS adatok olvasása

Kik használják?

Használat

Telepítést nem igényel, ha használni szeretnénk, akkor két lehetőségünk közül választhatunk.

  • Letölthetjük azt össze modult egyben a http://dotspatial.codeplex.com/ oldalról, majd később a szükséges projektekbe referenciázzuk őket.
  • Visual Studio 2010-től felfelé használhatjuk a NuGet csomagkezelő, ahonnan telepíthetjük az egyes modulokat a kiválasztott projektek alá. Nagy előnye, hogy csomag frissülése esetén automatikusan eljut hozzánk is az új csomag.

Windows Forms vezérlők

A DotSpatialt egyik legnagyobb előnye az előre megírt kontrolok, amiket a már jól megszokott Windows Formsos recept alapján akár vizuális szerkesztőben is összeállíthatunk.

DotSpatialt vezérlők telepítése

Ha szeretnénk használni a grafikus szerkesztőt, akkor mindenekelőtt hozzá kell adnunk a Toolbox-hoz a DotSpatialt vezérlőit.

  1. Jobbklikk a Toolboxon, majd válasszuk ki az Add Tab menüpontot.
  2. Nevezzük az előbb hozzáadott fület.
  3. Ismét jobbklikk az új fülön, és válasszuk ki a Choose Item opciót.
  4. A felugró ablakból válasszuk ki a DotSpatial.Controls.dll-t, ha nem találjuk a listából, akkor manuálisan adjuk hozz.

Most már ugyanúgy használhatjuk DotSpatial vezérlőit, mit a .NET alapértelmezettjeit.

Vezérlők demonstrációja

A DotSpatial vezérlők segítségével rendkívül gyorsan tudjuk alkalmazásunkat felruházni térinformatikai képességekkel. A következő alkalmazás remek példa az előbbiekre. Először készítsük el a felületet az alapértelmezett .NET, illetve a már ismertetett DotSpatial vezérlőkből.

<KÉP>

Miután megfelelően elneveztük a felületre elhelyezett elemeket, a hozzájuk tartozó kód mindössze ennyi:

public partial class DesktopMapping : Form

   {
       private AppManager _AppManager;
       public DesktopMapping()
       {
           InitializeComponent();
           _AppManager = new AppManager();
           _AppManager.LoadExtensions();
       }
       private void uxOpenFile_Click(object sender, EventArgs e)
       {
           uxMap.AddLayer();
       }
       private void uxZoomIn_Click(object sender, EventArgs e)
       {
           uxMap.ZoomIn();
       }
       private void uxZoomWide_Click(object sender, EventArgs e)
       {
           uxMap.ZoomToMaxExtent();
       }
       private void uxPan_Click(object sender, EventArgs e)
       {
           uxMap.FunctionMode = DotSpatial.Controls.FunctionMode.Pan;
       }
       private void uxGenShp_Click(object sender, EventArgs e)
       {
           var rnd = new Random();
           var pg = new Polygon[100];
           var f = new Feature();
           var fs = new FeatureSet(f.FeatureType);
            
           for (int i = 0; i < 100; i++)
           {
               var center = new Coordinate((rnd.Next(50) * 360) - 180, (rnd.Next(60) * 180) - 90);
               var coord = new Coordinate[50];
               for (int ii = 0; ii < 50; ii++)
               {
                   coord[ii] = new Coordinate(center.X + Math.Cos((ii * 10) * Math.PI / 10), center.Y + (ii * 10) * Math.PI / 10);
               }
               coord[35] = new Coordinate(coord[0].X, coord[0].Y);
               pg[i] = new Polygon(coord);
               fs.Features.Add(pg[i]);
           }
           fs.SaveAs("C:\\Temp\\test.shp", true);
       }
   }

Bővítmények

Lehetőségünk van bővítmények készítésére, amelyek akár a már kész alkalmazásokba is könnyedén integrálódnak (ilyen például a MapWindow).

Példaprogram beépülő modulra

A bemutatásra kerülő bővítménnyel lehetőségünk lesz vonalakat rajzolni, réteget létrehozni, illetve megjeleníthetünk velük kapcsolatos magassági adatokat. Elsőnek le kell töltenünk az online megtalálható sémával.

Diagram készítése

A magassági adatok megjelenítéséhez egy Windows Form alkalmazást készítünk.

public void Plot(double[] data) {

   chart1.Series.Clear();
   var series = chart1.Series.Add("Elevation (meters)");
   series.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
   series.Points.DataBindY(data);

}

Raszter adatok kinyerése

A DotSpatial segítségével könnyedén kinyerhetjük a szükséges magassági adatokat.

private static double GetElevation(IMapRasterLayer raster, Coordinate coordinate) {

   RcIndex rowColumn = raster.DataSet.Bounds.ProjToCell(coordinate);
   double elevation = raster.DataSet.Value[rowColumn.Row, rowColumn.Column];
   return elevation;

} private static double GetDistance(double x1, double y1, double x2, double y2) {

   return Math.Sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)));

}

Koordináták kinyerése

private List<Coordinate> GetCoordinatesFromLine(IMapLineLayer lineLayer) {

   IFeatureSet featureSet = lineLayer.DataSet;
   // The coordinates should be the first feature of the feature set.
   IList<Coordinate> lineCoordinates = featureSet.Features[0].Coordinates;
   // Though the original line may only have a few points, we split
   // each line segment into many points
   List<Coordinate> pathCoordinates = new List<Coordinate>();
   for (int i = 0; i < lineCoordinates.Count - 1; i++)
   {
       Coordinate startCoord = lineCoordinates[i];
       Coordinate endCoord = lineCoordinates[i + 1];
       List<Coordinate> segmentCoordinates = SplitSegment(startCoord.X, startCoord.Y, endCoord.X, endCoord.Y);
       //add list of points from this line segment to the complete list
       pathCoordinates.AddRange(segmentCoordinates);
   }
   return pathCoordinates;

}

private static List<Coordinate> SplitSegment(double startX, double startY, double endX, double endY) {

   const int MinimumDistanceBetweenPoints = 15;
   double points = Math.Floor(GetDistance(startX, startY, endX, endY) / MinimumDistanceBetweenPoints);
   int PointsPerSegment = (int)Math.Max(points, 1);
   double curX = startX;
   double curY = startY;
   double constXdif = ((endX - startX) / PointsPerSegment);
   double constYdif = ((endY - startY) / PointsPerSegment);
   List<Coordinate> pathPointList = new List<Coordinate>(PointsPerSegment);
   for (int i = 0; i <= PointsPerSegment; i++)
   {
       if (i == 0)
       {
           curX = startX;
           curY = startY;
       }
       else
       {
           curX = curX + constXdif;
           curY = curY + constYdif;
       }
       Coordinate coordinate = new Coordinate(curX, curY);
       pathPointList.Add(coordinate);
   }
   return pathPointList;

}

private void ShowElevation() {

   if (!map.GetRasterLayers().Any())
   {
       MessageBox.Show("Please add a DEM raster layer to the map.");
       return;
   }
   if (!map.GetLineLayers().Any())
   {
       MessageBox.Show("Please create a path by left clicking to add points and right-clicking to complete the path.");
       return;
   }
   try
   {
       IMapRasterLayer rasterLayer = map.GetRasterLayers().First();
       IMapLineLayer pathLayer = map.GetLineLayers().First();
       var coords = GetCoordinatesFromLine(pathLayer);
       double[] elevation = new double[coords.Count];
       for (int i = 0; i < coords.Count; i++)
       {
           elevation[i] = GetElevation(rasterLayer, coords[i]);
       }
       ChartForm chart = new ChartForm();
       chart.Plot(elevation);
       chart.Show();
   }
   catch (Exception ex)
   {
       MessageBox.Show("Error calculating elevation. The whole path should be inside the DEM area. " + ex.Message);
   }

}

SimpleActionItem használata (menüelem)

public void ButtonClick(object sender, EventArgs e) {

   // We're expecting this extension to only be run in a Windows Forms application.
   // We'll depend on a few Windows Forms (Map) features like MouseDown, so we cast
   // the App.Map as a Map and store a reference to it.
   map = App.Map as Map;
   // remove any existing path if needed.
   if (_PathLineLayer != null)
       map.Layers.Remove(_PathLineLayer);
   _PathLineLayer = null;
   _LineFeature = null;
   // Let the user know we are ready for them to set points by changing the cursor.
   map.Cursor = Cursors.Cross;
   map.MouseDown += map_MouseDown;

}

Vektor réteg létrehozása

private void map_MouseDown(object sender, MouseEventArgs e) {

   if (e.Button == MouseButtons.Left)
   {
       // Encourage the user to select a raster, if they haven't done so.
       if (!map.GetRasterLayers().Any())
       {
           map.AddRasterLayer();
           map.ZoomToMaxExtent();
           return;
       }
       StartOrContinueDrawingPath(e.Location);
       App.ProgressHandler.Progress(null, 0, "Point registered. Click again to add line segment. Right-click to finish.");
   }
   else if (e.Button == MouseButtons.Right)
   {
       EndDrawingPath();
       ShowElevation();
       App.ProgressHandler.Progress(null, 0, "Ready.");
   }

}

private IFeature AddLineFeatureSetToMap() {

   FeatureSet lineFeatureSet = new FeatureSet(FeatureType.Line);
   lineFeatureSet.Projection = map.Projection;
   // Initialize the featureSet attribute table by creating columns
   DataColumn column = new DataColumn("ID", typeof(short));
   lineFeatureSet.DataTable.Columns.Add(column);
   DataColumn column2 = new DataColumn("Number of Points", typeof(int));
   lineFeatureSet.DataTable.Columns.Add(column2);
   DataColumn column3 = new DataColumn("Description");
   lineFeatureSet.DataTable.Columns.Add(column3);
   // Add the featureSet as map layer
   _PathLineLayer = (MapLineLayer)map.Layers.Add(lineFeatureSet);
   _PathLineLayer.Symbolizer = new LineSymbolizer(Color.Blue, 2);
   _PathLineLayer.LegendText = "Path Layer";
   var newList = new List<Coordinate>();
   LineString lineGeometry = new LineString(newList);
   // AddFeature creates the point and a row in the DataTable
   return lineFeatureSet.AddFeature(lineGeometry);

}

private void StartOrContinueDrawingPath(System.Drawing.Point mouseLocation) {

   Coordinate coord = map.PixelToProj(mouseLocation);
   if (_LineFeature == null)
   {
       // This is the first time we see a left click; create empty line feature.
       _LineFeature = AddLineFeatureSetToMap();
       // Add first coordinate to the line feature.
       _LineFeature.Coordinates.Add(coord);
       // Set the line feature attribute. This line may have multiple points,
       // but there is only one row in the attribute table for the entire feature (line).
       _LineFeature.DataRow["ID"] = 0;
       _LineFeature.DataRow["Description"] = "Path (line)";
   }
   else
   {
       // Second or later click - add points to the existing feature
       _LineFeature.BasicGeometry.Coordinates.Add(coord);
       _LineFeature.ParentFeatureSet.InitializeVertices();
       // Draw the line.
       map.ResetBuffer();
       // Update the attribute table.
       _LineFeature.DataRow["Number of Points"] = _LineFeature.BasicGeometry.Coordinates.Count;
   }

}

private void EndDrawingPath() {

   // The path is complete.
   map.ResetBuffer();
   map.Cursor = Cursors.Arrow;
   map.MouseDown -= map_MouseDown;
   _LineFeature = null;

}