private IPolygon GetResult()
            {
                IGeometryFactory  gf        = _poly.Factory;
                ILinearRing       shell     = (ILinearRing)_poly.ExteriorRing;
                IPreparedGeometry shellPrep = PreparedGeometryFactory.Prepare(gf.CreatePolygon(shell));

                IList <IGeometry> holes = new List <IGeometry>();

                for (int i = 0; i < _poly.NumInteriorRings; i++)
                {
                    IGeometry hole = _poly.GetInteriorRingN(i);
                    if (shellPrep.Covers(hole))
                    {
                        holes.Add(hole);
                    }
                }
                // all holes valid, so return original
                if (holes.Count == _poly.NumInteriorRings)
                {
                    return(_poly);
                }

                // return new polygon with covered holes only
                ILinearRing[] arr    = GeometryFactory.ToLinearRingArray(holes);
                IPolygon      result = gf.CreatePolygon(shell, arr);

                return(result);
            }
        /// <summary>
        /// Converts the GML element to polygon.
        /// </summary>
        /// <param name="element">The GML element of the polygon.</param>
        /// <param name="factory">The geometry factory.</param>
        /// <returns>The converted polygon.</returns>
        private static IPolygon ToPolygon(XElement element, IGeometryFactory factory)
        {
            if (element.Elements() == null)
            {
                return(factory.CreatePolygon(new Coordinate[0]));
            }

            ILinearRing        shell = null;
            List <ILinearRing> holes = new List <ILinearRing>();

            foreach (XElement innerElement in element.Elements())
            {
                switch (innerElement.Name.LocalName)
                {
                case "outerBoundaryIs":
                    shell = ToLinearRing(innerElement.Elements().FirstOrDefault(), factory);
                    break;

                case "innerBoundaryIs":
                    holes.Add(ToLinearRing(innerElement.Elements().FirstOrDefault(), factory));
                    break;
                }
            }

            return(factory.CreatePolygon(shell, holes));
        }
        /// <summary>
        /// Computes the <see cref="IMultiPolygon" /> representation of the WKB.
        /// </summary>
        /// <param name="geometryBytes">The WKB representation of the geometry.</param>
        /// <param name="byteOrder">The byte-order of the conversion.</param>
        /// <param name="geometryModel">The geometry model of the conversion.</param>
        /// <param name="factory">The factory used for geometry production.</param>
        /// <returns>The <see cref="IMultiPolygon" /> representation of the geometry.</returns>
        private static IMultiPolygon ComputeMultiPolygon(Byte[] geometryBytes, ByteOrder byteOrder, GeometryModel geometryModel, IGeometryFactory factory)
        {
            Int32 coordinateSize = (geometryModel == GeometryModel.Spatial3D) ? 24 : 16;
            Int32 polygonCount   = EndianBitConverter.ToInt32(geometryBytes, 5, byteOrder);

            IPolygon[] polygons = new Polygon[polygonCount];

            Int32 startIndex = 9;

            for (Int32 i = 0; i < polygonCount; i++)
            {
                Int32 ringCount            = EndianBitConverter.ToInt32(geometryBytes, startIndex, byteOrder);
                Int32 shellCoordinateCount = EndianBitConverter.ToInt32(geometryBytes, startIndex + 4, byteOrder);

                startIndex += 8;

                Coordinate[] shellCoordinates = new Coordinate[shellCoordinateCount];

                for (Int32 byteIndex = startIndex, coordinateIndex = 0; coordinateIndex < shellCoordinateCount; byteIndex += coordinateSize, coordinateIndex++)
                {
                    shellCoordinates[coordinateIndex] = new Coordinate(EndianBitConverter.ToDouble(geometryBytes, byteIndex, byteOrder),
                                                                       EndianBitConverter.ToDouble(geometryBytes, byteIndex + 8, byteOrder),
                                                                       geometryModel == GeometryModel.Spatial3D ? EndianBitConverter.ToDouble(geometryBytes, byteIndex + 16, byteOrder) : 0);
                }
                startIndex += shellCoordinateCount * coordinateSize;

                if (ringCount > 1)
                {
                    Coordinate[][] holes = new Coordinate[ringCount - 1][];

                    for (Int32 j = 1; j < ringCount; j++)
                    {
                        Int32 holeCoordianteCount = EndianBitConverter.ToInt32(geometryBytes, startIndex, byteOrder);
                        startIndex += 4;

                        Coordinate[] holeCoordinates = new Coordinate[holeCoordianteCount];

                        for (Int32 byteIndex = startIndex, coordinateIndex = 0; coordinateIndex < holeCoordianteCount; byteIndex += coordinateSize, coordinateIndex++)
                        {
                            holeCoordinates[coordinateIndex] = new Coordinate(EndianBitConverter.ToDouble(geometryBytes, byteIndex, byteOrder),
                                                                              EndianBitConverter.ToDouble(geometryBytes, byteIndex + 8, byteOrder),
                                                                              geometryModel == GeometryModel.Spatial3D ? EndianBitConverter.ToDouble(geometryBytes, byteIndex + 16, byteOrder) : 0);
                        }

                        holes[j - 1] = holeCoordinates;

                        startIndex += holeCoordianteCount * coordinateSize;
                    }

                    polygons[i] = factory.CreatePolygon(shellCoordinates, holes);
                }
                else
                {
                    polygons[i] = factory.CreatePolygon(shellCoordinates);
                }
            }

            return(factory.CreateMultiPolygon(polygons));
        }
Exemple #4
0
        private static IGeometry ToSharpMapMultiPolygon(EsriShapeBuffer shapeBuffer)
        {
            if (shapeBuffer == null)
            {
                return(null);
            }

            var multiPartShapeBuffer = shapeBuffer as EsriMultiPartShapeBuffer;

            if (multiPartShapeBuffer == null)
            {
                Envelope box;
                return(FromShapeFilePolygon(shapeBuffer, out box));
            }

            var hasZ = EsriShapeBuffer.HasZs(shapeBuffer.shapeType);
            IList <IPolygon> polygons = new List <IPolygon>();
            //IPolygon poly = null;
            ILinearRing         shell = null;
            IList <ILinearRing> holes = new List <ILinearRing>();
            var offset = 0;

            for (var i = 0; i < multiPartShapeBuffer.NumParts; i++)
            {
                var vertices = new List <Coordinate>(multiPartShapeBuffer.Parts[i]);
                for (var j = 0; j < multiPartShapeBuffer.Parts[i]; j++)
                {
                    var index = offset + j;
                    var point = multiPartShapeBuffer.Points[index];
                    vertices.Add(hasZ
                        ? new Coordinate(point.x, point.y, multiPartShapeBuffer.Zs[index])
                        : new Coordinate(point.x, point.y));
                }

                var ring = geometryFactory.CreateLinearRing(vertices.ToArray());
                if (shell == null || !ring.IsCCW())
                {
                    shell = ring;
                    //poly = new Polygon(ring);
                    //polygons.Add(poly);
                }
                else
                {
                    holes.Add(ring);
                    //poly.InteriorRings.Add(ring);
                }

                offset += multiPartShapeBuffer.Parts[i];

                polygons.Add(geometryFactory.CreatePolygon(shell, holes.ToArray()));
            }

            if (polygons.Count == 1)
            {
                return(polygons[0]);
            }

            return(new MultiPolygon(polygons.ToArray()));
        }
        private IGeometry BuildPolygon()
        {
            if (_rings.Count == 0)
            {
                return(_factory.CreatePolygon(null, null));
            }
            var shell = _factory.CreateLinearRing(_rings[0]);
            var holes = _rings.GetRange(1, _rings.Count - 1)
                        .ConvertAll(coordinates => _factory.CreateLinearRing(coordinates)).ToArray();

            _rings.Clear();
            return(_factory.CreatePolygon(shell, holes));
        }
        public void TestWritePolygon()
        {
            Coordinate[] coordinates =
            {
                new Coordinate(10, 10, 0),
                new Coordinate(10, 20, 0),
                new Coordinate(20, 20, 0),
                new Coordinate(20, 15, 0),
                new Coordinate(10, 10, 0)
            };
            var linearRing = _factory.CreateLinearRing(coordinates);
            var polygon    = _factory.CreatePolygon(linearRing, new LinearRing[] { });

            Assert.AreEqual("POLYGON ((10 10, 10 20, 20 20, 20 15, 10 10))", _writer.Write(polygon));
        }
