예제 #1
0
        private bool AddPointToShapeFile(double x, double y, MapWinGIS.Shapefile shpFile, int shpIndex, int insertIndex)
        {
            try
            {
                MapWinGIS.Point p;

                //start editing shapes
                shpFile.StartEditingShapes(true, null);
                MapWinGIS.Shape shp = shpFile.get_Shape(shpIndex);

                p   = new MapWinGIS.Point();
                p.x = x;
                p.y = y;

                if (!shp.InsertPoint(p, ref insertIndex))
                {
                    return(false);
                }
                else if (shp.NumParts > 1)
                {
                    // Shift up part indices if needed (bugzilla 798)
                    bool shifting = false;
                    for (int i = 0; i < shp.NumParts; i++)
                    {
                        if (shp.get_Part(i) >= insertIndex)
                        {
                            // Shift up this one and all remaining
                            shifting = true;
                        }
                        if (shifting)
                        {
                            shp.set_Part(i, shp.get_Part(i) + 1);
                        }
                    }
                }

                m_Globals.CreateUndoPoint();

                //stop editing and save changes
                shpFile.StopEditingShapes(true, true, null);

                return(true);
            }
            catch (System.Exception ex)
            {
                m_MapWin.ShowErrorDialog(ex);
            }

            return(false);
        }
예제 #2
0
        /// <summary>
        /// If a Shape has multiple parts, this will create a separate polyline for each part.
        /// </summary>
        /// <param name="mwShape">A MapWinGIS.Shape that should be a LineString shape type</param>
        /// <returns>A List of Polylines derived from the various shapes</returns>
        public static List <LineString> mwShape_To_LineStrings(MapWinGIS.Shape mwShape)
        {
            if (Adapter.GetCategory(mwShape) != ShapeCategories.Line)
            {
                throw new ArgumentException("The Split method only takes Polyline shape types.");
            }
            List <LineString> newLines = new List <LineString>();

            if (mwShape.NumParts <= 1)
            {
                LineString Part = new LineString();
                for (int I = 0; I < mwShape.numPoints; I++)
                {
                    Part.Add_Point(mwShape.get_Point(I));
                }
                newLines.Add(Part);
                return(newLines);
            }
            int PartIndex = 0;

            for (int P = 0; P < mwShape.NumParts; P++)
            {
                LineString Part  = new LineString();
                int        Pnext = mwShape.get_Part(P);
                for (int I = PartIndex; I < Pnext; I++)
                {
                    Part.Add_Point(mwShape.get_Point(I));
                }
                newLines.Add(Part);
            }
            return(newLines);
        }
예제 #3
0
        /// <summary>
        /// This function scans a Polygon/PolygonM/PolygonZ to determine if any of the
        /// existing polygons are counter-clockwise.  If they are, then it creates a linear ring
        /// from the shape.
        /// </summary>
        /// <param name="mwShape">A MapWinGIS.Shape Polygon/PolygonM/PolygonZ that might have holes.</param>
        /// <returns>A List of Linear Rings, each item representing one of the holes from the polygon.</returns>
        public static List <ILinearRing> GetHoles(MapWinGIS.Shape mwShape)
        {
            List <ILinearRing> Holes = new List <ILinearRing>();

            MapWinGIS.Point mwPoint = new MapWinGIS.Point();
            int             pt      = 0;
            int             prt     = 0;

            do
            {
                int Start = mwShape.get_Part(prt);
                int End;
                if (prt >= mwShape.NumParts - 1)
                {
                    End = mwShape.numPoints;
                }
                else
                {
                    End = mwShape.get_Part(prt + 1);
                }
                int          Count  = End - Start + 1;
                Coordinate[] Coords = new Coordinate[Count];
                double       area   = 0;
                for (int PrtPoint = 0; PrtPoint < Count - 1; PrtPoint++)
                {
                    // PrtPoint will be tracking the index for the specific linestring
                    mwPoint          = mwShape.get_Point(pt);
                    Coords[PrtPoint] = new Coordinate(mwPoint.x, mwPoint.y);
                    if (PrtPoint > 0)
                    {
                        area += Coords[PrtPoint].X * Coords[PrtPoint - 1].Y - Coords[PrtPoint - 1].X * Coords[PrtPoint].Y;
                    }
                    pt++;
                }
                mwPoint           = mwShape.get_Point(Start); // close the loop
                Coords[Count - 1] = new Coordinate(mwPoint.x, mwPoint.y);
                area += Coords[Count - 2].X * Coords[Count - 1].Y - Coords[Count - 1].X * Coords[Count - 2].Y;

                // if the area is negative, then the shape is counter-clockwise and therefore a hole
                if (area < 0)
                {
                    Holes.Add(new LinearRing(Coords));
                }
                prt++;
            }while (prt < mwShape.NumParts);
            return(Holes);
        }
