예제 #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="ring"></param>
        /// <param name="clockwise"></param>
        private static void Normalize(ILinearRing ring, bool clockwise)
        {
            if (ring.IsEmpty)
            {
                return;
            }
            Coordinate[] uniqueCoordinates = new Coordinate[ring.Coordinates.Count - 1];
            for (int i = 0; i < uniqueCoordinates.Length; i++)
            {
                uniqueCoordinates[i] = ring.Coordinates[i];
            }
            Coordinate minCoordinate = CoordinateArrays.MinCoordinate(uniqueCoordinates);

            CoordinateArrays.Scroll(uniqueCoordinates, minCoordinate);
            List <Coordinate> result = new List <Coordinate>();

            for (int i = 0; i < uniqueCoordinates.Length; i++)
            {
                result.Add(ring.Coordinates[i]);
            }
            result.Add(uniqueCoordinates[0].Copy());
            ring.Coordinates = result;
            if (CgAlgorithms.IsCounterClockwise(ring.Coordinates) == clockwise)
            {
                ring.Coordinates.Reverse();
            }
        }
예제 #2
0
        private double GetArea(List <Coordinate> tempPolygon)
        {
            double area = Math.Abs(CgAlgorithms.SignedArea(tempPolygon));

            if (_previousParts == null || _previousParts.Count == 0)
            {
                _firstPartIsCounterClockwise = CgAlgorithms.IsCounterClockwise(tempPolygon);
            }
            else
            {
                if (CgAlgorithms.IsCounterClockwise(tempPolygon) != _firstPartIsCounterClockwise)
                {
                    area = -area;
                }
            }
            if (Map.Projection != null)
            {
                if (Map.Projection.IsLatLon)
                {
                    // this code really assumes the location is near the equator
                    const double RadiusOfEarth = 111319.5;
                    area *= RadiusOfEarth * RadiusOfEarth;
                }
                else
                {
                    area *= Map.Projection.Unit.Meters * Map.Projection.Unit.Meters;
                }
            }
            return(area);
        }
예제 #3
0
        /// <summary>
        /// The left and right topological location arguments assume that the ring is oriented CW.
        /// If the ring is in the opposite orientation,
        /// the left and right locations must be interchanged.
        /// </summary>
        /// <param name="lr"></param>
        /// <param name="cwLeft"></param>
        /// <param name="cwRight"></param>
        private void AddPolygonRing(IBasicGeometry lr, LocationType cwLeft, LocationType cwRight)
        {
            IList <Coordinate> coord = CoordinateArrays.RemoveRepeatedPoints(lr.Coordinates);

            if (coord.Count < 4)
            {
                _hasTooFewPoints = true;
                _invalidPoint    = coord[0];
                return;
            }
            LocationType left  = cwLeft;
            LocationType right = cwRight;

            if (CgAlgorithms.IsCounterClockwise(coord))
            {
                left  = cwRight;
                right = cwLeft;
            }
            Edge e = new Edge(coord, new Label(_argIndex, LocationType.Boundary, left, right));

            _lineEdgeMap.Add(lr, e);
            InsertEdge(e);
            // insert the endpoint as a node, to mark that it is on the boundary
            InsertPoint(_argIndex, coord[0], LocationType.Boundary);
        }
예제 #4
0
 /// <summary>
 /// Compute a LinearRing from the point list previously collected.
 /// Test if the ring is a hole (i.e. if it is CCW) and set the hole flag
 /// accordingly.
 /// </summary>
 public void ComputeRing()
 {
     if (_ring != null)
     {
         return;   // don't compute more than once
     }
     Coordinate[] coord = new Coordinate[_pts.Count];
     for (int i = 0; i < _pts.Count; i++)
     {
         coord[i] = (Coordinate)_pts[i];
     }
     _ring   = InnerGeometryFactory.CreateLinearRing(coord);
     _isHole = CgAlgorithms.IsCounterClockwise(_ring.Coordinates);
 }