Exemple #7
0
        /// <summary>
        /// Function to read a either a <see cref="IPolygon"/> or an <see cref="IMultiPolygon"/> from a ShapeFile stream using the specified <paramref name="reader"/>.
        /// </summary>
        /// <param name="reader">The reader to use</param>
        /// <param name="ordinates">The ordinates to read</param>
        /// <returns>The read polygonal geometry</returns>
        protected IGeometry ReadPolygon(BinaryReader reader, Ordinates ordinates)
        {
            /*var bbox = */ ReadBoundingBox(reader); // jump boundingbox

            var numParts = ReadNumParts(reader);
            var numPoints = ReadNumPoints(reader);
            var indexParts = ReadIndexParts(reader, numParts, numPoints);

            var buffer = new CoordinateBuffer(numPoints, ShapeFileConstants.NoDataBorder, true);
            ReadCoordinates(reader, numPoints, indexParts, ordinates, buffer);

            return numParts == 1
                ? _factory.CreatePolygon(_factory.CreateLinearRing(buffer.ToSequence()), null)
                : CreateSingleOrMultiPolygon(buffer);
        }
        private static IPolygon CreateComb(Envelope env, int nArms, IGeometryFactory geomFact)
        {
            int    npts     = 4 * (nArms - 1) + 2 + 2 + 1;
            var    pts      = new Coordinate[npts];
            double armWidth = env.Width / (2 * nArms - 1);
            double armLen   = env.Height - armWidth;

            double xBase = env.MinX;
            double yBase = env.MinY;

            int ipts = 0;

            for (int i = 0; i < nArms; i++)
            {
                double x1 = xBase + i * 2 * armWidth;
                double y1 = yBase + armLen + armWidth;
                pts[ipts++] = new Coordinate(x1, y1);
                pts[ipts++] = new Coordinate(x1 + armWidth, y1);
                if (i < nArms - 1)
                {
                    pts[ipts++] = new Coordinate(x1 + armWidth, yBase + armWidth);
                    pts[ipts++] = new Coordinate(x1 + 2 * armWidth, yBase + armWidth);
                }
            }
            pts[ipts++] = new Coordinate(env.MaxX, yBase);
            pts[ipts++] = new Coordinate(xBase, yBase);
            pts[ipts++] = new Coordinate(pts[0]);

            return(geomFact.CreatePolygon(pts));
        }
            public IPolygon GetResult()
            {
                IGeometryFactory gf = _poly.Factory;

                IList <IGeometry> holes = new List <IGeometry>();

                for (int i = 0; i < _poly.NumInteriorRings; i++)
                {
                    ILinearRing hole = (ILinearRing)_poly.GetInteriorRingN(i);
                    if (!_predicate.Value(hole))
                    {
                        holes.Add(hole);
                    }
                }
                // all holes valid, so return original
                if (holes.Count == _poly.NumInteriorRings)
                {
                    return(_poly);
                }

                // return new polygon with covered holes only
                ILinearRing shell = (ILinearRing)_poly.ExteriorRing;

                ILinearRing[] rings  = GeometryFactory.ToLinearRingArray(holes);
                IPolygon      result = gf.CreatePolygon(shell, rings);

                return(result);
            }
Exemple #10
0
        /// <summary>
        /// Gets the computed variable-width line buffer.
        /// </summary>
        /// <returns>A polygon</returns>
        public IGeometry GetResult()
        {
            Utilities.Assert.IsTrue(_line.NumPoints == _width.Length);

            var parts = new List <IGeometry>();

            var pts = _line.Coordinates;

            for (var i = 0; i < _line.NumPoints; i++)
            {
                var dist  = _width[i] / 2;
                var ptBuf = _line.GetPointN(i).Buffer(dist);
                parts.Add(ptBuf);

                if (i >= 1)
                {
                    var curvePts = GenerateSegmentCurve(pts[i - 1], pts[i],
                                                        _width[i - 1], _width[i]);
                    var segBuf = _geomFactory.CreatePolygon(curvePts);
                    parts.Add(segBuf);
                }
            }

            var partsGeom = _geomFactory.CreateGeometryCollection(GeometryFactory.ToGeometryArray(parts));
            var buffer    = partsGeom.Union();

            return(buffer);
        }
        // see: https://github.com/NetTopologySuite/NetTopologySuite/issues/111
        public void issue_111_polygonhandler_with_invalid_values()
        {
            IGeometryFactory factory = GeometryFactory.Default;

            Coordinate[] points = new Coordinate[5];
            points[0] = new Coordinate(0, 0);
            points[1] = new Coordinate(1, 0);
            points[2] = new Coordinate(1, 1);
            points[3] = new Coordinate(0, 1);
            points[4] = new Coordinate(0, 0);
            IPolygon poly = factory.CreatePolygon(points);

            IMultiPolygon mpoly = factory.CreateMultiPolygon(new[] { poly });

            IGeometry[]         arr        = new[] { mpoly, GeometryCollection.Empty };
            IGeometryCollection geometries = factory.CreateGeometryCollection(arr);

            ShapeGeometryType shapeType = Shapefile.GetShapeType(geometries);

            Assert.AreEqual(ShapeGeometryType.PolygonZM, shapeType);

            string          tempPath = Path.GetTempFileName();
            ShapefileWriter sfw      = new ShapefileWriter(Path.GetFileNameWithoutExtension(tempPath), shapeType);

            sfw.Write(geometries);
        }
Exemple #12
0
        /// <summary>
        /// Reads the <see cref="IPolygon" /> representation of the GM.
        /// </summary>
        /// <param name="node">The GM representation of the geometry.</param>
        /// <param name="factory">The factory used for geometry production.</param>
        /// <returns>The <see cref="IPolygon" /> representation of the geometry.</returns>
        private static IPolygon ReadPolygon(IEnumerable <XElement> node, IGeometryFactory factory)
        {
            IList <Coordinate>         shellCoordinates;
            List <IList <Coordinate> > holeCoordinates = new List <IList <Coordinate> >();

            XElement shellNode = node.FirstOrDefault(n => n.Name.LocalName == "outerBoundaryIs");

            if (shellNode == null)
            {
                throw new ArgumentException("The polygon geometry has no outer boundary", "node");
            }

            XElement linearRingNode = shellNode.Elements().First();

            shellCoordinates = ReadLinearRing(linearRingNode.Elements(), factory).Coordinates;

            if (node.Any(r => r.Name.LocalName == "innerBoundaryIs"))
            {
                foreach (XElement boundaryNode in node.Where(n => n.Name.LocalName == "innerBoundaryIs"))
                {
                    linearRingNode = boundaryNode.Elements().FirstOrDefault();

                    if (linearRingNode == null)
                    {
                        throw new ArgumentException("The polygon geometry's inner boundary has no linearrings", "node");
                    }

                    holeCoordinates.Add(ReadLinearRing(linearRingNode.Elements(), factory).Coordinates);
                }
            }

            return(factory.CreatePolygon(shellCoordinates, holeCoordinates));
        }
        /// <summary>
        /// Gets the Voronoi cell around a site specified
        /// by the origin of a QuadEdge.
        /// </summary>
        /// <remarks>
        /// The userData of the polygon is set to be the <see cref="Coordinate" />
        /// of the site.  This allows attaching external
        /// data associated with the site to this cell polygon.
        /// </remarks>
        /// <param name="qe">a quadedge originating at the cell site</param>
        /// <param name="geomFact">a factory for building the polygon</param>
        /// <returns>a polygon indicating the cell extent</returns>
        public IPolygon GetVoronoiCellPolygon(QuadEdge qe, IGeometryFactory geomFact)
        {
            var      cellPts = new List <Coordinate>();
            QuadEdge startQE = qe;

            do
            {
                // Coordinate cc = circumcentre(qe);
                // use previously computed circumcentre
                Coordinate cc = qe.Rot.Orig.Coordinate;
                cellPts.Add(cc);

                // move to next triangle CW around vertex
                qe = qe.OPrev;
            } while (qe != startQE);

            var coordList = new CoordinateList();

            coordList.AddAll(cellPts, false);
            coordList.CloseRing();

            if (coordList.Count < 4)
            {
                Console.WriteLine(coordList);
                coordList.Add(coordList[coordList.Count - 1], true);
            }

            Coordinate[] pts      = coordList.ToCoordinateArray();
            IPolygon     cellPoly = geomFact.CreatePolygon(geomFact.CreateLinearRing(pts), null);

            Vertex v = startQE.Orig;

            cellPoly.UserData = v.Coordinate;
            return(cellPoly);
        }
Exemple #14
0
        private static void generatePolygons(IGeometryFactory geometryFactory,
                                             ICollection <IGeometry> geometry,
                                             Random rndGen)
        {
            ICoordinateSequenceFactory coordinateSequenceFactory =
                geometryFactory.CoordinateSequenceFactory;
            ICoordinateFactory  coordinateFactory = geometryFactory.CoordinateFactory;
            ICoordinateSequence coords            = coordinateSequenceFactory.Create(CoordinateDimensions.Two);

            Int32 polyCount = rndGen.Next(10, 100);

            for (Int32 polyIndex = 0; polyIndex < polyCount; polyIndex++)
            {
                ICoordinate upperLeft = coordinateFactory.Create(rndGen.NextDouble() * 1000,
                                                                 rndGen.NextDouble() * 1000);

                Double sideLength = rndGen.NextDouble() * 50;

                // Make a square
                coords.Add(upperLeft);
                coords.Add(coordinateFactory.Create(upperLeft[Ordinates.X] + sideLength,
                                                    upperLeft[Ordinates.Y]));
                coords.Add(coordinateFactory.Create(upperLeft[Ordinates.X] + sideLength,
                                                    upperLeft[Ordinates.Y] - sideLength));
                coords.Add(coordinateFactory.Create(upperLeft[Ordinates.X],
                                                    upperLeft[Ordinates.Y] - sideLength));

                IPolygon polygon = geometryFactory.CreatePolygon(coords);
                geometry.Add(polygon);
            }
        }
