/// <summary> /// Instatiates a polygon based on one extorier ring /// and a collection of interior rings. /// </summary> /// <param name="exteriorRing">Exterior <see cref="LinearRing"/></param> /// <param name="interiorRings">Interior LinearRings</param> public Polygon(LinearRing exteriorRing, IEnumerable<LinearRing> interiorRings) { _exteriorRing = exteriorRing; if (interiorRings != null) _interiorRings.AddRange(interiorRings); }
/// <summary> /// Return a copy of this geometry /// </summary> /// <returns>Copy of Geometry</returns> public new LinearRing Clone() { LinearRing l = new LinearRing(); for (int i = 0; i < Vertices.Count; i++) l.Vertices.Add(Vertices[i].Clone()); return l; }
// METHOD IsCCW() IS MODIFIED FROM ANOTHER WORK AND IS ORIGINALLY BASED ON GeoTools.NET: /* * Copyright (C) 2002 Urban Science Applications, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /// <summary> /// Tests whether a ring is oriented counter-clockwise. /// </summary> /// <param name="ring">Ring to test.</param> /// <returns>Returns true if ring is oriented counter-clockwise.</returns> public static bool IsCCW(LinearRing ring) { Point PrevPoint, NextPoint; Point p; // Check if the ring has enough vertices to be a ring if (ring.Vertices.Count < 3) throw(new ArgumentException("Invalid LinearRing")); // find the point with the largest Y coordinate Point hip = ring.Vertices[0]; int hii = 0; for (int i = 1; i < ring.Vertices.Count; i++) { p = ring.Vertices[i]; if (p.Y > hip.Y) { hip = p; hii = i; } } // Point left to Hip int iPrev = hii - 1; if (iPrev < 0) iPrev = ring.Vertices.Count - 2; // Point right to Hip int iNext = hii + 1; if (iNext >= ring.Vertices.Count) iNext = 1; PrevPoint = ring.Vertices[iPrev]; NextPoint = ring.Vertices[iNext]; // translate so that hip is at the origin. // This will not affect the area calculation, and will avoid // finite-accuracy errors (i.e very small vectors with very large coordinates) // This also simplifies the discriminant calculation. double prev2x = PrevPoint.X - hip.X; double prev2y = PrevPoint.Y - hip.Y; double next2x = NextPoint.X - hip.X; double next2y = NextPoint.Y - hip.Y; // compute cross-product of vectors hip->next and hip->prev // (e.g. area of parallelogram they enclose) double disc = next2x * prev2y - next2y * prev2x; // If disc is exactly 0, lines are collinear. There are two possible cases: // (1) the lines lie along the x axis in opposite directions // (2) the line lie on top of one another // (2) should never happen, so we're going to ignore it! // (Might want to assert this) // (1) is handled by checking if next is left of prev ==> CCW if (disc == 0.0) { // poly is CCW if prev x is right of next x return (PrevPoint.X > NextPoint.X); } else { // if area is positive, points are ordered CCW return (disc > 0.0); } }
private static LinearRing CreateWKBLinearRing(BinaryReader reader, WkbByteOrder byteOrder) { SharpMap.Geometries.LinearRing l = new SharpMap.Geometries.LinearRing(); l.Vertices.AddRange(ReadCoordinates(reader, byteOrder)); //if polygon isn't closed, add the first point to the end (this shouldn't occur for correct WKB data) if (l.Vertices[0].X != l.Vertices[l.Vertices.Count - 1].X || l.Vertices[0].Y != l.Vertices[l.Vertices.Count - 1].Y) { l.Vertices.Add(new Point(l.Vertices[0].X, l.Vertices[0].Y)); } return(l); }
public void PolygonTest() { Polygon p = new Polygon(); Assert.IsTrue(p.IsEmpty()); Assert.AreEqual(0, p.NumInteriorRing); Assert.AreEqual(p.NumInteriorRing, p.InteriorRings.Count); Assert.IsFalse(p.Equals(null)); Assert.IsTrue(p.Equals(new Polygon())); Assert.IsNull(p.GetBoundingBox()); LinearRing ring = new LinearRing(); ring.Vertices.Add(new Point(10, 10)); ring.Vertices.Add(new Point(20, 10)); ring.Vertices.Add(new Point(20, 20)); Assert.IsFalse(ring.IsCCW()); ring.Vertices.Add(new Point(10, 20)); ring.Vertices.Add(ring.Vertices[0].Clone()); Assert.IsTrue(ring.IsPointWithin(new Point(15, 15))); Assert.AreNotSame(ring.Clone(), ring); p.ExteriorRing = ring; Assert.AreEqual(100, p.Area); LinearRing ring2 = new LinearRing(); ring2.Vertices.Add(new Point(11, 11)); ring2.Vertices.Add(new Point(19, 11)); ring2.Vertices.Add(new Point(19, 19)); ring2.Vertices.Add(new Point(11, 19)); ring2.Vertices.Add(ring2.Vertices[0].Clone()); p.InteriorRings.Add(ring2); Assert.AreEqual(100 + 64, p.Area); // Reverse() doesn't exist for Collections //ring2.Vertices.Reverse(); //Assert.AreEqual(100 - 64, p.Area); Assert.AreEqual(1, p.NumInteriorRing); Assert.AreEqual(new BoundingBox(10, 10, 20, 20), p.GetBoundingBox()); Polygon p2 = p.Clone(); Assert.AreEqual(p, p2); Assert.AreNotSame(p, p2); p2.InteriorRings.RemoveAt(0); Assert.AreNotEqual(p, p2); }
/// <summary> /// Transforms a <see cref="SharpMap.Geometries.LinearRing"/>. /// </summary> /// <param name="r">LinearRing to transform</param> /// <param name="transform">MathTransform</param> /// <returns>Transformed LinearRing</returns> public static LinearRing TransformLinearRing(LinearRing r, IMathTransform transform) { try { List<double[]> points = new List<double[]>(); for (int i = 0; i < r.Vertices.Count; i++) points.Add(new double[2] {r.Vertices[i].X, r.Vertices[i].Y}); return new LinearRing(transform.TransformList(points)); } catch { return null; } }
private static Geometry FromShapeFilePolygon(EsriShapeBuffer shapeBuffer, out BoundingBox box) { box = null; if (shapeBuffer == null) return null; var hasZ = EsriShapeBuffer.HasZs(shapeBuffer.shapeType); var hasM = EsriShapeBuffer.HasMs(shapeBuffer.shapeType); using (var reader = new BinaryReader(new MemoryStream(shapeBuffer.shapeBuffer))) { var type = reader.ReadInt32(); if (!(type == 5 || type == 15 || type == 25)) throw new InvalidOperationException(); box = new BoundingBox(reader.ReadDouble(), reader.ReadDouble(), reader.ReadDouble(), reader.ReadDouble()); var numParts = reader.ReadInt32(); var numPoints = reader.ReadInt32(); var allVertices = new List<Point>(numPoints); var parts = new int[numParts+1]; for (var i = 0; i < numParts; i++) parts[i] = reader.ReadInt32(); parts[numParts] = numPoints; var res = new MultiPolygon(); Polygon poly = null; for (var i = 0; i < numParts; i++) { var count = parts[i + 1] - parts[i]; var vertices = new List<Point>(count); for (var j = 0; j < count; j++) { var vertex = hasZ ? new Point3D(reader.ReadDouble(), reader.ReadDouble(), double.NaN) : new Point(reader.ReadDouble(), reader.ReadDouble()); vertices.Add(vertex); allVertices.Add(vertex); } var ring = new LinearRing(vertices); if (poly == null || !ring.IsCCW()) { poly = new Polygon(ring); res.Polygons.Add(poly); } else { poly.InteriorRings.Add(ring); } } if (hasZ) { var minZ = reader.ReadDouble(); var maxZ = reader.ReadDouble(); for (var i = 0; i < numPoints; i++) ((Point3D) allVertices[i]).Z = reader.ReadDouble(); } if (res.NumGeometries == 1) return res.Polygons[0]; return res; } }
private static Geometry ToSharpMapMultiPolygon(EsriShapeBuffer shapeBuffer) { if (shapeBuffer == null) return null; var multiPartShapeBuffer = shapeBuffer as EsriMultiPartShapeBuffer; if (multiPartShapeBuffer == null) { BoundingBox box; return FromShapeFilePolygon(shapeBuffer, out box); } var hasZ = EsriShapeBuffer.HasZs(shapeBuffer.shapeType); var res = new MultiPolygon(); Polygon poly = null; var offset = 0; for (var i = 0; i < multiPartShapeBuffer.NumParts; i++) { var vertices = new List<Point>(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 Point3D(point.x, point.y, multiPartShapeBuffer.Zs[index]) : new Point(point.x, point.y)); } var ring = new LinearRing(vertices); if (poly == null || !ring.IsCCW()) { poly = new Polygon(ring); res.Polygons.Add(poly); } else { poly.InteriorRings.Add(ring); } offset += multiPartShapeBuffer.Parts[i]; } if (res.NumGeometries == 1) return res.Polygons[0]; return res; }
public Polygon GetFootprint() { LinearRing myRing = new LinearRing(GetFourCorners()); return new Polygon(myRing); }
/// <summary> /// Instatiates a polygon based on one extorier ring and a collection of interior rings. /// </summary> /// <param name="exteriorRing">Exterior ring</param> /// <param name="interiorRings">Interior rings</param> public Polygon(LinearRing exteriorRing, List <LinearRing> interiorRings) { _ExteriorRing = exteriorRing; _InteriorRings = interiorRings; }
private static LinearRing CreateWKBLinearRing(BinaryReader reader, WkbByteOrder byteOrder) { SharpMap.Geometries.LinearRing l = new SharpMap.Geometries.LinearRing(); l.Vertices.AddRange(ReadCoordinates(reader, byteOrder)); //if polygon isn't closed, add the first point to the end (this shouldn't occur for correct WKB data) if (l.Vertices[0].X != l.Vertices[l.Vertices.Count - 1].X || l.Vertices[0].Y != l.Vertices[l.Vertices.Count - 1].Y) l.Vertices.Add(new Point(l.Vertices[0].X, l.Vertices[0].Y)); return l; }
/// <summary> /// Instatiates a polygon based on one extorier ring and a collection of interior rings. /// </summary> /// <param name="exteriorRing">Exterior ring</param> /// <param name="interiorRings">Interior rings</param> public Polygon(LinearRing exteriorRing, IList <LinearRing> interiorRings) { this.exteriorRing = exteriorRing; this.interiorRings = interiorRings; }
/// <summary> /// Instatiates a polygon based on one extorier ring and a collection of interior rings. /// </summary> /// <param name="exteriorRing">Exterior ring</param> /// <param name="interiorRings">Interior rings</param> public Polygon(LinearRing exteriorRing, IList <LinearRing> interiorRings) { _ExteriorRing = exteriorRing; _InteriorRings = interiorRings ?? new Collection <LinearRing>(); }
/// <summary> /// Instatiates a polygon based on one exterior ring. /// </summary> /// <param name="exteriorRing">Exterior ring</param> public Polygon(LinearRing exteriorRing) : this(exteriorRing, null) { }
/// <summary> /// Instatiates a polygon based on one extorier ring. /// </summary> /// <param name="exteriorRing">Exterior ring</param> public Polygon(LinearRing exteriorRing) : this(exteriorRing, new Collection<LinearRing>()) { }
/// <summary> /// Instatiates a polygon based on one extorier ring and a collection of interior rings. /// </summary> /// <param name="exteriorRing">Exterior ring</param> /// <param name="interiorRings">Interior rings</param> public Polygon(LinearRing exteriorRing, Collection<LinearRing> interiorRings) { _ExteriorRing = exteriorRing; _InteriorRings = interiorRings; }
/// <summary> /// Instatiates a polygon based on one extorier ring and a collection of interior rings. /// </summary> /// <param name="exteriorRing">Exterior ring</param> /// <param name="interiorRings">Interior rings</param> public Polygon(LinearRing exteriorRing, IList<LinearRing> interiorRings) { _ExteriorRing = exteriorRing; _InteriorRings = interiorRings; }
/// <summary> /// Instatiates a polygon based on one extorier ring. /// </summary> /// <param name="exteriorRing">Exterior ring</param> public Polygon(LinearRing exteriorRing) : this(exteriorRing, new List <LinearRing>()) { }
/// <summary> /// Transforms a <see cref="SharpMap.Geometries.LinearRing"/>. /// </summary> /// <param name="r">LinearRing to transform</param> /// <param name="transform">MathTransform</param> /// <returns>Transformed LinearRing</returns> public static LinearRing TransformLinearRing(LinearRing r, IMathTransform transform) { try { return new LinearRing(transform.TransformList(r.Vertices)); } catch { return null; } }
/// <summary> /// Instatiates a polygon based on one extorier ring and a collection of interior rings. /// </summary> /// <param name="exteriorRing">Exterior ring</param> /// <param name="interiorRings">Interior rings</param> public Polygon(LinearRing exteriorRing, IList<LinearRing> interiorRings) { _ExteriorRing = exteriorRing; _InteriorRings = interiorRings ?? new Collection<LinearRing>(); }
/// <summary> /// Returns the box filter string needed in SQL query /// </summary> /// <param name="bbox"></param> /// <returns></returns> private string GetBoxFilterStr(BoundingBox bbox) { //geography::STGeomFromText('LINESTRING(47.656 -122.360, 47.656 -122.343)', 4326); LinearRing lr = new LinearRing(); lr.Vertices.Add(new Point(bbox.Left, bbox.Bottom)); lr.Vertices.Add(new Point(bbox.Right, bbox.Bottom)); lr.Vertices.Add(new Point(bbox.Right, bbox.Top)); lr.Vertices.Add(new Point(bbox.Left, bbox.Top)); lr.Vertices.Add(new Point(bbox.Left, bbox.Bottom)); Polygon p = new Polygon(lr); string bboxText = Converters.WellKnownText.GeometryToWKT.Write(p); // ""; //string whereClause = GeometryColumn + ".STIntersects(geometry::STGeomFromText('" + bboxText + "', " + SRID + ")" + MakeValidString + ") = 1"; string whereClause = String.Format("{0}{1}.STIntersects({4}::STGeomFromText('{2}', {3})) = 1", GeometryColumn, MakeValidString, bboxText, SRID, _spatialObject); return whereClause; // strBbox; }
/// <summary> /// Instatiates a polygon based on one extorier ring. /// </summary> /// <param name="exteriorRing">Exterior ring</param> public Polygon(LinearRing exteriorRing) : this(exteriorRing, new List<LinearRing>()) { }
/// <summary> /// Instatiates a polygon based on one extorier ring. /// </summary> /// <param name="exteriorRing">Exterior ring</param> public Polygon(LinearRing exteriorRing) : this(exteriorRing, new Collection <LinearRing>()) { }
/// <summary> /// Transforms a <see cref="SharpMap.Geometries.LinearRing"/>. /// </summary> /// <param name="r">LinearRing to transform</param> /// <param name="from">Source Projection</param> /// <param name="to">Target Projection</param> /// <returns>Transformed LinearRing</returns> public static LinearRing TransformLinearRing(LinearRing r, ProjectionInfo from, ProjectionInfo to) { try { List<double[]> points = new List<double[]>(); for (int i = 0; i < r.Vertices.Count; i++) points.Add(new double[] {r.Vertices[i].X, r.Vertices[i].Y}); return new LinearRing(TransformList(points, from, to)); } catch { return null; } }
/// <summary> /// Creates a deep copy of the LinearRing. /// </summary> /// <returns>A copy of the LinearRing instance.</returns> public override Geometry Clone() { LinearRing ring = new LinearRing(Vertices); return ring; }
/// <summary> /// Reads and parses the geometry with ID 'oid' from the ShapeFile /// </summary> /// <remarks><see cref="FilterDelegate">Filtering</see> is not applied to this method</remarks> /// <param name="oid">Object ID</param> /// <returns>geometry</returns> private Geometry ReadGeometry(uint oid) { brShapeFile.BaseStream.Seek(GetShapeIndex(oid) + 8, 0); //Skip record number and content length ShapeType type = (ShapeType) brShapeFile.ReadInt32(); //Shape type if (type == ShapeType.Null) return null; if (_ShapeType == ShapeType.Point || _ShapeType == ShapeType.PointM || _ShapeType == ShapeType.PointZ) { Point tempFeature = new Point(); return new Point(brShapeFile.ReadDouble(), brShapeFile.ReadDouble()); } else if (_ShapeType == ShapeType.Multipoint || _ShapeType == ShapeType.MultiPointM || _ShapeType == ShapeType.MultiPointZ) { brShapeFile.BaseStream.Seek(32 + brShapeFile.BaseStream.Position, 0); //skip min/max box MultiPoint feature = new MultiPoint(); int nPoints = brShapeFile.ReadInt32(); // get the number of points if (nPoints == 0) return null; for (int i = 0; i < nPoints; i++) feature.Points.Add(new Point(brShapeFile.ReadDouble(), brShapeFile.ReadDouble())); return feature; } else if (_ShapeType == ShapeType.PolyLine || _ShapeType == ShapeType.Polygon || _ShapeType == ShapeType.PolyLineM || _ShapeType == ShapeType.PolygonM || _ShapeType == ShapeType.PolyLineZ || _ShapeType == ShapeType.PolygonZ) { brShapeFile.BaseStream.Seek(32 + brShapeFile.BaseStream.Position, 0); //skip min/max box int nParts = brShapeFile.ReadInt32(); // get number of parts (segments) if (nParts == 0) return null; int nPoints = brShapeFile.ReadInt32(); // get number of points int[] segments = new int[nParts + 1]; //Read in the segment indexes for (int b = 0; b < nParts; b++) segments[b] = brShapeFile.ReadInt32(); //add end point segments[nParts] = nPoints; if ((int) _ShapeType%10 == 3) { MultiLineString mline = new MultiLineString(); for (int LineID = 0; LineID < nParts; LineID++) { LineString line = new LineString(); for (int i = segments[LineID]; i < segments[LineID + 1]; i++) line.Vertices.Add(new Point(brShapeFile.ReadDouble(), brShapeFile.ReadDouble())); mline.LineStrings.Add(line); } if (mline.LineStrings.Count == 1) return mline[0]; return mline; } else //(_ShapeType == ShapeType.Polygon etc...) { //First read all the rings List<LinearRing> rings = new List<LinearRing>(); for (int RingID = 0; RingID < nParts; RingID++) { LinearRing ring = new LinearRing(); for (int i = segments[RingID]; i < segments[RingID + 1]; i++) ring.Vertices.Add(new Point(brShapeFile.ReadDouble(), brShapeFile.ReadDouble())); rings.Add(ring); } bool[] IsCounterClockWise = new bool[rings.Count]; int PolygonCount = 0; for (int i = 0; i < rings.Count; i++) { IsCounterClockWise[i] = rings[i].IsCCW(); if (!IsCounterClockWise[i]) PolygonCount++; } if (PolygonCount == 1) //We only have one polygon { Polygon poly = new Polygon(); poly.ExteriorRing = rings[0]; if (rings.Count > 1) for (int i = 1; i < rings.Count; i++) poly.InteriorRings.Add(rings[i]); return poly; } else { MultiPolygon mpoly = new MultiPolygon(); Polygon poly = new Polygon(); poly.ExteriorRing = rings[0]; for (int i = 1; i < rings.Count; i++) { if (!IsCounterClockWise[i]) { mpoly.Polygons.Add(poly); poly = new Polygon(rings[i]); } else poly.InteriorRings.Add(rings[i]); } mpoly.Polygons.Add(poly); return mpoly; } } } else throw (new ApplicationException("Shapefile type " + _ShapeType.ToString() + " not supported")); }
private static LinearRing CreateWKBLinearRing(BinaryReader reader, WkbByteOrder byteOrder) { LinearRing l = new LinearRing(); //l.Vertices.AddRange(ReadCoordinates(reader, byteOrder)); Point[] arrPoint = ReadCoordinates(reader, byteOrder); for (int i = 0; i < arrPoint.Length; i++) l.Vertices.Add(arrPoint[i]); //if polygon isn't closed, add the first point to the end (this shouldn't occur for correct WKB data) if (l.Vertices[0].X != l.Vertices[l.Vertices.Count - 1].X || l.Vertices[0].Y != l.Vertices[l.Vertices.Count - 1].Y) l.Vertices.Add(new Point(l.Vertices[0].X, l.Vertices[0].Y)); return l; }
/// <summary> /// Instatiates a polygon based on one extorier ring and a collection of interior rings. /// </summary> /// <param name="exteriorRing">Exterior ring</param> /// <param name="interiorRings">Interior rings</param> public Polygon(LinearRing exteriorRing, Collection <LinearRing> interiorRings) { _ExteriorRing = exteriorRing; _InteriorRings = interiorRings; }