예제 #1
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="g0"></param>
        public GeometryGraphOperation(IGeometry g0)
        {
            ComputationPrecision = g0.PrecisionModel;

            arg = new GeometryGraph[1];
            arg[0] = new GeometryGraph(0, g0);;
        }
예제 #2
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="g0"></param>
        /// <param name="g1"></param>
        public GeometryGraphOperation(IGeometry g0, IGeometry g1)
        {
            // use the most precise model for the result
            if (g0.PrecisionModel.CompareTo(g1.PrecisionModel) >= 0)
                 ComputationPrecision = g0.PrecisionModel;
            else ComputationPrecision = g1.PrecisionModel;

            arg = new GeometryGraph[2];
            arg[0] = new GeometryGraph(0, g0);
            arg[1] = new GeometryGraph(1, g1);
        }
예제 #3
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="geomGraph"></param>
        public void Build(GeometryGraph geomGraph)
        {
            // compute nodes for intersections between previously noded edges
            ComputeIntersectionNodes(geomGraph, 0);
            /*
            * Copy the labelling for the nodes in the parent Geometry.  These override
            * any labels determined by intersections.
            */
            CopyNodesAndLabels(geomGraph, 0);

            /*
            * Build EdgeEnds for all intersections.
            */
            EdgeEndBuilder eeBuilder = new EdgeEndBuilder();
            IList eeList = eeBuilder.ComputeEdgeEnds(geomGraph.GetEdgeEnumerator());
            InsertEdgeEnds(eeList);
        }
예제 #4
0
 /// <summary>
 /// Insert nodes for all intersections on the edges of a Geometry.
 /// Label the created nodes the same as the edge label if they do not already have a label.
 /// This allows nodes created by either self-intersections or
 /// mutual intersections to be labelled.
 /// Endpoint nodes will already be labelled from when they were inserted.
 /// Precondition: edge intersections have been computed.
 /// </summary>
 /// <param name="geomGraph"></param>
 /// <param name="argIndex"></param>
 public void ComputeIntersectionNodes(GeometryGraph geomGraph, int argIndex)
 {
     for (IEnumerator edgeIt = geomGraph.GetEdgeEnumerator(); edgeIt.MoveNext(); )
     {
         Edge e = (Edge) edgeIt.Current;
         Locations eLoc = e.Label.GetLocation(argIndex);
         for (IEnumerator eiIt = e.EdgeIntersectionList.GetEnumerator(); eiIt.MoveNext(); )
         {
             EdgeIntersection ei = (EdgeIntersection) eiIt.Current;
             RelateNode n = (RelateNode) nodes.AddNode(ei.Coordinate);
             if (eLoc == Locations.Boundary)
                 n.SetLabelBoundary(argIndex);
             else if (n.Label.IsNull(argIndex))
                 n.SetLabel(argIndex, Locations.Interior);
         }
     }
 }
예제 #5
0
        /// <summary> 
        /// Compute the labelling for all dirEdges in this star, as well
        /// as the overall labelling.
        /// </summary>
        /// <param name="geom"></param>
        public override void ComputeLabelling(GeometryGraph[] geom)
        {
            base.ComputeLabelling(geom);

            // determine the overall labelling for this DirectedEdgeStar
            // (i.e. for the node it is based at)
            label = new Label(Locations.Null);
            IEnumerator it = GetEnumerator();
            while(it.MoveNext())
            {
                EdgeEnd ee = (EdgeEnd)it.Current;
                Edge e = ee.Edge;
                Label eLabel = e.Label;
                for (int i = 0; i < 2; i++)
                {
                    Locations eLoc = eLabel.GetLocation(i);
                    if (eLoc == Locations.Interior || eLoc == Locations.Boundary)
                        label.SetLocation(i, Locations.Interior);
                }
            }
        }
예제 #6
0
 /// <summary>
 /// For all edges, check if there are any intersections which are NOT at an endpoint.
 /// The Geometry is not simple if there are intersections not at endpoints.
 /// </summary>
 /// <param name="graph"></param>
 private bool HasNonEndpointIntersection(GeometryGraph graph)
 {
     for (IEnumerator i = graph.GetEdgeEnumerator(); i.MoveNext(); )
     {
         Edge e = (Edge) i.Current;
         int maxSegmentIndex = e.MaximumSegmentIndex;
         for (IEnumerator eiIt = e.EdgeIntersectionList.GetEnumerator(); eiIt.MoveNext(); )
         {
             EdgeIntersection ei = (EdgeIntersection) eiIt.Current;
             if (!ei.IsEndPoint(maxSegmentIndex))
                 return true;
         }
     }
     return false;
 }