예제 #4
0
        /// <summary>
        /// Returns a MultiLineString geometry collection derived from the mwShape
        /// </summary>
        /// <param name="mwShape">The shape to convert into a multi-line string</param>
        public static MultiLineString CreateMultiLineString(MapWinGIS.Shape mwShape)
        {
            MultiLineString MLS = new MultiLineString();
            // Variables
            int        numParts;  // The number of parts in the shape
            int        numPoints; // The number of points in the shape
            LineString LS;

            // Parameter checking
            if (mwShape == null)
            {
                throw new ArgumentException("mwShape should either not be null, or not be specified.");
            }
            if (mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPATCH ||
                mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPOINT ||
                mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPOINTM ||
                mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPOINTZ ||
                mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_NULLSHAPE ||
                mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POINT ||
                mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POINTM ||
                mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POINTZ)
            {
                throw new ArgumentException("Argument mwShape shapetype must be a polyline or polygon.");
            }

            MLS.GeometryN = new List <Geometry>();
            numParts      = mwShape.NumParts;
            numPoints     = mwShape.numPoints;
            // if NumParts = 0, treat as though the whole shape was a single part
            int prt = 0;                 // prt is the part index
            int pt  = 0;                 // pt is the point index

            while (prt < numParts - 1)
            {
                int maxpt = mwShape.get_Part(prt + 1);
                LS = new LineString();
                while (pt < maxpt)
                {
                    Coordinate Coord = GeometryFactory.CreateCoordinate(mwShape.get_Point(pt));
                    LS.Coordinates.Add(Coord);
                    pt++;
                }
                MLS.GeometryN.Add(LS);
                prt++;
            }
            LS = new LineString();
            while (pt < numPoints)
            {
                Coordinate Coord = GeometryFactory.CreateCoordinate(mwShape.get_Point(pt));
                LS.Coordinates.Add(Coord);
                pt++;
            }
            MLS.GeometryN.Add(LS);
            return(MLS);
        }
예제 #5
0
 private void ShiftDownVertices(ref MapWinGIS.Shape shp, int deleteIndex)
 {
     if (shp.NumParts > 1)
     {
         // Shift down part indices if needed (bugzilla 798)
         bool shifting = false;
         for (int i = 0; i < shp.NumParts; i++)
         {
             if (shp.get_Part(i) > deleteIndex)
             {
                 // Shift up this one and all remaining
                 shifting = true;
             }
             if (shifting)
             {
                 shp.set_Part(i, Math.Max(0, shp.get_Part(i) - 1));
             }
         }
     }
 }
