Example #1
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="opCode"></param>
 /// <returns>
 /// A list of the LineStrings in the result of the specified overlay operation.
 /// </returns>
 public virtual IList Build(SpatialFunction opCode)
 {
     FindCoveredLineEdges();
     CollectLines(opCode);
     BuildLines(opCode);
     return _resultLineList;
 }
 public void MarkResultAreaEdges(SpatialFunction overlayOpCode)
 {
     foreach (var edge in _edges)
     {
         MarkInResultArea(edge, overlayOpCode);
     }
 }
Example #3
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="opCode"></param>
 /// <returns>
 /// A list of the LineStrings in the result of the specified overlay operation.
 /// </returns>
 public IList <Geometry> Build(SpatialFunction opCode)
 {
     FindCoveredLineEdges();
     CollectLines(opCode);
     BuildLines(opCode);
     return(_resultLineList);
 }
Example #4
0
        /// <summary>
        /// Determines nodes which are in the result, and creates <see cref="IPoint"/>s for them.
        /// </summary>
        /// <remarks>
        /// This method determines nodes which are candidates for the result via their
        /// labelling and their graph topology.
        /// </remarks>
        /// <param name="opCode">The overlay operation</param>
        private void ExtractNonCoveredResultNodes(SpatialFunction opCode)
        {
            // testing only
            //if (true) return resultNodeList;

            foreach (var n in _op.Graph.Nodes)
            {
                // filter out nodes which are known to be in the result
                if (n.IsInResult)
                {
                    continue;
                }
                // if an incident edge is in the result, then the node coordinate is included already
                if (n.IsIncidentEdgeInResult())
                {
                    continue;
                }
                if (n.Edges.Degree == 0 || opCode == SpatialFunction.Intersection)
                {
                    /**
                     * For nodes on edges, only INTERSECTION can result in edge nodes being included even
                     * if none of their incident edges are included
                     */
                    Label label = n.Label;
                    if (OverlayOp.IsResultOfOp(label, opCode))
                    {
                        FilterCoveredNodeToPoint(n);
                    }
                }
            }
            //Console.Writeline("connectedResultNodes collected = " + connectedResultNodes.size());
        }
        /// <summary>
        /// Tests if the result can be determined to be empty
        /// based on simple properties of the input geometries
        /// (such as whether one or both are empty,
        /// or their envelopes are disjoint).
        /// </summary>
        /// <param name="opCode">The overlay operation</param>
        /// <param name="a">The A operand geometry</param>
        /// <param name="b">The B operand geometry</param>
        /// <param name="pm">The precision model to use</param>
        /// <returns><c>true</c> if the overlay result is determined to be empty</returns>
        internal static bool IsEmptyResult(SpatialFunction opCode, Geometry a, Geometry b, PrecisionModel pm)
        {
            switch (opCode)
            {
            case OverlayNG.INTERSECTION:
                if (IsEnvDisjoint(a, b, pm))
                {
                    return(true);
                }
                break;

            case OverlayNG.DIFFERENCE:
                if (IsEmpty(a))
                {
                    return(true);
                }
                break;

            case OverlayNG.UNION:
            case OverlayNG.SYMDIFFERENCE:
                if (IsEmpty(a) && IsEmpty(b))
                {
                    return(true);
                }
                break;
            }
            return(false);
        }
Example #6
0
        /// <summary>
        /// Computes an overlay operation
        /// for the given geometry arguments.
        /// </summary>
        /// <param name="geom0">The first geometry argument</param>
        /// <param name="geom1">The second geometry argument</param>
        /// <param name="opCode">The code for the desired overlay operation</param>
        /// <returns>The result of the overlay operation</returns>
        /// <exception cref="TopologyException">Thrown if a robustness problem is encountered.</exception>
        public static Geometry Overlay(Geometry geom0, Geometry geom1, SpatialFunction opCode)
        {
            var gov    = new OverlayOp(geom0, geom1);
            var geomOv = gov.GetResultGeometry(opCode);

            return(geomOv);
        }
Example #7
0
        /// <summary>
        /// Creates an empty result geometry of the appropriate dimension,
        /// based on the given overlay operation and the dimensions of the inputs.
        /// The created geometry is always an atomic geometry,
        /// not a collection.
        /// <para/>
        /// The empty result is constructed using the following rules:
        /// <list type="bullet">
        /// <item><description><see cref="SpatialFunction.Intersection"/> - result has the dimension of the lowest input dimension</description></item>
        /// <item><description><see cref="SpatialFunction.Union"/> - result has the dimension of the highest input dimension</description></item>
        /// <item><description><see cref="SpatialFunction.Difference"/> - result has the dimension of the left-hand input</description></item>
        /// <item><description><see cref="SpatialFunction.SymDifference"/> - result has the dimension of the highest input dimension
        /// (since symDifference is the union of the differences).</description></item>
        /// </list>
        /// </summary>
        /// <param name="overlayOpCode">The overlay operation being performed</param>
        /// <param name="a">An input geometry</param>
        /// <param name="b">An input geometry</param>
        /// <param name="geomFact">The geometry factory being used for the operation</param>
        /// <returns>An empty atomic geometry of the appropriate dimension</returns>
        public static Geometry CreateEmptyResult(SpatialFunction overlayOpCode, Geometry a, Geometry b, GeometryFactory geomFact)
        {
            var resultDim = ResultDimension(overlayOpCode, a, b);

            // Handles resultDim == Dimension.False, although it should not happen
            return(geomFact.CreateEmpty(resultDim));
        }
