/// <summary> /// Check that a ring does not self-intersect, except at its endpoints. /// Algorithm is to count the number of times each node along edge occurs. /// If any occur more than once, that must be a self-intersection. /// </summary> /// <param name="eiList"></param> private void CheckSelfIntersectingRing(EdgeIntersectionList eiList) { //Set nodeSet = new TreeSet(); awc don't need sorted list, just a hashtable Hashtable nodeSet = new Hashtable(); bool isFirst = true; //for (Iterator i = eiList.iterator(); i.hasNext(); ) foreach (EdgeIntersection ei in eiList) { //EdgeIntersection ei = (EdgeIntersection) i.next(); if (isFirst) { isFirst = false; continue; } if (nodeSet.Contains(ei.Coordinate)) { _validErr = new TopologyValidationError( TopologyValidationError.RingSelfIntersection, ei.Coordinate); return; } else { //TODO: awc - should probably use hashcode nodeSet.Add(ei.Coordinate, ei.Coordinate); } } }
/// <summary> /// Test that each hole is inside the polygon shell. /// This routine assumes that the holes have previously been tested /// to ensure that all vertices lie on the shell or inside it. /// A simple test of a single point in the hole can be used, /// provide the point is chosen such that it does not lie on the /// boundary of the shell. /// </summary> /// <param name="p">The polygon to be tested for hole inclusion.</param> /// <param name="graph">Graph a GeometryGraph incorporating the polygon.</param> private void CheckHolesInShell(Polygon p, GeometryGraph graph) { LinearRing shell = (LinearRing)p.GetExteriorRing(); Coordinates shellPts = shell.GetCoordinates(); //PointInRing pir = new SimplePointInRing(shell); //PointInRing pir = new SIRtreePointInRing(shell); IPointInRing pir = new MCPointInRing(shell); for (int i = 0; i < p.GetNumInteriorRing(); i++) { LinearRing hole = (LinearRing)p.GetInteriorRingN(i); Coordinate holePt = FindPtNotNode(hole.GetCoordinates(), shell, graph); if (holePt == null) { throw new InvalidOperationException("Unable to find a hole point not a vertex of the shell."); } bool outside = !pir.IsInside(holePt); if (outside) { _validErr = new TopologyValidationError( TopologyValidationError.HoleOutsideShell, holePt); return; } } }
/// <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."); }
private void CheckTooFewPoints(GeometryGraph graph) { if (graph.HasTooFewPoints()) { _validErr = new TopologyValidationError( TopologyValidationError.TooFewPoints, graph.GetInvalidPoint()); return; } }
private void CheckConnectedInteriors(GeometryGraph graph) { ConnectedInteriorTester cit = new ConnectedInteriorTester(graph); if (!cit.IsInteriorsConnected()) { _validErr = new TopologyValidationError( TopologyValidationError.DisconnectedInterior, cit.GetCoordinate()); } }
private void CheckConsistentArea(GeometryGraph graph) { ConsistentAreaTester cat = new ConsistentAreaTester(graph); bool isValidArea = cat.IsNodeConsistentArea(); if (!isValidArea) { _validErr = new TopologyValidationError( TopologyValidationError.SelfIntersection, cat.GetInvalidPoint()); return; } if (cat.HasDuplicateRings()) { _validErr = new TopologyValidationError( TopologyValidationError.DuplicateRings, cat.GetInvalidPoint()); } }
private void CheckValid(Geometry g) { if (_isChecked) { return; } _validErr = null; if (g.IsEmpty()) { return; } if (g is Point) { return; } else if (g is MultiPoint) { return; } // LineString also handles LinearRings else if (g is LineString) { CheckValid((LineString)g); } else if (g is Polygon) { CheckValid((Polygon)g); } else if (g is MultiPolygon) { CheckValid((MultiPolygon)g); } else if (g is GeometryCollection) { CheckValid((GeometryCollection)g); } else { throw new NotSupportedException(g.GetType().Name); } }
/// <summary> /// Tests that no hole is nested inside another hole. /// </summary> /// <remarks> /// This routine assumes that the holes are disjoint. /// To ensure this, holes have previously been tested /// to ensure that: /// <ul> /// <li>they do not partially overlap /// (Checked by CheckRelateConsistency)</li> /// <li>they are not identical /// (Checked by CheckRelateConsistency)</li> /// <li>they do not touch at a vertex /// (Checked by ????)</li> /// </ul> /// </remarks> /// <param name="p"></param> /// <param name="graph"></param> private void CheckHolesNotNested(Polygon p, GeometryGraph graph) { QuadtreeNestedRingTester nestedTester = new QuadtreeNestedRingTester(graph); //SimpleNestedRingTester nestedTester = new SimpleNestedRingTester(_arg[0]); //SweeplineNestedRingTester nestedTester = new SweeplineNestedRingTester(_arg[0]); for (int i = 0; i < p.GetNumInteriorRing(); i++) { LinearRing innerHole = p.GetInteriorRingN(i); nestedTester.Add(innerHole); } bool isNonNested = nestedTester.IsNonNested(); if (!isNonNested) { _validErr = new TopologyValidationError( TopologyValidationError.NestedHoles, nestedTester.GetNestedPoint()); } }
/// <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; } } }
private void CheckValid(Geometry g) { if (_isChecked) { return; } _validErr = null; if ( g.IsEmpty() ) { return; } if (g is Point) { return; } else if (g is MultiPoint) { return; } // LineString also handles LinearRings else if (g is LineString) { CheckValid( (LineString) g); } else if (g is Polygon) { CheckValid( (Polygon) g); } else if (g is MultiPolygon) { CheckValid( (MultiPolygon) g); } else if (g is GeometryCollection) { CheckValid( (GeometryCollection) g); } else throw new NotSupportedException(g.GetType().Name); }
private void CheckConsistentArea(GeometryGraph graph) { ConsistentAreaTester cat = new ConsistentAreaTester(graph); bool isValidArea = cat.IsNodeConsistentArea(); if (! isValidArea) { _validErr = new TopologyValidationError( TopologyValidationError.SelfIntersection, cat.GetInvalidPoint()); return; } if (cat.HasDuplicateRings()) { _validErr = new TopologyValidationError( TopologyValidationError.DuplicateRings, cat.GetInvalidPoint()); } }
/// <summary> /// Test that each hole is inside the polygon shell. /// This routine assumes that the holes have previously been tested /// to ensure that all vertices lie on the shell or inside it. /// A simple test of a single point in the hole can be used, /// provide the point is chosen such that it does not lie on the /// boundary of the shell. /// </summary> /// <param name="p">The polygon to be tested for hole inclusion.</param> /// <param name="graph">Graph a GeometryGraph incorporating the polygon.</param> private void CheckHolesInShell(Polygon p, GeometryGraph graph) { LinearRing shell = (LinearRing) p.GetExteriorRing(); Coordinates shellPts = shell.GetCoordinates(); //PointInRing pir = new SimplePointInRing(shell); //PointInRing pir = new SIRtreePointInRing(shell); IPointInRing pir = new MCPointInRing(shell); for (int i = 0; i < p.GetNumInteriorRing(); i++) { LinearRing hole = (LinearRing) p.GetInteriorRingN(i); Coordinate holePt = FindPtNotNode(hole.GetCoordinates(), shell, graph); if (holePt == null) { throw new InvalidOperationException("Unable to find a hole point not a vertex of the shell."); } bool outside = ! pir.IsInside(holePt); if ( outside ) { _validErr = new TopologyValidationError( TopologyValidationError.HoleOutsideShell, holePt); return; } } }
/// <summary> /// Check that a ring does not self-intersect, except at its endpoints. /// Algorithm is to count the number of times each node along edge occurs. /// If any occur more than once, that must be a self-intersection. /// </summary> /// <param name="eiList"></param> private void CheckSelfIntersectingRing(EdgeIntersectionList eiList) { //Set nodeSet = new TreeSet(); awc don't need sorted list, just a hashtable Hashtable nodeSet = new Hashtable(); bool isFirst = true; //for (Iterator i = eiList.iterator(); i.hasNext(); ) foreach(EdgeIntersection ei in eiList) { //EdgeIntersection ei = (EdgeIntersection) i.next(); if (isFirst) { isFirst = false; continue; } if (nodeSet.Contains(ei.Coordinate)) { _validErr = new TopologyValidationError( TopologyValidationError.RingSelfIntersection, ei.Coordinate); return; } else { //TODO: awc - should probably use hashcode nodeSet.Add(ei.Coordinate, ei.Coordinate); } } }
/// <summary> /// Tests that no hole is nested inside another hole. /// </summary> /// <remarks> /// This routine assumes that the holes are disjoint. /// To ensure this, holes have previously been tested /// to ensure that: /// <ul> /// <li>they do not partially overlap /// (Checked by CheckRelateConsistency)</li> /// <li>they are not identical /// (Checked by CheckRelateConsistency)</li> /// <li>they do not touch at a vertex /// (Checked by ????)</li> /// </ul> /// </remarks> /// <param name="p"></param> /// <param name="graph"></param> private void CheckHolesNotNested(Polygon p, GeometryGraph graph) { QuadtreeNestedRingTester nestedTester = new QuadtreeNestedRingTester(graph); //SimpleNestedRingTester nestedTester = new SimpleNestedRingTester(_arg[0]); //SweeplineNestedRingTester nestedTester = new SweeplineNestedRingTester(_arg[0]); for (int i = 0; i < p.GetNumInteriorRing(); i++) { LinearRing innerHole = p.GetInteriorRingN( i ); nestedTester.Add(innerHole); } bool isNonNested = nestedTester.IsNonNested(); if ( ! isNonNested ) { _validErr = new TopologyValidationError( TopologyValidationError.NestedHoles, nestedTester.GetNestedPoint()); } }
/// <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; } }
private void CheckConnectedInteriors(GeometryGraph graph) { ConnectedInteriorTester cit = new ConnectedInteriorTester(graph); if (! cit.IsInteriorsConnected()) { _validErr = new TopologyValidationError( TopologyValidationError.DisconnectedInterior, cit.GetCoordinate()); } }
/// <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."); }