/// <summary>
        /// 
        /// </summary>
        /// <param name="g0"></param>
        public GeometryGraphOperation(IGeometry g0) 
        {
            ComputationPrecision = g0.PrecisionModel;

            arg = new GeometryGraph[1];
            arg[0] = new GeometryGraph(0, g0);;
        }
        /// <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);
        }
Exemplo n.º 3
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;
 }
Exemplo n.º 4
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;
        }
Exemplo n.º 5
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);                            
         }
     }
 }
Exemplo n.º 6
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);        
        }
Exemplo n.º 7
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="geom"></param>
        public virtual void ComputeLabelling(GeometryGraph[] geom)
        {
            ComputeEdgeEndLabels();
            // Propagate side labels  around the edges in the star
            // for each parent Geometry        
            PropagateSideLabels(0);        
            PropagateSideLabels(1);        

            /*
            * If there are edges that still have null labels for a point
            * this must be because there are no area edges for that point incident on this node.
            * In this case, to label the edge for that point we must test whether the
            * edge is in the interior of the point.
            * To do this it suffices to determine whether the node for the edge is in the interior of an area.
            * If so, the edge has location Interior for the point.
            * In all other cases (e.g. the node is on a line, on a point, or not on the point at all) the edge
            * has the location Exterior for the point.
            * 
            * Note that the edge cannot be on the Boundary of the point, since then
            * there would have been a parallel edge from the Geometry at this node also labelled Boundary
            * and this edge would have been labelled in the previous step.
            * 
            * This code causes a problem when dimensional collapses are present, since it may try and
            * determine the location of a node where a dimensional collapse has occurred.
            * The point should be considered to be on the Exterior
            * of the polygon, but locate() will return Interior, since it is passed
            * the original Geometry, not the collapsed version.
            *
            * If there are incident edges which are Line edges labelled Boundary,
            * then they must be edges resulting from dimensional collapses.
            * In this case the other edges can be labelled Exterior for this Geometry.
            *
            * MD 8/11/01 - NOT True!  The collapsed edges may in fact be in the interior of the Geometry,
            * which means the other edges should be labelled Interior for this Geometry.
            * Not sure how solve this...  Possibly labelling needs to be split into several phases:
            * area label propagation, symLabel merging, then finally null label resolution.
            */
            bool[] hasDimensionalCollapseEdge = { false, false };
            for (IEnumerator it = GetEnumerator(); it.MoveNext(); ) 
            {
                EdgeEnd e = (EdgeEnd) it.Current;
                Label label = e.Label;
                for (int geomi = 0; geomi < 2; geomi++) 
                    if (label.IsLine(geomi) && label.GetLocation(geomi) == Locations.Boundary)
                        hasDimensionalCollapseEdge[geomi] = true;                
            }        
            for (IEnumerator it = GetEnumerator(); it.MoveNext(); ) 
            {
                EdgeEnd e = (EdgeEnd) it.Current;
                Label label = e.Label;        
                for (int geomi = 0; geomi < 2; geomi++) 
                {
                    if (label.IsAnyNull(geomi)) 
                    {
                        Locations loc = Locations.Null;
                        if (hasDimensionalCollapseEdge[geomi])
                            loc = Locations.Exterior;                
                        else 
                        {
                            ICoordinate p = e.Coordinate;
                            loc = GetLocation(geomi, p, geom);
                        }
                        label.SetAllLocationsIfNull(geomi, loc);
                    }
                }        
            }        
        }
Exemplo n.º 8
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;
         }                
     }         
 }
Exemplo n.º 9
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);        
 }
Exemplo n.º 10
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;
                }
            }            
        }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="graph"></param>
 public SweeplineNestedRingTester(GeometryGraph graph)
 {
     this.graph = graph;
 }
Exemplo n.º 12
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="graph"></param>
 public SimpleNestedRingTester(GeometryGraph graph)
 {
     this.graph = graph;
 }
Exemplo n.º 13
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);
 }
Exemplo n.º 14
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);
        }
Exemplo n.º 15
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);
        }
Exemplo n.º 16
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);
 }
Exemplo n.º 17
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="geomGraph"></param>
 public ConnectedInteriorTester(GeometryGraph geomGraph)
 {
     this.geomGraph = geomGraph;
 }
Exemplo n.º 18
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);
                }
            }        
        }
Exemplo n.º 19
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;
 }
Exemplo n.º 20
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);
        }
Exemplo n.º 21
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;
 }
Exemplo n.º 22
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="geomIndex"></param>
 /// <param name="p"></param>
 /// <param name="geom"></param>
 /// <returns></returns>
 public Locations GetLocation(int geomIndex, ICoordinate p, GeometryGraph[] geom)
 {
     // compute location only on demand
     if (ptInAreaLocation[geomIndex] == Locations.Null) 
         ptInAreaLocation[geomIndex] = SimplePointInAreaLocator.Locate(p, geom[geomIndex].Geometry);            
     return ptInAreaLocation[geomIndex];
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="graph"></param>
 public QuadtreeNestedRingTester(GeometryGraph graph)
 {
     this.graph = graph;
 }
Exemplo n.º 24
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;
 }
Exemplo n.º 25
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="graph"></param>
 private void CheckTooFewPoints(GeometryGraph graph)
 {
     if (graph.HasTooFewPoints)
     {
         validErr = new TopologyValidationError(TopologyValidationErrors.TooFewPoints,
             graph.InvalidPoint);
         return;
     }
 }
Exemplo n.º 26
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;
 }
Exemplo n.º 27
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));            
     }
 }
Exemplo n.º 28
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;
     }
 }
Exemplo n.º 29
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;
     }
 }
Exemplo n.º 30
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="arg"></param>
 public RelateComputer(GeometryGraph[] arg)
 {
     this.arg = arg;
 }