internal AxisEdge(VisibilityVertex source, VisibilityVertex target)
     : base(source, target){
     RightBound = double.PositiveInfinity;
     LeftBound = double.NegativeInfinity;
     Direction = CompassVector.DirectionsFromPointToPoint(source.Point, target.Point);
     Debug.Assert(Direction == Directions.East || Direction == Directions.North);
 }
 internal void RemoveFromGraph() {
     // Currently all transient removals and edge restorations are done by TransientGraphUtility itself.
     foreach (var entrance in PortEntrances) {
         entrance.RemoveFromGraph();
     }
     CenterVertex = null;
 }
 internal void AddToAdjacentVertex(TransientGraphUtility transUtil
             , VisibilityVertex targetVertex, Directions dirToExtend, Rectangle limitRect) {
     if (!PointComparer.Equal(this.Point, targetVertex.Point)) {
         transUtil.FindOrAddEdge(this.Vertex, targetVertex, InitialWeight);
     }
     ExtendEdgeChain(transUtil, targetVertex, dirToExtend, limitRect);
 }
 void ProcessNeighbor(GenericBinaryHeapPriorityQueue<VisibilityVertex> pq, VisibilityEdge l,
                      VisibilityVertex v) {
     var len = l.Length;
     var c = current.Distance + len;
     if (c >= upperBound)
         return;
     if (targets.Contains(v)) {
         upperBound = c;
         closestTarget = v;
     }
     if (v != source && _visGraph.PreviosVertex(v) == null) {
         v.Distance = c;
         _visGraph.SetPreviousEdge(v, l);
         pq.Enqueue(v, c);
     } else if (c < v.Distance) {
         //This condition should never hold for the dequeued nodes.
         //However because of a very rare case of an epsilon error it might!
         //In this case DecreasePriority will fail to find "v" and the algorithm will continue working.
         //Since v is not in the queue changing its .Distance will not mess up the queue.
         //Changing v.Prev is fine since we come up with a path with an insignificantly
         //smaller distance.
         v.Distance = c;
         _visGraph.SetPreviousEdge(v, l);
         pq.DecreasePriority(v, c);
     }
 }
 /// <summary>
 /// needed for shortest path calculations
 /// </summary>        
 internal VisibilityVertex PreviosVertex(VisibilityVertex v)
 {
     VisibilityEdge prev;
     if (!_prevEdgesDictionary.TryGetValue(v, out prev))
         return null;
     if (prev.Source == v)
         return prev.Target;
     return prev.Source;
 }
        internal SingleSourceMultipleTargetsShortestPathOnVisibilityGraph(VisibilityVertex sourceVisVertex,
                                                                         IEnumerable<VisibilityVertex> targetVisVertices, VisibilityGraph visibilityGraph) {
            _visGraph = visibilityGraph;
            _visGraph.ClearPrevEdgesTable();
            foreach (var v in visibilityGraph.Vertices())
                v.Distance = Double.PositiveInfinity;

            source = sourceVisVertex;
            targets = new Set<VisibilityVertex>(targetVisVertices);
            source.Distance = 0;
        }
 internal static void CalculatePointVisibilityGraph(IEnumerable<Polyline> listOfHoles,
                                                    VisibilityGraph visibilityGraph, Point point,
                                        VisibilityKind visibilityKind, out VisibilityVertex qVertex) {
     //maybe there is nothing to do
     var qv = visibilityGraph.FindVertex(point);
     if (qv != null){
         qVertex = qv;
         return;
     }
         
     var calculator = new PointVisibilityCalculator(listOfHoles, visibilityGraph, point, visibilityKind);
     calculator.FillGraph();
     qVertex = calculator.QVertex;
     Debug.Assert(qVertex != null);
 }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="pathStart"></param>
        /// <param name="pathEnd"></param>
        /// <param name="obstacles"></param>
        /// <param name="sourceVertex">graph vertex corresponding to the source</param>
        /// <param name="targetVertex">graph vertex corresponding to the target</param>
        /// <returns></returns>
        internal static VisibilityGraph GetVisibilityGraphForShortestPath(Point pathStart, Point pathEnd,
                                                                          IEnumerable<Polyline> obstacles,
                                                                          out VisibilityVertex sourceVertex,
                                                                          out VisibilityVertex targetVertex) {
            var holes = new List<Polyline>(OrientHolesClockwise(obstacles));
            var visibilityGraph = CalculateGraphOfBoundaries(holes);
            var polygons = holes.Select(hole => new Polygon(hole)).ToList();

            TangentVisibilityGraphCalculator.AddTangentVisibilityEdgesToGraph(polygons, visibilityGraph);
            PointVisibilityCalculator.CalculatePointVisibilityGraph(holes, visibilityGraph, pathStart,
                                                                    VisibilityKind.Tangent, out sourceVertex);
            PointVisibilityCalculator.CalculatePointVisibilityGraph(holes, visibilityGraph, pathEnd,
                                                                    VisibilityKind.Tangent, out targetVertex);

            return visibilityGraph;
        }
示例#9
0
        internal void ExtendEdgeChain(TransientGraphUtility transUtil, VisibilityVertex paddedBorderVertex
                                      , VisibilityVertex targetVertex, Rectangle limitRect, bool routeToCenter)
        {
            // Extend the edge chain to the opposite side of the limit rectangle.
            transUtil.ExtendEdgeChain(targetVertex, limitRect, this.MaxVisibilitySegment, this.pointAndCrossingsList, this.IsOverlapped);

            // In order for Nudger to be able to map from the (near-) endpoint vertex to a PortEntry, we must
            // always connect a vertex at UnpaddedBorderIntersect to the paddedBorderVertex, even if routeToCenter.
            var unpaddedBorderVertex = transUtil.FindOrAddVertex(UnpaddedBorderIntersect);

            transUtil.FindOrAddEdge(unpaddedBorderVertex, paddedBorderVertex, this.unpaddedToPaddedBorderWeight);
            if (routeToCenter)
            {
                // Link the CenterVertex to the vertex at UnpaddedBorderIntersect.
                transUtil.ConnectVertexToTargetVertex(ObstaclePort.CenterVertex, unpaddedBorderVertex, OutwardDirection, InitialWeight);
            }
        }