Example #8
0
        /// <summary>
        /// Tests whether a point with a given topological <see cref="Label"/>
        /// relative to two geometries is contained in
        /// the result of overlaying the geometries using
        /// a given overlay operation.
        /// <para/>
        /// The method handles arguments of <see cref="Location.Null"/> correctly
        /// </summary>
        /// <param name="label">The topological label of the point</param>
        /// <param name="opCode">The code for the overlay operation to test</param>
        /// <returns><c>true</c> if the label locations correspond to the overlay <paramref name="opCode"/></returns>
        private static bool IsResultOfOpPoint(OverlayLabel label, SpatialFunction opCode)
        {
            var loc0 = label.GetLocation(0);
            var loc1 = label.GetLocation(1);

            return(IsResultOfOp(opCode, loc0, loc1));
        }
Example #9
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, SpatialFunction opCode, IList <Edge> edges)
        {
            var 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 == SpatialFunction.Intersection)
            {
                edges.Add(de.Edge);
                de.VisitedEdge = true;
            }
        }
Example #10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="opCode"></param>
        /// <returns></returns>
        public IGeometry GetResultGeometry(SpatialFunction opCode)
        {
            IGeometry[] prepGeom = Snap();
            IGeometry   result   = OverlayOp.Overlay(prepGeom[0], prepGeom[1], opCode);

            return(PrepareResult(result));
        }
Example #11
0
        private static Dimension ResultDimension(SpatialFunction opCode, IGeometry g0, IGeometry g1)
        {
            var dim0 = (int)g0.Dimension;
            var dim1 = (int)g1.Dimension;

            var resultDimension = -1;

            switch (opCode)
            {
            case SpatialFunction.Intersection:
                resultDimension = Math.Min(dim0, dim1);
                break;

            case SpatialFunction.Union:
                resultDimension = Math.Max(dim0, dim1);
                break;

            case SpatialFunction.Difference:
                resultDimension = dim0;
                break;

            case SpatialFunction.SymDifference:
                /**
                 * This result is chosen because
                 * <pre>
                 * SymDiff = Union(Diff(A, B), Diff(B, A)
                 * </pre>
                 * and Union has the dimension of the highest-dimension argument.
                 */
                resultDimension = Math.Max(dim0, dim1);
                break;
            }
            return((Dimension)resultDimension);
        }
Example #12
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="opCode"></param>
        /// <returns></returns>
        public Geometry GetResultGeometry(SpatialFunction opCode)
        {
            var prepGeom = Snap(_geom);
            var result   = OverlayOp.Overlay(prepGeom[0], prepGeom[1], opCode);

            return(PrepareResult(result));
        }
        /// <summary>
        /// Attempt overlay using snapping with repeated tries with increasing snap tolerances.
        /// </summary>
        /// <param name ="geom0"></param>
        /// <param name ="geom1"></param>
        /// <param name ="opCode"></param>
        /// <returns>The computed overlay result, or null if the overlay fails</returns>
        private static Geometry OverlaySnapTries(Geometry geom0, Geometry geom1, SpatialFunction opCode)
        {
            Geometry result;
            double   snapTol = SnapTolerance(geom0, geom1);

            for (int i = 0; i < NUM_SNAP_TRIES; i++)
            {
                result = OverlaySnapping(geom0, geom1, opCode, snapTol);
                if (result != null)
                {
                    return(result);
                }

                /*
                 * Now try snapping each input individually,
                 * and then doing the overlay.
                 */
                result = OverlaySnapBoth(geom0, geom1, opCode, snapTol);
                if (result != null)
                {
                    return(result);
                }

                // increase the snap tolerance and try again
                snapTol = snapTol * 10;
            }
            // failed to compute overlay
            return(null);
        }
Example #14
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, SpatialFunction opCode)
        {
            OverlayOp gov    = new OverlayOp(geom0, geom1);
            IGeometry geomOv = gov.GetResultGeometry(opCode);

            return(geomOv);
        }
Example #15
0
        static Geometry Overlay(Geometry a, Geometry b, SpatialFunction opCode)
        {
            var ov = new NetTopologySuite.Operation.OverlayNG.OverlayNG(a, b, opCode);

            ov.StrictMode = true;
            return(ov.GetResult());
        }