예제 #6
0
        /// <summary>
        /// Creates one multi-part polygon out of two input polygons.
        /// </summary>
        /// <param name="poly1">The first polygon to be combined.</param>
        /// <param name="poly2">The second polygon to be combined.</param>
        /// <param name="resultShp">The resulting multi-part polygon.</param>
        /// <returns>True if combining was successful, false otherwise.</returns>
        private static bool CombinePolygons(ref MapWinGIS.Shape poly1, ref MapWinGIS.Shape poly2, out MapWinGIS.Shape resultShp)
        {
            int p1NumParts = poly1.NumParts;

            if (p1NumParts == 0)
            {
                p1NumParts = 1;
            }
            int p2NumParts = poly2.NumParts;

            if (p2NumParts == 0)
            {
                p2NumParts = 1;
            }

            MapWinGIS.Shape multiShp = new MapWinGIS.ShapeClass();
            multiShp.Create(poly1.ShapeType);
            int partIndex  = 0;
            int pointIndex = 0;
            int numPoints  = poly1.numPoints;
            int begPart    = 0;
            int endPart    = numPoints;

            //deal with the first shape and all of its parts
            //			Globals.Vertex[][] p1VertArray = new Globals.Vertex[p1NumParts][];
            //			Globals.ConvertPolyToVertexArray(ref poly1, out p1VertArray);
            //bool firstIsClockwise = Globals.IsClockwise(ref p1VertArray[0]);

            for (int i = 0; i <= p1NumParts - 1; i++)
            {
                partIndex  = i;
                pointIndex = multiShp.numPoints;
                multiShp.InsertPart(pointIndex, ref partIndex);

                begPart = poly1.get_Part(i);
                if (i < p1NumParts - 1)
                {
                    endPart = poly1.get_Part(i + 1);
                }
                else
                {
                    endPart = poly1.numPoints;
                }
                //				if(firstIsClockwise)
                //				{
                //add part
                for (int j = begPart; j <= endPart - 1; j++)
                {
                    pointIndex = multiShp.numPoints;
                    multiShp.InsertPoint(poly1.get_Point(j), ref pointIndex);
                }
                //				}
                //				else
                //				{
                //					//add part in reverse order
                //					for(int j = endPart-1; j >= begPart; j--)
                //					{
                //						pointIndex = multiShp.numPoints;
                //						multiShp.InsertPoint(poly1.get_Point(j), ref pointIndex);
                //					}
                //				}
            }            //end of adding poly1 and all of its parts to the result shape

            //deal with the second shape and all of its parts
            //			Globals.Vertex[][] p2VertArray = new Globals.Vertex[p2NumParts][];
            //			Globals.ConvertPolyToVertexArray(ref poly2, out p2VertArray);
            //			bool secondIsClockwise = Globals.IsClockwise(ref p2VertArray[0]);
            partIndex++;
            numPoints = poly2.numPoints;
            begPart   = 0;
            endPart   = numPoints;

            for (int i = 0; i <= p2NumParts - 1; i++)
            {
                partIndex += i;
                pointIndex = multiShp.numPoints;
                multiShp.InsertPart(pointIndex, ref partIndex);

                begPart = poly2.get_Part(i);
                if (i < p2NumParts - 1)
                {
                    endPart = poly2.get_Part(i + 1);
                }
                else
                {
                    endPart = poly2.numPoints;
                }

                //				if(secondIsClockwise)
                //				{
                for (int j = begPart; j <= endPart - 1; j++)
                {
                    pointIndex = multiShp.numPoints;
                    multiShp.InsertPoint(poly2.get_Point(j), ref pointIndex);
                }
                //				}
                //				else
                //				{
                //					for(int j = endPart-1; j >= begPart; j--)
                //					{
                //						pointIndex = multiShp.numPoints;
                //						multiShp.InsertPoint(poly2.get_Point(j), ref pointIndex);
                //					}
                //				}
            }            //end of inserting parts from the second shape

            resultShp = multiShp;
            if (resultShp.numPoints > 0)
            {
                return(true);
            }
            else
            {
                gErrorMsg = "Error occured while trying to combine parts. No points in result shape.";
                Debug.WriteLine(gErrorMsg);
                Error.SetErrorMsg(gErrorMsg);
                MapWinUtility.Logger.Dbg(gErrorMsg);
                return(false);
            }
        }