예제 #7
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="graph"></param>
 public SweeplineNestedRingTester(GeometryGraph graph)
 {
     this.graph = graph;
 }
예제 #8
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="g"></param>
        private void CheckValid(IMultiPolygon g)
        {
            foreach(IPolygon p in g.Geometries)
            {
                CheckInvalidCoordinates(p);
                if (validErr != null) return;
                CheckClosedRings(p);
                if (validErr != null) return;
            }

            GeometryGraph graph = new GeometryGraph(0, g);
            CheckTooFewPoints(graph);
            if (validErr != null) return;
            CheckConsistentArea(graph);
            if (validErr != null) return;
            if (!IsSelfTouchingRingFormingHoleValid)
            {
                CheckNoSelfIntersectingRings(graph);
                if (validErr != null) return;
            }
            foreach(IPolygon p in g.Geometries)
            {
                CheckHolesInShell(p, graph);
                if (validErr != null) return;
            }
            foreach (IPolygon p in g.Geometries)
            {
                CheckHolesNotNested(p, graph);
                if (validErr != null) return;
            }
            CheckShellsNotNested(g, graph);
            if (validErr != null) return;
            CheckConnectedInteriors(graph);
        }
예제 #9
0
 /// <summary>
 /// Checks validity of a LineString.  
 /// Almost anything goes for lineStrings!
 /// </summary>
 /// <param name="g"></param>
 private void CheckValid(ILineString g)
 {
     CheckInvalidCoordinates(g.Coordinates);
     if (validErr != null) return;
     GeometryGraph graph = new GeometryGraph(0, g);
     CheckTooFewPoints(graph);
 }
예제 #10
0
 /// <summary>
 /// Tests that no element polygon is wholly in the interior of another element polygon.
 /// Preconditions:
 /// Shells do not partially overlap.
 /// Shells do not touch along an edge.
 /// No duplicate rings exists.
 /// This routine relies on the fact that while polygon shells may touch at one or
 /// more vertices, they cannot touch at ALL vertices.
 /// </summary>
 private void CheckShellsNotNested(IMultiPolygon mp, GeometryGraph graph)
 {
     for (int i = 0; i < mp.NumGeometries; i++)
     {
         IPolygon p = (IPolygon) mp.GetGeometryN(i);
         ILinearRing shell = p.Shell;
         for (int j = 0; j < mp.NumGeometries; j++)
         {
             if (i == j)
                 continue;
             IPolygon p2 = (IPolygon) mp.GetGeometryN(j);
             CheckShellNotNested(shell, p2, graph);
             if (validErr != null) return;
         }
     }
 }
예제 #11
0
 /// <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 ICoordinate CheckShellInsideHole(ILinearRing shell, ILinearRing hole, GeometryGraph graph)
 {
     ICoordinate[] shellPts = shell.Coordinates;
     ICoordinate[] holePts = hole.Coordinates;
     // TODO: improve performance of this - by sorting pointlists?
     ICoordinate 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;
     }
     ICoordinate 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;
 }
예제 #12
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="graph"></param>
 public QuadtreeNestedRingTester(GeometryGraph graph)
 {
     this.graph = graph;
 }
예제 #13
0
 /// <summary> 
 /// Test that no edge intersection is the
 /// endpoint of a closed line.  To check this we compute the
 /// degree of each endpoint. The degree of endpoints of closed lines
 /// must be exactly 2.
 /// </summary>
 /// <param name="graph"></param>
 private bool HasClosedEndpointIntersection(GeometryGraph graph)
 {
     IDictionary endPoints = new SortedList();
     for (IEnumerator i = graph.GetEdgeEnumerator(); i.MoveNext(); )
     {
         Edge e = (Edge) i.Current;
         bool isClosed = e.IsClosed;
         ICoordinate p0 = e.GetCoordinate(0);
         AddEndpoint(endPoints, p0, isClosed);
         ICoordinate p1 = e.GetCoordinate(e.NumPoints - 1);
         AddEndpoint(endPoints, p1, isClosed);
     }
     for (IEnumerator i = endPoints.Values.GetEnumerator(); i.MoveNext(); )
     {
         EndpointInfo eiInfo = (EndpointInfo) i.Current;
         if (eiInfo.IsClosed && eiInfo.Degree != 2)
             return true;
     }
     return false;
 }