Example #16
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="opCode"></param>
 /// <returns>
 /// A list of the LineStrings in the result of the specified overlay operation.
 /// </returns>
 public virtual IList Build(SpatialFunction opCode)
 {
     FindCoveredLineEdges();
     CollectLines(opCode);
     BuildLines(opCode);
     return(_resultLineList);
 }
Example #17
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="label"></param>
        /// <param name="opCode"></param>
        /// <returns></returns>
        public static bool IsResultOfOp(Label label, SpatialFunction opCode)
        {
            LocationType loc0 = label.GetLocation(0);
            LocationType loc1 = label.GetLocation(1);

            return(IsResultOfOp(loc0, loc1, opCode));
        }
Example #18
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(LocationType loc0, LocationType loc1, SpatialFunction opCode)
        {
            if (loc0 == LocationType.Boundary)
            {
                loc0 = LocationType.Interior;
            }
            if (loc1 == LocationType.Boundary)
            {
                loc1 = LocationType.Interior;
            }

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

            case SpatialFunction.Union:
                return(loc0 == LocationType.Interior || loc1 == LocationType.Interior);

            case SpatialFunction.Difference:
                return(loc0 == LocationType.Interior && loc1 != LocationType.Interior);

            case SpatialFunction.SymDifference:
                return((loc0 == LocationType.Interior && loc1 != LocationType.Interior) ||
                       (loc0 != LocationType.Interior && loc1 == LocationType.Interior));

            default:
                return(false);
            }
        }
        /// <summary>
        /// Computes the dimension of the result of
        /// applying the given operation to inputs
        /// with the given dimensions.
        /// This assumes that complete collapse does not occur.
        /// <para/>
        /// The result dimension is computed using the following rules:
        /// <list type="bullet">
        /// <item><term><see cref="SpatialFunction.Intersection"/></term><description>result has the dimension of the lowest input dimension</description></item>
        /// <item><term><see cref="SpatialFunction.Union"/></term><description>result has the dimension of the highest input dimension</description></item>
        /// <item><term><see cref="SpatialFunction.Difference"/></term><description>result has the dimension of the left-hand input</description></item>
        /// <item><term><see cref="SpatialFunction.SymDifference"/></term><description>result has the dimension of the highest input dimension
        /// (since the Symmetric Difference is the Union of the Differences).</description></item>
        /// </list>
        /// </summary>
        /// <param name="opCode">The overlay operation</param>
        /// <param name="dim0">Dimension of the LH input</param>
        /// <param name="dim1">Dimension of the RH input</param>
        /// <returns></returns>
        internal static Dimension ResultDimension(SpatialFunction opCode, Dimension dim0, Dimension dim1)
        {
            var resultDimension = Dimension.False;

            switch (opCode)
            {
            case OverlayNG.INTERSECTION:
                resultDimension = (Dimension)Math.Min((int)dim0, (int)dim1);
                break;

            case OverlayNG.UNION:
                resultDimension = (Dimension)Math.Max((int)dim0, (int)dim1);
                break;

            case OverlayNG.DIFFERENCE:
                resultDimension = dim0;
                break;

            case OverlayNG.SYMDIFFERENCE:
                /*
                 * This result is chosen because
                 * <pre>
                 * SymDiff = Union( Diff(A, B), Diff(B, A) )
                 * </pre>
                 * and Union has the dimension of the highest-dimension argument.
                 */
                resultDimension = (Dimension)Math.Max((int)dim0, (int)dim1);
                break;
            }
            return(resultDimension);
        }
Example #20
0
        public IGeometry GetResultGeometry(SpatialFunction opCode)
        {
            IGeometry result    = null;
            var       isSuccess = false;

            try
            {
                result = OverlayOp.Overlay(geom[0], geom[1], opCode);
                var isValid = true;
                // not needed if noding validation is used
                //      boolean isValid = OverlayResultValidator.isValid(geom[0], geom[1], OverlayOp.INTERSECTION, result);
                // if (isValid)
                isSuccess = true;
            }
            catch (Exception ex)
            {
                // Ignore this exception, since the operation will be rerun
                Debug.WriteLine(ex);
            }
            if (!isSuccess)
            {
                // This may still throw an exception - just let it go if it does
                result = SnapOverlayOp.Overlay(geom[0], geom[1], opCode);
            }
            return(result);
        }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="opCode"></param>
 /// <returns>
 /// A list of the LineStrings in the result of the specified overlay operation.
 /// </returns>
 public IList<IGeometry> Build(SpatialFunction opCode)
 {
     FindCoveredLineEdges();
     CollectLines(opCode);
     BuildLines(opCode);
     return _resultLineList;
 }