예제 #5
0
        /// <summary>
        /// Add an offset curve for a ring.
        /// The side and left and right topological location arguments
        /// assume that the ring is oriented CW.
        /// If the ring is in the opposite orientation,
        /// the left and right locations must be interchanged and the side flipped.
        /// </summary>
        /// <param name="coord">The coordinates of the ring (must not contain repeated points).</param>
        /// <param name="offsetDistance">The distance at which to create the buffer.</param>
        /// <param name="side">The side of the ring on which to construct the buffer line.</param>
        /// <param name="cwLeftLoc">The location on the L side of the ring (if it is CW).</param>
        /// <param name="cwRightLoc">The location on the R side of the ring (if it is CW).</param>
        private void AddPolygonRing(IList <Coordinate> coord, double offsetDistance, PositionType side, LocationType cwLeftLoc, LocationType cwRightLoc)
        {
            LocationType leftLoc  = cwLeftLoc;
            LocationType rightLoc = cwRightLoc;

            if (CgAlgorithms.IsCounterClockwise(coord))
            {
                leftLoc  = cwRightLoc;
                rightLoc = cwLeftLoc;
                side     = Position.Opposite(side);
            }
            IList lineList = _curveBuilder.GetRingCurve(coord, side, offsetDistance);

            AddCurves(lineList, leftLoc, rightLoc);
        }
