/// <summary> /// Return a copy of this geometry /// </summary> /// <returns>Copy of Geometry</returns> public new LinearRing Clone() { var 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) { // 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++) { Point 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; Point prevPoint = ring.Vertices[iPrev]; Point 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); } // if area is positive, points are ordered CCW return (disc > 0.0); }
private static Polygon CreatePolygon() { var polygon = new Polygon(); polygon.ExteriorRing.Vertices.Add(new Point(0, 0)); polygon.ExteriorRing.Vertices.Add(new Point(0, 10000000)); polygon.ExteriorRing.Vertices.Add(new Point(10000000, 10000000)); polygon.ExteriorRing.Vertices.Add(new Point(10000000, 0)); polygon.ExteriorRing.Vertices.Add(new Point(0, 0)); var linearRing = new LinearRing(); linearRing.Vertices.Add(new Point(1000000, 1000000)); linearRing.Vertices.Add(new Point(9000000, 1000000)); linearRing.Vertices.Add(new Point(9000000, 9000000)); linearRing.Vertices.Add(new Point(1000000, 9000000)); linearRing.Vertices.Add(new Point(1000000, 1000000)); polygon.InteriorRings.Add(linearRing); return polygon; }
/// <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, 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 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, IList <LinearRing> interiorRings) { ExteriorRing = exteriorRing; InteriorRings = interiorRings; }
/// <summary> /// Return a copy of this geometry /// </summary> /// <returns>Copy of Geometry</returns> public new LinearRing Clone() { var linearRing = new LinearRing(); for (var i = 0; i < Vertices.Count; i++) { linearRing.Vertices.Add(Vertices[i].Clone()); } return linearRing; }
private static LinearRing CreateWKBLinearRing(BinaryReader reader, WkbByteOrder byteOrder) { var l = new LinearRing(); //l.Vertices.AddRange(ReadCoordinates(reader, byteOrder)); IEnumerable<Point> arrPoint = ReadCoordinates(reader, byteOrder); foreach (Point t in arrPoint) { l.Vertices.Add(t); } //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> /// 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")); }
/// <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> /// 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> // ReSharper disable once CyclomaticComplexity // Fix when changes need to be made here private Geometry ReadGeometry(uint oid) { _brShapeFile.BaseStream.Seek(GetShapeIndex(oid) + 8, 0); //Skip record number and content length var type = (ShapeType)_brShapeFile.ReadInt32(); //Shape type if (type == ShapeType.Null) return null; if (_shapeType == ShapeType.Point || _shapeType == ShapeType.PointM || _shapeType == ShapeType.PointZ) { return new Point(_brShapeFile.ReadDouble(), _brShapeFile.ReadDouble()); } if (_shapeType == ShapeType.Multipoint || _shapeType == ShapeType.MultiPointM || _shapeType == ShapeType.MultiPointZ) { _brShapeFile.BaseStream.Seek(32 + _brShapeFile.BaseStream.Position, 0); //skip min/max box var 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; } 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 var 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) { var mline = new MultiLineString(); for (int lineId = 0; lineId < nParts; lineId++) { var 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 var rings = new List<LinearRing>(); for (int ringId = 0; ringId < nParts; ringId++) { var 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); } var 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 { var poly = new Polygon { ExteriorRing = rings[0] }; if (rings.Count > 1) for (int i = 1; i < rings.Count; i++) poly.InteriorRings.Add(rings[i]); return poly; } else { var mpoly = new MultiPolygon(); var poly = new Polygon { ExteriorRing = rings[0] }; for (var 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; } } } throw (new ApplicationException("Shapefile type " + _shapeType.ToString() + " not supported")); }
/// <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; }
public static Polygon ConvertScreenToWorld(Polygon sharpmapPolygon) { // Log4netLogger.Debug("Start converting screen polygon to map polygon"); var linearRing = new LinearRing(); foreach (var vertex in sharpmapPolygon.ExteriorRing.Vertices) { linearRing.Vertices.Add(ConvertScreenToWorld(vertex)); } // Log4netLogger.Debug("Screen polygon to map polygon conversion ended"); return new Polygon(linearRing); }