示例#10
0
        // Adds an edge from this.Vertex to a (possibly new) vertex at an intersection with an
        // existing Edge that adjoins the point.  We take 'dir' as an input parameter for edge
        // extension because we may be on the edge so can't calculate the direction.
        internal VisibilityVertex AddEdgeToAdjacentEdge(TransientGraphUtility transUtil
                                                        , VisibilityEdge targetEdge, Directions dirToExtend, Rectangle limitRect)
        {
            Point            targetIntersect = StaticGraphUtility.SegmentIntersection(targetEdge, this.Point);
            VisibilityVertex targetVertex    = transUtil.VisGraph.FindVertex(targetIntersect);

            if (null != targetVertex)
            {
                AddToAdjacentVertex(transUtil, targetVertex, dirToExtend, limitRect);
            }
            else
            {
                targetVertex = transUtil.AddEdgeToTargetEdge(this.Vertex, targetEdge, targetIntersect);
            }
            ExtendEdgeChain(transUtil, targetVertex, dirToExtend, limitRect);
            return(targetVertex);
        }
        internal VisibilityEdge FindNearestPerpendicularOrContainingEdge(VisibilityVertex startVertex
                                                                         , Directions dir, Point pointLocation)
        {
            // Similar to FindPerpendicularEdge, but first try to move closer to pointLocation,
            // as long as there are edges going in 'dir' that extend to pointLocation.
            Directions dirTowardLocation = ~dir& PointComparer.GetDirections(startVertex.Point, pointLocation);

            // If Directions. None then pointLocation is collinear.
            VisibilityVertex currentVertex            = startVertex;
            Directions       currentDirTowardLocation = dirTowardLocation;

            // First move toward pointLocation far as we can.
            while (Directions.None != currentDirTowardLocation)
            {
                VisibilityVertex nextVertex = StaticGraphUtility.FindNextVertex(currentVertex, dirTowardLocation);
                if (null == nextVertex)
                {
                    break;
                }

                if (0 != (CompassVector.OppositeDir(dirTowardLocation)
                          & PointComparer.GetDirections(nextVertex.Point, pointLocation)))
                {
                    break;
                }

                currentVertex            = nextVertex;
                currentDirTowardLocation = ~dir& PointComparer.GetDirections(currentVertex.Point, pointLocation);
            }

            // Now find the first vertex that has a chain that intersects pointLocation, if any, moving away
            // from pointLocation until we find it or arrive back at startVertex.
            VisibilityEdge perpEdge;

            while (true)
            {
                perpEdge = FindPerpendicularOrContainingEdge(currentVertex, dir, pointLocation);
                if ((null != perpEdge) || (currentVertex == startVertex))
                {
                    break;
                }

                currentVertex = StaticGraphUtility.FindNextVertex(currentVertex, CompassVector.OppositeDir(dirTowardLocation));
            }
            return(perpEdge);
        }
示例#12
0
        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;
        }
        /// <summary>
        /// Returns  a  path
        /// </summary>
        /// <returns>a path or null if the target is not reachable from the source</returns>
        internal IEnumerable<VisibilityVertex> GetPath() {
            var pq = new GenericBinaryHeapPriorityQueue<VisibilityVertex>();
            source.Distance = 0;
            pq.Enqueue(source, 0);
            while (!pq.IsEmpty()) {
                current = pq.Dequeue();
                if (targets.Contains(current))
                    break;

                foreach (var e in current.OutEdges.Where(PassableOutEdge))
                    ProcessNeighbor(pq, e, e.Target);

                foreach (var e in current.InEdges.Where(PassableInEdge))
                    ProcessNeighbor(pq, e, e.Source);
            }

            return _visGraph.PreviosVertex(current) == null ? null : CalculatePath();
        }
       // ReSharper restore InconsistentNaming

        private VisibilityEdge CreateEdge(VisibilityVertex first, VisibilityVertex second, double weight)
        {
            // All edges in the graph are ascending.
            VisibilityVertex source = first;
            VisibilityVertex target = second;

            if (!PointComparer.IsPureLower(source.Point, target.Point))
            {
                source = second;
                target = first;
            }

            var edge = new TollFreeVisibilityEdge(source, target, weight);

            VisibilityGraph.AddEdge(edge);
            this.AddedEdges.Add(edge);
            return(edge);
        }
        private static Point GetBarycenterOfUniquePortLocations(IEnumerable <VisibilityVertex> vertices)
        {
            var center = new Point();
            VisibilityVertex prevVertex = null;
            int count = 0;

            foreach (var vertex in vertices.OrderBy(s => s.Point))
            {
                if ((prevVertex != null) && ApproximateComparer.CloseIntersections(vertex.Point, prevVertex.Point))
                {
                    continue;
                }
                prevVertex = vertex;
                ++count;
                center += vertex.Point;
            }
            return(center / count);
        }
        private static VisibilityVertex TraverseToFirstVertexAtOrAbove(VisibilityVertex startVertex, Point start, Directions dir)
        {
            var returnVertex = startVertex;
            var oppositeDir  = CompassVector.OppositeDir(dir);

            for ( ; ;)
            {
                var nextVertex = StaticGraphUtility.FindNextVertex(returnVertex, dir);

                // This returns Directions. None on a match.
                if ((null == nextVertex) || (PointComparer.GetDirections(nextVertex.Point, start) == oppositeDir))
                {
                    break;
                }
                returnVertex = nextVertex;
            }
            return(returnVertex);
        }
        internal VisibilityEdge FindOrAddEdge(VisibilityVertex sourceVertex, VisibilityVertex targetVertex, double weight)
        {
            // Since we're adding transient edges into the graph, we're not doing full intersection
            // evaluation; thus there may already be an edge from the source vertex in the direction
            // of the target vertex, but ending before or after the target vertex.
            Directions       dirToTarget = PointComparer.GetPureDirection(sourceVertex, targetVertex);
            VisibilityVertex bracketSource, bracketTarget;

            // Is there an edge in the chain from sourceVertex in the direction of targetVertex
            // that brackets targetvertex?
            //      <sourceVertex> -> ..1.. -> ..2.. <end>   3
            // Yes if targetVertex is at the x above 1 or 2, No if it is at 3.  If false, bracketSource
            // will be set to the vertex at <end> (if there are any edges in that direction at all).
            VisibilityVertex splitVertex = targetVertex;

            if (!FindBracketingVertices(sourceVertex, targetVertex.Point, dirToTarget
                                        , out bracketSource, out bracketTarget))
            {
                // No bracketing of targetVertex from sourceVertex but bracketSource has been updated.
                // Is there a bracket of bracketSource from the targetVertex direction?
                //                      3   <end> ..2.. <- ..1..   <targetVertex>
                // Yes if bracketSource is at the x above 1 or 2, No if it is at 3.  If false, bracketTarget
                // will be set to the vertex at <end> (if there are any edges in that direction at all).
                // If true, then bracketSource and splitVertex must be updated.
                VisibilityVertex tempSource;
                if (FindBracketingVertices(targetVertex, sourceVertex.Point, CompassVector.OppositeDir(dirToTarget)
                                           , out bracketTarget, out tempSource))
                {
                    Debug.Assert(bracketSource == sourceVertex, "Mismatched bracketing detection");
                    bracketSource = tempSource;
                    splitVertex   = sourceVertex;
                }
            }

            // If null != edge then targetVertex is between bracketSource and bracketTarget and SplitEdge returns the
            // first half-edge (and weight is ignored as the split uses the edge weight).
            var edge = VisGraph.FindEdge(bracketSource.Point, bracketTarget.Point);

            edge = (null != edge)
                    ? this.SplitEdge(edge, splitVertex)
                    : CreateEdge(bracketSource, bracketTarget, weight);
            DevTrace_VerifyEdge(edge);
            return(edge);
        }
        internal void ExtendEdgeChain(VisibilityVertex startVertex, Rectangle limitRect, LineSegment maxVisibilitySegment,
                                      PointAndCrossingsList pacList, bool isOverlapped)
        {
            var dir = PointComparer.GetDirections(maxVisibilitySegment.Start, maxVisibilitySegment.End);

            if (dir == Directions.None)
            {
                return;
            }

            Debug.Assert(CompassVector.IsPureDirection(dir), "impure max visibility segment");

            // Shoot the edge chain out to the shorter of max visibility or intersection with the limitrect.
            StaticGraphUtility.Assert(PointComparer.Equal(maxVisibilitySegment.Start, startVertex.Point) ||
                                      (PointComparer.GetPureDirection(maxVisibilitySegment.Start, startVertex.Point) == dir)
                                      , "Inconsistent direction found", ObstacleTree, VisGraph);
            double oppositeFarBound      = StaticGraphUtility.GetRectangleBound(limitRect, dir);
            Point  maxDesiredSplicePoint = StaticGraphUtility.IsVertical(dir)
                                    ? ApproximateComparer.Round(new Point(startVertex.Point.X, oppositeFarBound))
                                    : ApproximateComparer.Round(new Point(oppositeFarBound, startVertex.Point.Y));

            if (PointComparer.Equal(maxDesiredSplicePoint, startVertex.Point))
            {
                // Nothing to do.
                return;
            }
            if (PointComparer.GetPureDirection(startVertex.Point, maxDesiredSplicePoint) != dir)
            {
                // It's in the opposite direction, so no need to do anything.
                return;
            }

            // If maxDesiredSplicePoint is shorter, create a new shorter segment.  We have to pass both segments
            // through to the worker function so it knows whether it can go past maxDesiredSegment (which may be limited
            // by limitRect).
            var maxDesiredSegment = maxVisibilitySegment;

            if (PointComparer.GetDirections(maxDesiredSplicePoint, maxDesiredSegment.End) == dir)
            {
                maxDesiredSegment = new LineSegment(maxDesiredSegment.Start, maxDesiredSplicePoint);
            }

            ExtendEdgeChain(startVertex, dir, maxDesiredSegment, maxVisibilitySegment, pacList, isOverlapped);
        }