예제 #7
0
        /// <summary>
        /// calculate the area of large shapes in lat/long coordinates.
        /// The coordinates must be in decimal degrees
        /// the return value is in square kilometres
        /// </summary>
        /// <param name="shape">Polygon shape (decimal degree coordinates)</param>
        /// <returns>Area of the shape in square kilometres</returns>
        private static double SphericPolygonArea(ref MapWinGIS.Shape shape)
        {
            // added by Jiri Kadlec 3/16/2008
            //
            // for each part of shape:
            // convert ellipsoid latitude to a latitude on equal-area unit sphere
            // convert the sphere coordinates from long/lat to x/y of sinusoidal equal-area projection
            // (x, y is in radians)
            // calculate area of the part
            // if it's a normal polygon, add it and if it's a hole, subtract it from total
            // area of shape
            //
            //note: this function uses the sphere approximation. It should be
            //used for large shapes with |max.latitude - min.latitude| > 1 degree.
            //please refer to: http://www.ucl.ac.uk/~ucessan/news/bob-aag2007.ppt
            // and: http://www.gmat.unsw.edu.au/wang/jgps/v5n12/v5n12p02.pdf

            //radius of equal-area sphere corresponding to WGS 84 ellipsoid
            double EARTH_RADIUS_SQUARED = Math.Pow(EqualAreaSphereRadius(), 2);

            //calculation modified from MapWinGeoProc.Statistics.Area
            double totalArea = 0.0;
            double indivArea = 0.0;

            int numParts  = shape.NumParts;
            int numPoints = shape.numPoints;

            if (numParts > 1) //dealing with a multi-part polygon, hole areas must be subtracted from total
            {
                MapWinGIS.Shape[] allPolygons = new MapWinGIS.Shape[numParts];
                int begPart;
                int endPart;
                for (int i = 0; i <= numParts - 1; i++)
                {
                    allPolygons[i]           = new MapWinGIS.ShapeClass();
                    allPolygons[i].ShapeType = shape.ShapeType;

                    begPart = shape.get_Part(i);
                    if (i < numParts - 1)
                    {
                        endPart = shape.get_Part(i + 1);
                    }
                    else
                    {
                        endPart = numPoints;
                    }

                    int ptIndex = 0;
                    for (int j = begPart; j <= endPart - 1; j++)
                    {
                        allPolygons[i].InsertPoint(shape.get_Point(j), ref ptIndex);
                        ptIndex++;
                    }//end of creating separate polygons out of each part

                    //calculate the area for each polygon part
                    int numPolyPts = allPolygons[i].numPoints;
                    indivArea = 0.0;
                    for (int j = 0; j <= numPolyPts - 2; j++)
                    {
                        double oneY = EqualAreaSphereLat(Utils.deg2rad(allPolygons[i].get_Point(j).y));
                        double oneX = Utils.deg2rad(allPolygons[i].get_Point(j).x) * Math.Cos(oneY);
                        double twoY = EqualAreaSphereLat(Utils.deg2rad(allPolygons[i].get_Point(j + 1).y));
                        double twoX = Utils.deg2rad(allPolygons[i].get_Point(j + 1).x) * Math.Cos(twoY);

                        double trapArea = ((oneX * twoY) - (twoX * oneY));
                        indivArea += trapArea;
                    } //end of calculating individual area for the current part
                    totalArea += indivArea;
                }     //end of looping through parts
                totalArea = 0.5 * Math.Abs(totalArea) * EARTH_RADIUS_SQUARED;
            }         //end of dealing with multi-part polygons
            else
            {
                for (int j = 0; j <= numPoints - 2; j++)
                {
                    double oneY = EqualAreaSphereLat(Utils.deg2rad(shape.get_Point(j).y));
                    double oneX = Utils.deg2rad(shape.get_Point(j).x) * Math.Cos(oneY);
                    double twoY = EqualAreaSphereLat(Utils.deg2rad(shape.get_Point(j + 1).y));
                    double twoX = Utils.deg2rad(shape.get_Point(j + 1).x) * Math.Cos(twoY);

                    double trapArea = ((oneX * twoY) - (twoX * oneY));
                    totalArea += trapArea;
                }
                totalArea = 0.5 * Math.Abs(totalArea) * EARTH_RADIUS_SQUARED;
            }

            return(totalArea);
        }