예제 #14
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="geom"></param>
        /// <returns></returns>
        private bool IsSimpleLinearGeometry(IGeometry geom)
        {
            if (geom.IsEmpty)
                return true;

            GeometryGraph graph = new GeometryGraph(0, geom);
            LineIntersector li = new RobustLineIntersector();
            SegmentIntersector si = graph.ComputeSelfNodes(li, true);
            // if no self-intersection, must be simple
            if (!si.HasIntersection) return true;
            if (si.HasProperIntersection) return false;
            if (HasNonEndpointIntersection(graph)) return false;
            if (HasClosedEndpointIntersection(graph)) return false;
            return true;
        }
예제 #15
0
 /// <summary>
 /// Tests that no hole is nested inside another hole.
 /// This routine assumes that the holes are disjoint.
 /// To ensure this, holes have previously been tested
 /// to ensure that:
 /// They do not partially overlap
 /// (checked by <c>checkRelateConsistency</c>).
 /// They are not identical
 /// (checked by <c>checkRelateConsistency</c>).
 /// </summary>
 private void CheckHolesNotNested(IPolygon p, GeometryGraph graph)
 {
     QuadtreeNestedRingTester nestedTester = new QuadtreeNestedRingTester(graph);
     foreach (ILinearRing innerHole in p.Holes)
         nestedTester.Add(innerHole);
     bool isNonNested = nestedTester.IsNonNested();
     if (!isNonNested)
         validErr = new TopologyValidationError(TopologyValidationErrors.NestedHoles,
             nestedTester.NestedPoint);
 }
예제 #16
0
 /// <summary>
 /// Check that there is no ring which self-intersects (except of course at its endpoints).
 /// This is required by OGC topology rules (but not by other models
 /// such as ESRI SDE, which allow inverted shells and exverted holes).
 /// </summary>
 /// <param name="graph"></param>
 private void CheckNoSelfIntersectingRings(GeometryGraph graph)
 {
     for (IEnumerator i = graph.GetEdgeEnumerator(); i.MoveNext(); )
     {
         Edge e = (Edge) i.Current;
         CheckNoSelfIntersectingRing(e.EdgeIntersectionList);
         if (validErr != null) return;
     }
 }
예제 #17
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="arg"></param>
 public RelateComputer(GeometryGraph[] arg)
 {
     this.arg = arg;
 }
예제 #18
0
        /// <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(ILinearRing shell, IPolygon p, GeometryGraph graph)
        {
            ICoordinate[] shellPts = shell.Coordinates;
            // test if shell is inside polygon shell
            ILinearRing polyShell = p.Shell;
            ICoordinate[] polyPts = polyShell.Coordinates;
            ICoordinate 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.NumInteriorRings <= 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.
             */
            ICoordinate badNestedPt = null;
            for (int i = 0; i < p.NumInteriorRings; i++)
            {
                ILinearRing hole = p.Holes[i];
                badNestedPt = CheckShellInsideHole(shell, hole, graph);
                if (badNestedPt == null) return;
            }
            validErr = new TopologyValidationError(TopologyValidationErrors.NestedShells, badNestedPt);
        }
예제 #19
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="geomGraph"></param>
 public ConsistentAreaTester(GeometryGraph geomGraph)
 {
     this.geomGraph = geomGraph;
 }
예제 #20
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="graph"></param>
 private void CheckTooFewPoints(GeometryGraph graph)
 {
     if (graph.HasTooFewPoints)
     {
         validErr = new TopologyValidationError(TopologyValidationErrors.TooFewPoints,
             graph.InvalidPoint);
         return;
     }
 }
예제 #21
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="geomGraph"></param>
 public ConnectedInteriorTester(GeometryGraph geomGraph)
 {
     this.geomGraph = geomGraph;
 }
예제 #22
0
        /// <summary>
        /// Checks validity of a LinearRing.
        /// </summary>
        /// <param name="g"></param>
        private void CheckValid(ILinearRing g)
        {
            CheckInvalidCoordinates(g.Coordinates);
            if (validErr != null) return;
            CheckClosedRing(g);
            if (validErr != null) return;

            GeometryGraph graph = new GeometryGraph(0, g);
            CheckTooFewPoints(graph);
            if (validErr != null) return;
            LineIntersector li = new RobustLineIntersector();
            graph.ComputeSelfNodes(li, true);
            CheckNoSelfIntersectingRings(graph);
        }