示例#19
0
        internal void AddToAdjacentVertex(TransientGraphUtility transUtil, VisibilityVertex targetVertex
                                          , Rectangle limitRect, bool routeToCenter)
        {
            VisibilityVertex borderVertex = transUtil.VisGraph.FindVertex(this.VisibilityBorderIntersect);

            if (null != borderVertex)
            {
                ExtendFromBorderVertex(transUtil, borderVertex, limitRect, routeToCenter);
                return;
            }

            // There is no vertex at VisibilityBorderIntersect, so create it and link it to targetVertex.
            // Note: VisibilityBorderIntersect may == targetIntersect if that is on our border, *and*
            // targetIntersect may be on the border of a touching obstacle, in which case this will splice
            // into or across the adjacent obstacle, which is consistent with "touching is overlapped".
            // So we don't use UnpaddedBorderIntersect as prevPoint when calling ExtendEdgeChain.

            // VisibilityBorderIntersect may be rounded just one Curve.DistanceEpsilon beyond the ScanSegment's
            // perpendicular coordinate; e.g. our X may be targetIntersect.X + Curve.DistanceEpsilon, thereby
            // causing the direction from VisibilityBorderIntersect to targetIntersect to be W instead of E.
            // So use the targetIntersect if they are close enough; they will be equal for flat borders, and
            // otherwise the exact value we use only needs be "close enough" to the border.  (We can't use
            // CenterVertex as the prevPoint because that could be an impure direction).
            // Update: With the change to carry MaxVisibilitySegment within the PortEntrance, PortManager finds
            // targetVertex between VisibilityBorderIntersect and MaxVisibilitySegment.End, so this should no longer
            // be able to happen.
            // See RectilinearTests.PaddedBorderIntersectMeetsIncomingScanSegment for an example of what happens
            // when VisibilityBorderIntersect is on the incoming ScanSegment (it jumps out above with borderVertex found).
            if (OutwardDirection == PointComparer.GetPureDirection(targetVertex.Point, this.VisibilityBorderIntersect))
            {
                Debug.Assert(false, "Unexpected reversed direction between VisibilityBorderIntersect and targetVertex");
// ReSharper disable HeuristicUnreachableCode
                this.VisibilityBorderIntersect = targetVertex.Point;
                borderVertex = targetVertex;
// ReSharper restore HeuristicUnreachableCode
            }
            else
            {
                borderVertex = transUtil.FindOrAddVertex(this.VisibilityBorderIntersect);
                transUtil.FindOrAddEdge(borderVertex, targetVertex, InitialWeight);
            }
            ExtendEdgeChain(transUtil, borderVertex, targetVertex, limitRect, routeToCenter);
        }