예제 #8
0
        //see: http://astronomy.swin.edu.au/~pbourke/geometry/polyarea/
        //for a simple explanation on how to calculate the area of a polygon.
        // 16. Mar 2008 modified by Jiri Kadlec for shapes in lat/long coordinates.
        /// <summary>
        /// Computes the area of a polygon. For multi-part polygons, assume holes are counter-clockwise.
        /// To calculate the area correctly, the shape must have an equal-area projection. For shapes
        /// in Lat/Long coordinates use the LLArea() function.
        /// </summary>
        /// <param name="shape">The polygon shape.</param>
        /// <returns>The area in square units, or 0.0 if it could not be found.</returns>
        public static double Area(ref MapWinGIS.Shape shape)
        {
            Error.ClearErrorLog();
            double area;

            if (shape == null)
            {
                area      = 0.0;
                gErrorMsg = "Unexpected null paramter: shape.";
                Error.SetErrorMsg(gErrorMsg);
                Debug.WriteLine(gErrorMsg);
                return(area);
            }

            MapWinGIS.ShpfileType shpType;
            shpType = shape.ShapeType;

            if (shpType != MapWinGIS.ShpfileType.SHP_POLYGON && shpType != MapWinGIS.ShpfileType.SHP_POLYGONM && shpType != MapWinGIS.ShpfileType.SHP_POLYGONZ)
            {
                area      = 0.0;
                gErrorMsg = "Incompatible shape type: must be of type polygon in order to calculate area.";
                Error.SetErrorMsg(gErrorMsg);
                Debug.WriteLine(gErrorMsg);
                return(area);
            }

            double totalArea = 0.0;
            double indivArea = 0.0;

            int numParts  = shape.NumParts;
            int numPoints = shape.numPoints;

            if (numParts > 1)            //dealing with a multi-part polygon, hole areas must be subtracted from total
            {
                MapWinGIS.Shape[] allPolygons = new MapWinGIS.Shape[numParts];
                int begPart;
                int endPart;
                for (int i = 0; i <= numParts - 1; i++)
                {
                    allPolygons[i]           = new MapWinGIS.ShapeClass();
                    allPolygons[i].ShapeType = shpType;

                    begPart = shape.get_Part(i);
                    if (i < numParts - 1)
                    {
                        endPart = shape.get_Part(i + 1);
                    }
                    else
                    {
                        endPart = numPoints;
                    }

                    int ptIndex = 0;
                    for (int j = begPart; j <= endPart - 1; j++)
                    {
                        allPolygons[i].InsertPoint(shape.get_Point(j), ref ptIndex);
                        ptIndex++;
                    }                    //end of creating separate polygons out of each part

                    //calculate the area for each polygon part
                    int numPolyPts = allPolygons[i].numPoints;
                    indivArea = 0.0;
                    for (int j = 0; j <= numPolyPts - 2; j++)
                    {
                        double oneX = allPolygons[i].get_Point(j).x;
                        double oneY = allPolygons[i].get_Point(j).y;
                        double twoX = allPolygons[i].get_Point(j + 1).x;
                        double twoY = allPolygons[i].get_Point(j + 1).y;

                        double trapArea = ((oneX * twoY) - (twoX * oneY));
                        indivArea += trapArea;
                    }    //end of calculating individual area for the current part
                    totalArea += indivArea;
                }        //end of looping through parts
                totalArea = 0.5 * Math.Abs(totalArea);
            }            //end of dealing with multi-part polygons
            else
            {
                for (int i = 0; i <= numPoints - 2; i++)
                {
                    double oneX = shape.get_Point(i).x;
                    double oneY = shape.get_Point(i).y;
                    double twoX = shape.get_Point(i + 1).x;
                    double twoY = shape.get_Point(i + 1).y;

                    double trapArea = ((oneX * twoY) - (twoX * oneY));
                    totalArea += trapArea;
                }
                totalArea = 0.5 * Math.Abs(totalArea);
            }

            return(totalArea);
        }
