// For a single vertex point, split its List of crossings in both directions into an array in each (opposite) // direction. CLR Array iteration is much faster than List. static internal GroupBoundaryCrossing[] ToCrossingArray(List <GroupBoundaryCrossing> crossings, Directions dirToInside) { // First find the number in each (opposite) direction, then create the arrays. // We expect a very small number of groups to share a boundary point so this is not optimized. int numInDir = 0; var crossingsCount = crossings.Count; // cache for perf for (int ii = 0; ii < crossingsCount; ++ii) { if (crossings[ii].DirectionToInside == dirToInside) { ++numInDir; } } if (0 == numInDir) { return(null); } var vector = new GroupBoundaryCrossing[numInDir]; int jj = 0; for (int ii = 0; ii < crossingsCount; ++ii) { if (crossings[ii].DirectionToInside == dirToInside) { vector[jj++] = crossings[ii]; } } return(vector); }
internal GroupBoundaryCrossing AddIntersection(Point intersection, Obstacle group, Directions dirToInside) { List <GroupBoundaryCrossing> crossings; if (!pointCrossingMap.TryGetValue(intersection, out crossings)) { crossings = new List <GroupBoundaryCrossing>(); pointCrossingMap[intersection] = crossings; } // We may hit the same point on neighbor traversal in multiple directions. We will have more than one item // in this list only if there are multiple group boundaries at this point, which should be unusual. var crossingsCount = crossings.Count; // cache for perf for (int ii = 0; ii < crossingsCount; ++ii) { var crossing = crossings[ii]; if (crossing.Group == group) { // At a given location for a given group, there is only one valid dirToInside. Debug.Assert(dirToInside == crossing.DirectionToInside, "Mismatched dirToInside"); return(crossing); } } var newCrossing = new GroupBoundaryCrossing(group, dirToInside); crossings.Add(newCrossing); return(newCrossing); }
private static VisibilityVertex GetCrossingInteriorVertex(VisibilityGraph vg, VisibilityVertex crossingVertex, GroupBoundaryCrossing crossing) { Point interiorPoint = crossing.GetInteriorVertexPoint(crossingVertex.Point); return(vg.FindVertex(interiorPoint) ?? vg.AddVertex(interiorPoint)); }
internal GroupBoundaryCrossing AddIntersection(Point intersection, Obstacle group, Directions dirToInside) { List<GroupBoundaryCrossing> crossings; if (!pointCrossingMap.TryGetValue(intersection, out crossings)) { crossings = new List<GroupBoundaryCrossing>(); pointCrossingMap[intersection] = crossings; } // We may hit the same point on neighbor traversal in multiple directions. We will have more than one item // in this list only if there are multiple group boundaries at this point, which should be unusual. var crossingsCount = crossings.Count; // cache for perf for (int ii = 0; ii < crossingsCount; ++ii) { var crossing = crossings[ii]; if (crossing.Group == group) { // At a given location for a given group, there is only one valid dirToInside. Debug.Assert(dirToInside == crossing.DirectionToInside, "Mismatched dirToInside"); return crossing; } } var newCrossing = new GroupBoundaryCrossing(group, dirToInside); crossings.Add(newCrossing); return newCrossing; }
// For a single vertex point, split its List of crossings in both directions into an array in each (opposite) // direction. CLR Array iteration is much faster than List. static internal GroupBoundaryCrossing[] ToCrossingArray(List<GroupBoundaryCrossing> crossings, Directions dirToInside){ // First find the number in each (opposite) direction, then create the arrays. // We expect a very small number of groups to share a boundary point so this is not optimized. int numInDir = 0; var crossingsCount = crossings.Count; // cache for perf for (int ii = 0; ii < crossingsCount; ++ii) { if (crossings[ii].DirectionToInside == dirToInside) { ++numInDir; } } if (0 == numInDir) { return null; } var vector = new GroupBoundaryCrossing[numInDir]; int jj = 0; for (int ii = 0; ii < crossingsCount; ++ii) { if (crossings[ii].DirectionToInside == dirToInside) { vector[jj++] = crossings[ii]; } } return vector; }
private void AddHighCrossings(VisibilityGraph vg, VisibilityVertex crossingVertex, GroupBoundaryCrossing[] crossings) { if (null != crossings) { VisibilityVertex interiorVertex = GetCrossingInteriorVertex(vg, crossingVertex, crossings[0]); this.AddCrossingEdge(vg, crossingVertex, interiorVertex, crossings); // low-to-high } }
private void AddCrossingEdge(VisibilityGraph vg, VisibilityVertex lowVertex, VisibilityVertex highVertex, GroupBoundaryCrossing[] crossings) { VisibilityEdge edge = null; if (null != HighestVisibilityVertex) { // We may have a case where point xx.xxxxx8 has added an ascending-direction crossing, and now we're on // xx.xxxxx9 adding a descending-direction crossing. In that case there should already be a VisibilityEdge // in the direction we want. if (PointComparer.Equal(this.HighestVisibilityVertex.Point, highVertex.Point)) { edge = vg.FindEdge(lowVertex.Point, highVertex.Point); Debug.Assert(edge != null, "Inconsistent forward-backward sequencing in HighVisibilityVertex"); } else { AppendHighestVisibilityVertex(lowVertex); } } if (edge == null) { edge = AddVisibilityEdge(lowVertex, highVertex); } var crossingsArray = crossings.Select(c => c.Group.InputShape).ToArray(); var prevIsPassable = edge.IsPassable; if (prevIsPassable == null) { edge.IsPassable = delegate { return crossingsArray.Any(s => s.IsTransparent); }; } else { // Because we don't have access to the previous delegate's internals, we have to chain. Fortunately this // will never be more than two deep. File Test: Groups_Forward_Backward_Between_Same_Vertices. edge.IsPassable = delegate { return crossingsArray.Any(s => s.IsTransparent) || prevIsPassable(); }; } if (null == LowestVisibilityVertex) { SetInitialVisibilityVertex(lowVertex); } HighestVisibilityVertex = highVertex; }
private static VisibilityVertex GetCrossingInteriorVertex(VisibilityGraph vg, VisibilityVertex crossingVertex, GroupBoundaryCrossing crossing) { Point interiorPoint = crossing.GetInteriorVertexPoint(crossingVertex.Point); return vg.FindVertex(interiorPoint) ?? vg.AddVertex(interiorPoint); }