示例#20
0
        static internal VisibilityEdge FindAdjacentEdge(VisibilityVertex a, Direction dir)
        {
            foreach (var edge in a.InEdges)
            {
                if (PointComparer.GetPureDirection(edge.SourcePoint, a.Point) == dir)
                {
                    return(edge);
                }
            }

            foreach (var edge in a.OutEdges)
            {
                if (PointComparer.GetPureDirection(a.Point, edge.TargetPoint) == dir)
                {
                    return(edge);
                }
            }
            return(null);
        }
        internal void ExtendEdgeChain(TransientGraphUtility transUtil, VisibilityVertex targetVertex, Directions dirToExtend, Rectangle limitRect) {
            // Extend the edge chain to the opposite side of the limit rectangle.
            StaticGraphUtility.Assert(PointComparer.Equal(this.Point, targetVertex.Point)
                        || (PointComparer.GetPureDirection(this.Point, targetVertex.Point) == dirToExtend)
                        , "input dir does not match with to-targetVertex direction", transUtil.ObstacleTree, transUtil.VisGraph);

            var extendOverlapped = IsOverlapped;
            if (extendOverlapped)
            {
                // The initial vertex we connected to may be on the border of the enclosing obstacle,
                // or of another also-overlapped obstacle.  If the former, we turn off overlap now.
                extendOverlapped = transUtil.ObstacleTree.PointIsInsideAnObstacle(targetVertex.Point, dirToExtend);
            }

            // If we're inside an obstacle's boundaries we'll never extend past the end of the obstacle
            // due to encountering the boundary from the inside.  So start the extension at targetVertex.
            SegmentAndCrossings segmentAndCrossings = GetSegmentAndCrossings(this.IsOverlapped ? targetVertex : this.Vertex, dirToExtend, transUtil);
            transUtil.ExtendEdgeChain(targetVertex, limitRect, segmentAndCrossings.Item1, segmentAndCrossings.Item2, extendOverlapped);
        }
        internal VisibilityEdge FindOrAddEdge(VisibilityVertex sourceVertex, VisibilityVertex targetVertex, double weight)
        {
            // Since we're adding transient edges into the graph, we're not doing full intersection
            // evaluation; thus there may already be an edge from the source vertex in the direction
            // of the target vertex, but ending before or after the target vertex.
            Direction        dirToTarget = PointComparer.GetPureDirection(sourceVertex, targetVertex);
            VisibilityVertex bracketSource, bracketTarget, splitVertex;

            GetBrackets(sourceVertex, targetVertex, dirToTarget, out bracketSource, out bracketTarget, out splitVertex);

            // If null != edge then targetVertex is between bracketSource and bracketTarget and SplitEdge returns the
            // first half-edge (and weight is ignored as the split uses the edge weight).
            var edge = VisGraph.FindEdge(bracketSource.Point, bracketTarget.Point);

            edge = (edge != null)
                    ? this.SplitEdge(edge, splitVertex)
                    : CreateEdge(bracketSource, bracketTarget, weight);
            DevTrace_VerifyEdge(edge);
            return(edge);
        }
        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)); };
            }
        }
        internal VisibilityVertex AddEdgeToTargetEdge(VisibilityVertex sourceVertex, VisibilityEdge targetEdge
                                                      , Point targetIntersect)
        {
            StaticGraphUtility.Assert(PointComparer.Equal(sourceVertex.Point, targetIntersect) ||
                                      PointComparer.IsPureDirection(sourceVertex.Point, targetIntersect)
                                      , "non-orthogonal edge request", ObstacleTree, VisGraph);
            StaticGraphUtility.Assert(StaticGraphUtility.PointIsOnSegment(targetEdge.SourcePoint, targetEdge.TargetPoint, targetIntersect)
                                      , "targetIntersect is not on targetEdge", ObstacleTree, VisGraph);

            // If the target vertex does not exist, we must split targetEdge to add it.
            VisibilityVertex targetVertex = VisGraph.FindVertex(targetIntersect);

            if (null == targetVertex)
            {
                targetVertex = AddVertex(targetIntersect);
                SplitEdge(targetEdge, targetVertex);
            }
            FindOrAddEdge(sourceVertex, targetVertex);
            return(targetVertex);
        }
        void ProcessNeighbor(GenericBinaryHeapPriorityQueue <VisibilityVertex> pq, VisibilityVertex u, VisibilityEdge l, VisibilityVertex v)
        {
            var len = l.Length;
            var c   = u.Distance + len;

            /*
             * if (_visGraph.visVertexToId[l.Source] < _g.N || _visGraph.visVertexToId[l.Target] < _g.N)
             * {
             *  if (!(l.Source == _source || l.Target == _source || l.Source == _target || l.Target == _target))
             *  {
             *      c = 500;
             *  }
             * }
             */
            // (v != _source && _visGraph.PreviosVertex(v) == null)

            if (v != _source && _visGraph.PreviosVertex(v) == null)
            {
                v.Distance = c;
                _visGraph.SetPreviousEdge(v, l);
                if (v != _target)
                {
                    pq.Enqueue(v, H(v));
                }
            }
            else if (v != _source && c < v.Distance)
            { //This condition should never hold for the dequeued nodes.
                //However because of a very rare case of an epsilon error it might!
                //In this case DecreasePriority will fail to find "v" and the algorithm will continue working.
                //Since v is not in the queue changing its .Distance will not influence other nodes.
                //Changing v.Prev is fine since we come up with the path with an insignificantly
                //smaller distance.
                var prevV = _visGraph.PreviosVertex(v);
                v.Distance = c;
                _visGraph.SetPreviousEdge(v, l);
                if (v != _target)
                {
                    pq.DecreasePriority(v, H(v));
                }
            }
        }
示例#26
0
        internal static IEnumerable <Point> RestorePath(ref VertexEntry entry, VisibilityVertex firstVertexInStage)
        {
            if (entry == null)
            {
                return(null);
            }

            var        list = new List <Point>();
            bool       skippedCollinearEntry = false;
            Directions lastEntryDir          = Directions.None;

            while (true)
            {
                // Reduce unnecessary AxisEdge creations in Nudger by including only bend points, not points in the middle of a segment.
                if (lastEntryDir == entry.Direction)
                {
                    skippedCollinearEntry = true;
                }
                else
                {
                    skippedCollinearEntry = false;
                    list.Add(entry.Vertex.Point);
                    lastEntryDir = entry.Direction;
                }

                var previousEntry = entry.PreviousEntry;
                if ((previousEntry == null) || (entry.Vertex == firstVertexInStage))
                {
                    break;
                }

                entry = previousEntry;
            }
            if (skippedCollinearEntry)
            {
                list.Add(entry.Vertex.Point);
            }

            list.Reverse();
            return(list);
        }
