Ejemplo n.º 1
0
        /// <summary>
        /// This function lets the user set up whether the shape should be regular, type M or type Z.
        /// This will not interfere with existing shapes in the geometry, but will simply
        /// add the specified geometry to the end of the existing information.  Sending a null shape
        /// will create a new shape of the appropriate kind.
        /// </summary>
        /// <param name="geom">A Geometries.Geometry specifying what to append to the shape.
        /// Simply returns mwShape unchanged if geom is null.</param>
        /// <param name="mwShape">An existing shape with a shapetype already specified.</param>
        public static void AppendGeometryToShape(IGeometry geom, ref MapWinGIS.Shape mwShape)
        {
            // we don't need to throw an error if geom is null, there is simply nothing to add.
            if (geom == null)
            {
                return;
            }

            // If we have to set up a new shape object, we will also have to specify a shape type.
            bool SpecifyShapeType = false;

            if (mwShape == null)
            {
                mwShape          = new MapWinGIS.Shape();
                SpecifyShapeType = true;
            }
            MapWinGIS.Point mwPoint;
            int             rfPt  = mwShape.numPoints; // Flexible Point Index
            int             rfPrt = mwShape.NumParts;  // Flexible Part Index

            if (rfPt > 0 && rfPrt == 0)
            {
                //Change single part to a multipart shapefile
                mwShape.InsertPart(0, ref rfPrt);
                rfPrt++;
            }

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

            if (geom.GetType() == typeof(Point))
            {
                if (SpecifyShapeType == true)
                {
                    mwShape.ShapeType = MapWinGIS.ShpfileType.SHP_POINT;
                }
                // Only allow appending to a point shape type if there isn't a point defined yet.
                if ((mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPOINT ||
                     mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPOINTM ||
                     mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPOINTZ) ||
                    ((mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POINT ||
                      mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POINTM ||
                      mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POINTZ) && rfPt == 0))
                {
                    Point newPoint = geom as Point;
                    mwPoint   = new MapWinGIS.Point();
                    mwPoint.x = newPoint.X;
                    mwPoint.y = newPoint.Y;
                    mwShape.InsertPoint(mwPoint, ref rfPt);
                    return;
                }
                else
                {
                    if ((mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POINT ||
                         mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POINTM ||
                         mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POINTZ))
                    {
                        throw new ArgumentException("The Shape type of mwShape must be MultiPoint, MultiPointM, or MultiPointZ in order to Append a Point Geometry to a shape that already contains a point.");
                    }
                    else
                    {
                        throw new ArgumentException("mwShape had a shape type that did not correspond to Point or MultiPoint.  Point geometry not added.");
                    }
                }
            }

            #endregion

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

            if (geom.GetType() == typeof(MultiPoint))
            {
                if (SpecifyShapeType == true)
                {
                    mwShape.ShapeType = MapWinGIS.ShpfileType.SHP_MULTIPOINT;
                }

                if (mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPOINT ||
                    mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPOINTM ||
                    mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPOINTZ)
                {
                    MultiPoint newPoints = geom as MultiPoint;
                    for (int iPoint = 0; iPoint < newPoints.Count; iPoint++)
                    {
                        Point CurPoint = newPoints.Geometries[iPoint] as Point;
                        mwPoint   = new MapWinGIS.Point();
                        mwPoint.x = CurPoint.X;
                        mwPoint.y = CurPoint.Y;
                        mwShape.InsertPoint(mwPoint, ref rfPt);
                        rfPt++;  // I don't think we can have multi-parts in a multipoint shape
                    }
                    return;
                }
                else
                {
                    throw new ArgumentException("The shape type must be one of the multipoint types to add a multipoint geometry.");
                }
            }

            #endregion

            #region -------------------------- LINE STRING -------------------------------------

            if (geom.GetType() == typeof(LineString) || geom.GetType() == typeof(LinearRing))
            {
                if (SpecifyShapeType == true)
                {
                    mwShape.ShapeType = MapWinGIS.ShpfileType.SHP_POLYLINE;
                }

                if (mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYLINE ||
                    mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYLINEM ||
                    mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYLINEZ)
                {
                    LineString newPoints = geom as LineString; // Polymorphism should allow linear rings to be line strings
                    for (int iPoint = 0; iPoint < newPoints.Count; iPoint++)
                    {
                        ICoordinate CurPoint = newPoints.Coordinates[iPoint];
                        mwPoint   = new MapWinGIS.Point();
                        mwPoint.x = CurPoint.X;
                        mwPoint.y = CurPoint.Y;
                        mwShape.InsertPoint(mwPoint, ref rfPt);
                        rfPt++;  // I don't think we can have multi-parts in a multipoint shape
                    }
                    return;
                }
                else
                {
                    throw new ArgumentException("The shape type must be one of the polyline types to add a LineString geometry.");
                }
            }
            #endregion

            #region -------------------------- MULTI LINESTRING --------------------------------

            if (geom.GetType() == typeof(MultiLineString))
            {
                if (SpecifyShapeType == true)
                {
                    mwShape.ShapeType = MapWinGIS.ShpfileType.SHP_POLYLINE;
                }

                MultiLineString MLS = geom as MultiLineString;

                if (mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYLINE ||
                    mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYLINEM ||
                    mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYLINEZ)
                {
                    for (int iGeom = 0; iGeom < MLS.NumGeometries; iGeom++)
                    {
                        LineString LS = MLS.Geometries[iGeom] as LineString;
                        AppendGeometryToShape(LS, ref mwShape); // prevents a lot of code duplication
                    }
                    return;
                }
                else
                {
                    throw new ArgumentException("Cannot append a MultiLineString geometry to a " + mwShape.ShapeType.ToString() + " shape.");
                }
            }

            #endregion

            #region -------------------------- POLYGON -----------------------------------------
            if (geom.GetType() == typeof(Polygon))
            {
                Polygon newPolygon = geom as Polygon;
                if (SpecifyShapeType == true)
                {
                    mwShape.ShapeType = MapWinGIS.ShpfileType.SHP_POLYGON;
                }


                if (mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGON ||
                    mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGONM ||
                    mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGONZ)
                {
                    mwShape.InsertPart(rfPt, ref rfPrt);
                    rfPrt++;
                    ILinearRing Shell = newPolygon.Shell;
                    for (int iPoint = 0; iPoint < Shell.NumPoints; iPoint++)
                    {
                        ICoordinate Coord = Shell.Coordinates[iPoint];
                        mwPoint   = new MapWinGIS.Point();
                        mwPoint.x = Coord.X;
                        mwPoint.y = Coord.Y;
                        mwShape.InsertPoint(mwPoint, ref rfPt);
                        rfPt++;
                    }

                    // The same hole may appear multiple times in overlapping polygons.
                    // Create a list of holes in order to test clockwise.
                    if (newPolygon.NumInteriorRings > 0)
                    {
                        List <ILinearRing> UniqueHoles = new List <ILinearRing>();
                        List <ILinearRing> Holes       = GetHoles(mwShape); //holes in the existing shape

                        for (int iHole = 0; iHole < newPolygon.NumInteriorRings; iHole++)
                        {
                            if (Holes.Count > 0)
                            {
                                for (int jHole = 0; jHole < Holes.Count; jHole++)
                                {
                                    if (newPolygon.Holes[iHole] == Holes[jHole])
                                    {
                                        continue;
                                    }
                                    // if we get here, the new hole is unique and should be added
                                    UniqueHoles.Add(newPolygon.Holes[iHole]);
                                    // Also add it to the list to compare against other future holes
                                    Holes.Add(newPolygon.Holes[iHole]); // Holes.Count is re-evaluated each time so this should be ok
                                }
                            }
                            //else
                            //{
                            //    //make sure holes are added to a shape with no holes
                            //    UniqueHoles.Add(newPolygon.Holes[iHole]);
                            //    Holes.Add(newPolygon.Holes[iHole]);
                            //}
                        }

                        for (int iHole = 0; iHole < UniqueHoles.Count; iHole++)
                        {
                            mwShape.InsertPart(rfPt, ref rfPrt);
                            rfPrt++;
                            ICoordinate[] Hole;
                            if (IsClockwise(UniqueHoles[iHole].Coordinates))
                            {
                                // Holes should be counter clockwise
                                Hole = UniqueHoles[iHole].Reverse().Coordinates;
                            }
                            else
                            {
                                Hole = UniqueHoles[iHole].Coordinates;
                            }

                            int Count = Hole.GetUpperBound(0) + 1;
                            for (int iPoint = 0; iPoint < Count; iPoint++)
                            {
                                ICoordinate Coord = Hole[iPoint];
                                mwPoint   = new MapWinGIS.Point();
                                mwPoint.x = Coord.X;
                                mwPoint.y = Coord.Y;
                                mwShape.InsertPoint(mwPoint, ref rfPt);
                                rfPt++;
                            }
                        }
                    }
                }
            }

            #endregion

            #region -------------------------- MULTI POLYGON------------------------------------

            // The reason not to just Call Add Polygon recursively with this is that we only
            // want to test for unique holes once.  Doing so each and every time we add a polygon
            // would be a major inefficiency, plus the overhead from converting back and forth
            // to a shape object.

            if (geom.GetType() == typeof(MultiPolygon))
            {
                MultiPolygon MPG = geom as MultiPolygon;

                if (SpecifyShapeType == true)
                {
                    mwShape.ShapeType = MapWinGIS.ShpfileType.SHP_POLYGON;
                }

                if (mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGON ||
                    mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGONM ||
                    mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGONZ)
                {
                    // By doing this one time up here, we prevent a lot of duplication
                    List <ILinearRing> Holes = Holes = GetHoles(mwShape);

                    for (int iPolygon = 0; iPolygon < MPG.NumGeometries; iPolygon++)
                    {
                        Polygon newPolygon = MPG.Geometries[iPolygon] as Polygon;
                        mwShape.InsertPart(rfPt, ref rfPrt);
                        rfPrt++;
                        ILinearRing Shell = newPolygon.Shell;
                        for (int iPoint = 0; iPoint < Shell.NumPoints; iPoint++)
                        {
                            ICoordinate Coord = Shell.Coordinates[iPoint];
                            mwPoint   = new MapWinGIS.Point();
                            mwPoint.x = Coord.X;
                            mwPoint.y = Coord.Y;
                            mwShape.InsertPoint(mwPoint, ref rfPt);
                            rfPt++;
                        }

                        // The same hole may appear multiple times in overlapping polygons.
                        // Create a list of holes in order to test clockwise.
                        if (newPolygon.NumInteriorRings > 0)
                        {
                            List <ILinearRing> UniqueHoles = new List <ILinearRing>();


                            for (int iHole = 0; iHole < newPolygon.NumInteriorRings; iHole++)
                            {
                                for (int jHole = 0; jHole < Holes.Count; jHole++)
                                {
                                    if (newPolygon.Holes[iHole] == Holes[jHole])
                                    {
                                        continue;
                                    }
                                    // if we get here, the new hole is unique and should be added
                                    UniqueHoles.Add(newPolygon.Holes[iHole]);
                                    // Also add it to the list to compare against other future holes
                                    Holes.Add(newPolygon.Holes[iHole]); // Holes.Count is re-evaluated each time so this should be ok
                                }
                            }

                            for (int iHole = 0; iHole < UniqueHoles.Count; iHole++)
                            {
                                mwShape.InsertPart(rfPt, ref rfPrt);
                                rfPrt++;
                                ICoordinate[] Hole;
                                if (IsClockwise(UniqueHoles[iHole].Coordinates))
                                {
                                    // Holes should be counter clockwise
                                    Hole = UniqueHoles[iHole].Reverse().Coordinates;
                                }
                                else
                                {
                                    Hole = UniqueHoles[iHole].Coordinates;
                                }

                                int Count = Hole.GetUpperBound(0) + 1;
                                for (int iPoint = 0; iPoint < Count; iPoint++)
                                {
                                    ICoordinate Coord = Hole[iPoint];
                                    mwPoint   = new MapWinGIS.Point();
                                    mwPoint.x = Coord.X;
                                    mwPoint.y = Coord.Y;
                                    mwShape.InsertPoint(mwPoint, ref rfPt);
                                    rfPt++;
                                }
                            }
                        }
                    }
                }
            }

            #endregion
        }