Ejemplo n.º 1
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;
        }