/// <summary>
 /// Update incomplete dirEdge labels from the labelling for the node.
 /// </summary>
 /// <param name="nodeLabel"></param>
 public virtual void UpdateLabelling(Label nodeLabel)
 {
     for (IEnumerator it = GetEnumerator(); it.MoveNext();)
     {
         DirectedEdge de    = (DirectedEdge)it.Current;
         Label        label = de.Label;
         label.SetAllLocationsIfNull(0, nodeLabel.GetLocation(0));
         label.SetAllLocationsIfNull(1, nodeLabel.GetLocation(1));
     }
 }
Exemple #2
0
        /// <summary>
        /// Updates the label of a node to BOUNDARY,
        /// obeying the mod-2 boundaryDetermination rule.
        /// </summary>
        /// <param name="argIndex"></param>
        public virtual void SetLabelBoundary(int argIndex)
        {
            // determine the current location for the point (if any)
            LocationType loc = LocationType.Null;

            if (Label != null)
            {
                loc = Label.GetLocation(argIndex);
            }
            // flip the loc
            LocationType newLoc;

            switch (loc)
            {
            case LocationType.Boundary:
                newLoc = LocationType.Interior;
                break;

            case LocationType.Interior:
                newLoc = LocationType.Boundary;
                break;

            default:
                newLoc = LocationType.Boundary;
                break;
            }
            base.Label.SetLocation(argIndex, newLoc);
        }
        /// <summary>
        /// Adds points using the mod-2 rule of SFS.  This is used to add the boundary
        /// points of dim-1 geometries (Curves/MultiCurves).  According to the SFS,
        /// an endpoint of a Curve is on the boundary
        /// if it is in the boundaries of an odd number of Geometries.
        /// </summary>
        /// <param name="argIndex"></param>
        /// <param name="coord"></param>
        private void InsertBoundaryPoint(int argIndex, Coordinate coord)
        {
            Node  n   = Nodes.AddNode(coord);
            Label lbl = n.Label;
            // the new point to insert is on a boundary
            int boundaryCount = 1;
            // determine the current location for the point (if any)
            LocationType loc = LocationType.Null;

            if (lbl != null)
            {
                loc = lbl.GetLocation(argIndex, PositionType.On);
            }
            if (loc == LocationType.Boundary)
            {
                boundaryCount++;
            }

            // determine the boundary status of the point according to the Boundary Determination Rule
            LocationType newLoc = DetermineBoundary(boundaryCount);

            if (lbl != null)
            {
                lbl.SetLocation(argIndex, newLoc);
            }
        }
Exemple #4
0
        /// <summary>
        /// Converts a Label to a Line label (that is, one with no side Locations).
        /// </summary>
        /// <param name="label">Label to convert.</param>
        /// <returns>Label as Line label.</returns>
        public static Label ToLineLabel(Label label)
        {
            Label lineLabel = new Label(LocationType.Null);

            for (int i = 0; i < 2; i++)
            {
                lineLabel.SetLocation(i, label.GetLocation(i));
            }
            return(lineLabel);
        }
Exemple #5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="geomIndex"></param>
        /// <returns></returns>
        private bool CheckAreaLabelsConsistent(int geomIndex)
        {
            // Since edges are stored in CCW order around the node,
            // As we move around the ring we move from the right to the left side of the edge
            IList edges = Edges;

            // if no edges, trivially consistent
            if (edges.Count <= 0)
            {
                return(true);
            }
            // initialize startLoc to location of last Curve side (if any)
            int          lastEdgeIndex = edges.Count - 1;
            Label        startLabel    = ((EdgeEnd)edges[lastEdgeIndex]).Label;
            LocationType startLoc      = startLabel.GetLocation(geomIndex, PositionType.Left);

            Assert.IsTrue(startLoc != LocationType.Null, "Found unlabelled area edge");

            LocationType currLoc = startLoc;

            for (IEnumerator it = GetEnumerator(); it.MoveNext();)
            {
                EdgeEnd e     = (EdgeEnd)it.Current;
                Label   label = e.Label;
                // we assume that we are only checking a area
                Assert.IsTrue(label.IsArea(geomIndex), "Found non-area edge");
                LocationType leftLoc  = label.GetLocation(geomIndex, PositionType.Left);
                LocationType rightLoc = label.GetLocation(geomIndex, PositionType.Right);
                // check that edge is really a boundary between inside and outside!
                if (leftLoc == rightLoc)
                {
                    return(false);
                }
                // check side location conflict
                if (rightLoc != currLoc)
                {
                    return(false);
                }
                currLoc = leftLoc;
            }
            return(true);
        }