Exemple #15
0
        ///<summary>
        /// Converts a flat path to a <see cref="IGeometry"/>.
        ///</summary>
        /// <param name="pathIt">The path iterator of the path to convert</param>
        /// <returns>A Geometry representing the path</returns>
        public IGeometry Read(WpfGeometry pathIt)
        {
            var pathPtSeq = ToCoordinates(pathIt);

            var polys    = new List <IGeometry>();
            var seqIndex = 0;

            while (seqIndex < pathPtSeq.Count)
            {
                // assume next seq is shell
                // TODO: test this
                var pts   = pathPtSeq[seqIndex];
                var shell = _geometryFactory.CreateLinearRing(pts);
                seqIndex++;

                var          holes = new List <ILinearRing>();
                Coordinate[] holePts;
                // add holes as long as rings are CCW
                while (seqIndex < pathPtSeq.Count && IsHole(holePts = pathPtSeq[seqIndex]))
                {
                    var hole = _geometryFactory.CreateLinearRing(holePts);
                    holes.Add(hole);
                    seqIndex++;
                }
                var holeArray = holes.ToArray();//GeometryFactory.ToLinearRingArray(holes);
                polys.Add(_geometryFactory.CreatePolygon(shell, holeArray));
            }
            return(_geometryFactory.BuildGeometry(polys));
        }
Exemple #16
0
        public IEnumerable <IGeometry> CreateTestGeometries(int count, double minx, double miny, double maxx, double maxy)
        {
            double xrange = Math.Abs(maxx - minx);
            double yrange = Math.Abs(maxy - miny);

            for (int i = 0; i < count; i++)
            {
                double x1 = _rnd.NextDouble() * xrange + minx;
                double x2 = _rnd.NextDouble() * xrange + minx;
                double y1 = _rnd.NextDouble() * yrange + miny;
                double y2 = _rnd.NextDouble() * yrange + miny;

                double lrx  = Math.Min(x1, x2);
                double lry  = Math.Min(y1, y2);
                double trx  = Math.Max(x1, x2);
                double @try = Math.Max(y1, y2);

                ICoordinate[] coords = new ICoordinate[]
                {
                    new Coordinate(lrx, lry),
                    new Coordinate(lrx, @try),
                    new Coordinate(trx, @try),
                    new Coordinate(trx, lry),
                    new Coordinate(lrx, lry)
                };

                yield return(_geometryFactory.CreatePolygon(
                                 _geometryFactory.CreateLinearRing(
                                     _geometryFactory.CoordinateSequenceFactory.Create(coords)
                                     ), new ILinearRing[] { }));
            }
        }
        private static GeoAPI.Geometries.IPolygon ReadPolygon(byte[] geom, ref int idx, bool isLittleEndian, IGeometryFactory factory)
        {
            double[] adfTuple = new double[2];
            int      nRings;


            nRings = ReadUInt32(geom, ref idx, isLittleEndian);

            if (nRings < 1 || nRings > Int32.MaxValue / (2 * 8))
            {
                throw new ApplicationException("Currupt SpatialLite geom");
            }

            List <GeoAPI.Geometries.ILineString> lineStrings = new List <GeoAPI.Geometries.ILineString>();

            for (int i = 0; i < nRings; i++)
            {
                lineStrings.Add(ReadLineString(geom, ref idx, isLittleEndian, factory));
            }

            List <GeoAPI.Geometries.ILinearRing> holes = null;
            var shell = factory.CreateLinearRing(lineStrings[0].Coordinates);

            if (lineStrings.Count > 1)
            {
                holes = new List <GeoAPI.Geometries.ILinearRing>();
                for (int i = 1; i < lineStrings.Count; i++)
                {
                    holes.Add(new NetTopologySuite.Geometries.LinearRing(lineStrings[i].Coordinates));
                }
            }
            return(factory.CreatePolygon(shell, holes == null ? null : holes.ToArray()));
        }
        public void SetUp()
        {
            _factory = new GeometryFactory();

            _geometries = new IGeometry[]
            {
                _factory.CreatePoint(1, 1, 1),
                _factory.CreateLineString(Enumerable.Range(1, 4).Select(i => new Coordinate(i, i, i))),
                _factory.CreatePolygon(Enumerable.Range(1, 4).Select(i => new Coordinate(i * i, i * i, i * i)),
                                       new Coordinate[][] { Enumerable.Range(1, 100).Select(i => new Coordinate(i, i, i)).ToArray(),
                                                            Enumerable.Range(1, 4).Select(i => new Coordinate(i, i, i)).ToArray() }),
                _factory.CreateMultiPoint(Enumerable.Range(1, 4).Select(i => _factory.CreatePoint(i, i, i))),
                _factory.CreateMultiLineString(new ILineString[] { _factory.CreateLineString(Enumerable.Range(1, 4).Select(i => new Coordinate(i, i, i))) }),
                _factory.CreateMultiPolygon(new IPolygon[] { _factory.CreatePolygon(Enumerable.Range(1, 4).Select(i => new Coordinate(i * i, i * i, i * i)),
                                                                                    new Coordinate[][] { Enumerable.Range(1, 4).Select(i => new Coordinate(i, i, i)).ToArray(), Enumerable.Range(1, 4).Select(i => new Coordinate(i, i, i)).ToArray() }) })
            };
        }
        /// <summary>
        /// Computes the <see cref="IPolygon" /> representation of the WKB.
        /// </summary>
        /// <param name="geometryBytes">The WKB representation of the geometry.</param>
        /// <param name="byteOrder">The byte-order of the conversion.</param>
        /// <param name="geometryModel">The geometry model of the conversion.</param>
        /// <param name="factory">The factory used for geometry production.</param>
        /// <returns>The <see cref="IPolygon" /> representation of the geometry.</returns>
        private static IPolygon ComputePolygon(Byte[] geometryBytes, ByteOrder byteOrder, GeometryModel geometryModel, IGeometryFactory factory)
        {
            Int32 coordinateSize       = (geometryModel == GeometryModel.Spatial3D) ? 24 : 16;
            Int32 ringCount            = EndianBitConverter.ToInt32(geometryBytes, 5, byteOrder);
            Int32 shellCoordinateCount = EndianBitConverter.ToInt32(geometryBytes, 9, byteOrder);

            Coordinate[] shellCoordinates = new Coordinate[shellCoordinateCount];

            for (Int32 byteIndex = 13, coordinateIndex = 0; coordinateIndex < shellCoordinateCount; byteIndex += coordinateSize, coordinateIndex++)
            {
                shellCoordinates[coordinateIndex] = new Coordinate(EndianBitConverter.ToDouble(geometryBytes, byteIndex, byteOrder),
                                                                   EndianBitConverter.ToDouble(geometryBytes, byteIndex + 8, byteOrder),
                                                                   geometryModel == GeometryModel.Spatial3D ? EndianBitConverter.ToDouble(geometryBytes, byteIndex + 16, byteOrder) : 0);
            }

            if (ringCount > 1)
            {
                Coordinate[][] holes = new Coordinate[ringCount - 1][];

                Int32 holeStartIndex = 13 + shellCoordinateCount * coordinateSize;

                for (Int32 i = 1; i < ringCount; i++)
                {
                    Int32 holeCoordianteCount = EndianBitConverter.ToInt32(geometryBytes, holeStartIndex, byteOrder);
                    holeStartIndex += 4;
                    Coordinate[] holeCoordinates = new Coordinate[holeCoordianteCount];

                    for (Int32 byteIndex = holeStartIndex, coordinateIndex = 0; coordinateIndex < holeCoordianteCount; byteIndex += coordinateSize, coordinateIndex++)
                    {
                        holeCoordinates[coordinateIndex] = new Coordinate(EndianBitConverter.ToDouble(geometryBytes, byteIndex, byteOrder),
                                                                          EndianBitConverter.ToDouble(geometryBytes, byteIndex + 8, byteOrder),
                                                                          geometryModel == GeometryModel.Spatial3D ? EndianBitConverter.ToDouble(geometryBytes, byteIndex + 16, byteOrder) : 0);
                    }

                    holes[i - 1] = holeCoordinates;

                    holeStartIndex += holeCoordianteCount * coordinateSize;
                }

                return(factory.CreatePolygon(shellCoordinates, holes));
            }
            else
            {
                return(factory.CreatePolygon(shellCoordinates));
            }
        }