示例#27
0
        internal void ExtendEdgeChain(TransientGraphUtility transUtil, VisibilityVertex targetVertex, Directions dirToExtend, Rectangle limitRect)
        {
            // Extend the edge chain to the opposite side of the limit rectangle.
            StaticGraphUtility.Assert(PointComparer.Equal(this.Point, targetVertex.Point) ||
                                      (PointComparer.GetPureDirection(this.Point, targetVertex.Point) == dirToExtend)
                                      , "input dir does not match with to-targetVertex direction", transUtil.ObstacleTree, transUtil.VisGraph);

            var extendOverlapped = IsOverlapped;

            if (extendOverlapped)
            {
                // The initial vertex we connected to may be on the border of the enclosing obstacle,
                // or of another also-overlapped obstacle.  If the former, we turn off overlap now.
                extendOverlapped = transUtil.ObstacleTree.PointIsInsideAnObstacle(targetVertex.Point, dirToExtend);
            }

            // If we're inside an obstacle's boundaries we'll never extend past the end of the obstacle
            // due to encountering the boundary from the inside.  So start the extension at targetVertex.
            SegmentAndCrossings segmentAndCrossings = GetSegmentAndCrossings(this.IsOverlapped ? targetVertex : this.Vertex, dirToExtend, transUtil);

            transUtil.ExtendEdgeChain(targetVertex, limitRect, segmentAndCrossings.Item1, segmentAndCrossings.Item2, extendOverlapped);
        }
        internal VisibilityEdge FindOrAddEdge(VisibilityVertex sourceVertex, VisibilityVertex targetVertex, double weight) {
            // Since we're adding transient edges into the graph, we're not doing full intersection
            // evaluation; thus there may already be an edge from the source vertex in the direction
            // of the target vertex, but ending before or after the target vertex.
            Directions dirToTarget = PointComparer.GetPureDirection(sourceVertex, targetVertex);
            VisibilityVertex bracketSource, bracketTarget;

            // Is there an edge in the chain from sourceVertex in the direction of targetVertex
            // that brackets targetvertex?
            //      <sourceVertex> -> ..1.. -> ..2.. <end>   3
            // Yes if targetVertex is at the x above 1 or 2, No if it is at 3.  If false, bracketSource
            // will be set to the vertex at <end> (if there are any edges in that direction at all).
            VisibilityVertex splitVertex = targetVertex;
            if (!FindBracketingVertices(sourceVertex, targetVertex.Point, dirToTarget
                                    , out bracketSource, out bracketTarget)) {
                // No bracketing of targetVertex from sourceVertex but bracketSource has been updated.
                // Is there a bracket of bracketSource from the targetVertex direction?
                //                      3   <end> ..2.. <- ..1..   <targetVertex>
                // Yes if bracketSource is at the x above 1 or 2, No if it is at 3.  If false, bracketTarget
                // will be set to the vertex at <end> (if there are any edges in that direction at all).
                // If true, then bracketSource and splitVertex must be updated.
                VisibilityVertex tempSource;
                if (FindBracketingVertices(targetVertex, sourceVertex.Point, CompassVector.OppositeDir(dirToTarget)
                                        , out bracketTarget, out tempSource)) {
                    Debug.Assert(bracketSource == sourceVertex, "Mismatched bracketing detection");
                    bracketSource = tempSource;
                    splitVertex = sourceVertex;
                }
            }

            // If null != edge then targetVertex is between bracketSource and bracketTarget and SplitEdge returns the 
            // first half-edge (and weight is ignored as the split uses the edge weight).
            var edge = VisGraph.FindEdge(bracketSource.Point, bracketTarget.Point);
            edge = (null != edge)
                    ? this.SplitEdge(edge, splitVertex)
                    : CreateEdge(bracketSource, bracketTarget, weight);
            DevTrace_VerifyEdge(edge);
            return edge;
        }
        private void Debug_VerifyNonOverlappedExtension(bool isOverlapped, VisibilityVertex extendVertex, VisibilityVertex nextExtendVertex,
                                                        VisibilityVertex spliceSource, VisibilityVertex spliceTarget)
        {
            if (isOverlapped)
            {
                return;
            }
#if TEST_MSAGL
            StaticGraphUtility.Assert(!this.ObstacleTree.SegmentCrossesANonGroupObstacle(extendVertex.Point, nextExtendVertex.Point)
                                      , "extendDir edge crosses an obstacle", this.ObstacleTree, this.VisGraph);
#endif // TEST_MSAGL

            if (spliceSource == null)
            {
                // Only verifying the direct extension.
                return;
            }

            // Verify lateral splices as well.
            if ((null == spliceTarget) ||
                (null == this.VisGraph.FindEdge(spliceSource.Point, spliceTarget.Point) &&
                 (null == this.VisGraph.FindEdge(spliceSource.Point, nextExtendVertex.Point))))
            {
                // If targetVertex isn't null and the proposed edge from nextExtendVertex -> targetVertex
                // edge doesn't already exist, then we assert that we're not creating a new edge that
                // crosses the obstacle bounds (a bounds-crossing edge may already exist, from a port
                // within the obstacle; in that case nextExtendPoint splits that edge).  As above, don't
                // splice laterally across groups.
                StaticGraphUtility.Assert(!this.ObstacleTree.SegmentCrossesAnObstacle(spliceSource.Point, nextExtendVertex.Point)
                                          , "spliceSource->extendVertex edge crosses an obstacle", this.ObstacleTree, this.VisGraph);

                // Above we moved spliceTarget over when nextExtendVertex existed, so account
                // for that here.
                StaticGraphUtility.Assert((null == spliceTarget) ||
                                          (null != this.VisGraph.FindEdge(nextExtendVertex.Point, spliceTarget.Point)) ||
                                          !this.ObstacleTree.SegmentCrossesAnObstacle(nextExtendVertex.Point, spliceTarget.Point)
                                          , "extendVertex->spliceTarget edge crosses an obstacle", this.ObstacleTree, this.VisGraph);
            }
        }
示例#30
0
        private SegmentAndCrossings GetSegmentAndCrossings(VisibilityVertex startVertex, Directions dirToExtend, TransientGraphUtility transUtil)
        {
            var dirIndex            = CompassVector.ToIndex(dirToExtend);
            var segmentAndCrossings = this.maxVisibilitySegmentsAndCrossings[dirIndex];

            if (null == segmentAndCrossings)
            {
                PointAndCrossingsList pacList;
                var maxVisibilitySegment = transUtil.ObstacleTree.CreateMaxVisibilitySegment(startVertex.Point, dirToExtend, out pacList);
                segmentAndCrossings = new SegmentAndCrossings(maxVisibilitySegment, pacList);
                this.maxVisibilitySegmentsAndCrossings[dirIndex] = segmentAndCrossings;
            }
            else
            {
                // For a waypoint this will be a target and then a source, so there may be a different lateral edge to
                // connect to. In that case make sure we are consistent in directions - back up the start point if needed.
                if (PointComparer.GetDirections(startVertex.Point, segmentAndCrossings.Item1.Start) == dirToExtend)
                {
                    segmentAndCrossings.Item1.Start = startVertex.Point;
                }
            }
            return(segmentAndCrossings);
        }
        static internal VisibilityVertex FindNextVertex(VisibilityVertex vertex, Directions dir) {
            // This function finds the next vertex in the desired direction relative to the
            // current vertex, not necessarily the edge orientation, hence it does not use
            // EdgeDirection().  This is so the caller can operate on a desired movement
            // direction without having to track whether we're going forward or backward
            // through the In/OutEdge chain.
            int cEdges = vertex.InEdges.Count;      // indexing is faster than foreach for Lists
            for (int ii = 0; ii < cEdges; ++ii) {
                var edge = vertex.InEdges[ii];
                if (PointComparer.GetPureDirection(vertex.Point, edge.SourcePoint) == dir) {
                    return edge.Source;
                }
            }

            // Avoid GetEnumerator overhead.
            var outEdgeNode = vertex.OutEdges.IsEmpty() ? null : vertex.OutEdges.TreeMinimum();
            for (; outEdgeNode != null; outEdgeNode = vertex.OutEdges.Next(outEdgeNode)) {
                var edge = outEdgeNode.Item;
                if (PointComparer.GetPureDirection(vertex.Point, edge.TargetPoint) == dir) {
                    return edge.Target;
                }
            }
            return null;
        }