Exemple #6
0
 /// <summary>
 /// To merge labels for two nodes,
 /// the merged location for each LabelElement is computed.
 /// The location for the corresponding node LabelElement is set to the result,
 /// as long as the location is non-null.
 /// </summary>
 /// <param name="label2"></param>
 public virtual void MergeLabel(Label label2)
 {
     for (int i = 0; i < 2; i++)
     {
         LocationType loc     = ComputeMergedLocation(label2, i);
         LocationType thisLoc = Label.GetLocation(i);
         if (thisLoc == LocationType.Null)
         {
             Label.SetLocation(i, loc);
         }
     }
 }
Exemple #7
0
        /// <summary>
        /// The location for a given eltIndex for a node will be one
        /// of { Null, Interior, Boundary }.
        /// A node may be on both the boundary and the interior of a point;
        /// in this case, the rule is that the node is considered to be in the boundary.
        /// The merged location is the maximum of the two input values.
        /// </summary>
        /// <param name="label2"></param>
        /// <param name="eltIndex"></param>
        public virtual LocationType ComputeMergedLocation(Label label2, int eltIndex)
        {
            LocationType loc = Label.GetLocation(eltIndex);

            if (!label2.IsNull(eltIndex))
            {
                LocationType nLoc = label2.GetLocation(eltIndex);
                if (loc != LocationType.Boundary)
                {
                    loc = nLoc;
                }
            }
            return(loc);
        }
Exemple #8
0
 /// <summary>
 /// Updates an IM from the label for an edge.
 /// Handles edges from both L and A geometries.
 /// </summary>
 /// <param name="label"></param>
 /// <param name="im"></param>
 public static void UpdateIm(Label label, IntersectionMatrix im)
 {
     im.SetAtLeastIfValid(label.GetLocation(0, PositionType.On), label.GetLocation(1, PositionType.On), DimensionType.Curve);
     if (!label.IsArea())
     {
         return;
     }
     im.SetAtLeastIfValid(label.GetLocation(0, PositionType.Left), label.GetLocation(1, PositionType.Left), DimensionType.Surface);
     im.SetAtLeastIfValid(label.GetLocation(0, PositionType.Right), label.GetLocation(1, PositionType.Right), DimensionType.Surface);
 }
Exemple #9
0
        /// <summary>
        /// Merge the RHS label from a DirectedEdge into the label for this EdgeRing.
        /// The DirectedEdge label may be null.  This is acceptable - it results
        /// from a node which is NOT an intersection node between the Geometries
        /// (e.g. the end node of a LinearRing).  In this case the DirectedEdge label
        /// does not contribute any information to the overall labelling, and is simply skipped.
        /// </summary>
        /// <param name="deLabel"></param>
        /// <param name="geomIndex"></param>
        protected virtual void MergeLabel(Label deLabel, int geomIndex)
        {
            LocationType loc = deLabel.GetLocation(geomIndex, PositionType.Right);

            // no information to be had from this label
            if (loc == LocationType.Null)
            {
                return;
            }
            // if there is no current RHS value, set it
            if (_label.GetLocation(geomIndex) == LocationType.Null)
            {
                _label.SetLocation(geomIndex, loc);
                return;
            }
        }