Exemple #20
0
        /// <summary>
        /// Converts the Well-known Binary (WKB) to a polygon.
        /// </summary>
        /// <param name="geometryBytes">The WKB representation of the polygon.</param>
        /// <param name="byteOrder">The byte-order of the conversion.</param>
        /// <param name="dimension">The dimension of the geometry.</param>
        /// <param name="factory">The geometry factory.</param>
        /// <returns>The converted polygon.</returns>
        private static IPolygon ToPolygon(Byte[] geometryBytes, ByteOrder byteOrder, Int32 dimension, IGeometryFactory factory)
        {
            Int32 coordinateSize       = (dimension == 3) ? 24 : 16;
            Int32 ringCount            = EndianBitConverter.ToInt32(geometryBytes, 5, byteOrder);
            Int32 shellCoordinateCount = EndianBitConverter.ToInt32(geometryBytes, 9, byteOrder);

            Coordinate[] shellCoordinates = new Coordinate[shellCoordinateCount];

            for (Int32 byteIndex = 13, coordinateIndex = 0; coordinateIndex < shellCoordinateCount; byteIndex += coordinateSize, coordinateIndex++)
            {
                shellCoordinates[coordinateIndex] = new Coordinate(EndianBitConverter.ToDouble(geometryBytes, byteIndex, byteOrder),
                                                                   EndianBitConverter.ToDouble(geometryBytes, byteIndex + 8, byteOrder),
                                                                   dimension == 3 ? EndianBitConverter.ToDouble(geometryBytes, byteIndex + 16, byteOrder) : 0);
            }

            if (ringCount > 1)
            {
                Coordinate[][] holes = new Coordinate[ringCount - 1][];

                Int32 holeStartIndex = 13 + shellCoordinateCount * coordinateSize;

                for (Int32 ringIndex = 1; ringIndex < ringCount; ringIndex++)
                {
                    Int32 holeCoordianteCount = EndianBitConverter.ToInt32(geometryBytes, holeStartIndex, byteOrder);
                    holeStartIndex += 4;
                    Coordinate[] holeCoordinates = new Coordinate[holeCoordianteCount];

                    for (Int32 byteIndex = holeStartIndex, coordinateIndex = 0; coordinateIndex < holeCoordianteCount; byteIndex += coordinateSize, coordinateIndex++)
                    {
                        holeCoordinates[coordinateIndex] = new Coordinate(EndianBitConverter.ToDouble(geometryBytes, byteIndex, byteOrder),
                                                                          EndianBitConverter.ToDouble(geometryBytes, byteIndex + 8, byteOrder),
                                                                          dimension == 3 ? EndianBitConverter.ToDouble(geometryBytes, byteIndex + 16, byteOrder) : 0);
                    }

                    holes[ringIndex - 1] = holeCoordinates;

                    holeStartIndex += holeCoordianteCount * coordinateSize;
                }

                return(factory.CreatePolygon(shellCoordinates, holes));
            }
            else
            {
                return(factory.CreatePolygon(shellCoordinates));
            }
        }
        private void ProcessPolygonGeometry(Polygon f)
        {
            var outerRing = _geometryFactory.CreateLinearRing(
                f.OuterBoundary.LinearRing.Coordinates.Select(crd => new Coordinate(crd.Longitude, crd.Latitude)).ToArray());

            var innerHoles = new List <ILinearRing>();

            foreach (var hole in f.InnerBoundary)
            {
                innerHoles.Add(_geometryFactory.CreateLinearRing(
                                   hole.LinearRing.Coordinates.Select(crd => new Coordinate(crd.Longitude, crd.Latitude)).ToArray()));
            }

            var pGeom = _geometryFactory.CreatePolygon(outerRing, innerHoles.ToArray());

            AddGeometryToCollection(f.GetParent <Placemark>(), pGeom);
        }
        public IGeometry ToGeometry(IGeometryFactory geomFactory)
        {
            if (IsNull)
            {
                return(geomFactory.CreatePoint((ICoordinateSequence)null));
            }

            Coordinate px00 = new Coordinate(_minX, _minA - _minX);
            Coordinate px01 = new Coordinate(_minX, _minX - _minB);

            Coordinate px10 = new Coordinate(_maxX, _maxX - _maxB);
            Coordinate px11 = new Coordinate(_maxX, _maxA - _maxX);

            Coordinate py00 = new Coordinate(_minA - _minY, _minY);
            Coordinate py01 = new Coordinate(_minY + _maxB, _minY);

            Coordinate py10 = new Coordinate(_maxY + _minB, _maxY);
            Coordinate py11 = new Coordinate(_maxA - _maxY, _maxY);

            IPrecisionModel pm = geomFactory.PrecisionModel;

            pm.MakePrecise(px00);
            pm.MakePrecise(px01);
            pm.MakePrecise(px10);
            pm.MakePrecise(px11);
            pm.MakePrecise(py00);
            pm.MakePrecise(py01);
            pm.MakePrecise(py10);
            pm.MakePrecise(py11);

            CoordinateList coordList = new CoordinateList();

            coordList.Add(px00, false);
            coordList.Add(px01, false);
            coordList.Add(py10, false);
            coordList.Add(py11, false);
            coordList.Add(px11, false);
            coordList.Add(px10, false);
            coordList.Add(py01, false);
            coordList.Add(py00, false);

            if (coordList.Count == 1)
            {
                return(geomFactory.CreatePoint(px00));
            }
            Coordinate[] pts;
            if (coordList.Count == 2)
            {
                pts = coordList.ToCoordinateArray();
                return(geomFactory.CreateLineString(pts));
            }
            // must be a polygon, so add closing point
            coordList.Add(px00, false);
            pts = coordList.ToCoordinateArray();
            return(geomFactory.CreatePolygon(geomFactory.CreateLinearRing(pts), null));
        }
        private IGeometry ReadPolygon(int dim, int lrsDim, SdoGeometry sdoGeom)
        {
            ILinearRing shell = null;

            //ILinearRing[] holes = new LinearRing[sdoGeom.ElemArray.Length - 1];
            ILinearRing[] holes            = new LinearRing[0];
            var           info             = sdoGeom.ElemArray;
            var           infoSize         = info.Length / 3;
            int           i                = 0;
            int           idxInteriorRings = 0;

            while (i < infoSize)
            {
                ICoordinateSequence cs = null;
                int numCompounds       = 0;
                //if (info.getElementType(i).isCompound())
                //{
                //    numCompounds = info.getNumCompounds(i);
                //    cs = Add(cs, GetCompoundCSeq(i + 1, i + numCompounds, sdoGeom));
                //}
                //else
                //{
                cs = Add(cs, GetElementCSeq(i, sdoGeom, false));
                //}
                //if (info.getElementType(i).isInteriorRing())
                //{
                //    holes[idxInteriorRings] = factory
                //        .CreateLinearRing(cs);
                //    holes[idxInteriorRings].SRID = (int)sdoGeom.Sdo_Srid;
                //    idxInteriorRings++;
                //}
                //else
                //{
                shell      = factory.CreateLinearRing(cs);
                shell.SRID = (int)sdoGeom.Sdo_Srid;
                //}
                i += 1 + numCompounds;
            }
            IPolygon polygon = factory.CreatePolygon(shell, holes);

            polygon.SRID = (int)sdoGeom.Sdo_Srid;
            return(polygon);
        }
            /// <summary>
            /// Converts the face to a SFA polygon.
            /// </summary>
            /// <param name="factory">The geometry factory used to produce the polygon.</param>
            /// <returns>The polygon geometry representing the face.</returns>
            public IPolygon ToGeometry(IGeometryFactory factory = null)
            {
                if (factory == null)
                {
                    factory = FactoryRegistry.GetFactory <IGeometryFactory>();
                }

                return(factory.CreatePolygon(Vertices.Select(vertex => vertex.Position),
                                             Holes.Select(hole => hole.Vertices.Select(vertex => vertex.Position).Reverse())));
            }
Exemple #25
0
        private static IPolygon RandomPolygonal(IGeometryFactory geometryFactory)
        {
            switch (Random.Next(0, 1))
            {
            case 0:
                var    center = RandomCoordinate(geometryFactory.CoordinateFactory);
                double a      = Random.Next(2, 5);
                double b      = Random.Next(2, 5);
                var    shell  = CreateEllipse(geometryFactory, center, a, b, false);
                a *= 0.5d;
                b *= 0.35d;
                var holes = new[] { CreateEllipse(geometryFactory, center, a, b, true) };
                return(geometryFactory.CreatePolygon(shell, holes));

            default:
                break;
            }
            return(geometryFactory.CreatePolygon());
        }
Exemple #26
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="geom"></param>
        /// <param name="parent"></param>
        /// <returns></returns>
        protected virtual IGeometry TransformPolygon(IPolygon geom, IGeometry parent)
        {
            bool      isAllValidLinearRings = true;
            IGeometry shell = TransformLinearRing(geom.Shell, geom);

            if (shell == null || !(shell is ILinearRing) || shell.IsEmpty)
            {
                isAllValidLinearRings = false;
            }

            var holes = new List <ILineString>();

            for (int i = 0; i < geom.NumInteriorRings; i++)
            {
                IGeometry hole = TransformLinearRing(geom.Holes[i], geom);
                if (hole == null || hole.IsEmpty)
                {
                    continue;
                }
                if (!(hole is ILinearRing))
                {
                    isAllValidLinearRings = false;
                }
                holes.Add((ILineString)hole);
            }

            if (isAllValidLinearRings)
            {
#if !PCL
                var holesAsLinearRing = holes.ConvertAll <ILinearRing>(ls => (ILinearRing)ls).ToArray();
#else
                var tmp = new List <ILinearRing>();
                foreach (var lineString in holes)
                {
                    tmp.Add((ILinearRing)lineString);
                }
                var holesAsLinearRing = tmp.ToArray();
#endif

                return(Factory.CreatePolygon((ILinearRing)shell, holesAsLinearRing));
            }
            else
            {
                var components = new List <IGeometry>();
                if (shell != null)
                {
                    components.Add(shell);
                }
                foreach (IGeometry hole in holes)
                {
                    components.Add(hole);
                }
                return(Factory.BuildGeometry(components));
            }
        }