Example #22
0
        /// <summary>
        /// Determines nodes which are in the result, and creates <see cref="IPoint"/>s for them.
        /// </summary>
        /// <remarks>
        /// This method determines nodes which are candidates for the result via their
        /// labelling and their graph topology.
        /// </remarks>
        /// <param name="opCode">The overlay operation</param>
        private void ExtractNonCoveredResultNodes(SpatialFunction opCode)
        {
            // testing only
            //if (true) return resultNodeList;

            foreach (var n in _op.Graph.Nodes)
            {
                // filter out nodes which are known to be in the result
                if (n.IsInResult)
                    continue;
                // if an incident edge is in the result, then the node coordinate is included already
                if (n.IsIncidentEdgeInResult())
                    continue;
                if (n.Edges.Degree == 0 || opCode == SpatialFunction.Intersection)
                {

                    /**
                     * For nodes on edges, only INTERSECTION can result in edge nodes being included even
                     * if none of their incident edges are included
                     */
                    Label label = n.Label;
                    if (OverlayOp.IsResultOfOp(label, opCode))
                    {
                        FilterCoveredNodeToPoint(n);
                    }
                }
            }
            //Console.Writeline("connectedResultNodes collected = " + connectedResultNodes.size());
        }
        public IGeometry GetResultGeometry(SpatialFunction opCode)
        {
            IGeometry result = null;
            var isSuccess = false;
            try
            {
                result = OverlayOp.Overlay(geom[0], geom[1], opCode);
                var isValid = true;
                // not needed if noding validation is used
                //      boolean isValid = OverlayResultValidator.isValid(geom[0], geom[1], OverlayOp.INTERSECTION, result);
                // if (isValid)
                    isSuccess = true;

            }
            catch (Exception ex)
            {
                // Ignore this exception, since the operation will be rerun                
                Debug.WriteLine(ex);
            }
            if (!isSuccess)
            {
                // This may still throw an exception - just let it go if it does
                result = SnapOverlayOp.Overlay(geom[0], geom[1], opCode);
            }
            return result;
        }
Example #24
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(SpatialFunction opCode)
        {
            IList nodeList        = CollectNodes(opCode);
            IList resultPointList = SimplifyPoints(nodeList);

            return(resultPointList);
        }
Example #25
0
        /// <summary>
        /// Tests whether a point with a given topological <see cref="Label"/>
        /// relative to two geometries is contained in
        /// the result of overlaying the geometries using
        /// a given overlay operation.
        /// <para/>
        /// The method handles arguments of <see cref="Location.Null"/> correctly
        /// </summary>
        /// <param name="label">The topological label of the point</param>
        /// <param name="overlayOpCode">The code for the overlay operation to test</param>
        /// <returns><c>true</c> if the label locations correspond to the overlayOpCode</returns>
        public static bool IsResultOfOp(Label label, SpatialFunction overlayOpCode)
        {
            var loc0 = label.GetLocation(0);
            var loc1 = label.GetLocation(1);

            return(IsResultOfOp(loc0, loc1, overlayOpCode));
        }
 public IGeometry GetResultGeometry(SpatialFunction opCode)
 {
     IGeometry result = null;
     var isSuccess = false;
     Exception savedException = null;
     try
     {
         // try basic operation with input geometries
         result = OverlayOp.Overlay(_geom[0], _geom[1], opCode);
         var isValid = true;
         // not needed if noding validation is used
         //      boolean isValid = OverlayResultValidator.isValid(geom[0], geom[1], OverlayOp.INTERSECTION, result);
         // if (isValid)
         isSuccess = true;
     }
     catch (Exception ex)
     {
         savedException = ex;
         // Ignore this exception, since the operation will be rerun
     }
     if (!isSuccess)
     {
         // this may still throw an exception
         // if so, throw the original exception since it has the input coordinates
         try
         {
             result = SnapOverlayOp.Overlay(_geom[0], _geom[1], opCode);
         }
         catch (Exception)
         {
             throw savedException;
         }
     }
     return result;
 }
Example #27
0
        /// <summary>
        /// Tests whether a point with given <see cref="Location"/>s
        /// relative to two geometries would be contained in
        /// the result of overlaying the geometries using
        /// a given overlay operation.
        /// This is used to determine whether components
        /// computed during the overlay process should be
        /// included in the result geometry.
        /// <para/>
        /// The method handles arguments of <see cref="Location.Null"/> correctly.
        /// </summary>
        /// <param name="overlayOpCode">The code for the overlay operation to test</param>
        /// <param name="loc0">The code for the location in the first geometry</param>
        /// <param name="loc1">The code for the location in the second geometry</param>
        /// <returns><c>true</c> if a point with given locations is in the result of the overlay operation</returns>
        internal static bool IsResultOfOp(SpatialFunction overlayOpCode, Location loc0, Location loc1)
        {
            if (loc0 == Location.Boundary)
            {
                loc0 = Location.Interior;
            }
            if (loc1 == Location.Boundary)
            {
                loc1 = Location.Interior;
            }
            switch (overlayOpCode)
            {
            case INTERSECTION:
                return(loc0 == Location.Interior &&
                       loc1 == Location.Interior);

            case UNION:
                return(loc0 == Location.Interior ||
                       loc1 == Location.Interior);

            case DIFFERENCE:
                return(loc0 == Location.Interior &&
                       loc1 != Location.Interior);

            case SYMDIFFERENCE:
                return((loc0 == Location.Interior && loc1 != Location.Interior) ||
                       (loc0 != Location.Interior && loc1 == Location.Interior));
            }
            return(false);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="opCode"></param>
        /// <returns>
        /// A list of the Points in the result of the specified overlay operation.
        /// </returns>
        public IList <IGeometry> Build(SpatialFunction opCode)
        {
            var nodeList        = CollectNodes(opCode);
            var resultPointList = SimplifyPoints(nodeList);

            return(resultPointList);
        }
Example #29
0
        private void ComputeOverlay(SpatialFunction 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();

            if (!NodingValidatorDisabled)
            {
                var nv = new EdgeNodingValidator(edgeList.Edges);
                nv.checkValid();
            }

            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();
            var polyBuilder = new PolygonBuilder(geomFact);

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

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

            resultLineList = lineBuilder.Build(opCode);

            var 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);
        }
