예제 #1
0
        private void ExtendPathAlongEdge(VertexEntry bestEntry, VisibilityEdge edge, bool isInEdges, Directions preferredBendDir)
        {
            if (!IsPassable(edge))
            {
                return;
            }

            // This is after the initial source vertex so PreviousEntry won't be null.
            var neigVer = (VisibilityVertexRectilinear)(isInEdges ? edge.Source : edge.Target);

            if (neigVer == bestEntry.PreviousVertex)
            {
                // For multistage paths, the source may be a waypoint outside the graph boundaries that is collinear
                // with both the previous and next points in the path; in that case it may have only one degree.
                // For other cases, we just ignore it and the path will be abandoned.
                if ((bestEntry.Vertex.Degree > 1) || (bestEntry.Vertex != this.Source))
                {
                    return;
                }
                this.ExtendPathToNeighborVertex(bestEntry, neigVer, edge.Weight);
                return;
            }

            // Enqueue in reverse order of preference per comments on NextNeighbor class.
            var neigDir      = CompassVector.PureDirectionFromPointToPoint(bestEntry.Vertex.Point, neigVer.Point);
            var nextNeighbor = this.nextNeighbors[2];

            if (neigDir != bestEntry.Direction)
            {
                nextNeighbor = this.nextNeighbors[(neigDir == preferredBendDir) ? 1 : 0];
            }
            Debug.Assert(nextNeighbor.Vertex == null, "bend neighbor already exists");
            nextNeighbor.Set(neigVer, edge.Weight);
        }
예제 #2
0
        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);
        }
예제 #3
0
        private void ExtendPathToNeighborVertex(VertexEntry bestEntry, VisibilityVertexRectilinear neigVer, double weight)
        {
            var dirToNeighbor = CompassVector.PureDirectionFromPointToPoint(bestEntry.Vertex.Point, neigVer.Point);

            var neigEntry = (neigVer.VertexEntries != null) ? neigVer.VertexEntries[CompassVector.ToIndex(dirToNeighbor)] : null;

            if (neigEntry == null)
            {
                if (!this.CreateAndEnqueueReversedEntryToNeighborVertex(bestEntry, neigVer, weight))
                {
                    this.CreateAndEnqueueEntryToNeighborVertex(bestEntry, neigVer, weight);
                }
            }
            else if (!neigEntry.IsClosed)
            {
                this.UpdateEntryToNeighborVertexIfNeeded(bestEntry, neigEntry, weight);
            }
        }
        internal void ResetEntry(VertexEntry prevEntry, double length, int numberOfBends, double cost)
        {
            // A new prevEntry using the same previous vertex but a different entry to that vertex is valid here;
            // e.g. we could have prevEntry from S, which in turn had a prevEntry from E, replaced by prevEntry from
            // S which has a prevEntry from S.
#if TEST_MSAGL
            if (this.PreviousEntry != null)
            {
                Debug.Assert(this.PreviousEntry.Vertex == prevEntry.Vertex, "Inconsistent prevEntry vertex");
                Debug.Assert(this.PreviousEntry.Direction != prevEntry.Direction, "Duplicate prevEntry direction");
                Debug.Assert(this.Direction == CompassVector.PureDirectionFromPointToPoint(this.PreviousEntry.Vertex.Point, this.Vertex.Point),
                             "Inconsistent entryDir");
            }
#endif // TEST_MSAGL
            this.PreviousEntry = prevEntry;
            this.Length        = length;
            this.NumberOfBends = numberOfBends;
            this.Cost          = cost;
        }
예제 #5
0
 private bool CreateAndEnqueueReversedEntryToNeighborVertex(VertexEntry bestEntry, VisibilityVertexRectilinear neigVer, double weight)
 {
     // VertexEntries is null for the initial source. Otherwise, if there is already a path into bestEntry's vertex
     // from neigVer, we're turning back on the path; therefore we have already enqueued the neighbors of neigVer.
     // However, the path cost includes both path length to the current point and the lookahead; this means that we
     // may now be coming into the neigVer from the opposite side with an equal score to the previous entry, but
     // the new path may be going toward the target while the old one (from neigVer to bestEntry) went away from
     // the target.  So, if we score better going in the opposite direction, enqueue bestEntry->neigVer; ignore
     // neigVer->bestEntry as it probably won't be extended again.
     if (bestEntry.Vertex.VertexEntries != null)
     {
         var dirFromNeighbor   = CompassVector.PureDirectionFromPointToPoint(neigVer.Point, bestEntry.Vertex.Point);
         var entryFromNeighbor = bestEntry.Vertex.VertexEntries[CompassVector.ToIndex(dirFromNeighbor)];
         if (entryFromNeighbor != null)
         {
             Debug.Assert(entryFromNeighbor.PreviousVertex == neigVer, "mismatch in turnback PreviousEntry");
             Debug.Assert(entryFromNeighbor.PreviousEntry.IsClosed, "turnback PreviousEntry should be closed");
             this.QueueReversedEntryToNeighborVertexIfNeeded(bestEntry, entryFromNeighbor, weight);
             return(true);
         }
     }
     return(false);
 }
 /// <summary>
 /// A class that records an entry from a specific direction for a vertex.
 /// </summary>
 /// <param name="vertex">Vertex that this VertexEntry enters</param>
 /// <param name="prevEntry">The previous VertexEntry along this path; null for a path source</param>
 /// <param name="length">Length of the path up to this vertex</param>
 /// <param name="numberOfBends">Number of bends in the path up to this vertex</param>
 /// <param name="cost">Cost of the path up to this vertex</param>
 internal VertexEntry(VisibilityVertexRectilinear vertex, VertexEntry prevEntry, double length, int numberOfBends, double cost)
 {
     this.Vertex    = vertex;
     this.Direction = (prevEntry != null) ? CompassVector.PureDirectionFromPointToPoint(prevEntry.Vertex.Point, vertex.Point) : Directions.None;
     this.ResetEntry(prevEntry, length, numberOfBends, cost);
 }