예제 #6
0
        /// <inheritdoc/>
        protected override void AppendBasicGeometry(ShapefileHeader header, IBasicGeometry feature, int numFeatures)
        {
            FileInfo fi     = new FileInfo(Filename);
            int      offset = Convert.ToInt32(fi.Length / 2);

            FileStream shpStream = new FileStream(Filename, FileMode.Append, FileAccess.Write, FileShare.None, 10000);
            FileStream shxStream = new FileStream(header.ShxFilename, FileMode.Append, FileAccess.Write, FileShare.None, 100);

            List <int> parts = new List <int>();

            List <Coordinate> points = new List <Coordinate>();
            int contentLength        = 22;

            for (int iPart = 0; iPart < feature.NumGeometries; iPart++)
            {
                parts.Add(points.Count);
                IBasicPolygon pg = feature.GetBasicGeometryN(iPart) as IBasicPolygon;
                if (pg == null)
                {
                    continue;
                }
                var bl     = pg.Shell;
                var coords = bl.Coordinates;

                if (CgAlgorithms.IsCounterClockwise(coords))
                {
                    // Exterior rings need to be clockwise
                    coords.Reverse();
                }

                points.AddRange(coords);
                foreach (IBasicLineString hole in pg.Holes)
                {
                    parts.Add(points.Count);
                    var holeCoords = hole.Coordinates;
                    if (CgAlgorithms.IsCounterClockwise(holeCoords) == false)
                    {
                        // Interior rings need to be counter-clockwise
                        holeCoords.Reverse();
                    }
                    points.AddRange(holeCoords);
                }
            }
            contentLength += 2 * parts.Count;
            if (header.ShapeType == ShapeType.Polygon)
            {
                contentLength += points.Count * 8;
            }
            if (header.ShapeType == ShapeType.PolygonM)
            {
                contentLength += 8;                 // mmin mmax
                contentLength += points.Count * 12; // x, y, m
            }
            if (header.ShapeType == ShapeType.PolygonZ)
            {
                contentLength += 16;                // mmin, mmax, zmin, zmax
                contentLength += points.Count * 16; // x, y, m, z
            }

            //                                              Index File
            //                                              ---------------------------------------------------------
            //                                              Position     Value               Type        Number      Byte Order
            //                                              ---------------------------------------------------------
            shxStream.WriteBe(offset);                      // Byte 0     Offset             Integer     1           Big
            shxStream.WriteBe(contentLength);               // Byte 4    Content Length      Integer     1           Big
            shxStream.Flush();
            shxStream.Close();
            //                                              X Y Poly Lines
            //                                              ---------------------------------------------------------
            //                                              Position     Value               Type        Number      Byte Order
            //                                              ---------------------------------------------------------
            shpStream.WriteBe(numFeatures);                 // Byte 0       Record Number       Integer     1           Big
            shpStream.WriteBe(contentLength);               // Byte 4       Content Length      Integer     1           Big
            shpStream.WriteLe((int)header.ShapeType);       // Byte 8       Shape Type 3        Integer     1           Little
            if (header.ShapeType == ShapeType.NullShape)
            {
                return;
            }

            shpStream.WriteLe(feature.Envelope.Minimum.X);             // Byte 12      Xmin                Double      1           Little
            shpStream.WriteLe(feature.Envelope.Minimum.Y);             // Byte 20      Ymin                Double      1           Little
            shpStream.WriteLe(feature.Envelope.Maximum.X);             // Byte 28      Xmax                Double      1           Little
            shpStream.WriteLe(feature.Envelope.Maximum.Y);             // Byte 36      Ymax                Double      1           Little
            shpStream.WriteLe(parts.Count);                            // Byte 44      NumParts            Integer     1           Little
            shpStream.WriteLe(points.Count);                           // Byte 48      NumPoints           Integer     1           Little
            // Byte 52      Parts               Integer     NumParts    Little
            foreach (int iPart in parts)
            {
                shpStream.WriteLe(iPart);
            }
            double[] xyVals = new double[points.Count * 2];

            int i = 0;

            foreach (Coordinate coord in points)
            {
                xyVals[i * 2]     = coord.X;
                xyVals[i * 2 + 1] = coord.Y;
                i++;
            }
            shpStream.WriteLe(xyVals, 0, 2 * points.Count);

            if (header.ShapeType == ShapeType.PolygonZ)
            {
                shpStream.WriteLe(feature.Envelope.Minimum.Z);
                shpStream.WriteLe(feature.Envelope.Maximum.Z);
                double[] zVals = new double[points.Count];
                for (int ipoint = 0; ipoint < points.Count; ipoint++)
                {
                    zVals[ipoint] = points[ipoint].Z;
                }
                shpStream.WriteLe(zVals, 0, points.Count);
            }

            if (header.ShapeType == ShapeType.PolygonM || header.ShapeType == ShapeType.PolygonZ)
            {
                if (feature.Envelope == null)
                {
                    shpStream.WriteLe(0.0);
                    shpStream.WriteLe(0.0);
                }
                else
                {
                    shpStream.WriteLe(feature.Envelope.Minimum.M);
                    shpStream.WriteLe(feature.Envelope.Maximum.M);
                }

                double[] mVals = new double[points.Count];
                for (int ipoint = 0; ipoint < points.Count; i++)
                {
                    mVals[ipoint] = points[ipoint].M;
                    ipoint++;
                }
                shpStream.WriteLe(mVals, 0, points.Count);
            }
            shpStream.Flush();
            shpStream.Close();
            offset += contentLength;
            Shapefile.WriteFileLength(Filename, offset);
            Shapefile.WriteFileLength(header.ShxFilename, 50 + numFeatures * 4);
        }