Example #30
0
        static Geometry Overlay(Geometry a, Geometry b, double scaleFactor, SpatialFunction opCode)
        {
            var pm = new PrecisionModel(scaleFactor);
            var ov = new NetTopologySuite.Operation.OverlayNG.OverlayNG(a, b, pm, opCode);

            ov.StrictMode = true;
            return(ov.GetResult());
        }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="opCode"></param>
 private void CollectLines(SpatialFunction opCode)
 {
     foreach (DirectedEdge de in _op.Graph.EdgeEnds)
     {
         CollectLineEdge(de, opCode, _lineEdgesList);
         CollectBoundaryTouchEdge(de, opCode, _lineEdgesList);
     }           
 }
Example #32
0
 /// <summary>
 /// Creates a builder for linear elements which may be present
 /// in the overlay result.
 /// </summary>
 /// <param name="inputGeom">The input geometries</param>
 /// <param name="graph">The topology graph</param>
 /// <param name="hasResultArea"><c>true</c> if an area has been generated for the result</param>
 /// <param name="opCode">The overlay operation code</param>
 /// <param name="geomFact">The output geometry factory</param>
 public LineBuilder(InputGeometry inputGeom, OverlayGraph graph, bool hasResultArea, SpatialFunction opCode, GeometryFactory geomFact)
 {
     _graph           = graph;
     _opCode          = opCode;
     _geometryFactory = geomFact;
     _hasResultArea   = hasResultArea;
     _inputAreaIndex  = inputGeom.GetAreaIndex();
 }
Example #33
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="opCode"></param>
 private void CollectLines(SpatialFunction opCode)
 {
     foreach (DirectedEdge de in _op.Graph.EdgeEnds)
     {
         CollectLineEdge(de, opCode, _lineEdgesList);
         CollectBoundaryTouchEdge(de, opCode, _lineEdgesList);
     }
 }
 /// <summary>
 /// Creates an instance of an overlay operation on inputs which are both point geometries.
 /// </summary>
 /// <param name="opCode">The code for the desired overlay operation</param>
 /// <param name="geom0">The first geometry argument</param>
 /// <param name="geom1">The second geometry argument</param>
 /// <param name="pm">The precision model to use</param>
 public OverlayPoints(SpatialFunction opCode, Geometry geom0, Geometry geom1, PrecisionModel pm)
 {
     _opCode          = opCode;
     _geom0           = geom0;
     _geom1           = geom1;
     _pm              = pm;
     _geometryFactory = geom0.Factory;
 }
Example #35
0
        /// <summary>
        /// Computes an overlay operation for
        /// the given geometry operands, with the
        /// noding strategy determined by the precision model.
        /// </summary>
        /// <param name="geom0">The first geometry argument</param>
        /// <param name="geom1">The second geometry argument</param>
        /// <param name="opCode">The code for the desired overlay operation</param>
        /// <param name="pm">The precision model to use</param>
        /// <returns>The result of the overlay operation</returns>
        public static Geometry Overlay(Geometry geom0, Geometry geom1,
                                       SpatialFunction opCode, PrecisionModel pm)
        {
            var ov     = new OverlayNG(geom0, geom1, pm, opCode);
            var geomOv = ov.GetResult();

            return(geomOv);
        }
 /// <summary>
 ///
 /// </summary>
 /// <param name="opCode"></param>
 private void BuildLines(SpatialFunction opCode)
 {
     foreach (Edge e in _lineEdgesList)
     {
         ILineString line = _geometryFactory.CreateLineString(e.Coordinates);
         _resultLineList.Add(line);
         e.InResult = true;
     }
 }