示例#32
0
        static internal VisibilityVertex FindAdjacentVertex(VisibilityVertex a, Direction dir)
        {
            // This function finds the next vertex in the desired direction relative to the
            // current vertex, not necessarily the edge orientation, hence it does not use
            // EdgeDirection().  This is so the caller can operate on a desired movement
            // direction without having to track whether we're going forward or backward
            // through the In/OutEdge chain.
            foreach (var edge in a.InEdges)
            {
                if (PointComparer.GetPureDirection(a.Point, edge.SourcePoint) == dir)
                {
                    return(edge.Source);
                }
            }

            foreach (var edge in a.OutEdges)
            {
                if (PointComparer.GetPureDirection(a.Point, edge.TargetPoint) == dir)
                {
                    return(edge.Target);
                }
            }
            return(null);
        }
示例#33
0
        private IEnumerable <VisibilityEdge> GetAllEdgesTest(VisibilityVertex vertex)
        {
            var processedVertices = new Set <VisibilityVertex>();
            var q = new Queue <VisibilityVertex>();

            q.Enqueue(vertex);

            // Target may not be connected to source.
            bool targetFound = (vertex == this.Target);

            while (!targetFound)
            {
                while (q.Count > 0)
                {
                    VisibilityVertex v = q.Dequeue();
                    if (processedVertices.Contains(v))
                    {
                        continue;
                    }

                    targetFound |= (v == this.Target);
                    processedVertices.Insert(v);
                    foreach (var u in VertsToGo(v).Where(u => !processedVertices.Contains(u)))
                    {
                        q.Enqueue(u);
                    }

                    foreach (VisibilityEdge edge in v.OutEdges)
                    {
                        yield return(edge);
                    }
                }
                q.Enqueue(this.Target);
                targetFound = true;
            }
        }
示例#34
0
        private bool InitEntryDirectionsAtTarget(VisibilityVertex vert)
        {
            EntryDirectionsToTarget = Directions.None;

            // This routine is only called once so don't worry about optimizing foreach.
            foreach (var edge in vert.OutEdges)
            {
#if SHARPKIT //http://code.google.com/p/sharpkit/issues/detail?id=368 property assignment not working with |= operator
                EntryDirectionsToTarget = EntryDirectionsToTarget | CompassVector.DirectionsFromPointToPoint(edge.TargetPoint, vert.Point);
#else
                EntryDirectionsToTarget |= CompassVector.DirectionsFromPointToPoint(edge.TargetPoint, vert.Point);
#endif
            }
            foreach (var edge in vert.InEdges)
            {
#if SHARPKIT //http://code.google.com/p/sharpkit/issues/detail?id=368 property assignment not working with |= operator
                EntryDirectionsToTarget = EntryDirectionsToTarget | CompassVector.DirectionsFromPointToPoint(edge.SourcePoint, vert.Point);
#else
                EntryDirectionsToTarget |= CompassVector.DirectionsFromPointToPoint(edge.SourcePoint, vert.Point);
#endif
            }
            // If this returns false then the target is isolated.
            return(EntryDirectionsToTarget != Directions.None);
        }
        void DevTraceShowAllPartialPaths(VisibilityVertex source, VertexEntry mostRecentlyExtendedPath) { 
#if DEVTRACE
            if (ssstTrace.IsLevel(3))
            {
                this.TestShowAllPaths(source, mostRecentlyExtendedPath);
            }
#endif // DEVTRACE
        }
示例#36
0
        private static VisibilityVertex GetCrossingInteriorVertex(VisibilityGraph vg, VisibilityVertex crossingVertex,
                                                                  GroupBoundaryCrossing crossing)
        {
            Point interiorPoint = crossing.GetInteriorVertexPoint(crossingVertex.Point);

            return(vg.FindVertex(interiorPoint) ?? vg.AddVertex(interiorPoint));
        }
 private static Directions GetLengthAndNumberOfBendsToNeighborVertex(VertexEntry prevEntry, 
             VisibilityVertex vertex, double weight, out int numberOfBends, out double length) {
     length = prevEntry.Length + ManhattanDistance(prevEntry.Vertex.Point, vertex.Point)*weight;
     Directions directionToVertex = CompassVector.PureDirectionFromPointToPoint(prevEntry.Vertex.Point, vertex.Point);
     numberOfBends = prevEntry.NumberOfBends;
     if (prevEntry.Direction != Directions. None && directionToVertex != prevEntry.Direction) {
         numberOfBends++;
     }
     return directionToVertex;
 }
 void FindBeforeAfterV(VisibilityVertex v, RbTree<VisibilityVertex> nodeBoundaryRbTree,
     out VisibilityVertex beforeV, out VisibilityVertex afterV, Point center) {
     Point xDir=new Point(1,0);
     var vAngle = Point.Angle(xDir, v.Point - center);
     var rNode = nodeBoundaryRbTree.FindLast(w => Point.Angle(xDir, w.Point - center) <= vAngle);
     beforeV = rNode!=null? rNode.Item : nodeBoundaryRbTree.TreeMaximum().Item;
     rNode = nodeBoundaryRbTree.FindFirst(w => Point.Angle(xDir, w.Point - center) >= vAngle);
     afterV = rNode != null ? rNode.Item : nodeBoundaryRbTree.TreeMinimum().Item;
 }
        internal List<Point> GetPath(VisibilityVertex vs, VisibilityVertex vt,
            bool shrinkDistances) {
            var pathPoints = new List<Point>();

            vs.IsShortestPathTerminal = vt.IsShortestPathTerminal = true;
            _visGraph.ClearPrevEdgesTable();
            var router = new SingleSourceSingleTargetShortestPathOnVisibilityGraph(_visGraph, vs, vt)
            {
                LengthMultiplier = 0.8,
                LengthMultiplierForAStar = 0.3
            };
            var vpath = router.GetPath(shrinkDistances);
            if (vpath == null) {
                Console.WriteLine("seeing a null path");
                vs.IsShortestPathTerminal = vt.IsShortestPathTerminal = false; 
                return pathPoints;
            }
            var path = vpath.ToList();
            for (int i = 0; i < path.Count(); i++)
                pathPoints.Add(path[i].Point);

            
            vs.IsShortestPathTerminal = vt.IsShortestPathTerminal = false;                 
            return pathPoints;
        }
示例#40
0
 static internal Directions GetPureDirection(VisibilityVertex first, VisibilityVertex second)
 {
     Assert_Rounded(first.Point);
     Assert_Rounded(second.Point);
     return(GetPureDirection(first.Point, second.Point));
 }
 VisibilityVertex GlueOrAddToPolylineAndVisGraph(Point[] polySplitArray, int i, VisibilityVertex v, Polyline poly) {
     var ip = polySplitArray[i];
     if (ApproximateComparer.Close(v.Point, ip))
         return v; // gluing ip to the previous point on the polyline
     if (ApproximateComparer.Close(ip, poly.StartPoint.Point)) {
         var vv = VisGraph.FindVertex(poly.StartPoint.Point);
         Debug.Assert(vv != null);
         return vv;
     }
     poly.AddPoint(ip);
     return VisGraph.AddVertex(ip);
 }
