示例#1
0
        /// <summary>
        /// Collect edges from Area inputs which should be in the result but
        /// which have not been included in a result area.
        /// This happens ONLY:
        /// during an intersection when the boundaries of two
        /// areas touch in a line segment
        /// OR as a result of a dimensional collapse.
        /// </summary>
        /// <param name="de"></param>
        /// <param name="opCode"></param>
        /// <param name="edges"></param>
        public void CollectBoundaryTouchEdge(DirectedEdge de, SpatialFunctions opCode, IList edges)
        {
            Label label = de.Label;

            if (de.IsLineEdge)
            {
                return;         // only interested in area edges
            }
            if (de.IsVisited)
            {
                return;         // already processed
            }
            if (de.IsInteriorAreaEdge)
            {
                return; // added to handle dimensional collapses
            }
            if (de.Edge.IsInResult)
            {
                return;     // if the edge linework is already included, don't include it again
            }
            // sanity check for labelling of result edgerings
            Assert.IsTrue(!(de.IsInResult || de.Sym.IsInResult) || !de.Edge.IsInResult);
            // include the linework if it's in the result of the operation
            if (OverlayOp.IsResultOfOp(label, opCode) && opCode == SpatialFunctions.Intersection)
            {
                edges.Add(de.Edge);
                de.VisitedEdge = true;
            }
        }
示例#2
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="opCode"></param>
 /// <returns>
 /// A list of the LineStrings in the result of the specified overlay operation.
 /// </returns>
 public IList Build(SpatialFunctions opCode)
 {
     FindCoveredLineEdges();
     CollectLines(opCode);
     BuildLines(opCode);
     return resultLineList;
 }