Example #37
0
 /// <summary>
 /// Computes the Point geometries which will appear in the result,
 /// given the specified overlay operation.
 /// </summary>
 /// <param name="opCode">The spatial function</param>
 /// <returns>
 /// A list of the Points in the result.
 /// </returns>
 public IList<IGeometry> Build(SpatialFunction opCode)
 {
     ExtractNonCoveredResultNodes(opCode);
     /**
      * It can happen that connected result nodes are still covered by
      * result geometries, so must perform this filter.
      * (For instance, this can happen during topology collapse).
      */
     return _resultPointList;
 }
Example #38
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="opCode"></param>
 /// <returns></returns>
 private IList CollectNodes(SpatialFunction 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) continue;
         Label label = n.Label;
         if (OverlayOp.IsResultOfOp(label, opCode))
             resultNodeList.Add(n);
     }
     return resultNodeList;
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="opCode"></param>
 /// <returns></returns>
 private IList<Node> CollectNodes(SpatialFunction opCode)
 {
     IList<Node> resultNodeList = new List<Node>();
     // add nodes from edge intersections which have not already been included in the result
     foreach (Node n in _op.Graph.Nodes)
     {
         if (!n.IsInResult)
         {
             Label label = n.Label;
             if (OverlayOp.IsResultOfOp(label, opCode))                    
                 resultNodeList.Add(n);                    
         }
     }
     return resultNodeList;
 }
        public bool IsValid(SpatialFunction overlayOp)
        {
            AddTestPts(_geom[0]);
            AddTestPts(_geom[1]);
            bool isValid = CheckValid(overlayOp);

            /*
            System.out.println("OverlayResultValidator: " + isValid);
            System.out.println("G0");
            System.out.println(geom[0]);
            System.out.println("G1");
            System.out.println(geom[1]);
            System.out.println("Result");
            System.out.println(geom[2]);
            */

            return isValid;
        }
        /// <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, SpatialFunction opCode, IList<Edge> 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 == SpatialFunction.Intersection)
            {
                edges.Add(de.Edge);
                de.VisitedEdge = true;
            }
        }
Example #42
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, SpatialFunction opCode)
        {
            if (loc0 == Locations.Boundary) 
                loc0 = Locations.Interior;
            if (loc1 == Locations.Boundary) 
                loc1 = Locations.Interior;
            
            switch (opCode) 
            {
                case SpatialFunction.Intersection:
                    return loc0 == Locations.Interior && loc1 == Locations.Interior;
                case SpatialFunction.Union:
                    return loc0 == Locations.Interior || loc1 == Locations.Interior;
                case SpatialFunction.Difference:
                    return loc0 == Locations.Interior && loc1 != Locations.Interior;
                case SpatialFunction.SymDifference:
                    return   (loc0 == Locations.Interior &&  loc1 != Locations.Interior)
                          || (loc0 != Locations.Interior &&  loc1 == Locations.Interior);
	            default:
                    return false;
            }            
        }
        private static void ReportResult(SpatialFunction overlayOp, Location[] location, bool expectedInterior)
        {
#if !PCL
// ReSharper disable RedundantStringFormatCall
            // String.Format needed to build 2.0 release!
            Debug.WriteLine(String.Format("{0}:" + " A:{1} B:{2} expected:{3} actual:{4}", 
                overlayOp,
                LocationUtility.ToLocationSymbol(location[0]), 
                LocationUtility.ToLocationSymbol(location[1]), expectedInterior ? 'i' : 'e', 
                LocationUtility.ToLocationSymbol(location[2])));
// ReSharper restore RedundantStringFormatCall
#endif
        }
        private static bool IsValidResult(SpatialFunction overlayOp, Location[] location)
        {
            bool expectedInterior = OverlayOp.IsResultOfOp(location[0], location[1], overlayOp);

            bool resultInInterior = (location[2] == Location.Interior);
            // MD use simpler: boolean isValid = (expectedInterior == resultInInterior);
            bool isValid = !(expectedInterior ^ resultInInterior);

            if (!isValid) ReportResult(overlayOp, location, expectedInterior);

            return isValid;
        }
        private bool CheckValid(SpatialFunction overlayOp, Coordinate pt)
        {
            _location[0] = _locFinder[0].GetLocation(pt);
            _location[1] = _locFinder[1].GetLocation(pt);
            _location[2] = _locFinder[2].GetLocation(pt);

            /*
             * If any location is on the Boundary, can't deduce anything, so just return true
             */
            if (HasLocation(_location, Location.Boundary))
                return true;

            return IsValidResult(overlayOp, _location);
        }