예제 #9
0
        private void btnOK_Click(object sender, EventArgs e)
        {
            double tolerance = 0;

            if (!double.TryParse(txtTolerance.Text, out tolerance))
            {
                MapWinUtility.Logger.Message("Please enter only numbers in the distance field.", "Enter Only Numbers", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, DialogResult.OK);
                return;
            }

            this.Cursor = Cursors.WaitCursor;

            prgShape.Visible = true;
            prgPoint.Visible = true;

            sf.StartEditingShapes(true, null);
            long totalRemoved = 0;
            long fromShapes   = 0;
            int  numPts;

            System.Collections.ArrayList removeList = new System.Collections.ArrayList();

            if (sf.NumShapes > 0)
            {
                prgShape.Maximum = sf.NumShapes;

                for (int z = 0; z < sf.NumShapes; z++)
                {
                    MapWinGIS.Shape shp = sf.get_Shape(z);
                    if (z < 100 || z % 5 == 0)
                    {
                        prgShape.Value = z;
                        this.Refresh();
                    }
                    Application.DoEvents();

                    numPts = shp.numPoints;
                    if (numPts > 0)
                    {
                        prgPoint.Maximum = numPts;

                        for (int i = numPts - 1; i > 0; i--) // 0 never needs to actually be hit, inner loop will compare against all zeros
                        {
                            if (i % 5 == 0)
                            {
                                prgPoint.Value = numPts - i;
                                this.Refresh();
                            }

                            for (int j = i - 1; j >= 0; j--)
                            {
                                if (Math.Sqrt(Math.Pow(shp.get_Point(i).x - shp.get_Point(j).x, 2) + Math.Pow(shp.get_Point(i).y - shp.get_Point(j).y, 2)) < tolerance)
                                {
                                    // Make sure that !(i == numPts - 1 && j == 0) -- polygon completion point
                                    if (!removeList.Contains(i) && !(i == numPts - 1 && j == 0))
                                    {
                                        removeList.Add(i);
                                    }
                                }
                            }
                        }
                    }

                    if (removeList.Count > 0)
                    {
                        if (removeList.Count >= shp.numPoints - 1)
                        {
                            // Probably not a good thing.....
                            MapWinUtility.Logger.Message("Aborting: Proceeding will remove all points from one or more shapes. The distance may need to be smaller, particularly for unprojected (latitute and longitude) coordinate systems.", "Aborting -- All Points Would Be Removed", MessageBoxButtons.OK, MessageBoxIcon.Error, DialogResult.OK);
                            sf.StopEditingShapes(false, true, null);
                            this.Cursor      = Cursors.Default;
                            prgPoint.Value   = 0;
                            prgShape.Value   = 0;
                            prgPoint.Visible = false;
                            prgShape.Visible = false;
                            this.Cursor      = Cursors.Default;
                            return;
                        }

                        totalRemoved += removeList.Count;
                        fromShapes++;

                        while (removeList.Count > 0)
                        {
                            for (int part = 0; part < shp.NumParts; part++)
                            {
                                if (shp.get_Part(part) >= (int)removeList[0])
                                {
                                    shp.set_Part(part, shp.get_Part(part) - 1);
                                }
                            }
                            shp.DeletePoint((int)removeList[0]);
                            removeList.RemoveAt(0);
                        }

                        // If this is a polygon and there are now less than 3 shapes, panic
                        if ((shp.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGON || shp.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGONZ || shp.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGONM) && shp.numPoints < 3)
                        {
                            // Probably not a good thing.....
                            MapWinUtility.Logger.Message("Aborting: Proceeding will leave less than 3 points in a polygon. The distance may need to be smaller, particularly for unprojected (latitute and longitude) coordinate systems.", "Aborting -- Polygons Would Be Destroyed", MessageBoxButtons.OK, MessageBoxIcon.Error, DialogResult.OK);
                            sf.StopEditingShapes(false, true, null);
                            this.Cursor      = Cursors.Default;
                            prgPoint.Value   = 0;
                            prgShape.Value   = 0;
                            prgPoint.Visible = false;
                            prgShape.Visible = false;
                            this.Cursor      = Cursors.Default;
                            return;
                        }

                        // If the first and last points are not the same now, reclose it
                        if (shp.get_Point(0).x != shp.get_Point(shp.numPoints - 1).x || shp.get_Point(0).y != shp.get_Point(shp.numPoints - 1).y)
                        {
                            MapWinGIS.Point pnt = new MapWinGIS.Point();
                            pnt.x = shp.get_Point(0).x;
                            pnt.y = shp.get_Point(0).y;
                            pnt.Z = shp.get_Point(0).Z;
                            int ptidx = shp.numPoints;
                            shp.InsertPoint(pnt, ref ptidx);
                        }
                    }
                }
            }

            prgPoint.Value = prgPoint.Maximum;
            prgShape.Value = prgShape.Maximum;

            g.CreateUndoPoint();

            sf.StopEditingShapes(true, true, null);

            this.Cursor = Cursors.Default;

            if (totalRemoved > 0)
            {
                MapWinUtility.Logger.Message("There were " + totalRemoved.ToString() + " points removed from " + fromShapes.ToString() + " shapes.", "Finished", MessageBoxButtons.OK, MessageBoxIcon.Information, DialogResult.OK);
            }
            else
            {
                MapWinUtility.Logger.Message("Finished -- no extra points needed to be removed.", "Finished", MessageBoxButtons.OK, MessageBoxIcon.Information, DialogResult.OK);
            }

            this.DialogResult = DialogResult.OK;
            this.Close();
        }