Exemple #27
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="geometryFactory"></param>
        /// <returns></returns>
        public IPolygon ToPolygon(IGeometryFactory geometryFactory)
        {
            ILinearRing[] holeLR = new ILinearRing[holes.Count];
            for (int i = 0; i < holes.Count; i++)
            {
                holeLR[i] = ((EdgeRing)holes[i]).LinearRing;
            }
            IPolygon poly = geometryFactory.CreatePolygon(LinearRing, holeLR);

            return(poly);
        }
        private IPolygon CreatePolygon(List <Coordinate[]> coordinates)
        {
            ILinearRing shell = _factory.CreateLinearRing(coordinates[0]);

            ILinearRing[] rings = new ILinearRing[coordinates.Count - 1];
            for (int i = 1; i < coordinates.Count; i++)
            {
                rings[i - 1] = _factory.CreateLinearRing(coordinates[i]);
            }
            return(_factory.CreatePolygon(shell, rings));
        }
        private IPolygon CreatePolygon(IList <Coordinate[]> coordinatess)
        {
            var shell = _factory.CreateLinearRing(coordinatess[0]);
            var rings = new List <ILinearRing>();

            for (int i = 1; i < coordinatess.Count; i++)
            {
                rings.Add(_factory.CreateLinearRing(coordinatess[i]));
            }
            return(_factory.CreatePolygon(shell, rings.ToArray()));
        }
 public object ToPolygon(CoordinateInfo[][] coordinates)
 {
     if (coordinates.Length == 0)
     {
         return(Polygon.Empty);
     }
     return(_geometryFactory.CreatePolygon(
                _geometryFactory.CreateLinearRing(coordinates.First().Select(MakeCoordinate).ToArray()),
                coordinates.Skip(1).Select(x => _geometryFactory.CreateLinearRing(x.Select(MakeCoordinate).ToArray())).ToArray()
                ));
 }
 public static IPolygon CreateCircle(
                       IGeometryFactory fact,
                       double basex,
                       double basey,
                       double size,
                       int nPts)
 {
     Coordinate[] pts = CreateCircle(basex, basey, size, nPts);
     var ring = fact.CreateLinearRing(pts);
     var poly = fact.CreatePolygon(ring, null);
     return poly;
 }
 internal static NTSPolygon ToNTSPolygon(Geometries.Polygon geom,
     IGeometryFactory factory)
 {
     NTSLinearRing shell = ToNTSLinearRing(geom.ExteriorRing, factory);
     NTSLinearRing[] holes = new NTSLinearRing[geom.InteriorRings.Count];
     int index = 0;
     foreach (Geometries.LinearRing hole in geom.InteriorRings)
         holes[index++] = ToNTSLinearRing(hole, factory);
     return factory.CreatePolygon(shell, holes) as NTSPolygon;
 }
Exemple #33
0
        private static void GeneratePolygons(IGeometryFactory factory, ICollection<IGeometry> geometry, Random rndGen)
        {
            int numPolygons = rndGen.Next(10, 100);
            for (var polyIndex = 0; polyIndex < numPolygons; polyIndex++)
            {
                var vertices = new GeoPoint[5];
                var upperLeft = new GeoPoint(rndGen.NextDouble()*1000, rndGen.NextDouble()*1000);
                var sideLength = rndGen.NextDouble()*50;

                // Make a square
                vertices[0] = new GeoPoint(upperLeft.X, upperLeft.Y);
                vertices[1] = new GeoPoint(upperLeft.X + sideLength, upperLeft.Y);
                vertices[2] = new GeoPoint(upperLeft.X + sideLength, upperLeft.Y - sideLength);
                vertices[3] = new GeoPoint(upperLeft.X, upperLeft.Y - sideLength);
                vertices[4] = upperLeft;

                geometry.Add(factory.CreatePolygon(factory.CreateLinearRing(vertices), null));
            }
        }
Exemple #34
0
        private IPolygon ReprojectPolygon(IGeometryFactory factory, IPolygon polygon, ISpatialReference @from,
                                                 ISpatialReference to)
        {
            var exterior = (ILinearRing)ReprojectLineString(factory, polygon.ExteriorRing, from, to, false);
            var interior = new ILinearRing[polygon.NumInteriorRings];
            for (var i = 0; i < polygon.NumInteriorRings; i++)
            {
                interior[i] = (ILinearRing)ReprojectLineString(factory, polygon.GetInteriorRingN(i), from, to, false);
            }

            return factory.CreatePolygon(exterior, interior);
        }
        private static IPolygon ParseWkbPolygon(byte[] blob, ref int offset, IGeometryFactory factory, ReadCoordinatesFunction readCoordinates, GaiaImport gaiaImport)
        {
            var number = gaiaImport.GetInt32(blob, ref offset) - 1;
            var shell = (ILinearRing)ParseWkbLineString(blob, ref offset, factory, factory.CreateLinearRing, readCoordinates, gaiaImport);
            var holes = new ILinearRing[number];
            for (var i = 0; i < number; i++)
                holes[i] = (ILinearRing)ParseWkbLineString(blob, ref offset, factory, factory.CreateLinearRing, readCoordinates, gaiaImport);

            return factory.CreatePolygon(shell, holes);
        }
        /// <summary>
        /// Gets the Voronoi cell around a site specified
        /// by the origin of a QuadEdge.
        /// </summary>
        /// <remarks>
        /// The userData of the polygon is set to be the <see cref="Coordinate" />
        /// of the site.  This allows attaching external
        /// data associated with the site to this cell polygon.
        /// </remarks>
        /// <param name="qe">a quadedge originating at the cell site</param>
        /// <param name="geomFact">a factory for building the polygon</param>
        /// <returns>a polygon indicating the cell extent</returns>
        public IPolygon GetVoronoiCellPolygon(QuadEdge qe, IGeometryFactory geomFact)
        {
            var cellPts = new List<Coordinate>();
            QuadEdge startQE = qe;

            do
            {
                // Coordinate cc = circumcentre(qe);
                // use previously computed circumcentre
                Coordinate cc = qe.Rot.Orig.Coordinate;
                cellPts.Add(cc);

                // move to next triangle CW around vertex
                qe = qe.OPrev;
            } while (qe != startQE);

            var coordList = new CoordinateList();
            coordList.AddAll(cellPts, false);
            coordList.CloseRing();

            if (coordList.Count < 4)
            {
            #if !PCL
                Debug.WriteLine(coordList);
            #endif
                coordList.Add(coordList[coordList.Count - 1], true);
            }

            Coordinate[] pts = coordList.ToCoordinateArray();
            IPolygon cellPoly = geomFact.CreatePolygon(geomFact.CreateLinearRing(pts), null);

            Vertex v = startQE.Orig;
            cellPoly.UserData = v.Coordinate;
            return cellPoly;
        }
        private static void generatePolygons(IGeometryFactory geometryFactory,
                                             ICollection<IGeometry> geometry, 
                                             Random rndGen)
        {
            ICoordinateSequenceFactory coordinateSequenceFactory =
                geometryFactory.CoordinateSequenceFactory;
            ICoordinateFactory coordinateFactory = geometryFactory.CoordinateFactory;
            ICoordinateSequence coords = coordinateSequenceFactory.Create(CoordinateDimensions.Two);

            Int32 polyCount = rndGen.Next(10, 100);

            for (Int32 polyIndex = 0; polyIndex < polyCount; polyIndex++)
            {
                ICoordinate upperLeft = coordinateFactory.Create(rndGen.NextDouble() * 1000,
                                                                  rndGen.NextDouble() * 1000);

                Double sideLength = rndGen.NextDouble() * 50;

                // Make a square
                coords.Add(upperLeft);
                coords.Add(coordinateFactory.Create(upperLeft[Ordinates.X] + sideLength,
                                                    upperLeft[Ordinates.Y]));
                coords.Add(coordinateFactory.Create(upperLeft[Ordinates.X] + sideLength,
                                                    upperLeft[Ordinates.Y] - sideLength));
                coords.Add(coordinateFactory.Create(upperLeft[Ordinates.X],
                                                    upperLeft[Ordinates.Y] - sideLength));

                IPolygon polygon = geometryFactory.CreatePolygon(coords);
                geometry.Add(polygon);
            }
        }
        private static IPolygon RandomPolygonal(IGeometryFactory geometryFactory)
        {
            switch (Random.Next(0, 1))
            {
                case 0:
                    var center = RandomCoordinate(geometryFactory.CoordinateFactory);
                    double a = Random.Next(2, 5);
                    double b = Random.Next(2, 5);
                    var shell = CreateEllipse(geometryFactory, center, a, b, false);
                    a *= 0.5d;
                    b *= 0.35d;
                    var holes = new[] {CreateEllipse(geometryFactory, center, a, b, true)};
                    return geometryFactory.CreatePolygon(shell, holes);
                default:
                    break;

            }
            return geometryFactory.CreatePolygon();
        }
        private static GeoAPI.Geometries.IPolygon ReadPolygon(byte[] geom, ref int idx, bool isLittleEndian, IGeometryFactory factory)
        {
            double[] adfTuple = new double[2];
            int nRings;

            nRings = ReadUInt32(geom,ref idx, isLittleEndian);

            if (nRings < 1 || nRings > Int32.MaxValue / (2 * 8))
                throw new ApplicationException("Currupt SpatialLite geom");

            List<GeoAPI.Geometries.ILineString> lineStrings = new List<GeoAPI.Geometries.ILineString>();
            for (int i = 0; i < nRings; i++)
                lineStrings.Add(ReadLineString(geom,ref idx, isLittleEndian, factory));

            List<GeoAPI.Geometries.ILinearRing> holes = null;
            var shell = factory.CreateLinearRing(lineStrings[0].Coordinates);
            if (lineStrings.Count > 1)
            {
                holes = new List<GeoAPI.Geometries.ILinearRing>();
                for (int i = 1; i < lineStrings.Count; i++)
                {
                    holes.Add(new NetTopologySuite.Geometries.LinearRing(lineStrings[i].Coordinates));
                }
            }
            return factory.CreatePolygon(shell, holes == null ? null : holes.ToArray());
        }