Example #46
0
 /// <summary>
 /// Creates an empty result geometry of the appropriate dimension,
 /// based on the given overlay operation and the dimensions of the inputs.
 /// The created geometry is always an atomic geometry, 
 /// not a collection.
 /// <para/>
 /// The empty result is constructed using the following rules:
 /// <list type="Bullet">
 /// <item><see cref="SpatialFunction.Intersection"/> - result has the dimension of the lowest input dimension</item>
 /// <item><see cref="SpatialFunction.Union"/> - result has the dimension of the highest input dimension</item>
 /// <item><see cref="SpatialFunction.Difference"/> - result has the dimension of the left-hand input</item>
 /// <item><see cref="SpatialFunction.SymDifference"/> - result has the dimension of the highest input dimension
 /// (since symDifference is the union of the differences).</item>
 /// </list>
 /// </summary>
 /// <param name="overlayOpCode">The overlay operation being performed</param>
 /// <param name="a">An input geometry</param>
 /// <param name="b">An input geometry</param>
 /// <param name="geomFact">The geometry factory being used for the operation</param>
 /// <returns>An empty atomic geometry of the appropriate dimension</returns>
 public static IGeometry CreateEmptyResult(SpatialFunction overlayOpCode, IGeometry a, IGeometry b, IGeometryFactory geomFact)
 {
     IGeometry result = null;
     switch (ResultDimension(overlayOpCode, a, b))
     {
         case Dimension.False:
             result = geomFact.CreateGeometryCollection(new IGeometry[0]);
             break;
         case Dimension.Point:
             result = geomFact.CreatePoint((Coordinate)null);
             break;
         case Dimension.Curve:
             result = geomFact.CreateLineString((Coordinate[])null);
             break;
         case Dimension.Surface:
             result = geomFact.CreatePolygon(null, null);
             break;
     }
     return result;
 }
Example #47
0
 /// <summary>
 /// Tests whether a point with a given topological <see cref="Label"/>
 /// relative to two geometries is contained in 
 /// the result of overlaying the geometries using
 /// a given overlay operation.
 /// <para/>
 /// The method handles arguments of <see cref="Location.Null"/> correctly
 /// </summary>
 /// <param name="label">The topological label of the point</param>
 /// <param name="overlayOpCode">The code for the overlay operation to test</param>
 /// <returns><c>true</c> if the label locations correspond to the overlayOpCode</returns>
 public static bool IsResultOfOp(Label label, SpatialFunction overlayOpCode)
 {
     var loc0 = label.GetLocation(0);
     var loc1 = label.GetLocation(1);
     return IsResultOfOp(loc0, loc1, overlayOpCode);
 }
Example #48
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(SpatialFunction opCode)
 {
     var it = _graph.EdgeEnds.GetEnumerator();
     while (it.MoveNext())
     {
         var de = (DirectedEdge) it.Current;
         // mark all dirEdges with the appropriate label
         var label = de.Label;
         if (label.IsArea() && !de.IsInteriorAreaEdge &&
             IsResultOfOp(label.GetLocation(0, Positions.Right), label.GetLocation(1, Positions.Right), opCode))
                 de.InResult = true;
     }
 }
Example #49
0
 /// <summary>
 /// Gets the result of the overlay for a given overlay operation.
 /// <para/>
 /// Note: this method can be called once only.
 /// </summary>
 /// <param name="overlayOpCode">The code of the overlay operation to perform</param>
 /// <returns>The computed result geometry</returns>
 /// <exception cref="TopologyException">Thrown if a robustness problem is encountered</exception>
 public IGeometry GetResultGeometry(SpatialFunction overlayOpCode)
 {
     ComputeOverlay(overlayOpCode);
     return _resultGeom;
 }
Example #50
0
 /// <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(SpatialFunction opCode)
 {
     IList nodeList = CollectNodes(opCode);
     IList resultPointList = SimplifyPoints(nodeList);
     return resultPointList;
 }
Example #51
0
        private static Dimension ResultDimension(SpatialFunction opCode, IGeometry g0, IGeometry g1)
        {
            var dim0 = (int)g0.Dimension;
            var dim1 = (int)g1.Dimension;

            var resultDimension = -1;
            switch (opCode)
            {
                case SpatialFunction.Intersection:
                    resultDimension = Math.Min(dim0, dim1);
                    break;
                case SpatialFunction.Union:
                    resultDimension = Math.Max(dim0, dim1);
                    break;
                case SpatialFunction.Difference:
                    resultDimension = dim0;
                    break;
                case SpatialFunction.SymDifference:
                    /**
                     * This result is chosen because
                     * <pre>
                     * SymDiff = Union(Diff(A, B), Diff(B, A)
                     * </pre>
                     * and Union has the dimension of the highest-dimension argument.
                     */
                    resultDimension = Math.Max(dim0, dim1);
                    break;
            }
            return (Dimension)resultDimension;
        }
