private void MapRasterToTriangulation() { Console.WriteLine("Mapping elevation raster pixels to triangulation...\n"); List<River> rivers = model.Rivers.Values.ToList(); List<WaterSurfacePolygon> waterSurfacePolygons = new List<WaterSurfacePolygon>(); //Create triangulation for each river for (int k = 0; k < rivers.Count; k++) { River river = rivers[k]; foreach (Reach reach in river.Reaches.Values) { reach.CreateGISFeatures(); reach.CreateTriangulationForWaterSurface(); foreach (WaterSurfacePolygon polygon in reach.WaterSurfaces) { waterSurfacePolygons.Add(polygon); } } } float[] mapping = new float[xSize * ySize]; rasterWaterSurfaceMapping = new int[xSize][]; rasterTriangleMapping = new int[xSize][]; for (int i = 0; i < xSize; i++) { rasterWaterSurfaceMapping[i] = new int[ySize]; rasterTriangleMapping[i] = new int[ySize]; for (int j = 0; j < ySize; j++) { rasterWaterSurfaceMapping[i][j] = -1; rasterTriangleMapping[i][j] = -1; mapping[j * xSize + i] = noData; } } int count = 0; int foundCount = 0; int stepSize = (int)Math.Floor(xSize * ySize * 0.01); List<List<Coordinate>> coordinates = new List<List<Coordinate>>(); //Parallel.For(0, waterSurfacePolygons.Count, k => for (int k = 0; k < waterSurfacePolygons.Count; k++) { WaterSurfacePolygon watersurfacePolygon = waterSurfacePolygons[k]; Interlocked.Increment(ref count); double progress = count * 100.0 / (waterSurfacePolygons.Count * 1.0); lock (Console.Out) { Console.SetCursorPosition(0, Console.CursorTop); Console.Write("Progress => " + progress.ToString("###") + " %"); } lock (watersurfacePolygon) { Point pltc = getCoordIndexes(watersurfacePolygon.MinX, watersurfacePolygon.MaxY); Point prbc = getCoordIndexes(watersurfacePolygon.MaxX, watersurfacePolygon.MinY); List<Coordinate> coordinate = new List<Coordinate>(); Point ptt1 = getCoords((int)pltc.X, (int)pltc.Y); Point ptt2 = getCoords((int)prbc.X, (int)prbc.Y); coordinate.Add(new Coordinate(ptt1.X, ptt1.Y)); coordinate.Add(new Coordinate(ptt1.X, ptt2.Y)); coordinate.Add(new Coordinate(ptt2.X, ptt1.Y)); coordinate.Add(new Coordinate(ptt2.X, ptt2.Y)); for (int i = (int)pltc.X; i < prbc.X; i++) { for (int j = (int)pltc.Y; j < prbc.Y; j++) { Point p2 = getCoords(i, j); lock (watersurfacePolygon) { if (watersurfacePolygon.Contains(p2.X, p2.Y)) { int m = watersurfacePolygon.FindTriangleThatContains(p2.X, p2.Y); if (m > -1) { rasterWaterSurfaceMapping[i][j] = k; mapping[j * xSize + i] = k; rasterTriangleMapping[i][j] = m; } } } } } coordinates.Add(coordinate); } } using(IFeatureSet set = new FeatureSet(FeatureType.MultiPoint)) { foreach(var p in coordinates) set.AddFeature(new MultiPoint(p)); set.SaveAs(localWorkspace + "\\" + name + "_point.shp", true); } //); OSGeo.GDAL.Driver driver = Gdal.GetDriverByName(rasterDriver); Dataset newRaster = driver.Create(localWorkspace + "\\" + name + "_mapping.tif", xSize, ySize, 1, dataType, new string[] { "TFW=YES", "COMPRESS=LZW" }); newRaster.GetRasterBand(1).SetNoDataValue(noData); newRaster.SetGeoTransform(geoTransformation); newRaster.SetProjection(projection); Band newRasterBand = newRaster.GetRasterBand(1); newRasterBand.WriteRaster(0, 0, xSize, ySize, mapping, xSize, ySize, 0, 0); double min, max, mean, stdev; newRasterBand.GetStatistics(0, 1, out min, out max, out mean, out stdev); newRasterBand.FlushCache(); newRaster.FlushCache(); newRaster.Dispose(); newRaster = null; driver.Dispose(); driver = null; using (IFeatureSet fs = new FeatureSet(DotSpatial.Topology.FeatureType.Polygon)) { fs.DataTable.Columns.AddRange(new DataColumn[] { new DataColumn("Identifier" , typeof(int)), }); int tcount = 0; for (int k = 0; k < waterSurfacePolygons.Count; k++) { WaterSurfacePolygon surface = waterSurfacePolygons[k]; foreach (TriangleNet.Data.Triangle pgon in surface.Triangles) { TriangleNet.Data.Triangle ts = pgon; List<Coordinate> vertices = new List<Coordinate>(); Point p0 = surface.Points[ts.P0]; Point p1 = surface.Points[ts.P1]; Point p2 = surface.Points[ts.P2]; Coordinate c1 = new Coordinate(p0.X, p0.Y, p0.Z); Coordinate c2 = new Coordinate(p1.X, p1.Y, p1.Z); Coordinate c3 = new Coordinate(p2.X, p2.Y, p2.Z); vertices.Add(c1); vertices.Add(c2); vertices.Add(c3); Polygon polygon = new Polygon(vertices); IFeature fset = fs.AddFeature(polygon); fset.DataRow.BeginEdit(); fset.DataRow["Identifier"] = k; fset.DataRow.EndEdit(); tcount++; } } fs.SaveAs(localWorkspace + "\\" + name + "_polygon.shp", true); fs.Close(); fs.Dispose(); } double temp = 100; Console.SetCursorPosition(0, Console.CursorTop); Console.WriteLine("Progress => " + temp.ToString("###") + " % \n"); temp = foundCount * 100.0 / (xSize * ySize * 1.0); Console.WriteLine(temp.ToString("###.0") + " % of pixels were found in triangulation \n"); Console.WriteLine("Finished mapping elevation raster pixels to triangulation !\n"); }
/// <summary> /// Overload of BuildJoinedBasins that takes an outlets shape path used for Inlets resolution. If no outlets/inlets path given, it will treat all points as outlets /// </summary> // 2/11/09 rewritten by Chris George to dramatically improve speed: // (a) use utils.ClipPolygon instead of SpatialOperations.MergeShapes // (b) create a binary tree modeling the drainage pattern of the subbasins // (b) merge "upstream-first" using the drainage tree so that each merge combines abutting polygons public static bool BuildJoinedBasins(string subBasinShapePath, string outletsShapePath, string joinBasinShapeResultPath, IProgressHandler callback) { var shapeIdxList = new ArrayList(); BinTree drainage; IFeatureSet outlets = null; if (outletsShapePath != string.Empty) { outlets = FeatureSet.Open(outletsShapePath); } var shed = FeatureSet.Open(subBasinShapePath); var dsNodeFieldNum = -1; var dsShedFieldNum = -1; var us1FieldNum = -1; var us2FieldNum = -1; for (var i = 0; i < shed.DataTable.Columns.Count; i++) { switch (shed.DataTable.Columns[i].ColumnName.ToUpper()) { case "DSNODEID": dsNodeFieldNum = i; break; case "DSWSID": dsShedFieldNum = i; break; case "US1WSID": us1FieldNum = i; break; case "US2WSID": us2FieldNum = i; break; } } //DataManagement.DeleteShapefile(joinBasinShapeResultPath); var newShed = new FeatureSet(); newShed.FeatureType = FeatureType.Polygon; newShed.Filename = joinBasinShapeResultPath; var idfieldnum = AddField(newShed, "MWShapeID", typeof(int)); var linkfieldnum = AddField(newShed, "LinkIDs", typeof(string)); var outletfieldnum = AddField(newShed, "OutletID", typeof(int)); var dswsfieldnum = AddField(newShed, "DSWSID", typeof(int)); var uswsfieldnum1 = AddField(newShed, "USWSID1", typeof(int)); var uswsfieldnum2 = AddField(newShed, "USWSID2", typeof(int)); var reservoirfieldnum = AddField(newShed, "Reservoir", typeof(int)); var oldperc = 0; for (var sindx = 0; sindx < shed.NumRows(); sindx++) { if (shed.NumRows() > 1) { var newperc = Convert.ToInt32((Convert.ToDouble(sindx) / Convert.ToDouble(shed.NumRows())) * 100); if (newperc > oldperc) { if (callback != null) { callback.Progress("Status", newperc, "Merging Watersheds to Outlets/Inlets"); } oldperc = newperc; } } DSNode dsNodeType = DSNode.Outlet; var dsNodeVal = int.Parse(shed.get_CellValue(dsNodeFieldNum, sindx).ToString()); if (dsNodeVal > -1) { // an outlet, inlet, reservoir or point source if (outletsShapePath == string.Empty) { // assume this is an outlet drainage = getDrainageFromSubbasin(shed, outlets, false, true, sindx, dsNodeFieldNum, us1FieldNum, us2FieldNum); } else { dsNodeType = getDSNodeType(outlets, dsNodeVal); if ((dsNodeType == DSNode.Outlet) || (dsNodeType == DSNode.Reservoir)) { if (isUpstreamOfInlet(shed, outlets, sindx)) { drainage = null; } else { drainage = getDrainageFromSubbasin(shed, outlets, true, true, sindx, dsNodeFieldNum, us1FieldNum, us2FieldNum); } } else { // ignore inlets and point sources drainage = null; } } shapeIdxList.Clear(); if (drainage != null) { char[] sep = { ',' }; var idxs = drainage.ToString().Split(sep); for (var i = 0; i < idxs.Length; i++) { shapeIdxList.Add(idxs[i]); } } if (shapeIdxList.Count != 0) { IFeature mergeShape; string strLinks; if (shapeIdxList.Count == 1) { mergeShape = shed.get_Shape(int.Parse(shapeIdxList[0].ToString())); strLinks = shed.get_CellValue(0, int.Parse(shapeIdxList[0].ToString())).ToString(); } else { strLinks = shed.get_CellValue(0, int.Parse(shapeIdxList[0].ToString())).ToString(); for (int i = 1; i <= shapeIdxList.Count - 1; i++) { strLinks = strLinks + ", " + shed.get_CellValue(0, int.Parse(shapeIdxList[i].ToString())); } DateTime time = DateTime.Now; mergeShape = mergeBasinsByDrainage(shed, drainage); var elapsed = DateTime.Now.Subtract(time); Trace.WriteLine("Made merged watershed of " + shapeIdxList.Count + " subbasins in " + elapsed.TotalSeconds.ToString("F1") + " seconds"); } // Check merged shape for single part and clockwise if (mergeShape.NumGeometries > 1) { Trace.WriteLine("Merged polygon has " + mergeShape.NumGeometries + " parts"); } else { var area = SignedArea(mergeShape); if (area < 0) { Trace.WriteLine("Needed to reverse merged polygon"); mergeShape = ReverseShape(mergeShape); } } var currshpidx = newShed.NumRows(); newShed.AddFeature(mergeShape); newShed.EditCellValue(idfieldnum, currshpidx, currshpidx); newShed.EditCellValue(linkfieldnum, currshpidx, strLinks); newShed.EditCellValue(outletfieldnum, currshpidx, dsNodeVal); if (int.Parse(shed.get_CellValue(dsShedFieldNum, sindx).ToString()) != -1) { newShed.EditCellValue(dswsfieldnum, currshpidx, shed.get_CellValue(dsShedFieldNum, sindx)); } else { newShed.EditCellValue(dswsfieldnum, currshpidx, -1); } newShed.EditCellValue(uswsfieldnum1, currshpidx, -1); newShed.EditCellValue(uswsfieldnum2, currshpidx, -1); if (dsNodeType == DSNode.Reservoir) { newShed.EditCellValue(reservoirfieldnum, currshpidx, 1); } else { newShed.EditCellValue(reservoirfieldnum, currshpidx, 0); } } } } buildMergeDownstreamUpStream(newShed, idfieldnum, linkfieldnum, dswsfieldnum, uswsfieldnum1, uswsfieldnum2); newShed.Projection = shed.Projection; shed.Close(); newShed.Save(); newShed.Close(); if (outletsShapePath != string.Empty) { outlets.Close(); } if (callback != null) { callback.Progress(string.Empty, 0, string.Empty); } return true; }