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");
    }
Exemple #2
0
        /// <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;
        }