Example #52
0
        private IGeometry ComputeGeometry(IEnumerable<IGeometry> resultPtList, IEnumerable<IGeometry> resultLiList, IEnumerable<IGeometry> resultPlList, SpatialFunction opCode)
        {
            var geomList = new List<IGeometry>();

            // element geometries of the result are always in the order Point,Curve,A
            geomList.AddRange(resultPtList);
            geomList.AddRange(resultLiList);
            geomList.AddRange(resultPlList);

            if (geomList.Count == 0)
                return CreateEmptyResult(opCode, arg[0].Geometry, arg[1].Geometry, _geomFact);

            // build the most specific point possible
            return _geomFact.BuildGeometry(geomList);
        }
 private bool CheckValid(SpatialFunction overlayOp)
 {
     for (int i = 0; i < _testCoords.Count; i++)
     {
         Coordinate pt = _testCoords[i];
         if (!CheckValid(overlayOp, pt))
         {
             _invalidLocation = pt;
             return false;
         }
     }
     return true;
 }
        /**
         *
         * and optionally validating the result.
         *
         * @param opCode
         * @param g0
         * @param args
         * @return
         * @throws Exception
         */

        /// <summary>
        /// Invokes an overlay op, optionally using snapping,
        /// and optionally validating the result.
        /// </summary>
        public IResult InvokeValidatedOverlayOp(SpatialFunction opCode, IGeometry g0, Object[] args)
        {
            var g1 = (IGeometry)args[0];

            var result = InvokeGeometryOverlayMethod(opCode, g0, g1);

            // validate
            Validate(opCode, g0, g1, result);
            AreaValidate(g0, g1);

            /**
             * Return an empty GeometryCollection as the result.
             * This allows the test case to avoid specifying an exact result
             */
            if (ReturnEmptyGeometryCollection)
            {
                result = result.Factory.CreateGeometryCollection(null);
            }

            return new GeometryResult(result);
        }
 public static bool IsValid(IGeometry a, IGeometry b, SpatialFunction overlayOp, IGeometry result)
 {
     OverlayResultValidator validator = new OverlayResultValidator(a, b, result);
     return validator.IsValid(overlayOp);
 }
Example #56
0
 /// <summary>
 /// Computes an overlay operation 
 /// for the given geometry arguments.
 /// </summary>
 /// <param name="geom0">The first geometry argument</param>
 /// <param name="geom1">The second geometry argument</param>
 /// <param name="opCode">The code for the desired overlay operation</param>
 /// <returns>The result of the overlay operation</returns>
 /// <exception cref="TopologyException">Thrown if a robustness problem is encountered.</exception>
 public static IGeometry Overlay(IGeometry geom0, IGeometry geom1, SpatialFunction opCode)
 {
     var gov = new OverlayOp(geom0, geom1);
     var geomOv = gov.GetResultGeometry(opCode);
     return geomOv;
 }
 private static void Validate(SpatialFunction opCode, IGeometry g0, IGeometry g1, IGeometry result)
 {
     var validator = new OverlayResultValidator(g0, g1, result);
     // check if computed result is valid
     if (!validator.IsValid(opCode))
     {
         var invalidLoc = validator.InvalidLocation;
         String msg = "Operation result is invalid [OverlayResultValidator] ( " + WKTWriter.ToPoint(invalidLoc) + " )";
         ReportError(msg);
     }
 }
Example #58
0
        private void ComputeOverlay(SpatialFunction 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<Edge> baseSplitEdges = new List<Edge>();
            arg[0].ComputeSplitEdges(baseSplitEdges);
            arg[1].ComputeSplitEdges(baseSplitEdges);
            // add the noded edges to this result graph
            InsertUniqueEdges(baseSplitEdges);

            ComputeLabelsFromDepths();
            ReplaceCollapsedEdges();

            if (!NodingValidatorDisabled)
            {
                /*
                 * Check that the noding completed correctly.
                 *
                 * This test is slow, but necessary in order to catch robustness failure
                 * situations.
                 * If an exception is thrown because of a noding failure,
                 * then snapping will be performed, which will hopefully avoid the problem.
                 * In the future hopefully a faster check can be developed.
                 *
                 */
                var nv = new EdgeNodingValidator(_edgeList.Edges);
                nv.CheckValid();
            }

            _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();
            var polyBuilder = new PolygonBuilder(_geomFact);
            polyBuilder.Add(_graph);
            _resultPolyList = polyBuilder.Polygons;

            var lineBuilder = new LineBuilder(this, _geomFact, _ptLocator);
            _resultLineList = lineBuilder.Build(opCode);

            var 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, opCode);
        }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="opCode"></param>
 /// <returns>
 /// A list of the Points in the result of the specified overlay operation.
 /// </returns>
 public IList<IGeometry> Build(SpatialFunction opCode)
 {
     var nodeList = CollectNodes(opCode);
     var resultPointList = SimplifyPoints(nodeList);
     return resultPointList;
 }
        public static IGeometry InvokeGeometryOverlayMethod(SpatialFunction opCode, IGeometry g0, IGeometry g1)
        {
            switch (opCode)
            {
                case SpatialFunction.Intersection:
                    return g0.Intersection(g1);

                case SpatialFunction.Union:
                    return g0.Union(g1);

                case SpatialFunction.Difference:
                    return g0.Difference(g1);

                case SpatialFunction.SymDifference:
                    return g0.SymmetricDifference(g1);
            }
            throw new ArgumentException(@"Unknown overlay op code");
        }