Exemple #40
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;
            var shells = new List<ILinearRing>();
            var 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);
        }
        public IGeometry ToGeometry(IGeometryFactory geomFactory)
        {
            if (IsNull)
            {
                return geomFactory.CreatePoint((ICoordinateSequence)null);
            }

            Coordinate px00 = new Coordinate(_minX, _minA - _minX);
            Coordinate px01 = new Coordinate(_minX, _minX - _minB);

            Coordinate px10 = new Coordinate(_maxX, _maxX - _maxB);
            Coordinate px11 = new Coordinate(_maxX, _maxA - _maxX);

            Coordinate py00 = new Coordinate(_minA - _minY, _minY);
            Coordinate py01 = new Coordinate(_minY + _maxB, _minY);

            Coordinate py10 = new Coordinate(_maxY + _minB, _maxY);
            Coordinate py11 = new Coordinate(_maxA - _maxY, _maxY);

            IPrecisionModel pm = geomFactory.PrecisionModel;
            pm.MakePrecise(px00);
            pm.MakePrecise(px01);
            pm.MakePrecise(px10);
            pm.MakePrecise(px11);
            pm.MakePrecise(py00);
            pm.MakePrecise(py01);
            pm.MakePrecise(py10);
            pm.MakePrecise(py11);

            CoordinateList coordList = new CoordinateList();
            coordList.Add(px00, false);
            coordList.Add(px01, false);
            coordList.Add(py10, false);
            coordList.Add(py11, false);
            coordList.Add(px11, false);
            coordList.Add(px10, false);
            coordList.Add(py01, false);
            coordList.Add(py00, false);

            if (coordList.Count == 1)
            {
                return geomFactory.CreatePoint(px00);
            }
            Coordinate[] pts;
            if (coordList.Count == 2)
            {
                pts = coordList.ToCoordinateArray();
                return geomFactory.CreateLineString(pts);
            }
            // must be a polygon, so add closing point
            coordList.Add(px00, false);
            pts = coordList.ToCoordinateArray();
            return geomFactory.CreatePolygon(geomFactory.CreateLinearRing(pts), null);
        }
 /// <summary>
 /// Transforms a <see cref="GeoAPI.Geometries.IPolygon"/>.
 /// </summary>
 /// <param name="p">Polygon to transform</param>
 /// <param name="transform">MathTransform</param>
 /// <param name="targetFactory">The factory to create the target geometry</param>
 /// <returns>Transformed Polygon</returns>
 public static IPolygon TransformPolygon(IPolygon p, IMathTransform transform, IGeometryFactory targetFactory)
 {
     var shell = TransformLinearRing((ILinearRing) p.ExteriorRing, transform, targetFactory);
     ILinearRing[] holes = null;
     var holesCount = p.NumInteriorRings;
     if (holesCount > 0)
     {
         holes = new ILinearRing[holesCount];
         for (var i = 0; i < holesCount; i++)
             holes[i] = TransformLinearRing((ILinearRing)p.GetInteriorRingN(i), transform, targetFactory);
     }
     return targetFactory.CreatePolygon(shell, holes);
 }
Exemple #43
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="geometryFactory"></param>
 /// <returns></returns>
 public virtual IPolygon ToPolygon(IGeometryFactory geometryFactory)
 {
     ILinearRing[] holeLr = new LinearRing[_holes.Count];
     for (int i = 0; i < _holes.Count; i++)
         holeLr[i] = ((EdgeRing)_holes[i]).LinearRing;
     IPolygon poly = geometryFactory.CreatePolygon(LinearRing, holeLr);
     return poly;
 }
		/// <summary>
		/// Reads a stream and converts the shapefile record to an equilivent geometry object.
		/// </summary>
		/// <param name="file">The stream to read.</param>
		/// <param name="geometryFactory">The geometry factory to use when making the object.</param>
		/// <returns>The Geometry object that represents the shape file record.</returns>
		public override IGeometry Read(BigEndianBinaryReader file, IGeometryFactory geometryFactory)
		{
			int shapeTypeNum = file.ReadInt32();
            ShapeGeometryTypes shapeType = (ShapeGeometryTypes)Enum.Parse(typeof(ShapeGeometryTypes), shapeTypeNum.ToString());
            if ( ! ( shapeType == ShapeGeometryTypes.Polygon  || shapeType == ShapeGeometryTypes.PolygonM ||
                     shapeType == ShapeGeometryTypes.PolygonZ || shapeType == ShapeGeometryTypes.PolygonZM))	
				throw new ShapefileException("Attempting to load a non-polygon as polygon.");

			// Read and for now ignore bounds.
			double[] box = new double[4];
			for (int i = 0; i < 4; i++) 
				box[i] = file.ReadDouble();

		    int numParts = file.ReadInt32();
			int numPoints = file.ReadInt32();
			int[] partOffsets = new int[numParts];
			for (int i = 0; i < numParts; i++)
				partOffsets[i] = file.ReadInt32();

			ArrayList shells = new ArrayList();
			ArrayList holes = new ArrayList();

		    for (int part = 0; part < numParts; part++)
			{
				int start = partOffsets[part];
			    int finish;
			    if (part == numParts - 1)
					 finish = numPoints;
				else finish = partOffsets[part + 1];
				int length = finish - start;
                CoordinateList points = new CoordinateList();
				for (int i = 0; i < length; i++)
				{
					Coordinate external = new Coordinate(file.ReadDouble(), file.ReadDouble() );					
                    new PrecisionModel(geometryFactory.PrecisionModel).MakePrecise(external);
                    Coordinate internalCoord = external;
					points.Add(internalCoord);
				}

				ILinearRing ring = geometryFactory.CreateLinearRing(points.ToArray());
				
                // If shape have only a part, jump orientation check and add to shells
                if (numParts == 1)
                    shells.Add(ring);
                else
                {
                    // Orientation check
                    if (CGAlgorithms.IsCounterClockwise(points.ToArray()))
                        holes.Add(ring);
                    else shells.Add(ring);
                }
			}

			// Now we have a list of all shells and all holes
			ArrayList holesForShells = new ArrayList(shells.Count);
			for (int i = 0; i < shells.Count; i++)
				holesForShells.Add(new ArrayList());
			// Find holes
			for (int i = 0; i < holes.Count; i++)
			{
				LinearRing testRing = (LinearRing) holes[i];
				LinearRing minShell = null;
				IEnvelope minEnv = null;
				IEnvelope testEnv = testRing.EnvelopeInternal;
				Coordinate testPt = testRing.GetCoordinateN(0);
				LinearRing tryRing;
				for (int j = 0; j < shells.Count; j++)
				{
					tryRing = (LinearRing) shells[j];
					IEnvelope tryEnv = tryRing.EnvelopeInternal;
					if (minShell != null) 
						minEnv = minShell.EnvelopeInternal;
					bool isContained = false;
					CoordinateList coordList = new CoordinateList(tryRing.Coordinates);
					if (tryEnv.Contains(testEnv)
                        && (CGAlgorithms.IsPointInRing(testPt, coordList.ToArray()) 
                        || (PointInList(testPt, coordList)))) 				
						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;

                        // Suggested by Brian Macomber and added 3/28/2006:
                        // holes were being found but never added to the holesForShells array
                        // so when converted to geometry by the factory, the inner rings were never created.
                        ArrayList holesForThisShell = (ArrayList)holesForShells[j];
                        holesForThisShell.Add(holes[i]);
                    }
				}
			}

			IPolygon[] polygons = new Polygon[shells.Count];
			for (int i = 0; i < shells.Count; i++)			
				polygons[i] = geometryFactory.CreatePolygon((LinearRing) shells[i], 
                    (LinearRing[])((ArrayList) holesForShells[i]).ToArray(typeof(LinearRing)));
        
			if (polygons.Length == 1)
				return polygons[0];
			// It's a multi part
			return geometryFactory.CreateMultiPolygon(polygons);
		}