예제 #23
0
 /// <summary>
 /// Find a point from the list of testCoords
 /// that is NOT a node in the edge for the list of searchCoords.
 /// </summary>
 /// <param name="testCoords"></param>
 /// <param name="searchRing"></param>
 /// <param name="graph"></param>
 /// <returns>The point found, or <c>null</c> if none found.</returns>
 public static ICoordinate FindPointNotNode(ICoordinate[] testCoords, ILinearRing searchRing, GeometryGraph graph)
 {
     // find edge corresponding to searchRing.
     Edge searchEdge = graph.FindEdge(searchRing);
     // find a point in the testCoords which is not a node of the searchRing
     EdgeIntersectionList eiList = searchEdge.EdgeIntersectionList;
     // somewhat inefficient - is there a better way? (Use a node map, for instance?)
     foreach(ICoordinate pt in testCoords)
         if(!eiList.IsIntersection(pt))
             return pt;
     return null;
 }
예제 #24
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="graph"></param>
 public SimpleNestedRingTester(GeometryGraph graph)
 {
     this.graph = graph;
 }
예제 #25
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="graph"></param>
 private void CheckConnectedInteriors(GeometryGraph graph)
 {
     ConnectedInteriorTester cit = new ConnectedInteriorTester(graph);
     if (!cit.IsInteriorsConnected())
         validErr = new TopologyValidationError(TopologyValidationErrors.DisconnectedInteriors,
             cit.Coordinate);
 }
예제 #26
0
 /// <summary>
 /// Copy all nodes from an arg point into this graph.
 /// The node label in the arg point overrides any previously computed
 /// label for that argIndex.
 /// (E.g. a node may be an intersection node with
 /// a computed label of Boundary,
 /// but in the original arg Geometry it is actually
 /// in the interior due to the Boundary Determination Rule).
 /// </summary>
 /// <param name="geomGraph"></param>
 /// <param name="argIndex"></param>
 public void CopyNodesAndLabels(GeometryGraph geomGraph, int argIndex)
 {
     for (IEnumerator nodeIt = geomGraph.GetNodeEnumerator(); nodeIt.MoveNext(); )
     {
         Node graphNode = (Node) nodeIt.Current;
         Node newNode = nodes.AddNode(graphNode.Coordinate);
         newNode.SetLabel(argIndex, graphNode.Label.GetLocation(argIndex));
     }
 }
예제 #27
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="graph"></param>
 private void CheckConsistentArea(GeometryGraph graph)
 {
     ConsistentAreaTester cat = new ConsistentAreaTester(graph);
     bool isValidArea = cat.IsNodeConsistentArea;
     if (!isValidArea)
     {
         validErr = new TopologyValidationError(TopologyValidationErrors.SelfIntersection, cat.InvalidPoint);
         return;
     }
     if (cat.HasDuplicateRings)
     {
         validErr = new TopologyValidationError(TopologyValidationErrors.DuplicateRings, cat.InvalidPoint);
         return;
     }
 }
예제 #28
0
        /// <summary>
        /// Tests 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">A GeometryGraph incorporating the polygon.</param>
        private void CheckHolesInShell(IPolygon p, GeometryGraph graph)
        {
            ILinearRing shell = p.Shell;

            IPointInRing pir = new MCPointInRing(shell);
            for (int i = 0; i < p.NumInteriorRings; i++)
            {
                ILinearRing hole = p.Holes[i];
                ICoordinate holePt = FindPointNotNode(hole.Coordinates, shell, graph);

                /*
                 * If no non-node hole vertex can be found, the hole must
                 * split the polygon into disconnected interiors.
                 * This will be caught by a subsequent check.
                 */
                if (holePt == null)
                    return;

                bool outside = !pir.IsInside((Coordinate) holePt);
                if(outside)
                {
                    validErr = new TopologyValidationError(TopologyValidationErrors.HoleOutsideShell, holePt);
                    return;
                }
            }
        }
예제 #29
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="g"></param>
 /// <param name="li"></param>
 /// <param name="includeProper"></param>
 /// <returns></returns>
 public SegmentIntersector ComputeEdgeIntersections(GeometryGraph g, 
     LineIntersector li, bool includeProper)
 {
     SegmentIntersector si = new SegmentIntersector(li, includeProper, true);
     si.SetBoundaryNodes(BoundaryNodes, g.BoundaryNodes);
     EdgeSetIntersector esi = CreateEdgeSetIntersector();
     esi.ComputeIntersections(edges, g.edges, si);
     return si;
 }