示例#42
0
 static VisibilityVertex OtherVertex(VisibilityEdge axisEdge, VisibilityVertex v)
 {
     return(axisEdge.Source == v?axisEdge.Target:axisEdge.Source);
 }
        private bool InitEntryDirectionsAtTarget(VisibilityVertex vert) {
            EntryDirectionsToTarget = Directions. None;

            // This routine is only called once so don't worry about optimizing foreach.
            foreach (var edge in vert.OutEdges) {
                EntryDirectionsToTarget |= CompassVector.DirectionsFromPointToPoint(edge.TargetPoint, vert.Point);
            }
            foreach (var edge in vert.InEdges) {
                EntryDirectionsToTarget |= CompassVector.DirectionsFromPointToPoint(edge.SourcePoint, vert.Point);
            }
            // If this returns false then the target is isolated.
            return EntryDirectionsToTarget != Directions. None;
        }
        bool AngleIsTooSmallAfterShortcutAtVertex(VisibilityVertex v1, VisibilityVertex v2, VisibilityVertex v3)
        {
            foreach (var edge in v1.OutEdges)
            {
                var t = edge.Target;
                if (t == v3 || t == v2)
                {
                    continue;
                }
                //LayoutAlgorithmSettings.ShowDebugCurves(new DebugCurve(1, "red", new LineSegment(v3.Point, v1.Point)),
                //new DebugCurve(1, "blue", new LineSegment(v1.Point, t.Point)));
                if (AngleIsTooSmall(Point.Angle(v3.Point, v1.Point, t.Point)))
                {
                    return(true);
                }
            }

            foreach (var edge in v1.InEdges)
            {
                var t = edge.Source;
                if (t == v3 || t == v2)
                {
                    continue;
                }

                if (AngleIsTooSmall(Point.Angle(v3.Point, v1.Point, t.Point)))
                {
                    return(true);
                }
            }

            return(false);
        }
        bool ShortcutIntersectsNewVerticesOrCuttingInsideNodes(VisibilityVertex v0, VisibilityVertex v, VisibilityVertex v1)
        {
            Set <LgNodeInfo> oldIntersected = IntersectedByLineSegNodeInfos(v0.Point, v.Point) +
                                              IntersectedByLineSegNodeInfos(v.Point, v1.Point);

            Set <LgNodeInfo> newIntersected = IntersectedByLineSegNodeInfos(v0.Point, v1.Point);

            if (CuttingInsideOfNodes(newIntersected, v0.Point, v1.Point))
            {
                return(true);
            }
            return(!oldIntersected.Contains(newIntersected));
        }
 bool AngleIsTooSmallAfterShortcut(VisibilityVertex v1, VisibilityVertex v2, VisibilityVertex v3)
 {
     return(AngleIsTooSmallAfterShortcutAtVertex(v1, v2, v3) || AngleIsTooSmallAfterShortcutAtVertex(v3, v2, v1));
 }
示例#47
0
        static internal VisibilityEdge FindNextEdge(VisibilityGraph vg, VisibilityVertex vertex, Directions dir)
        {
            VisibilityVertex nextVertex = FindNextVertex(vertex, dir);

            return((null == nextVertex) ? null : vg.FindEdge(vertex.Point, nextVertex.Point));
        }
