///<summary> /// Converts a linearring to be sure it is clockwise. ///</summary> ///<remarks>Normal form is a unique representation /// for Geometry's. It can be used to test whether two Geometrys are equal in a way that is /// independent of the ordering of the coordinates within them. Normal form equality is a stronger /// condition than topological equality, but weaker than pointwise equality. The definitions for /// normal form use the standard lexicographical ordering for coordinates. Sorted in order of /// coordinates means the obvious extension of this ordering to sequences of coordinates. ///</remarks> private void Normalize(LinearRing ring, bool clockwise) { if (ring.IsEmpty()) { return; } Coordinates uniqueCoordinates = new Coordinates(); for (int i = 0; i < ring.GetNumPoints() - 1; i++) { uniqueCoordinates.Add(ring.GetCoordinateN(i)); // copy all but last one into uniquecoordinates } Coordinate minCoordinate = MinCoordinate(ring.GetCoordinates()); Scroll(uniqueCoordinates, minCoordinate); Coordinates ringCoordinates = ring.GetCoordinates(); ringCoordinates.Clear(); ringCoordinates.AddRange(uniqueCoordinates); ringCoordinates.Add(uniqueCoordinates[0].Clone()); // add back in the closing point. if (_cgAlgorithms.IsCCW(ringCoordinates) == clockwise) { ReversePointOrder(ringCoordinates); } }
///<summary> /// Returns this Geometry's vertices. Do not modify the array, as it may be the actual array stored /// by this Geometry. The Geometries contained by composite Geometries must be Geometry's; /// that is, they must implement get Coordinates. ///</summary> ///<returns>Returns the vertices of this Geometry.</returns> public override Coordinates GetCoordinates() { Coordinates coords = new Coordinates(); if (IsEmpty()) { return(coords); } coords.AddRange(_shell.GetCoordinates()); if (_holes != null) { for (int i = 0; i < _holes.Length; i++) { coords.AddRange(_holes[i].GetCoordinates()); } } return(coords); }
private bool IsInside(LinearRing innerRing, LinearRing searchRing) { Coordinates innerRingPts = innerRing.GetCoordinates(); Coordinates searchRingPts = searchRing.GetCoordinates(); if (! innerRing.GetEnvelopeInternal().Intersects(searchRing.GetEnvelopeInternal())) return false; Coordinate innerRingPt = IsValidOp.FindPtNotNode(innerRingPts, searchRing, _graph); //Assert.isTrue(innerRingPt != null, "Unable to find a ring point not a node of the search ring"); bool isInside = _cga.IsPointInRing(innerRingPt, searchRingPts); if (isInside) { _nestedPt = innerRingPt; return true; } return false; }
/// <summary> /// Initializes a new instance of the SimplePointInRing class. /// </summary> public SimplePointInRing(LinearRing ring) { _pts = ring.GetCoordinates(); }
} // private int Locate( Coordinate p, LineString l ) /// <summary> /// /// </summary> /// <param name="p"></param> /// <param name="ring"></param> /// <returns></returns> private int Locate( Coordinate p, LinearRing ring ) { if ( _cga.IsOnLine( p, ring.GetCoordinates() ) ) { return Location.Boundary; } if ( _cga.IsPointInRing( p, ring.GetCoordinates() ) ) { return Location.Interior; } return Location.Exterior; } // private int Locate( Coordinate p, LinearRing ring )
/// <summary> /// Compute a LinearRing from the point list previously collected. /// Test if the ring is a hole (i.e. if it is CCW) and set the hole flag /// accordingly. /// </summary> public void ComputeRing() { if ( _ring != null ) return; // don't compute more than once // create ring using geometry factory. _ring = _geometryFactory.CreateLinearRing( _pts ); _isHole = _cga.IsCCW( _ring.GetCoordinates() ); }
/// <summary> /// The left and right topological location arguments assume that the ring is oriented CW. /// If the ring is in the opposite orientation, the left and right locations must be interchanged. /// </summary> /// <param name="lr"></param> /// <param name="cwLeft"></param> /// <param name="cwRight"></param> private void AddPolygonRing( LinearRing lr, int cwLeft, int cwRight ) { Coordinates coord = Coordinates.RemoveRepeatedPoints(lr.GetCoordinates()); if (coord.Count<4) { _hasTooFewPoints=true; _invalidPoint=coord[0]; } int left = cwLeft; int right = cwRight; if ( _cga.IsCCW( coord ) ) { left = cwRight; right = cwLeft; } Edge e = new Edge(coord, new Label(_argIndex, Location.Boundary, left, right)); _lineEdgeMap[ lr]= e; InsertEdge( e ); // insert the endpoint as a node, to mark that it is on the boundary InsertPoint( _argIndex, coord[0], Location.Boundary ); }
///<summary> /// Converts a linearring to be sure it is clockwise. ///</summary> ///<remarks>Normal form is a unique representation /// for Geometry's. It can be used to test whether two Geometrys are equal in a way that is /// independent of the ordering of the coordinates within them. Normal form equality is a stronger /// condition than topological equality, but weaker than pointwise equality. The definitions for /// normal form use the standard lexicographical ordering for coordinates. Sorted in order of /// coordinates means the obvious extension of this ordering to sequences of coordinates. ///</remarks> private void Normalize( LinearRing ring, bool clockwise ) { if ( ring.IsEmpty() ) { return; } Coordinates uniqueCoordinates = new Coordinates(); for ( int i=0; i < ring.GetNumPoints()-1; i++ ) { uniqueCoordinates.Add( ring.GetCoordinateN( i ) ); // copy all but last one into uniquecoordinates } Coordinate minCoordinate = MinCoordinate( ring.GetCoordinates() ); Scroll( uniqueCoordinates, minCoordinate ); Coordinates ringCoordinates = ring.GetCoordinates(); ringCoordinates.Clear(); ringCoordinates.AddRange( uniqueCoordinates ); ringCoordinates.Add( uniqueCoordinates[0].Clone() ); // add back in the closing point. if ( _cgAlgorithms.IsCCW( ringCoordinates ) == clockwise ) { ReversePointOrder( ringCoordinates ); } }
/// <summary> /// The side and left and right topological location arguments assume that the ring is oriented CW. /// If the ring is in the opposite orientation, the left and right locations must be interchanged /// and the side flipped. /// </summary> /// <param name="lr">lr the LinearRing around which to create the buffer</param> /// <param name="distance">distance the distance at which to create the buffer</param> /// <param name="side">side the side of the ring on which to construct the buffer line</param> /// <param name="cwLeftLoc">cwLeftLoc the location on the L side of the ring (if it is CW)</param> /// <param name="cwRightLoc">cwRightLoc the location on the R side of the ring (if it is CW)</param> private void AddPolygonRing(LinearRing lr, double distance, int side, int cwLeftLoc, int cwRightLoc) { Coordinates coord = Coordinates.RemoveRepeatedPoints(lr.GetCoordinates()); int leftLoc = cwLeftLoc; int rightLoc = cwRightLoc; if (_cga.IsCCW(coord)) { leftLoc = cwRightLoc; rightLoc = cwLeftLoc; side = Position.Opposite(side); } ArrayList lineList = _lineBuilder.GetRingBuffer(coord, side, distance); AddEdges(lineList, leftLoc, rightLoc); /* This section was already commented out in the java code. Leave it commented out... Edge e = new Edge(coord, new Label(0, Location.BOUNDARY, left, right)); insertEdge(e); // insert the endpoint as a node, to mark that it is on the boundary insertPoint(argIndex, coord[0], Location.BOUNDARY); */ }
/// <summary> /// This routine Checks to see if a shell is properly contained in a hole. /// </summary> /// <param name="shell"></param> /// <param name="hole"></param> /// <param name="graph"></param> private void CheckShellInsideHole(LinearRing shell, LinearRing hole, GeometryGraph graph) { Coordinates shellPts = shell.GetCoordinates(); Coordinates holePts = hole.GetCoordinates(); // TODO: improve performance of this - by sorting pointlists for instance? Coordinate shellPt = FindPtNotNode(shellPts, hole, graph); // if point is on shell but not hole, Check that the shell is inside the hole if (shellPt != null) { bool insideHole = _cga.IsPointInRing(shellPt, holePts); if (! insideHole) _validErr = new TopologyValidationError( TopologyValidationError.NestedShells, shellPt); return; } Coordinate holePt = FindPtNotNode(holePts, shell, graph); // if point is on hole but not shell, Check that the hole is outside the shell if (holePt != null) { bool insideShell = _cga.IsPointInRing(holePt, shellPts); if (insideShell) { _validErr = new TopologyValidationError( TopologyValidationError.NestedShells, holePt); } return; } throw new InvalidOperationException("Points in shell and hole appear to be equal."); }
/// <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 /// CheckRelateConsistency /// </summary> /// <param name="shell"></param> /// <param name="p"></param> /// <param name="graph"></param> private void CheckShellNotNested(LinearRing shell, Polygon p, GeometryGraph graph) { Coordinates shellPts = shell.GetCoordinates(); // test if shell is inside polygon shell LinearRing polyShell = (LinearRing) p.GetExteriorRing(); Coordinates polyPts = polyShell.GetCoordinates(); Coordinate shellPt = FindPtNotNode(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 = _cga.IsPointInRing(shellPt, polyPts); if (! insidePolyShell) return; // if no holes, this is an error! if (p.GetNumInteriorRing() <= 0) { _validErr = new TopologyValidationError( TopologyValidationError.NestedShells, shellPt); return; } for (int i = 0; i < p.GetNumInteriorRing(); i++) { LinearRing hole = p.GetInteriorRingN( i ); CheckShellInsideHole(shell, hole, graph); if (_validErr != null) return; } }