internal void MergeFrom(PointAndCrossingsList other) { Reset(); if ((null == other) || (0 == other.ListOfPointsAndCrossings.Count)) { return; } if (0 == this.ListOfPointsAndCrossings.Count) { this.ListOfPointsAndCrossings.AddRange(other.ListOfPointsAndCrossings); } if (null == this.ListOfPointsAndCrossings) { this.ListOfPointsAndCrossings = new List <PointAndCrossings>(other.ListOfPointsAndCrossings); return; } // Do the usual sorted-list merge. int thisIndex = 0, thisMax = this.ListOfPointsAndCrossings.Count; int otherIndex = 0, otherMax = other.ListOfPointsAndCrossings.Count; var newCrossingsList = new List <PointAndCrossings>(this.ListOfPointsAndCrossings.Count); while ((thisIndex < thisMax) || (otherIndex < otherMax)) { if (thisIndex >= thisMax) { newCrossingsList.Add(other.ListOfPointsAndCrossings[otherIndex++]); continue; } if (otherIndex >= otherMax) { newCrossingsList.Add(this.ListOfPointsAndCrossings[thisIndex++]); continue; } PointAndCrossings thisPac = this.ListOfPointsAndCrossings[thisIndex]; PointAndCrossings otherPac = other.ListOfPointsAndCrossings[otherIndex]; int cmp = PointComparer.Compare(thisPac.Location, otherPac.Location); if (0 == cmp) { // No duplicates newCrossingsList.Add(thisPac); ++thisIndex; ++otherIndex; } else if (-1 == cmp) { newCrossingsList.Add(thisPac); ++thisIndex; } else { newCrossingsList.Add(otherPac); ++otherIndex; } } this.ListOfPointsAndCrossings = newCrossingsList; }
private void SpliceGroupBoundaryCrossings(PointAndCrossingsList crossingList, VisibilityVertex startVertex, LineSegment maxSegment) { if ((null == crossingList) || (0 == crossingList.Count)) { return; } crossingList.Reset(); var start = maxSegment.Start; var end = maxSegment.End; var dir = PointComparer.GetPureDirection(start, end); // Make sure we are going in the ascending direction. if (!StaticGraphUtility.IsAscending(dir)) { start = maxSegment.End; end = maxSegment.Start; dir = CompassVector.OppositeDir(dir); } // We need to back up to handle group crossings that are between a VisibilityBorderIntersect on a sloped border and the // incoming startVertex (which is on the first ScanSegment in Perpendicular(dir) that is outside that padded border). startVertex = TraverseToFirstVertexAtOrAbove(startVertex, start, CompassVector.OppositeDir(dir)); // Splice into the Vertices between and including the start/end points. for (var currentVertex = startVertex; null != currentVertex; currentVertex = StaticGraphUtility.FindNextVertex(currentVertex, dir)) { bool isFinalVertex = (PointComparer.Compare(currentVertex.Point, end) >= 0); while (crossingList.CurrentIsBeforeOrAt(currentVertex.Point)) { PointAndCrossings pac = crossingList.Pop(); // If it's past the start and at or before the end, splice in the crossings in the descending direction. if (PointComparer.Compare(pac.Location, startVertex.Point) > 0) { if (PointComparer.Compare(pac.Location, end) <= 0) { SpliceGroupBoundaryCrossing(currentVertex, pac, CompassVector.OppositeDir(dir)); } } // If it's at or past the start and before the end, splice in the crossings in the descending direction. if (PointComparer.Compare(pac.Location, startVertex.Point) >= 0) { if (PointComparer.Compare(pac.Location, end) < 0) { SpliceGroupBoundaryCrossing(currentVertex, pac, dir); } } } if (isFinalVertex) { break; } } }
private bool AppendGroupCrossingsThroughPoint(VisibilityGraph vg, Point lastPoint) { if (null == GroupBoundaryPointAndCrossingsList) { return(false); } bool found = false; while (GroupBoundaryPointAndCrossingsList.CurrentIsBeforeOrAt(lastPoint)) { // We will only create crossing Edges that the segment actually crosses, not those it ends before crossing. // For those terminal crossings, the adjacent segment creates the interior vertex and crossing edge. PointAndCrossings pac = GroupBoundaryPointAndCrossingsList.Pop(); GroupBoundaryCrossing[] lowDirCrossings = null; GroupBoundaryCrossing[] highDirCrossings = null; if (PointComparer.Compare(pac.Location, Start) > 0) { lowDirCrossings = PointAndCrossingsList.ToCrossingArray(pac.Crossings, ScanDirection.OppositeDirection); } if (PointComparer.Compare(pac.Location, End) < 0) { highDirCrossings = PointAndCrossingsList.ToCrossingArray(pac.Crossings, ScanDirection.Direction); } found = true; VisibilityVertex crossingVertex = vg.FindVertex(pac.Location) ?? vg.AddVertex(pac.Location); if ((null != lowDirCrossings) || (null != highDirCrossings)) { AddLowCrossings(vg, crossingVertex, lowDirCrossings); AddHighCrossings(vg, crossingVertex, highDirCrossings); } else { // This is at this.Start with only lower-direction toward group interior(s), or at this.End with only // higher-direction toward group interior(s). Therefore an adjacent ScanSegment will create the crossing // edge, so create the crossing vertex here and we'll link to it. if (null == LowestVisibilityVertex) { SetInitialVisibilityVertex(crossingVertex); } else { Debug.Assert(PointComparer.Equal(End, crossingVertex.Point), "Expected this.End crossingVertex"); AppendHighestVisibilityVertex(crossingVertex); } } } return(found); }
private void SpliceGroupBoundaryCrossing(VisibilityVertex currentVertex, PointAndCrossings pac, Directions dirToInside) { GroupBoundaryCrossing[] crossings = PointAndCrossingsList.ToCrossingArray(pac.Crossings, dirToInside); if (null != crossings) { var outerVertex = VisGraph.FindVertex(pac.Location) ?? AddVertex(pac.Location); if (currentVertex.Point != outerVertex.Point) { FindOrAddEdge(currentVertex, outerVertex); } var interiorPoint = crossings[0].GetInteriorVertexPoint(pac.Location); var interiorVertex = VisGraph.FindVertex(interiorPoint) ?? AddVertex(interiorPoint); // FindOrAddEdge splits an existing edge so may not return the portion bracketed by outerVertex and interiorVertex. FindOrAddEdge(outerVertex, interiorVertex); var edge = VisGraph.FindEdge(outerVertex.Point, interiorVertex.Point); var crossingsArray = crossings.Select(c => c.Group.InputShape).ToArray(); edge.IsPassable = delegate { return(crossingsArray.Any(s => s.IsTransparent)); }; } }
private void SpliceGroupBoundaryCrossing(VisibilityVertex currentVertex, PointAndCrossings pac, Directions dirToInside) { GroupBoundaryCrossing[] crossings = PointAndCrossingsList.ToCrossingArray(pac.Crossings, dirToInside); if (null != crossings) { var outerVertex = VisGraph.FindVertex(pac.Location) ?? AddVertex(pac.Location); if (currentVertex.Point != outerVertex.Point) { FindOrAddEdge(currentVertex, outerVertex); } var interiorPoint = crossings[0].GetInteriorVertexPoint(pac.Location); var interiorVertex = VisGraph.FindVertex(interiorPoint) ?? AddVertex(interiorPoint); // FindOrAddEdge splits an existing edge so may not return the portion bracketed by outerVertex and interiorVertex. FindOrAddEdge(outerVertex, interiorVertex); var edge = VisGraph.FindEdge(outerVertex.Point, interiorVertex.Point); var crossingsArray = crossings.Select(c => c.Group.InputShape).ToArray(); edge.IsPassable = delegate { return crossingsArray.Any(s => s.IsTransparent); }; } }