Exemple #45
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);
        }
        /// <summary>
        /// Transforms a <see cref="GeoAPI.Geometries.IPolygon"/>.
        /// </summary>
        /// <param name="p">Polygon to transform</param>
        /// <param name="from">Source Projection</param>
        /// <param name="to">Target Projection</param>
        /// <param name="toFactory">The factory to create geometries for <paramref name="to"/></param>
        /// <returns>Transformed Polygon</returns>
        public static IPolygon TransformPolygon(IPolygon p, ProjectionInfo from, ProjectionInfo to, IGeometryFactory toFactory)
        {
            var shell = toFactory.CreateLinearRing(TransformSequence(p.Shell.CoordinateSequence, from, to, toFactory.CoordinateSequenceFactory));
            var holes = new ILinearRing[p.NumInteriorRings];
            for (var i = 0; i < p.NumInteriorRings; i++)
                holes[i] = toFactory.CreateLinearRing(TransformSequence(p.GetInteriorRingN(i).CoordinateSequence, from, to, toFactory.CoordinateSequenceFactory));

            return toFactory.CreatePolygon(shell, holes);
        }
	    /// <summary>
		/// Transforms a <see cref="Polygon" /> object.
		/// </summary>
		/// <param name="factory"></param>
		/// <param name="p"></param>
		/// <param name="transform"></param>
		/// <returns></returns>
        public static IPolygon TransformPolygon(IGeometryFactory factory,
            IPolygon p, IMathTransform transform)
		{
			List<ILinearRing> holes = new List<ILinearRing>(p.InteriorRings.Length); 
            for (int i = 0; i < p.InteriorRings.Length; i++)
            {
                ILinearRing hole = TransformLinearRing(factory, 
                    (ILinearRing) p.InteriorRings[i], transform);
                holes.Add(hole);
            }
	        ILinearRing shell = TransformLinearRing(factory, 
                (ILinearRing) p.ExteriorRing, transform);
	        return factory.CreatePolygon(shell, holes.ToArray());
		}
 public static IPolygon CreateSineStar(
                       IGeometryFactory fact,
                       double basex,
                       double basey,
                       double size,
                       double armLen,
                       int nArms,
                       int nPts)
 {
     Coordinate[] pts = CreateSineStar(basex, basey, size, armLen, nArms, nPts);
     var ring = fact.CreateLinearRing(pts);
     var poly = fact.CreatePolygon(ring, null);
     return poly;
 }
        private static IPolygon CreateWKBPolygon(BinaryReader reader, WkbByteOrder byteOrder, IGeometryFactory factory)
        {
            // Get the Number of rings in this Polygon.
            var numRings = (int) ReadUInt32(reader, byteOrder);

            Debug.Assert(numRings >= 1, "Number of rings in polygon must be 1 or more.");

            var shell = CreateWKBLinearRing(reader, byteOrder, factory);

            var holes = new ILinearRing[--numRings];
            for (var i = 0; i < numRings; i++)
                holes[i] = CreateWKBLinearRing(reader, byteOrder, factory);

            return factory.CreatePolygon(shell, holes);
        }
 public static IPolygon CreateBox(
     IGeometryFactory fact,
                       double minx, double miny,
                       int nSide,
                       double segLen)
 {
     Coordinate[] pts = CreateBox(minx, minx, nSide, segLen);
     var ring = fact.CreateLinearRing(pts);
     var poly = fact.CreatePolygon(ring, null);
     return poly;
 }
 /// <summary>
 /// Creates an empty result geometry of the appropriate dimension,
 /// based on the given overlay operation and the dimensions of the inputs.
 /// The created geometry is always an atomic geometry, 
 /// not a collection.
 /// <para/>
 /// The empty result is constructed using the following rules:
 /// <list type="Bullet">
 /// <item><see cref="SpatialFunction.Intersection"/> - result has the dimension of the lowest input dimension</item>
 /// <item><see cref="SpatialFunction.Union"/> - result has the dimension of the highest input dimension</item>
 /// <item><see cref="SpatialFunction.Difference"/> - result has the dimension of the left-hand input</item>
 /// <item><see cref="SpatialFunction.SymDifference"/> - result has the dimension of the highest input dimension
 /// (since symDifference is the union of the differences).</item>
 /// </list>
 /// </summary>
 /// <param name="overlayOpCode">The overlay operation being performed</param>
 /// <param name="a">An input geometry</param>
 /// <param name="b">An input geometry</param>
 /// <param name="geomFact">The geometry factory being used for the operation</param>
 /// <returns>An empty atomic geometry of the appropriate dimension</returns>
 public static IGeometry CreateEmptyResult(SpatialFunction overlayOpCode, IGeometry a, IGeometry b, IGeometryFactory geomFact)
 {
     IGeometry result = null;
     switch (ResultDimension(overlayOpCode, a, b))
     {
         case Dimension.False:
             result = geomFact.CreateGeometryCollection(new IGeometry[0]);
             break;
         case Dimension.Point:
             result = geomFact.CreatePoint((Coordinate)null);
             break;
         case Dimension.Curve:
             result = geomFact.CreateLineString((Coordinate[])null);
             break;
         case Dimension.Surface:
             result = geomFact.CreatePolygon(null, null);
             break;
     }
     return result;
 }
 /// <summary>
 /// Gets the geometry for the triangles in a triangulated subdivision as a <see cref="IGeometryCollection"/>
 /// of triangular <see cref="IPolygon"/>s.
 /// </summary>
 /// <param name="geomFact">the GeometryFactory to use</param>
 /// <returns>a GeometryCollection of triangular Polygons</returns>
 public IGeometryCollection GetTriangles(IGeometryFactory geomFact)
 {
     var triPtsList = GetTriangleCoordinates(false);
     IPolygon[] tris = new Polygon[triPtsList.Count];
     int i = 0;
     foreach (var triPt in triPtsList)
     {
         tris[i++] = geomFact
                     .CreatePolygon(geomFact.CreateLinearRing(triPt), null);
     }
     return geomFact.CreateGeometryCollection(tris);
 }
        /// <summary>
        /// Creates a Polygon using the next token in the stream.
        /// </summary>
        /// <param name="tokenizer">Tokenizer over a stream of text in Well-known Text
        ///  format. The next tokens must form a &lt;Polygon Text&gt;.</param>
        /// <param name="factory">The factory to create the result geometry</param>
        /// <returns>Returns a Polygon specified by the next token
        ///  in the stream</returns>
        ///  <remarks>
        ///  ParseException is thrown if the coordinates used to create the Polygon
        ///  shell and holes do not form closed linestrings, or if an unexpected
        ///  token is encountered.
        ///  </remarks>
        private static IPolygon ReadPolygonText(WktStreamTokenizer tokenizer, IGeometryFactory factory)
        {
            string nextToken = GetNextEmptyOrOpener(tokenizer);
            if (nextToken == "EMPTY")
                return factory.CreatePolygon(null, null);

            var exteriorRing = factory.CreateLinearRing(GetCoordinates(tokenizer));
            nextToken = GetNextCloserOrComma(tokenizer);
            var interiorRings = new List<ILinearRing>();
            while (nextToken == ",")
            {
                //Add holes
                interiorRings.Add(factory.CreateLinearRing(GetCoordinates(tokenizer)));
                nextToken = GetNextCloserOrComma(tokenizer);
            }
            return factory.CreatePolygon(exteriorRing, interiorRings.ToArray());
        }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="geometryFactory"></param>
 /// <returns></returns>
 public IPolygon ToPolygon(IGeometryFactory geometryFactory)
 {
     ILinearRing[] holeLR = new ILinearRing[_holes.Count];
     for (int i = 0; i < _holes.Count; i++)
         holeLR[i] = _holes[i].LinearRing;
     IPolygon poly = geometryFactory.CreatePolygon(LinearRing, holeLR);
     return poly;
 }
        /// <summary>
        /// Reads a stream and converts the shapefile record to an equilivent geometry object.
        /// </summary>
        /// <param name="file">The stream to read.</param>
        /// <param name="geometryFactory">The geometry factory to use when making the object.</param>
        /// <returns>The Geometry object that represents the shape file record.</returns>
        public override IGeometry Read(BigEndianBinaryReader file, IGeometryFactory geometryFactory)
        {
            int shapeTypeNum = file.ReadInt32();
            type = (ShapeGeometryType) Enum.Parse(typeof(ShapeGeometryType), shapeTypeNum.ToString());
            if (type == ShapeGeometryType.NullShape)
                return geometryFactory.CreatePolygon(null, null);

            if (!(type == ShapeGeometryType.Polygon  || type == ShapeGeometryType.PolygonM ||
                  type == ShapeGeometryType.PolygonZ || type == ShapeGeometryType.PolygonZM))	
                throw new ShapefileException("Attempting to load a non-polygon as polygon.");

            // Read and for now ignore bounds.
            int bblength = GetBoundingBoxLength();
            bbox = new double[bblength];
            for (; bbindex < 4; bbindex++)
            {
                double d = file.ReadDouble();
                bbox[bbindex] = d;
            }
            
            int[] partOffsets;        
            int numParts = file.ReadInt32();
            int numPoints = file.ReadInt32();
            partOffsets = new int[numParts];
            for (int i = 0; i < numParts; i++)
                partOffsets[i] = file.ReadInt32();

            ArrayList shells = new ArrayList();
            ArrayList holes = new ArrayList();

            int start, finish, length;
            for (int part = 0; part < numParts; part++)
            {
                start = partOffsets[part];
                if (part == numParts - 1)
                    finish = numPoints;
                else finish = partOffsets[part + 1];
                length = finish - start;
                CoordinateList points = new CoordinateList();
                points.Capacity = length;
                for (int i = 0; i < length; i++)
                {
                    ICoordinate external = new Coordinate(file.ReadDouble(), file.ReadDouble() );					
                    geometryFactory.PrecisionModel.MakePrecise( external);
                    ICoordinate internalCoord = external;

                    // Thanks to Abhay Menon!
                    if (!Double.IsNaN(internalCoord.Y) && !Double.IsNaN(internalCoord.X))
                        points.Add(internalCoord, false);
                }

                if (points.Count > 2) // Thanks to Abhay Menon!
                {
                    if (points[0].Distance(points[points.Count - 1]) > .00001)
                        points.Add(new Coordinate(points[0]));
                    else if (points[0].Distance(points[points.Count - 1]) > 0.0)
                        points[points.Count - 1].CoordinateValue = points[0];

                    ILinearRing ring = geometryFactory.CreateLinearRing(points.ToArray());

                    // If shape have only a part, jump orientation check and add to shells
                    if (numParts == 1)
                        shells.Add(ring);
                    else
                    {
                        // Orientation check
                        if (CGAlgorithms.IsCCW(points.ToArray()))
                             holes.Add(ring);
                        else shells.Add(ring);
                    }                    
                }
            }

            // Now we have a list of all shells and all holes
            ArrayList holesForShells = new ArrayList(shells.Count);
            for (int i = 0; i < shells.Count; i++)
                holesForShells.Add(new ArrayList());

            // Find holes
            for (int i = 0; i < holes.Count; i++)
            {
                ILinearRing testRing = (ILinearRing) holes[i];
                ILinearRing minShell = null;
                IEnvelope minEnv = null;
                IEnvelope testEnv = testRing.EnvelopeInternal;
                ICoordinate testPt = testRing.GetCoordinateN(0);
                ILinearRing tryRing;
                for (int j = 0; j < shells.Count; j++)
                {
                    tryRing = (ILinearRing) shells[j];
                    IEnvelope tryEnv = tryRing.EnvelopeInternal;
                    if (minShell != null)
                        minEnv = minShell.EnvelopeInternal;
                    bool isContained = false;
                    CoordinateList coordList = new CoordinateList(tryRing.Coordinates);
                    if (tryEnv.Contains(testEnv) && 
                       (CGAlgorithms.IsPointInRing(testPt, coordList.ToArray()) || (PointInList(testPt, coordList)))) 				
                        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;             

                        // Suggested by Brian Macomber and added 3/28/2006:
                        // holes were being found but never added to the holesForShells array
                        // so when converted to geometry by the factory, the inner rings were never created.
                        ArrayList holesForThisShell = (ArrayList) holesForShells[j];
                        holesForThisShell.Add(testRing);
                    }
                }
            }

            IPolygon[] polygons = new IPolygon[shells.Count];
            for (int i = 0; i < shells.Count; i++)
                polygons[i] = (geometryFactory.CreatePolygon((ILinearRing) shells[i], 
                    (ILinearRing[]) ((ArrayList) holesForShells[i]).ToArray(typeof(ILinearRing))));

            if (polygons.Length == 1)
                 geom = polygons[0];
            else geom = geometryFactory.CreateMultiPolygon(polygons);
            GrabZMValues(file);
            return geom;
        }
        /// <summary>
        /// Reads a stream and converts the shapefile record to an equilivent geometry object.
        /// </summary>
        /// <param name="file">The stream to read.</param>
        /// <param name="totalRecordLength">Total length of the record we are about to read</param>
        /// <param name="factory">The geometry factory to use when making the object.</param>
        /// <returns>The Geometry object that represents the shape file record.</returns>
        public override IGeometry Read(BigEndianBinaryReader file, int totalRecordLength, IGeometryFactory factory)
        {
            int totalRead = 0;
            var type = (ShapeGeometryType)ReadInt32(file, totalRecordLength, ref totalRead);
            if (type == ShapeGeometryType.NullShape)
                return factory.CreatePolygon(null, null);

            if (type != ShapeType)
                throw new ShapefileException(string.Format("Encountered a '{0}' instead of a  '{1}'", type, ShapeType));

            // Read and for now ignore bounds.
            var bblength = GetBoundingBoxLength();
            boundingBox = new double[bblength];
            for (; boundingBoxIndex < 4; boundingBoxIndex++)
                boundingBox[boundingBoxIndex] = ReadDouble(file, totalRecordLength, ref totalRead);

            var numParts = ReadInt32(file, totalRecordLength, ref totalRead);
            var numPoints = ReadInt32(file, totalRecordLength, ref totalRead);
            var partOffsets = new int[numParts];
            for (var i = 0; i < numParts; i++)
                partOffsets[i] = ReadInt32(file, totalRecordLength, ref totalRead);

            var skippedList = new HashSet<int>();

            //var allPoints = new List<Coordinate>();
            var buffer = new CoordinateBuffer(numPoints, NoDataBorderValue, true);
            var pm = factory.PrecisionModel;
            for (var part = 0; part < numParts; part++)
            {
                var start = partOffsets[part];
                var finish = (part == numParts - 1) 
                    ? numPoints 
                    : partOffsets[part + 1];
                
                var length = finish - start;
                for (var i = 0; i < length; i++)
                {
                    var x = pm.MakePrecise(ReadDouble(file, totalRecordLength, ref totalRead));
                    var y = pm.MakePrecise(ReadDouble(file, totalRecordLength, ref totalRead));

                    // Thanks to Abhay Menon!
                    if (!(Coordinate.NullOrdinate.Equals(x) || Coordinate.NullOrdinate.Equals(y)))
                        buffer.AddCoordinate(x, y);
                    else
                        skippedList.Add(start + i);
                }
                //Add a marker that we have finished one part of the geometry
                buffer.AddMarker();
            }

            // Trond Benum: We have now read all the parts, let's read optional Z and M values
            // and populate Z in the coordinate before we start manipulating the segments
            // We have to track corresponding optional M values and set them up in the 
            // Geometries via ICoordinateSequence further down.
            GetZMValues(file, totalRecordLength, ref totalRead, buffer, skippedList);

            // Get the resulting sequences
            var sequences = buffer.ToSequences(factory.CoordinateSequenceFactory);
            var shells = new List<ILinearRing>();
            var holes = new List<ILinearRing>();
            for (var i = 0; i < sequences.Length; i++)
            {
                //Skip garbage input data with 0 points
                if (sequences[i].Count < 1) continue;

                var tmp = EnsureClosedSequence(sequences[i], factory.CoordinateSequenceFactory);
                var ring = factory.CreateLinearRing(tmp);
                if (ring.IsCCW)
                    holes.Add(ring);
                else
                    shells.Add(ring);
            }

            // Ensure the ring is encoded right
            if (shells.Count == 0 && holes.Count == 1)
            {
                shells.Add(factory.CreateLinearRing(holes[0].CoordinateSequence.Reversed()));
                holes.Clear();
            }


            // Now we have lists of all shells and all holes
            var holesForShells = new List<List<ILinearRing>>(shells.Count);
            for (var i = 0; i < shells.Count; i++)
                holesForShells.Add(new List<ILinearRing>());

            //Thanks to Bruno.Labrecque
            //Sort shells by area, rings should only be added to the smallest shell, that contains the ring
            shells.Sort(ProbeLinearRing);

            // Find holes
            foreach (var testHole in holes)
            {
                var testEnv = testHole.EnvelopeInternal;
                var testPt = testHole.GetCoordinateN(0);
                
                //We have the shells sorted
                for (var j = 0; j < shells.Count; j++)
                {
                    var tryShell = shells[j];
                    var tryEnv = tryShell.EnvelopeInternal;
                    var isContained = tryEnv.Contains(testEnv) && CGAlgorithms.IsPointInRing(testPt, tryShell.Coordinates);

                    // Check if this new containing ring is smaller than the current minimum ring
                    if (isContained)
                    {
                        // Suggested by Brian Macomber and added 3/28/2006:
                        // holes were being found but never added to the holesForShells array
                        // so when converted to geometry by the factory, the inner rings were never created.
                        var holesForThisShell = holesForShells[j];
                        holesForThisShell.Add(testHole);
                        
                        //Suggested by Bruno.Labrecque
                        //A LinearRing should only be added to one outer shell
                        break;
                    }
                }
            }

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

            if (polygons.Length == 1)
                geom = polygons[0];
            else 
                geom = factory.CreateMultiPolygon(polygons);
      
            return geom;
        }
        /// <summary>  
        /// Creates a <c>Polygon</c> using the next token in the stream.
        /// </summary>
        /// <param name="tokens">
        ///   Tokenizer over a stream of text in Well-known Text
        ///   format. The next tokens must form a Polygon Text.
        /// </param>
        /// <param name="factory"> </param>
        /// <returns>
        /// A <c>Polygon</c> specified by the next token
        /// in the stream.        
        /// </returns>
        private IPolygon ReadPolygonText(IEnumerator<Token> tokens, IGeometryFactory factory)
        {
            string nextToken = GetNextEmptyOrOpener(tokens);
            if (nextToken.Equals("EMPTY"))
                return factory.CreatePolygon(
                    factory.CreateLinearRing(new Coordinate[] { } ), new ILinearRing[] { } );

            var holes = new List<ILinearRing>();
            var shell = ReadLinearRingText(tokens, factory);
            nextToken = GetNextCloserOrComma(tokens);
            while (nextToken.Equals(","))
            {
                ILinearRing hole = ReadLinearRingText(tokens, factory);
                holes.Add(hole);
                nextToken = GetNextCloserOrComma(tokens);
            }
            return factory.CreatePolygon(shell, holes.ToArray());
        }