Exemple #10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="geomIndex"></param>
        /// <param name="coord"></param>
        /// <returns></returns>
        public virtual bool IsBoundaryNode(int geomIndex, Coordinate coord)
        {
            Node node = _nodes.Find(coord);

            if (node == null)
            {
                return(false);
            }
            Label label = node.Label;

            if (label != null && label.GetLocation(geomIndex) == LocationType.Boundary)
            {
                return(true);
            }
            return(false);
        }
Exemple #11
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(LocationType.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++)
                {
                    LocationType eLoc = eLabel.GetLocation(i);
                    if (eLoc == LocationType.Interior || eLoc == LocationType.Boundary)
                    {
                        _label.SetLocation(i, LocationType.Interior);
                    }
                }
            }
        }
 /// <summary>
 /// Update incomplete dirEdge labels from the labelling for the node.
 /// </summary>
 /// <param name="nodeLabel"></param>
 public virtual void UpdateLabelling(Label nodeLabel)
 {
     for (IEnumerator it = GetEnumerator(); it.MoveNext(); )
     {
         DirectedEdge de = (DirectedEdge)it.Current;
         Label label = de.Label;
         label.SetAllLocationsIfNull(0, nodeLabel.GetLocation(0));
         label.SetAllLocationsIfNull(1, nodeLabel.GetLocation(1));
     }
 }
Exemple #13
0
 /// <summary>
 /// Converts a Label to a Line label (that is, one with no side Locations).
 /// </summary>
 /// <param name="label">Label to convert.</param>
 /// <returns>Label as Line label.</returns>
 public static Label ToLineLabel(Label label)
 {
     Label lineLabel = new Label(LocationType.Null);
     for (int i = 0; i < 2; i++)
         lineLabel.SetLocation(i, label.GetLocation(i));
     return lineLabel;
 }
Exemple #14
0
 /// <summary>
 /// Updates an IM from the label for an edge.
 /// Handles edges from both L and A geometries.
 /// </summary>
 /// <param name="label"></param>
 /// <param name="im"></param>
 public static void UpdateIm(Label label, IntersectionMatrix im)
 {
     im.SetAtLeastIfValid(label.GetLocation(0, PositionType.On), label.GetLocation(1, PositionType.On), DimensionType.Curve);
     if (!label.IsArea()) return;
     im.SetAtLeastIfValid(label.GetLocation(0, PositionType.Left), label.GetLocation(1, PositionType.Left), DimensionType.Surface);
     im.SetAtLeastIfValid(label.GetLocation(0, PositionType.Right), label.GetLocation(1, PositionType.Right), DimensionType.Surface);
 }
Exemple #15
0
 /// <summary>
 /// The location for a given eltIndex for a node will be one
 /// of { Null, Interior, Boundary }.
 /// A node may be on both the boundary and the interior of a point;
 /// in this case, the rule is that the node is considered to be in the boundary.
 /// The merged location is the maximum of the two input values.
 /// </summary>
 /// <param name="label2"></param>
 /// <param name="eltIndex"></param>
 public virtual LocationType ComputeMergedLocation(Label label2, int eltIndex)
 {
     LocationType loc = Label.GetLocation(eltIndex);
     if (!label2.IsNull(eltIndex))
     {
         LocationType nLoc = label2.GetLocation(eltIndex);
         if (loc != LocationType.Boundary)
             loc = nLoc;
     }
     return loc;
 }
Exemple #16
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);
 }
Exemple #17
0
 /// <summary>
 /// Merge the RHS label from a DirectedEdge into the label for this EdgeRing.
 /// The DirectedEdge label may be null.  This is acceptable - it results
 /// from a node which is NOT an intersection node between the Geometries
 /// (e.g. the end node of a LinearRing).  In this case the DirectedEdge label
 /// does not contribute any information to the overall labelling, and is simply skipped.
 /// </summary>
 /// <param name="deLabel"></param>
 /// <param name="geomIndex"></param>
 protected virtual void MergeLabel(Label deLabel, int geomIndex)
 {
     LocationType loc = deLabel.GetLocation(geomIndex, PositionType.Right);
     // no information to be had from this label
     if (loc == LocationType.Null)
         return;
     // if there is no current RHS value, set it
     if (_label.GetLocation(geomIndex) == LocationType.Null)
     {
         _label.SetLocation(geomIndex, loc);
         return;
     }
 }
