/// <summary> /// /// </summary> /// <param name="geomIndex"></param> public 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 Location startLoc = Location.Null; // initialize loc to location of last Curve side (if any) foreach (EdgeEnd e in Edges) { Label label = e.Label; if (label.IsArea(geomIndex) && label.GetLocation(geomIndex, Positions.Left) != Location.Null) { startLoc = label.GetLocation(geomIndex, Positions.Left); } } // no labelled sides found, so no labels to propagate if (startLoc == Location.Null) { return; } Location currLoc = startLoc; foreach (EdgeEnd e in Edges) { Label label = e.Label; // set null On values to be in current location if (label.GetLocation(geomIndex, Positions.On) == Location.Null) { label.SetLocation(geomIndex, Positions.On, currLoc); } // set side labels (if any) if (label.IsArea(geomIndex)) { Location leftLoc = label.GetLocation(geomIndex, Positions.Left); Location rightLoc = label.GetLocation(geomIndex, Positions.Right); // if there is a right location, that is the next location to propagate if (rightLoc != Location.Null) { if (rightLoc != currLoc) { throw new TopologyException("side location conflict", e.Coordinate); } if (leftLoc == Location.Null) { Assert.ShouldNeverReachHere("found single null side (at " + 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, Positions.Left) == Location.Null, "found single null side"); label.SetLocation(geomIndex, Positions.Right, currLoc); label.SetLocation(geomIndex, Positions.Left, currLoc); } } } }
/// <summary> /// /// </summary> /// <param name="geomGraph"></param> public virtual void ComputeLabelling(GeometryGraph[] geomGraph) { ComputeEdgeEndLabels(geomGraph[0].BoundaryNodeRule); // Propagate side labels around the edges in the star // for each parent Geometry PropagateSideLabels(0); PropagateSideLabels(1); /* * If there are edges that still have null labels for a point * this must be because there are no area edges for that point incident on this node. * In this case, to label the edge for that point we must test whether the * edge is in the interior of the point. * To do this it suffices to determine whether the node for the edge is in the interior of an area. * If so, the edge has location Interior for the point. * In all other cases (e.g. the node is on a line, on a point, or not on the point at all) the edge * has the location Exterior for the point. * * Note that the edge cannot be on the Boundary of the point, since then * there would have been a parallel edge from the Geometry at this node also labelled Boundary * and this edge would have been labelled in the previous step. * * This code causes a problem when dimensional collapses are present, since it may try and * determine the location of a node where a dimensional collapse has occurred. * The point should be considered to be on the Exterior * of the polygon, but locate() will return Interior, since it is passed * the original Geometry, not the collapsed version. * * If there are incident edges which are Line edges labelled Boundary, * then they must be edges resulting from dimensional collapses. * In this case the other edges can be labelled Exterior for this Geometry. * * MD 8/11/01 - NOT True! The collapsed edges may in fact be in the interior of the Geometry, * which means the other edges should be labelled Interior for this Geometry. * Not sure how solve this... Possibly labelling needs to be split into several phases: * area label propagation, symLabel merging, then finally null label resolution. */ bool[] hasDimensionalCollapseEdge = { false, false }; foreach (var e in Edges) { Label label = e.Label; for (int geomi = 0; geomi < 2; geomi++) { if (label.IsLine(geomi) && label.GetLocation(geomi) == Location.Boundary) { hasDimensionalCollapseEdge[geomi] = true; } } } foreach (var e in Edges) { Label label = e.Label; for (int geomi = 0; geomi < 2; geomi++) { if (label.IsAnyNull(geomi)) { Location loc; if (hasDimensionalCollapseEdge[geomi]) { loc = Location.Exterior; } else { Coordinate p = e.Coordinate; loc = GetLocation(geomi, p, geomGraph); } label.SetAllLocationsIfNull(geomi, loc); } } } }