예제 #7
0
        private void ReadPolygonShape(Shape shape)
        {
            _envelope = shape.Range.Extent.ToEnvelope();
            List <ILinearRing> shells = new List <ILinearRing>();
            List <ILinearRing> holes  = new List <ILinearRing>();

            foreach (PartRange part in shape.Range.Parts)
            {
                List <Coordinate> coords = new List <Coordinate>();
                int i = part.StartIndex;
                foreach (Vertex d in part)
                {
                    Coordinate c = new Coordinate(d.X, d.Y);
                    if (shape.M != null && shape.M.Length > 0)
                    {
                        c.M = shape.M[i];
                    }
                    if (shape.Z != null && shape.Z.Length > 0)
                    {
                        c.Z = shape.Z[i];
                    }
                    i++;
                    coords.Add(c);
                }
                LinearRing ring = new LinearRing(coords);
                if (shape.Range.Parts.Count == 1)
                {
                    shells.Add(ring);
                }
                else
                {
                    if (CgAlgorithms.IsCounterClockwise(ring.Coordinates))
                    {
                        holes.Add(ring);
                    }
                    else
                    {
                        shells.Add(ring);
                    }
                    //if (part.IsHole())
                    //{
                    //    holes.Add(ring);
                    //}
                    //else
                    //{
                    //    shells.Add(ring);
                    //}
                }
            }
            if (shells.Count == 0 && holes.Count > 0)
            {
                shells = holes;
                holes  = new List <ILinearRing>();
            }
            //// Now we have a list of all shells and all holes
            List <ILinearRing>[] holesForShells = new List <ILinearRing> [shells.Count];
            for (int i = 0; i < shells.Count; i++)
            {
                holesForShells[i] = new List <ILinearRing>();
            }

            // Find holes
            for (int i = 0; i < holes.Count; i++)
            {
                ILinearRing testRing = holes[i];
                ILinearRing minShell = null;
                IEnvelope   minEnv   = null;
                IEnvelope   testEnv  = testRing.EnvelopeInternal;
                Coordinate  testPt   = testRing.Coordinates[0];
                ILinearRing tryRing;
                for (int j = 0; j < shells.Count; j++)
                {
                    tryRing = shells[j];
                    IEnvelope tryEnv = tryRing.EnvelopeInternal;
                    if (minShell != null)
                    {
                        minEnv = minShell.EnvelopeInternal;
                    }
                    bool isContained = false;

                    if (tryEnv.Contains(testEnv) &&
                        (CgAlgorithms.IsPointInRing(testPt, tryRing.Coordinates) ||
                         (PointInList(testPt, tryRing.Coordinates))))
                    {
                        isContained = true;
                    }

                    // Check if this new containing ring is smaller than the current minimum ring
                    if (isContained)
                    {
                        if (minShell == null || minEnv.Contains(tryEnv))
                        {
                            minShell = tryRing;
                        }
                        holesForShells[j].Add(holes[i]);
                    }
                }
            }

            var polygons = new Polygon[shells.Count];

            for (int i = 0; i < shells.Count; i++)
            {
                polygons[i] = new Polygon(shells[i], holesForShells[i].ToArray());
            }

            if (polygons.Length == 1)
            {
                _basicGeometry = polygons[0];
            }
            else
            {
                // It's a multi part
                _basicGeometry = new MultiPolygon(polygons);
            }
        }