示例#48
0
 static internal Directions EdgeDirection(VisibilityVertex source, VisibilityVertex target)
 {
     return(PointComparer.GetPureDirection(source.Point, target.Point));
 }
        private void DevTraceShowPath(VisibilityVertex source, VertexEntry lastEntry) {
#if DEVTRACE
            if (ssstTrace.IsLevel(1)) {
                var pathPoints = RestorePath(lastEntry);
                if (pathPoints != null) {
                    this.TestShowPath(source, pathPoints, lastEntry.Cost, lastEntry.Length, lastEntry.NumberOfBends);
                    return;
                }
                Console.WriteLine("path abandoned; iters = {0}/{1}", this.currentIterations, totalIterations);
            }
#endif // DEVTRACE
        }
        internal static IEnumerable<Point> RestorePath(ref VertexEntry entry, VisibilityVertex firstVertexInStage) {
            if (entry == null) {
                return null;
            }
            var list = new List<Point>();
            bool skippedCollinearEntry = false;
            Directions lastEntryDir = Directions. None;
            while (true) {
                // Reduce unnecessary AxisEdge creations in Nudger by including only bend points, not points in the middle of a segment.
                if (lastEntryDir == entry.Direction) {
                    skippedCollinearEntry = true;
                } else {
                    skippedCollinearEntry = false;
                    list.Add(entry.Vertex.Point);
                    lastEntryDir = entry.Direction;
                }

                var previousEntry = entry.PreviousEntry;
                if ((previousEntry == null) || (entry.Vertex == firstVertexInStage)) {
                    break;
                }
                entry = previousEntry;
            }
            if (skippedCollinearEntry) {
                list.Add(entry.Vertex.Point);
            }
            list.Reverse();
            return list;
        }
        private void DevTracePrintSourceAndTarget(VisibilityVertex source, VisibilityVertex target) {
#if DEVTRACE
            if (ssstTrace.IsLevel(2))
            {
                // Don't use this.Target as it hasn't been set yet.
                Console.WriteLine("find path: {0} -> {1} distance {2} sourceAdjust {3} targetAdjust {4} bendPenalty {5}",
                            source.Point, target.Point, ManhattanDistance(source.Point, target.Point),
                            this.sourceCostAdjustment, this.targetCostAdjustment, this.BendsImportance);
            }
#endif // DEVTRACE
        }
        private void TestShowAllPaths(VisibilityVertex source, VertexEntry mostRecentlyExtendedPath) {
// ReSharper restore UnusedMember.Local
            var edges = GetAllEdgesTest(source).Select(e => (ICurve) (new LineSegment(e.SourcePoint, e.TargetPoint))).
                        Select(c => new DebugCurve(c));
            var q = queue.Select(ent => CurveFactory.CreateDiamond(2, 2, ent.Vertex.Point)).Select(c => new DebugCurve(c));
            var so = new[] {
                              new DebugCurve(1, "brown", new Ellipse(3, 3, source.Point)),
                              new DebugCurve(1, "purple", CurveFactory.CreateDiamond(4, 4, Target.Point)),
                              new DebugCurve(1, "red", CurveFactory.CreateDiamond(6, 6, mostRecentlyExtendedPath.Vertex.Point))
                          };

            var pathEdges = new List<DebugCurve>();
            var newEntries = new List<VertexEntry>();
            var count = this.visitedVertices.Count;
            for (int ii = 0; ii < count; ++ii) {
                var vertex = this.visitedVertices[ii];
                if (vertex.VertexEntries == null) {
                    continue;   // this is the source vertex
                }
                foreach (var entry in vertex.VertexEntries) {
                    if (entry == null) {
                        continue;
                    }
                    var color = "green";
                    if (entry.PreviousEntry == mostRecentlyExtendedPath) {
                        newEntries.Add(entry);
                        color = "red";
                    } else if (!entry.IsClosed) {
                        color = "yellow";
                    }
                    pathEdges.Add(new DebugCurve(2, color, new LineSegment(entry.PreviousVertex.Point, vertex.Point)));
                }
            }
            Console.WriteLine("entry {0} seq = {1} len = {2} nbend = {3} ccost = {4} hcost = {5} iters = {6}/{7}", mostRecentlyExtendedPath,
                             this.lastDequeueTimestamp,
                             mostRecentlyExtendedPath.Length, mostRecentlyExtendedPath.NumberOfBends,
                             this.CombinedCost(mostRecentlyExtendedPath.Length, mostRecentlyExtendedPath.NumberOfBends),
                             this.HeuristicDistanceFromVertexToTarget(mostRecentlyExtendedPath.Vertex.Point, mostRecentlyExtendedPath.Direction),
                             this.currentIterations, totalIterations);
            foreach (var newEntry in newEntries) {
                Console.WriteLine("   newEntry {0} len = {1} nbend = {2} ccost = {3} hcost = {4}", newEntry,
                                 newEntry.Length, newEntry.NumberOfBends,
                                 this.CombinedCost(newEntry.Length, newEntry.NumberOfBends),
                                 this.HeuristicDistanceFromVertexToTarget(newEntry.Vertex.Point, newEntry.Direction));
            }
            DevTraceDisplay(edges.Concat(q).Concat(so).Concat(pathEdges));
        }
 internal bool IsInBounds(VisibilityVertex vertex) {
     return IsInBounds(vertex.Point);
 }
        private void TestShowPath(VisibilityVertex source, IEnumerable<Point> pathPoints, double cost, double length, int numberOfBends) {
// ReSharper restore UnusedMember.Local
            var edges = GetAllEdgesTest(source).Select(e => (ICurve) (new LineSegment(e.SourcePoint, e.TargetPoint))).
                        Select(c => new DebugCurve(c));
            var so = new[] {
                              new DebugCurve(1, "brown", new Ellipse(3, 3, source.Point)),
                              new DebugCurve(1, "purple", CurveFactory.CreateDiamond(4, 4, Target.Point)),
                          };

            List<DebugCurve> pathEdges = GetPathEdgeDebugCurves(pathPoints, "green");
            Console.WriteLine("path {0} -> {1} cost = {2} len = {3} nbend = {4} iters = {5}/{6}",
                            source.Point, this.Target.Point, cost, length, numberOfBends, this.currentIterations, totalIterations);
            DevTraceDisplay(edges.Concat(so).Concat(pathEdges));
        }
 void SnapToAfterBefore(VisibilityVertex v, RbTree<VisibilityVertex> nodeBoundaryRbTree, Point center, Dictionary<VisibilityEdge, VisibilityVertex> ret, VisibilityEdge e) {
     VisibilityVertex beforeV, afterV;
     FindBeforeAfterV(v, nodeBoundaryRbTree, out beforeV, out afterV, center);
     var beforeAngle = Point.Angle(beforeV.Point - center, v.Point - center);
     var afterAngle = Point.Angle(v.Point - center, afterV.Point - center);
     ret[e] = beforeAngle <= afterAngle ? beforeV : afterV;
 }
        private IEnumerable<VisibilityEdge> GetAllEdgesTest(VisibilityVertex vertex) {
            var processedVertices = new Set<VisibilityVertex>();
            var q = new Queue<VisibilityVertex>();
            q.Enqueue(vertex);

            // Target may not be connected to source.
            bool targetFound = (vertex == this.Target);
            while (!targetFound) {
                while (q.Count > 0) {
                    VisibilityVertex v = q.Dequeue();
                    if (processedVertices.Contains(v)) {
                        continue;
                    }
                    targetFound |= (v == this.Target);
                    processedVertices.Insert(v);
                    foreach (var u in VertsToGo(v).Where(u => !processedVertices.Contains(u))) {
                        q.Enqueue(u);
                    }
                    foreach (VisibilityEdge edge in v.OutEdges) {
                        yield return edge;
                    }
                }
                q.Enqueue(this.Target);
                targetFound = true;
            }
        }
 int CompareByAngleFromNodeCenter(VisibilityVertex a, VisibilityVertex b, Point center) {
     var x = new Point(1, 0);
     var aAngle = Point.Angle(x, a.Point - center);
     var bAngle = Point.Angle(x, b.Point - center);
     return aAngle.CompareTo(bAngle);
 }
 private static IEnumerable<VisibilityVertex> VertsToGo(VisibilityVertex visibilityVertex) {
     foreach (var edge in visibilityVertex.OutEdges) {
         yield return edge.Target;
     }
     foreach (var edge in visibilityVertex.InEdges) {
         yield return edge.Source;}
 }
//        internal VisibilityVertex GetExistingVvCloseBy(Point p) {
//            var rect = new Rectangle(p);
//            rect.Pad(searchEps);
//            VisibilityVertex v=null;
//            
//
//            var crossed = _visGraphVerticesTree.GetAllIntersecting(rect);
//            if (crossed.Length == 0) {
//                return null;
//            }
//            double dist = double.PositiveInfinity;
//            for (int i = 0; i < crossed.Length; i++) {
//                var vv = crossed[i];
//                var vvDist = (vv.Point - p).LengthSquared;
//                if (vvDist < dist) {
//                    dist = vvDist;
//                    v = vv;
//                }
//            }
//            return v;
//        }

        void RegisterInTree(VisibilityVertex vv) {
            var rect = new Rectangle(vv.Point);
            VisibilityVertex treeVv;
            if (_visGraphVerticesTree.OneIntersecting(rect, out treeVv)) {
                Debug.Assert(treeVv == vv);
                return;
            }
            _visGraphVerticesTree.Add(rect, vv);
        }
 private VisibilityEdge AddEdgeToClosestSegmentEnd(ScanSegment scanSeg, VisibilityVertex segsegVertex, double weight) {
     // FindOrAddEdge will walk until it finds the minimal bracketing vertices.
     if (PointComparer.IsPureLower(scanSeg.HighestVisibilityVertex.Point, segsegVertex.Point)) {
         return this.TransUtil.FindOrAddEdge(scanSeg.HighestVisibilityVertex, segsegVertex, weight);
     }
     if (PointComparer.IsPureLower(segsegVertex.Point, scanSeg.LowestVisibilityVertex.Point)) {
         return this.TransUtil.FindOrAddEdge(segsegVertex, scanSeg.LowestVisibilityVertex, weight);
     }
     return this.TransUtil.FindOrAddEdge(scanSeg.LowestVisibilityVertex, segsegVertex);
 }