예제 #10
0
        /// <summary>
        /// Converts a MapWinGIS.Shape of any type to the associated geometry.
        /// Clockwise/Counter clockwise arrangements are important for polygons.
        /// Any hole that isn't correctly counter-clockwise will be treated as a polygon.
        /// Any clockwise "hole" that is not contained by at least one polygon will be
        /// reversed to clockwise and returned as a polygon.
        /// NULLSHAPE || MULTIPATCH --> throws exception.
        /// POINT || POINTM || POINTZ --> Geometries.Point
        /// MULTIPOINT || MULTIPOINTM || MULTIPOINTZ --> Geometries.MultiPoint
        /// {1 part} POLYLINE || POLYLINEM || POLYLINEZ --> Geometires.LineString
        /// {n parts} POLYLINE || POLYLINEM || POLYLINEZ --> Geometires.MultiLineString
        /// {1 shell} POLYGON || POLYGONM || POLYGONZ --> Geometires.Polygon
        /// {n shells} POLYGON || POLYGONM || POLYGONZ --> Geometries.MultiPolygon
        /// </summary>
        /// <param name="mwShape">A MapWinGIS.Shape to convert to a Geometry</param>
        /// <returns>Geometry representing the shape specified by mwShape.</returns>
        ///
        public static Geometry ShapeToGeometry(MapWinGIS.Shape mwShape)
        {
            #region -------------------------- UNSUPPORTED -------------------------------------

            MapWinGIS.Point mwPoint; // a generic MapWinGIS style point

            // ------------ NOT SUPPORTED
            if (mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_NULLSHAPE ||
                mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPATCH)
            {
                throw new ArgumentException("Shape type is not supported.");
            }
            #endregion

            #region -------------------------- POINT -------------------------------------------

            // ------------- POINT
            if (mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POINT ||
                mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POINTM ||
                mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POINTZ)
            {
                // The shape represents a single point, so return a single point
                Coordinate Coord = new Coordinate(mwShape.get_Point(0).x, mwShape.get_Point(0).y);
                return(new Point(Coord));
            }

            #endregion

            #region -------------------------- MULTI POINT -------------------------------------

            if (mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPOINT ||
                mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPOINTM ||
                mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPOINTZ)
            {
                Point[] Coords = new Point[mwShape.numPoints];
                for (int pt = 0; pt < mwShape.numPoints; pt++)
                {
                    mwPoint    = mwShape.get_Point(pt);
                    Coords[pt] = new Point(mwPoint.x, mwPoint.y);
                }
                return(new MultiPoint(Coords));
            }
            #endregion

            #region -------------------------- LINE STRINGS ------------------------------------


            if (mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYLINE ||
                mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYLINEM ||
                mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYLINEZ)
            {
                // ------------- LINE STRING
                if (mwShape.NumParts < 2)
                {
                    Coordinate[] Coords = new Coordinate[mwShape.numPoints];
                    for (int pt = 0; pt < mwShape.numPoints; pt++)
                    {
                        mwPoint    = mwShape.get_Point(pt);
                        Coords[pt] = new Coordinate(mwPoint.x, mwPoint.y);
                    }
                    return(new LineString(Coords));
                }

                // ------------- MULTI LINE STRING
                else
                {
                    int          pt    = 0;
                    LineString[] Lines = new LineString[mwShape.NumParts];
                    for (int prt = 0; prt < mwShape.NumParts; prt++)
                    {
                        int Start = mwShape.get_Part(prt);
                        int End;
                        if (prt == mwShape.NumParts - 1)
                        {
                            End = mwShape.numPoints;
                        }
                        else
                        {
                            End = mwShape.get_Part(prt + 1);
                        }
                        Coordinate[] Coords = new Coordinate[End - Start];
                        for (int PrtPoint = 0; PrtPoint < End - Start; PrtPoint++)
                        {
                            // PrtPoint will be tracking the index for the specific linestring
                            mwPoint          = mwShape.get_Point(pt);
                            Coords[PrtPoint] = new Coordinate(mwPoint.x, mwPoint.y);
                            pt++;
                        }
                        // Create a new linestring using only the coordinates for a specific part
                        Lines[prt] = new LineString(Coords);
                    }
                    return(new MultiLineString(Lines));
                }
            }
            #endregion

            #region -------------------------- POLYGONS ----------------------------------------

            if (mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGON ||
                mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGONM ||
                mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGONZ)
            {
                // Polygons are complex and not as straight forward as linear rings.
                // A multi-part shape might just be a single polygon with a hole.

                List <NRings>     Rings = new List <NRings>();
                List <LinearRing> Holes = new List <LinearRing>();
                int pt  = 0;
                int prt = 0;
                List <LinearRing> RawRings = new List <LinearRing>();
                do
                {
                    int Start = mwShape.get_Part(prt);
                    int End;
                    if (prt >= mwShape.NumParts - 1)
                    {
                        End = mwShape.numPoints;
                    }
                    else
                    {
                        End = mwShape.get_Part(prt + 1);
                    }
                    int          Count  = End - Start + 1;
                    Coordinate[] Coords = new Coordinate[Count];
                    double       area   = 0;
                    for (int PrtPoint = 0; PrtPoint < Count - 1; PrtPoint++)
                    {
                        // PrtPoint will be tracking the index for the specific linestring
                        mwPoint          = mwShape.get_Point(pt);
                        Coords[PrtPoint] = new Coordinate(mwPoint.x, mwPoint.y);
                        if (PrtPoint > 0)
                        {
                            area += Coords[PrtPoint].X * Coords[PrtPoint - 1].Y - Coords[PrtPoint - 1].X * Coords[PrtPoint].Y;
                        }
                        pt++;
                    }
                    mwPoint           = mwShape.get_Point(Start); // close the loop
                    Coords[Count - 1] = new Coordinate(mwPoint.x, mwPoint.y);
                    area += Coords[Count - 2].X * Coords[Count - 1].Y - Coords[Count - 1].X * Coords[Count - 2].Y;

                    // if the area is negative, then the shape is counter-clockwise and therefore a hole
                    if (area < 0)
                    {
                        Holes.Add(new LinearRing(Coords));
                    }
                    else
                    {
                        Rings.Add(new NRings(Coords));
                    }

                    prt++;
                } while (prt < mwShape.NumParts);
                // Add the holes to every ring that can hold it.
                for (int iHole = 0; iHole < Holes.Count; iHole++)
                {
                    bool HolePunched = false;
                    for (int iRing = 0; iRing < Rings.Count; iRing++)
                    {
                        if (Rings[iRing].Ring.Contains(Holes[iHole]))
                        {
                            Rings[iRing].Holes.Add(Holes[iHole]);
                            HolePunched = true;
                        }
                    }
                    // If we couldn't punch the hole anywhere, then we will turn it into a polygon
                    if (HolePunched == false)
                    {
                        ILineString LS = Holes[iHole].Reverse(); //Switch to clockwise
                        Rings.Add(new NRings(LS.Coordinates));
                    }
                }

                // Create polygons from each of the rings and add them to a multipolygon
                if (Rings.Count == 1)
                {
                    if (Rings[0].Holes.Count > 0)
                    {
                        LinearRing[] HoleArray = new LinearRing[Rings[0].Holes.Count];
                        for (int iHole = 0; iHole < Rings[0].Holes.Count; iHole++)
                        {
                            HoleArray[iHole] = Rings[0].Holes[iHole];
                        }
                        return(new Polygon(Rings[0].Ring, HoleArray));
                    }
                    else
                    {
                        return(new Polygon(Rings[0].Ring));
                    }
                }
                Polygon[] Polygons = new Polygon[Rings.Count];
                for (int iRing = 0; iRing < Rings.Count; iRing++)
                {
                    if (Rings[iRing].Holes.Count > 0)
                    {
                        LinearRing[] HoleArray = new LinearRing[Rings[iRing].Holes.Count];
                        for (int iHole = 0; iHole < Rings[iRing].Holes.Count; iHole++)
                        {
                            HoleArray[iHole] = Rings[0].Holes[iHole];
                        }
                        Polygons[iRing] = new Polygon(Rings[iRing].Ring, HoleArray);
                    }
                    else
                    {
                        Polygons[iRing] = new Polygon(Rings[iRing].Ring);
                    }
                }
                return(new MultiPolygon(Polygons));
            }
            #endregion

            // There shouldn't be any way to get here.
            throw new ApplicationException("The shapetype specified is invalid, or new and not handled yet.");
        }