示例#3
0
        /// <summary>
        /// This method will handle arguments of Location.NULL correctly.
        /// </summary>
        /// <returns><c>true</c> if the locations correspond to the opCode.</returns>
        public static bool IsResultOfOp(Locations loc0, Locations loc1, SpatialFunctions opCode)
        {
            if (loc0 == Locations.Boundary)
            {
                loc0 = Locations.Interior;
            }
            if (loc1 == Locations.Boundary)
            {
                loc1 = Locations.Interior;
            }

            switch (opCode)
            {
            case SpatialFunctions.Intersection:
                return(loc0 == Locations.Interior && loc1 == Locations.Interior);

            case SpatialFunctions.Union:
                return(loc0 == Locations.Interior || loc1 == Locations.Interior);

            case SpatialFunctions.Difference:
                return(loc0 == Locations.Interior && loc1 != Locations.Interior);

            case SpatialFunctions.SymDifference:
                return((loc0 == Locations.Interior && loc1 != Locations.Interior) ||
                       (loc0 != Locations.Interior && loc1 == Locations.Interior));

            default:
                return(false);
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="opCode"></param>
        /// <returns>
        /// A list of the Points in the result of the specified overlay operation.
        /// </returns>
        public virtual IList Build(SpatialFunctions opCode)
        {
            IList nodeList        = CollectNodes(opCode);
            IList resultPointList = SimplifyPoints(nodeList);

            return(resultPointList);
        }
示例#5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="geom0"></param>
        /// <param name="geom1"></param>
        /// <param name="opCode"></param>
        /// <returns></returns>
        public static IGeometry Overlay(IGeometry geom0, IGeometry geom1, SpatialFunctions opCode)
        {
            OverlayOp gov    = new OverlayOp(geom0, geom1);
            IGeometry geomOv = gov.GetResultGeometry(opCode);

            return(geomOv);
        }
示例#6
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="label"></param>
        /// <param name="opCode"></param>
        /// <returns></returns>
        public static bool IsResultOfOp(Label label, SpatialFunctions opCode)
        {
            Locations loc0 = label.GetLocation(0);
            Locations loc1 = label.GetLocation(1);

            return(IsResultOfOp(loc0, loc1, opCode));
        }
示例#7
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="opCode"></param>
 /// <returns>
 /// A list of the LineStrings in the result of the specified overlay operation.
 /// </returns>
 public IList Build(SpatialFunctions opCode)
 {
     FindCoveredLineEdges();
     CollectLines(opCode);
     BuildLines(opCode);
     return(resultLineList);
 }
示例#8
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="opCode"></param>
 private void BuildLines(SpatialFunctions opCode)
 {
     for (IEnumerator it = lineEdgesList.GetEnumerator(); it.MoveNext();)
     {
         Edge        e    = (Edge)it.Current;
         ILineString line = geometryFactory.CreateLineString(e.Coordinates);
         resultLineList.Add(line);
         e.InResult = true;
     }
 }
示例#9
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="opCode"></param>
        private void CollectLines(SpatialFunctions opCode)
        {
            IEnumerator it = op.Graph.EdgeEnds.GetEnumerator();

            while (it.MoveNext())
            {
                DirectedEdge de = (DirectedEdge)it.Current;
                CollectLineEdge(de, opCode, lineEdgesList);
                CollectBoundaryTouchEdge(de, opCode, lineEdgesList);
            }
        }
示例#10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="opCode"></param>
        private void ComputeOverlay(SpatialFunctions opCode)
        {
            // copy points from input Geometries.
            // This ensures that any Point geometries
            // in the input are considered for inclusion in the result set
            CopyPoints(0);
            CopyPoints(1);

            // node the input Geometries
            arg[0].ComputeSelfNodes(lineIntersector, false);
            arg[1].ComputeSelfNodes(lineIntersector, false);

            // compute intersections between edges of the two input geometries
            arg[0].ComputeEdgeIntersections(arg[1], lineIntersector, true);

            IList baseSplitEdges = new ArrayList();

            arg[0].ComputeSplitEdges(baseSplitEdges);
            arg[1].ComputeSplitEdges(baseSplitEdges);
            // add the noded edges to this result graph
            InsertUniqueEdges(baseSplitEdges);

            ComputeLabelsFromDepths();
            ReplaceCollapsedEdges();

            graph.AddEdges(edgeList.Edges);
            ComputeLabelling();
            LabelIncompleteNodes();

            /*
             * The ordering of building the result Geometries is important.
             * Areas must be built before lines, which must be built before points.
             * This is so that lines which are covered by areas are not included
             * explicitly, and similarly for points.
             */
            FindResultAreaEdges(opCode);
            CancelDuplicateResultEdges();
            PolygonBuilder polyBuilder = new PolygonBuilder(geomFact);

            polyBuilder.Add(graph);
            resultPolyList = polyBuilder.Polygons;

            LineBuilder lineBuilder = new LineBuilder(this, geomFact, ptLocator);

            resultLineList = lineBuilder.Build(opCode);

            PointBuilder pointBuilder = new PointBuilder(this, geomFact, ptLocator);

            resultPointList = pointBuilder.Build(opCode);

            // gather the results from all calculations into a single Geometry for the result set
            resultGeom = ComputeGeometry(resultPointList, resultLineList, resultPolyList);
        }
示例#11
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="de"></param>
        /// <param name="opCode"></param>
        /// <param name="edges"></param>
        public void CollectLineEdge(DirectedEdge de, SpatialFunctions opCode, IList edges)
        {
            Label label = de.Label;
            Edge  e     = de.Edge;

            // include Curve edges which are in the result
            if (de.IsLineEdge)
            {
                if (!de.IsVisited && OverlayOp.IsResultOfOp(label, opCode) && !e.IsCovered)
                {
                    edges.Add(e);
                    de.VisitedEdge = true;
                }
            }
        }
示例#12
0
        /// <summary>
        /// Find all edges whose label indicates that they are in the result area(s),
        /// according to the operation being performed.  Since we want polygon shells to be
        /// oriented CW, choose dirEdges with the interior of the result on the RHS.
        /// Mark them as being in the result.
        /// Interior Area edges are the result of dimensional collapses.
        /// They do not form part of the result area boundary.
        /// </summary>
        private void FindResultAreaEdges(SpatialFunctions opCode)
        {
            IEnumerator it = graph.EdgeEnds.GetEnumerator();

            while (it.MoveNext())
            {
                DirectedEdge de = (DirectedEdge)it.Current;
                // mark all dirEdges with the appropriate label
                Label label = de.Label;
                if (label.IsArea() && !de.IsInteriorAreaEdge &&
                    IsResultOfOp(label.GetLocation(0, Positions.Right), label.GetLocation(1, Positions.Right), opCode))
                {
                    de.InResult = true;
                }
            }
        }
示例#13
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="opCode"></param>
 /// <returns></returns>
 private IList CollectNodes(SpatialFunctions opCode)
 {
     IList resultNodeList = new ArrayList();
     // add nodes from edge intersections which have not already been included in the result
     IEnumerator nodeit = op.Graph.Nodes.GetEnumerator();
     while (nodeit.MoveNext()) 
     {
         Node n = (Node) nodeit.Current;
         if (!n.IsInResult)
         {
             Label label = n.Label;
             if (OverlayOp.IsResultOfOp(label, opCode))                    
                 resultNodeList.Add(n);                    
         }
     }
     return resultNodeList;
 }
        /// <summary>
        ///
        /// </summary>
        /// <param name="opCode"></param>
        /// <returns></returns>
        private IList CollectNodes(SpatialFunctions opCode)
        {
            IList resultNodeList = new ArrayList();
            // add nodes from edge intersections which have not already been included in the result
            IEnumerator nodeit = op.Graph.Nodes.GetEnumerator();

            while (nodeit.MoveNext())
            {
                Node n = (Node)nodeit.Current;
                if (!n.IsInResult)
                {
                    Label label = n.Label;
                    if (OverlayOp.IsResultOfOp(label, opCode))
                    {
                        resultNodeList.Add(n);
                    }
                }
            }
            return(resultNodeList);
        }
示例#15
0
        /// <summary>
        /// Collect edges from Area inputs which should be in the result but
        /// which have not been included in a result area.
        /// This happens ONLY:
        /// during an intersection when the boundaries of two
        /// areas touch in a line segment
        /// OR as a result of a dimensional collapse.
        /// </summary>
        /// <param name="de"></param>
        /// <param name="opCode"></param>
        /// <param name="edges"></param>
        public void CollectBoundaryTouchEdge(DirectedEdge de, SpatialFunctions opCode, IList edges)
        {
            Label label = de.Label;
            if (de.IsLineEdge)
                return;         // only interested in area edges
            if (de.IsVisited)
                return;         // already processed
            if (de.IsInteriorAreaEdge)
                return; // added to handle dimensional collapses
            if (de.Edge.IsInResult)
                return;     // if the edge linework is already included, don't include it again

            // sanity check for labelling of result edgerings
            Assert.IsTrue(!(de.IsInResult || de.Sym.IsInResult) || !de.Edge.IsInResult);
            // include the linework if it's in the result of the operation
            if (OverlayOp.IsResultOfOp(label, opCode) && opCode == SpatialFunctions.Intersection)
            {
                edges.Add(de.Edge);
                de.VisitedEdge = true;
            }
        }
示例#16
0
        /// <summary>
        /// This method will handle arguments of Location.NULL correctly.
        /// </summary>
        /// <returns><c>true</c> if the locations correspond to the opCode.</returns>
        public static bool IsResultOfOp(Locations loc0, Locations loc1, SpatialFunctions opCode)
        {
            if (loc0 == Locations.Boundary) 
                loc0 = Locations.Interior;
            if (loc1 == Locations.Boundary) 
                loc1 = Locations.Interior;
            
            switch (opCode) 
            {
                case SpatialFunctions.Intersection:
                    return loc0 == Locations.Interior && loc1 == Locations.Interior;
                case SpatialFunctions.Union:
                    return loc0 == Locations.Interior || loc1 == Locations.Interior;
                case SpatialFunctions.Difference:
                    return loc0 == Locations.Interior && loc1 != Locations.Interior;
                case SpatialFunctions.SymDifference:
                    return   (loc0 == Locations.Interior &&  loc1 != Locations.Interior)
                          || (loc0 != Locations.Interior &&  loc1 == Locations.Interior);
	            default:
                    return false;
            }            
        }
示例#17
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="funcCode"></param>
 /// <returns></returns>
 public IGeometry GetResultGeometry(SpatialFunctions funcCode)
 {
     ComputeOverlay(funcCode);
     return(resultGeom);
 }
示例#18
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="de"></param>
 /// <param name="opCode"></param>
 /// <param name="edges"></param>
 public void CollectLineEdge(DirectedEdge de, SpatialFunctions opCode, IList edges)
 {
     Label label = de.Label;
     Edge e = de.Edge;
     // include Curve edges which are in the result
     if (de.IsLineEdge)
     {                
         if (!de.IsVisited && OverlayOp.IsResultOfOp(label, opCode) && !e.IsCovered)
         {                    
             edges.Add(e);                    
             de.VisitedEdge = true;
         }
     }
 }
示例#19
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="opCode"></param>
 /// <returns>
 /// A list of the Points in the result of the specified overlay operation.
 /// </returns>
 public IList Build(SpatialFunctions opCode)
 {
     IList nodeList = CollectNodes(opCode);
     IList resultPointList = SimplifyPoints(nodeList);
     return resultPointList;
 }
示例#20
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="label"></param>
 /// <param name="opCode"></param>
 /// <returns></returns>
 public static bool IsResultOfOp(Label label, SpatialFunctions opCode)
 {
     Locations loc0 = label.GetLocation(0);
     Locations loc1 = label.GetLocation(1);
     return IsResultOfOp(loc0, loc1, opCode);
 }
示例#21
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="geom0"></param>
 /// <param name="geom1"></param>
 /// <param name="opCode"></param>
 /// <returns></returns>
 public static IGeometry Overlay(IGeometry geom0, IGeometry geom1, SpatialFunctions opCode)
 {
     OverlayOp gov = new OverlayOp(geom0, geom1);
     IGeometry geomOv = gov.GetResultGeometry(opCode);
     return geomOv;
 }
示例#22
0
 /// <summary>
 /// Find all edges whose label indicates that they are in the result area(s),
 /// according to the operation being performed.  Since we want polygon shells to be
 /// oriented CW, choose dirEdges with the interior of the result on the RHS.
 /// Mark them as being in the result.
 /// Interior Area edges are the result of dimensional collapses.
 /// They do not form part of the result area boundary.
 /// </summary>
 private void FindResultAreaEdges(SpatialFunctions opCode)
 {
     IEnumerator it = graph.EdgeEnds.GetEnumerator();
     while (it.MoveNext()) 
     {
         DirectedEdge de = (DirectedEdge) it.Current;
         // mark all dirEdges with the appropriate label
         Label label = de.Label;
         if (label.IsArea() && !de.IsInteriorAreaEdge &&
             IsResultOfOp(label.GetLocation(0, Positions.Right), label.GetLocation(1, Positions.Right), opCode))                 
                 de.IsInResult = true;                            
     }
 }
示例#23
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="opCode"></param>
 private void BuildLines(SpatialFunctions opCode)
 {            
     for (IEnumerator it = lineEdgesList.GetEnumerator(); it.MoveNext(); )
     {
         Edge e = (Edge) it.Current;                
         ILineString line = geometryFactory.CreateLineString(e.Coordinates);
         resultLineList.Add(line);
         e.InResult = true;
     }
 }
示例#24
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="funcCode"></param>
 /// <returns></returns>
 public IGeometry GetResultGeometry(SpatialFunctions funcCode)
 {
     ComputeOverlay(funcCode);
     return resultGeom;
 }
示例#25
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="opCode"></param>
 private void CollectLines(SpatialFunctions opCode)
 {
     IEnumerator it = op.Graph.EdgeEnds.GetEnumerator();
     while (it.MoveNext()) 
     {
         DirectedEdge de = (DirectedEdge) it.Current;                
         CollectLineEdge(de, opCode, lineEdgesList);
         CollectBoundaryTouchEdge(de, opCode, lineEdgesList);
     }           
 }
示例#26
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="opCode"></param>
        private void ComputeOverlay(SpatialFunctions opCode)
        {
            // copy points from input Geometries.
            // This ensures that any Point geometries
            // in the input are considered for inclusion in the result set
            CopyPoints(0);
            CopyPoints(1);

            // node the input Geometries
            arg[0].ComputeSelfNodes(lineIntersector, false);
            arg[1].ComputeSelfNodes(lineIntersector, false);            

            // --- Needs to convert args to monotonic edges or something.

            // compute intersections between edges of the two input geometries
            arg[0].ComputeEdgeIntersections(arg[1], lineIntersector, true);

            IList baseSplitEdges = new ArrayList();
            arg[0].ComputeSplitEdges(baseSplitEdges);            
            arg[1].ComputeSplitEdges(baseSplitEdges);            
            // add the noded edges to this result graph
            InsertUniqueEdges(baseSplitEdges);

            ComputeLabelsFromDepths();
            ReplaceCollapsedEdges();        

            graph.AddEdges(edgeList.Edges);
            ComputeLabelling();
            LabelIncompleteNodes();

            /*
            * The ordering of building the result Geometries is important.
            * Areas must be built before lines, which must be built before points.
            * This is so that lines which are covered by areas are not included
            * explicitly, and similarly for points.
            */
            FindResultAreaEdges(opCode);
            CancelDuplicateResultEdges();
            PolygonBuilder polyBuilder = new PolygonBuilder(geomFact);
            polyBuilder.Add(graph);
            resultPolyList = polyBuilder.Polygons;

            LineBuilder lineBuilder = new LineBuilder(this, geomFact, ptLocator);
            resultLineList = lineBuilder.Build(opCode);

            PointBuilder pointBuilder = new PointBuilder(this, geomFact, ptLocator);
            resultPointList = pointBuilder.Build(opCode);

            // gather the results from all calculations into a single Geometry for the result set
            resultGeom = ComputeGeometry(resultPointList, resultLineList, resultPolyList);
        }