예제 #8
0
        /// <summary>
        /// Saves the file to a new location
        /// </summary>
        /// <param name="fileName">The fileName to save</param>
        /// <param name="overwrite">Boolean that specifies whether or not to overwrite the existing file</param>
        public override void SaveAs(string fileName, bool overwrite)
        {
            if (IndexMode)
            {
                SaveAsIndexed(fileName, overwrite);
                return;
            }
            Filename = fileName;
            string dir = Path.GetDirectoryName(Path.GetFullPath(fileName));

            if (dir != null && !Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
            if (File.Exists(fileName))
            {
                if (fileName != Filename && overwrite == false)
                {
                    throw new IOException("File exists.");
                }
                File.Delete(fileName);
                string shx = Path.ChangeExtension(fileName, ".shx");
                if (File.Exists(shx))
                {
                    File.Delete(shx);
                }
            }
            InvalidateEnvelope();
            if (CoordinateType == CoordinateType.Regular)
            {
                Header.ShapeType = ShapeType.Polygon;
            }
            if (CoordinateType == CoordinateType.M)
            {
                Header.ShapeType = ShapeType.PolygonM;
            }
            if (CoordinateType == CoordinateType.Z)
            {
                Header.ShapeType = ShapeType.PolygonZ;
            }
            // Set ShapeType before setting extent.
            Header.SetExtent(Extent);
            Header.ShxLength = Features.Count * 4 + 50;
            Header.SaveAs(fileName);

            BufferedBinaryWriter bbWriter    = new BufferedBinaryWriter(fileName);
            BufferedBinaryWriter indexWriter = new BufferedBinaryWriter(Header.ShxFilename);
            int fid           = 0;
            int offset        = 50; // the shapefile header starts at 100 bytes, so the initial offset is 50 words
            int contentLength = 0;

            foreach (IFeature f in Features)
            {
                List <int> parts = new List <int>();

                offset += contentLength; // adding the previous content length from each loop calculates the word offset
                List <Coordinate> points = new List <Coordinate>();
                contentLength = 22;
                for (int iPart = 0; iPart < f.NumGeometries; iPart++)
                {
                    parts.Add(points.Count);
                    IBasicPolygon pg = f.GetBasicGeometryN(iPart) as IBasicPolygon;
                    if (pg == null)
                    {
                        continue;
                    }
                    IBasicLineString   bl     = pg.Shell;
                    IList <Coordinate> coords = bl.Coordinates;

                    if (CgAlgorithms.IsCounterClockwise(coords))
                    {
                        // Exterior rings need to be clockwise
                        coords.Reverse();
                    }

                    foreach (Coordinate coord in coords)
                    {
                        points.Add(coord);
                    }
                    foreach (IBasicLineString hole in pg.Holes)
                    {
                        parts.Add(points.Count);
                        IList <Coordinate> holeCoords = hole.Coordinates;
                        if (CgAlgorithms.IsCounterClockwise(holeCoords) == false)
                        {
                            // Interior rings need to be counter-clockwise
                            holeCoords.Reverse();
                        }
                        foreach (Coordinate coord in holeCoords)
                        {
                            points.Add(coord);
                        }
                    }
                }
                contentLength += 2 * parts.Count;
                if (Header.ShapeType == ShapeType.Polygon)
                {
                    contentLength += points.Count * 8;
                }
                if (Header.ShapeType == ShapeType.PolygonM)
                {
                    contentLength += 8;                 // mmin mmax
                    contentLength += points.Count * 12; // x, y, m
                }
                if (Header.ShapeType == ShapeType.PolygonZ)
                {
                    contentLength += 16;                // mmin, mmax, zmin, zmax
                    contentLength += points.Count * 16; // x, y, m, z
                }

                //                                              Index File
                //                                              ---------------------------------------------------------
                //                                              Position     Value               Type        Number      Byte Order
                //                                              ---------------------------------------------------------
                indexWriter.Write(offset, false);               // Byte 0     Offset             Integer     1           Big
                indexWriter.Write(contentLength, false);        // Byte 4    Content Length      Integer     1           Big

                //                                              X Y Poly Lines
                //                                              ---------------------------------------------------------
                //                                              Position     Value               Type        Number      Byte Order
                //                                              ---------------------------------------------------------
                bbWriter.Write(fid + 1, false);              // Byte 0       Record Number       Integer     1           Big
                bbWriter.Write(contentLength, false);        // Byte 4       Content Length      Integer     1           Big
                bbWriter.Write((int)Header.ShapeType);       // Byte 8       Shape Type 3        Integer     1           Little
                if (Header.ShapeType == ShapeType.NullShape)
                {
                    continue;
                }

                bbWriter.Write(f.Envelope.Minimum.X);        // Byte 12      Xmin                Double      1           Little
                bbWriter.Write(f.Envelope.Minimum.Y);        // Byte 20      Ymin                Double      1           Little
                bbWriter.Write(f.Envelope.Maximum.X);        // Byte 28      Xmax                Double      1           Little
                bbWriter.Write(f.Envelope.Maximum.Y);        // Byte 36      Ymax                Double      1           Little
                bbWriter.Write(parts.Count);                 // Byte 44      NumParts            Integer     1           Little
                bbWriter.Write(points.Count);                // Byte 48      NumPoints           Integer     1           Little
                // Byte 52      Parts               Integer     NumParts    Little
                foreach (int iPart in parts)
                {
                    bbWriter.Write(iPart);
                }
                double[] xyVals = new double[points.Count * 2];

                int i = 0;

                // Byte X       Points              Point       NumPoints   Little
                foreach (Coordinate coord in points)
                {
                    xyVals[i * 2]     = coord.X;
                    xyVals[i * 2 + 1] = coord.Y;
                    i++;
                }
                bbWriter.Write(xyVals);

                if (Header.ShapeType == ShapeType.PolygonZ)
                {
                    bbWriter.Write(f.Envelope.Minimum.Z);
                    bbWriter.Write(f.Envelope.Maximum.Z);
                    double[] zVals = new double[points.Count];
                    for (int ipoint = 0; ipoint < points.Count; i++)
                    {
                        zVals[ipoint] = points[ipoint].Z;
                        ipoint++;
                    }
                    bbWriter.Write(zVals);
                }

                if (Header.ShapeType == ShapeType.PolygonM || Header.ShapeType == ShapeType.PolygonZ)
                {
                    if (f.Envelope == null)
                    {
                        bbWriter.Write(0.0);
                        bbWriter.Write(0.0);
                    }
                    else
                    {
                        bbWriter.Write(f.Envelope.Minimum.M);
                        bbWriter.Write(f.Envelope.Maximum.M);
                    }

                    double[] mVals = new double[points.Count];
                    for (int ipoint = 0; ipoint < points.Count; i++)
                    {
                        mVals[ipoint] = points[ipoint].M;
                        ipoint++;
                    }
                    bbWriter.Write(mVals);
                }

                fid++;
                offset += 4; // header bytes
            }

            bbWriter.Close();
            indexWriter.Close();

            offset += contentLength;
            //offset += 4;
            WriteFileLength(fileName, offset);
            WriteFileLength(Header.ShxFilename, 50 + fid * 4);
            UpdateAttributes();
            SaveProjection();
        }
예제 #9
0
        private IGeometry ReadPolygon()
        {
            ShapefileGeometryType type = (ShapefileGeometryType)_reader.ReadInt32();

            if (type == ShapefileGeometryType.NullShape)
            {
                return(_gf.CreatePolygon(null, null));
            }

            if (type != ShapefileGeometryType.Polygon && type != ShapefileGeometryType.PolygonZ)
            {
                throw new Exception("Attempting to load a non-polygon as polygon.");
            }

            // Read the box
            double xMin = _reader.ReadDouble(), yMin = _reader.ReadDouble();

            ShapeEnvelope.Init(xMin, _reader.ReadDouble(),
                               yMin, _reader.ReadDouble());

            // Read poly header
            int numParts  = _reader.ReadInt32();
            int numPoints = _reader.ReadInt32();

            // Read parts array
            int[] partOffsets = new int[numParts];
            for (int i = 0; i < numParts; i++)
            {
                partOffsets[i] = _reader.ReadInt32();
            }

            // Read the parts and their points
            List <ILinearRing> shells = new List <ILinearRing>();
            List <ILinearRing> holes  = new List <ILinearRing>();

            Coordinate[] allCoords = new Coordinate[numPoints];
            for (int part = 0, last = numParts - 1, x = 0; part < numParts; part++)
            {
                int          start = partOffsets[part], stop = (part == last ? numPoints : partOffsets[part + 1]);
                Coordinate[] coords = new Coordinate[stop - start];

                for (int i = 0; i < coords.Length; i++)
                {
                    coords[i] = allCoords[x++] = new Coordinate(
                        _reader.ReadDouble(),
                        _reader.ReadDouble());
                }

                ILinearRing ring = _gf.CreateLinearRing(coords);

                // Check for hole.
                if (CgAlgorithms.IsCounterClockwise(coords))
                {
                    holes.Add(ring);
                }
                else
                {
                    shells.Add(ring);
                }
            }

            if (type == ShapefileGeometryType.PolygonZ)
            {
                // z min/max
                _reader.ReadDouble();
                _reader.ReadDouble();

                for (int i = 0; i < allCoords.Length; i++)
                {
                    allCoords[i].Z = _reader.ReadDouble();
                }

                // m min/max
                _reader.ReadDouble();
                _reader.ReadDouble();
                for (int i = 0; i < allCoords.Length; i++)
                {
                    allCoords[i].M = _reader.ReadDouble();
                }
            }

            // Create the polygon
            if (shells.Count == 1)
            {
                return(_gf.CreatePolygon(shells[0], holes.ToArray()));
            }
            else // Create a multipolygon
            {
                List <IPolygon> polys = new List <IPolygon>(shells.Count);
                foreach (ILinearRing shell in shells)
                {
                    IEnvelope          shellEnv   = shell.EnvelopeInternal;
                    List <ILinearRing> shellHoles = new List <ILinearRing>();
                    for (int i = holes.Count - 1; i >= 0; i--)
                    {
                        ILinearRing hole = holes[i];
                        if (shellEnv.Contains(hole.EnvelopeInternal))
                        {
                            shellHoles.Add(hole);
                            holes.RemoveAt(i);
                        }
                    }

                    polys.Add(_gf.CreatePolygon(shell, shellHoles.ToArray()));
                }

                // Add the holes that weren't contains as shells
                foreach (ILinearRing hole in holes)
                {
                    LinearRing ring = new LinearRing(hole.Reverse());
                    polys.Add(_gf.CreatePolygon(ring, null));
                }

                return(_gf.CreateMultiPolygon(polys.ToArray()));
            }
        }
예제 #10
0
        /// <summary>
        /// Creates a Polygon or MultiPolygon from this Polygon shape.
        /// </summary>
        /// <param name="factory">The IGeometryFactory to use to create the new IGeometry.</param>
        /// <returns>The IPolygon or IMultiPolygon created from this shape.</returns>
        protected IGeometry FromPolygon(IGeometryFactory factory)
        {
            if (factory == null)
            {
                factory = Geometry.DefaultFactory;
            }
            List <ILinearRing> shells = new List <ILinearRing>();
            List <ILinearRing> holes  = new List <ILinearRing>();

            foreach (PartRange part in _shapeRange.Parts)
            {
                List <Coordinate> coords = new List <Coordinate>();
                int i = part.StartIndex;
                foreach (Vertex d in part)
                {
                    Coordinate c = new Coordinate(d.X, d.Y);
                    if (M != null && M.Length > 0)
                    {
                        c.M = M[i];
                    }
                    if (Z != null && Z.Length > 0)
                    {
                        c.Z = Z[i];
                    }
                    i++;
                    coords.Add(c);
                }
                ILinearRing ring = factory.CreateLinearRing(coords);
                if (_shapeRange.Parts.Count == 1)
                {
                    shells.Add(ring);
                }
                else
                {
                    if (CgAlgorithms.IsCounterClockwise(ring.Coordinates))
                    {
                        holes.Add(ring);
                    }
                    else
                    {
                        shells.Add(ring);
                    }
                }
            }
            //// Now we have a list of all shells and all holes
            List <ILinearRing>[] holesForShells = new List <ILinearRing> [shells.Count];
            for (int i = 0; i < shells.Count; i++)
            {
                holesForShells[i] = new List <ILinearRing>();
            }

            // Find holes
            foreach (ILinearRing t in holes)
            {
                ILinearRing testRing = t;
                ILinearRing minShell = null;
                IEnvelope   minEnv   = null;
                IEnvelope   testEnv  = testRing.EnvelopeInternal;
                Coordinate  testPt   = testRing.Coordinates[0];
                ILinearRing tryRing;
                for (int j = 0; j < shells.Count; j++)
                {
                    tryRing = shells[j];
                    IEnvelope tryEnv = tryRing.EnvelopeInternal;
                    if (minShell != null)
                    {
                        minEnv = minShell.EnvelopeInternal;
                    }
                    bool isContained = false;

                    if (tryEnv.Contains(testEnv) &&
                        (CgAlgorithms.IsPointInRing(testPt, tryRing.Coordinates) ||
                         (PointInList(testPt, tryRing.Coordinates))))
                    {
                        isContained = true;
                    }

                    // Check if this new containing ring is smaller than the current minimum ring
                    if (isContained)
                    {
                        if (minShell == null || minEnv.Contains(tryEnv))
                        {
                            minShell = tryRing;
                        }
                        holesForShells[j].Add(t);
                    }
                }
            }

            IPolygon[] polygons = new Polygon[shells.Count];
            for (int i = 0; i < shells.Count; i++)
            {
                polygons[i] = factory.CreatePolygon(shells[i], holesForShells[i].ToArray());
            }

            if (polygons.Length == 1)
            {
                return(polygons[0]);
            }
            // It's a multi part
            return(factory.CreateMultiPolygon(polygons));
        }
예제 #11
0
        /// <summary>
        /// Creates a Polygon or MultiPolygon from this Polygon shape.
        /// </summary>
        /// <param name="factory">The IGeometryFactory to use to create the new IGeometry.</param>
        /// <returns>The IPolygon or IMultiPolygon created from this shape.</returns>
        protected IGeometry FromPolygon(IGeometryFactory factory)
        {
            if (factory == null)
            {
                factory = Geometry.DefaultFactory;
            }
            List <ILinearRing> shells = new List <ILinearRing>();
            List <ILinearRing> holes  = new List <ILinearRing>();

            foreach (var part in _shapeRange.Parts)
            {
                var coords = GetCoordinates(part);
                var ring   = factory.CreateLinearRing(coords);
                if (_shapeRange.Parts.Count == 1)
                {
                    shells.Add(ring);
                }
                else
                {
                    if (CgAlgorithms.IsCounterClockwise(ring.Coordinates))
                    {
                        holes.Add(ring);
                    }
                    else
                    {
                        shells.Add(ring);
                    }
                }
            }
            //// Now we have a list of all shells and all holes
            List <ILinearRing>[] holesForShells = new List <ILinearRing> [shells.Count];
            for (int i = 0; i < shells.Count; i++)
            {
                holesForShells[i] = new List <ILinearRing>();
            }

            // Find holes
            foreach (ILinearRing t in holes)
            {
                ILinearRing testRing = t;
                ILinearRing minShell = null;
                IEnvelope   minEnv   = null;
                IEnvelope   testEnv  = testRing.EnvelopeInternal;
                Coordinate  testPt   = testRing.Coordinates[0];
                for (int j = 0; j < shells.Count; j++)
                {
                    ILinearRing tryRing = shells[j];
                    IEnvelope   tryEnv  = tryRing.EnvelopeInternal;
                    if (minShell != null)
                    {
                        minEnv = minShell.EnvelopeInternal;
                    }
                    var isContained = tryEnv.Contains(testEnv) &&
                                      (CgAlgorithms.IsPointInRing(testPt, tryRing.Coordinates) ||
                                       (PointInList(testPt, tryRing.Coordinates)));

                    // Check if this new containing ring is smaller than the current minimum ring
                    if (isContained)
                    {
                        if (minShell == null || minEnv.Contains(tryEnv))
                        {
                            minShell = tryRing;
                        }
                        holesForShells[j].Add(t);
                    }
                }
            }

            var polygons = new IPolygon[shells.Count];

            for (int i = 0; i < shells.Count; i++)
            {
                polygons[i] = factory.CreatePolygon(shells[i], holesForShells[i].ToArray());
            }

            if (polygons.Length == 1)
            {
                return(polygons[0]);
            }
            // It's a multi part
            return(factory.CreateMultiPolygon(polygons));
        }