Exemple #18
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.
             *
             * Notice 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) == LocationType.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))
                    {
                        LocationType loc;
                        if (hasDimensionalCollapseEdge[geomi])
                        {
                            loc = LocationType.Exterior;
                        }
                        else
                        {
                            Coordinate p = e.Coordinate;
                            loc = GetLocation(geomi, p, geom);
                        }
                        label.SetAllLocationsIfNull(geomi, loc);
                    }
                }
            }
        }
Exemple #19
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="geomIndex"></param>
        public virtual void PropagateSideLabels(int geomIndex)
        {
            // Since edges are stored in CCW order around the node,
            // As we move around the ring we move from the right to the left side of the edge
            LocationType startLoc = LocationType.Null;

            // initialize loc to location of last Curve side (if any)
            for (IEnumerator it = GetEnumerator(); it.MoveNext();)
            {
                EdgeEnd e     = (EdgeEnd)it.Current;
                Label   label = e.Label;
                if (label.IsArea(geomIndex) && label.GetLocation(geomIndex, PositionType.Left) != LocationType.Null)
                {
                    startLoc = label.GetLocation(geomIndex, PositionType.Left);
                }
            }
            // no labelled sides found, so no labels to propagate
            if (startLoc == LocationType.Null)
            {
                return;
            }

            LocationType currLoc = startLoc;

            for (IEnumerator it = GetEnumerator(); it.MoveNext();)
            {
                EdgeEnd e     = (EdgeEnd)it.Current;
                Label   label = e.Label;
                // set null On values to be in current location
                if (label.GetLocation(geomIndex, PositionType.On) == LocationType.Null)
                {
                    label.SetLocation(geomIndex, PositionType.On, currLoc);
                }
                // set side labels (if any)
                // if (label.IsArea())    //ORIGINAL
                if (label.IsArea(geomIndex))
                {
                    LocationType leftLoc  = label.GetLocation(geomIndex, PositionType.Left);
                    LocationType rightLoc = label.GetLocation(geomIndex, PositionType.Right);
                    // if there is a right location, that is the next location to propagate
                    if (rightLoc != LocationType.Null)
                    {
                        if (rightLoc != currLoc)
                        {
                            throw new TopologyException(TopologyText.SideLocationConflict, e.Coordinate);
                        }
                        if (leftLoc == LocationType.Null)
                        {
                            throw new TopologyException(TopologyText.SingleNullSide, e.Coordinate);
                        }
                        currLoc = leftLoc;
                    }
                    else
                    {
                        /* RHS is null - LHS must be null too.
                         *  This must be an edge from the other point, which has no location
                         *  labelling for this point.  This edge must lie wholly inside or outside
                         *  the other point (which is determined by the current location).
                         *  Assign both sides to be the current location.
                         */
                        Assert.IsTrue(label.GetLocation(geomIndex, PositionType.Left) == LocationType.Null, "found single null side");
                        label.SetLocation(geomIndex, PositionType.Right, currLoc);
                        label.SetLocation(geomIndex, PositionType.Left, currLoc);
                    }
                }
            }
        }
 /// <summary>
 /// Compute the change in depth as an edge is crossed from R to L.
 /// </summary>
 /// <param name="label"></param>
 private static int DepthDelta(Label label)
 {
     LocationType lLoc = label.GetLocation(0, PositionType.Left);
     LocationType rLoc = label.GetLocation(0, PositionType.Right);
     if (lLoc == LocationType.Interior && rLoc == LocationType.Exterior)
         return 1;
     if (lLoc == LocationType.Exterior && rLoc == LocationType.Interior)
         return -1;
     return 0;
 }