/// <summary> /// /// </summary> /// <param name="linearRing"></param> /// <param name="writer"></param> protected virtual void Write(LinearRing linearRing, XmlTextWriter writer) { writer.WriteStartElement("LinearRing"); Write(linearRing.Coordinates, writer); writer.WriteEndElement(); }
/// <summary> /// /// </summary> /// <param name="reader"></param> /// <returns></returns> protected virtual IGeometry ReadPolygon(BinaryReader reader) { int numRings = reader.ReadInt32(); ILinearRing exteriorRing = ReadRing(reader); ILinearRing[] interiorRings = new LinearRing[numRings - 1]; for (int i = 0; i < numRings - 1; i++) interiorRings[i] = ReadRing(reader); return Factory.CreatePolygon(exteriorRing, interiorRings); }
/// <summary> /// /// </summary> /// <param name="ring"></param> public virtual void Add(LinearRing ring) { _rings.Add(ring); _totalEnv.ExpandToInclude(ring.EnvelopeInternal); }
/// <summary> /// If the FeatureType is polygon, this is the code for converting the vertex array /// into a feature. /// </summary> /// <param name="index"></param> /// <returns></returns> protected IFeature GetPolygon(int index) { Feature feature = new Feature(); feature.Envelope = ShapeIndices[index].Extent.ToEnvelope(); ShapeRange shape = ShapeIndices[index]; List<ILinearRing> shells = new List<ILinearRing>(); List<ILinearRing> holes = new List<ILinearRing>(); foreach (PartRange part in shape.Parts) { List<Coordinate> coords = new List<Coordinate>(); int i = part.StartIndex; foreach (Vertex d in part) { Coordinate c = new Coordinate(d); if (M != null && M.Length > 0) c.M = M[i]; if (Z != null && Z.Length > 0) c.Z = Z[i]; i++; coords.Add(c); } LinearRing ring = new LinearRing(coords); if (shape.Parts.Count == 1) { shells.Add(ring); } else { if (CGAlgorithms.IsCounterClockwise(ring.Coordinates)) { holes.Add(ring); } else { shells.Add(ring); } //if(part.IsHole()) //{ // holes.Add(ring); //} //else //{ // shells.Add(ring); //} } } //// Now we have a list of all shells and all holes List<ILinearRing>[] holesForShells = new List<ILinearRing>[shells.Count]; for (int i = 0; i < shells.Count; i++) { holesForShells[i] = new List<ILinearRing>(); } // Find holes for (int i = 0; i < holes.Count; i++) { ILinearRing testRing = holes[i]; ILinearRing minShell = null; IEnvelope minEnv = null; IEnvelope testEnv = testRing.EnvelopeInternal; Coordinate testPt = testRing.Coordinates[0]; ILinearRing tryRing; for (int j = 0; j < shells.Count; j++) { tryRing = shells[j]; IEnvelope tryEnv = tryRing.EnvelopeInternal; if (minShell != null) minEnv = minShell.EnvelopeInternal; bool isContained = false; if (tryEnv.Contains(testEnv) && (CGAlgorithms.IsPointInRing(testPt, tryRing.Coordinates) || (PointInList(testPt, tryRing.Coordinates)))) { isContained = true; } // Check if this new containing ring is smaller than the current minimum ring if (isContained) { if (minShell == null || minEnv.Contains(tryEnv)) { minShell = tryRing; } holesForShells[j].Add(holes[i]); } } } IPolygon[] polygons = new Polygon[shells.Count]; for (int i = 0; i < shells.Count; i++) { polygons[i] = new Polygon(shells[i], holesForShells[i].ToArray()); } if (polygons.Length == 1) { feature.BasicGeometry = polygons[0]; } else { // It's a multi part feature.BasicGeometry = new MultiPolygon(polygons); } // feature.FID = feature.RecordNumber; FID is now dynamic feature.ParentFeatureSet = this; feature.ShapeIndex = shape; feature.RecordNumber = shape.RecordNumber; feature.ContentLength = shape.ContentLength; feature.ShapeType = shape.ShapeType; //Attributes handled in the overridden case return feature; }
/// <summary> /// Check if a shell is incorrectly nested within a polygon. This is the case /// if the shell is inside the polygon shell, but not inside a polygon hole. /// (If the shell is inside a polygon hole, the nesting is valid.) /// The algorithm used relies on the fact that the rings must be properly contained. /// E.g. they cannot partially overlap (this has been previously checked by /// <c>CheckRelateConsistency</c>). /// </summary> private void CheckShellNotNested(LinearRing shell, Polygon p, GeometryGraph graph) { IList<Coordinate> shellPts = shell.Coordinates; // test if shell is inside polygon shell LinearRing polyShell = (LinearRing)p.ExteriorRing; IList<Coordinate> polyPts = polyShell.Coordinates; Coordinate shellPt = FindPointNotNode(shellPts, polyShell, graph); // if no point could be found, we can assume that the shell is outside the polygon if (shellPt == null) return; bool insidePolyShell = CGAlgorithms.IsPointInRing(shellPt, polyPts); if (!insidePolyShell) return; // if no holes, this is an error! if (p.NumHoles <= 0) { _validErr = new TopologyValidationError(TopologyValidationErrors.NestedShells, shellPt); return; } /* * Check if the shell is inside one of the holes. * This is the case if one of the calls to checkShellInsideHole * returns a null coordinate. * Otherwise, the shell is not properly contained in a hole, which is an error. */ Coordinate badNestedPt = null; for (int i = 0; i < p.NumHoles; i++) { LinearRing hole = (LinearRing)p.GetInteriorRingN(i); badNestedPt = CheckShellInsideHole(shell, hole, graph); if (badNestedPt == null) return; } _validErr = new TopologyValidationError(TopologyValidationErrors.NestedShells, badNestedPt); }
/// <summary> /// This routine checks to see if a shell is properly contained in a hole. /// It assumes that the edges of the shell and hole do not /// properly intersect. /// </summary> /// <param name="shell"></param> /// <param name="hole"></param> /// <param name="graph"></param> /// <returns> /// <c>null</c> if the shell is properly contained, or /// a Coordinate which is not inside the hole if it is not. /// </returns> private static Coordinate CheckShellInsideHole(LinearRing shell, LinearRing hole, GeometryGraph graph) { IList<Coordinate> shellPts = shell.Coordinates; IList<Coordinate> holePts = hole.Coordinates; // TODO: improve performance of this - by sorting pointlists? Coordinate shellPt = FindPointNotNode(shellPts, hole, graph); // if point is on shell but not hole, check that the shell is inside the hole if (shellPt != null) { bool insideHole = CGAlgorithms.IsPointInRing(shellPt, holePts); if (!insideHole) return shellPt; } Coordinate holePt = FindPointNotNode(holePts, shell, graph); // if point is on hole but not shell, check that the hole is outside the shell if (holePt != null) { bool insideShell = CGAlgorithms.IsPointInRing(holePt, shellPts); if (insideShell) return holePt; return null; } Assert.ShouldNeverReachHere("points in shell and hole appear to be equal"); return null; }
/// <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> /// /// </summary> /// <param name="ring"></param> public virtual void Add(LinearRing ring) { _rings.Add(ring); }
/// <summary> /// Constructor for a polygon /// </summary> /// <param name="polygonBase">A simpler BasicPolygon to empower with topology functions</param> public Polygon(IBasicPolygon polygonBase) : base(DefaultFactory) { SetHoles(polygonBase.Holes); LinearRing shell = new LinearRing(polygonBase.Shell); if (HasNullElements(_holes)) throw new PolygonException(MessageStrings.PolygonException_HoleElementNull); if (shell.IsEmpty && HasNonEmptyElements(_holes)) throw new PolygonException(MessageStrings.PolygonException_ShellEmptyButHolesNot); _shell = shell; }
/// <summary> /// Constructs a <c>Polygon</c> with the given exterior boundary and /// interior boundaries. /// </summary> /// <param name="inShell"> /// The outer boundary of the new <c>Polygon</c>, /// or <c>null</c> or an empty <c>LinearRing</c> if the empty /// point is to be created. /// </param> /// <param name="inHoles"> /// The inner boundaries of the new <c>Polygon</c> /// , or <c>null</c> or empty <c>LinearRing</c>s if the empty /// point is to be created. /// </param> /// <param name="factory"></param> /// <exception cref="PolygonException">Holes must not contain null elements</exception> public Polygon(ILinearRing inShell, ILinearRing[] inHoles, IGeometryFactory factory) : base(factory) { if (inShell == null) inShell = Factory.CreateLinearRing(null); if (inHoles == null) inHoles = new LinearRing[] { }; if (HasNullElements(inHoles)) { throw new PolygonException(MessageStrings.PolygonException_HoleElementNull); } if (inShell.IsEmpty && HasNonEmptyElements(inHoles)) throw new PolygonException(MessageStrings.PolygonException_ShellEmptyButHolesNot); _shell = inShell; _holes = inHoles; }
private int _crossings; // number of segment/ray crossings /// <summary> /// /// </summary> /// <param name="ring"></param> public SIRtreePointInRing(LinearRing ring) { _ring = ring; BuildIndex(); }