Beispiel #1
0
 /// <summary>
 /// Return the distance from me to another face. Distances are computed
 /// by the backend and stored by the UI
 /// </summary>
 /// <param name="otherFace">Other face</param>
 /// <returns>Distance</returns>
 public double GetDistanceToFace(Face otherFace)
 {
     if (DistanceVector.ContainsKey(otherFace))
     {
         return(DistanceVector[otherFace]);
     }
     return(_mainCanvas.OptionDialog.DefaultMaxDistance);
 }
Beispiel #2
0
        /// <summary>
        /// Finds the shortest route to a target.
        ///
        /// To start with can be in one of two states:
        /// A: No route known
        /// B: There is a route known
        ///
        /// Can finish in one of four states
        /// 1. There was no route originally and one has been found
        /// 2. There is a new, shorter route along a different link
        /// 3. The target can no longer be reached but used to be reachable
        /// 4. The original route is still shortest but is now a different length
        /// 5. The original route is no longer available but a new route was found
        /// 6. The original route is still shortest and has not changed
        /// 7. The target was not reachable before and is still not reachable
        ///
        /// 1 = Update distance vector, broadcast update, trigger routing table changed event
        /// 2 = Update distance vector, broadcast update, trigger routing table changed event
        /// 3 = Update distance vector, broadcast update, trigger routing table changed event
        /// 4 = Update distance vector, broadcast update, trigger routing table changed event
        /// 5 = Update distance vector, broadcast update, trigger routing table changed event
        /// 6 = No events triggered
        /// 7 = No events triggered
        /// </summary>
        /// <param name="targetNode"></param>
        /// <returns></returns>
        private bool findShortestPath(IMNodeInternal targetNode, List <string> changes)
        {
            UUID target = targetNode.ID;

            //oldDist == null indicates initial state A, otherwise initial state B.
            Distance oldDist;

            lock (distanceVector)
                oldDist = distanceVector.ContainsKey(target) ? distanceVector[target].copy() : null;

            IKeyTable <DistanceVector> tmpNeighbours = neighbourVectors.Copy();

            IMLink link = null;
            float  dist = float.MaxValue;

            if (oldDist != null && oldDist.Link.OtherEnd(ID).Equals(target) && Links.ContainsKey(target))
            {
                //If there was an old route and target is a neighbour and the link was the link between them use the weight of that link as the starting weight
                link = Links[target];
                dist = link.Weight;
            }
            else if (oldDist != null && tmpNeighbours.ContainsKey(oldDist.Hop.ID) && tmpNeighbours[oldDist.Hop.ID].ContainsKey(target) && tmpNeighbours[oldDist.Hop.ID][target].Dist > 0f)
            {
                //If there was an old route and it involved routing via a neighbour and that neighbour can still route then take the starting weight as the distance to the neighbour + the distance from the neighbour to the target
                link = Links[oldDist.Hop.ID];
                dist = tmpNeighbours[oldDist.Hop.ID][target].Dist + link.Weight;
            }

            //Check every neighbour to see if the weight of the link to that neighbour + the distance the neighbour can achieve to the target is shorter     .
            foreach (var neighbour in Neighbours)
            {
                var neighbourLink   = Links[neighbour.ID];
                var neighbourVector = tmpNeighbours.ContainsKey(neighbour.ID) && tmpNeighbours[neighbour.ID].ContainsKey(target) ? tmpNeighbours[neighbour.ID][target] : null;
                var neighbourDist   = neighbourVector != null ? neighbourLink.Weight + neighbourVector.Dist : float.MaxValue;
                //Neighbour vector distance of 0 or less indicates poison reverse or a link to itself
                //Also checks to see if the link at the other end is the neighbour and whether the weight of the link is less than the current distance
                if ((neighbourVector != null && neighbourVector.Dist > 0 && neighbourDist < dist) ||
                    neighbour.Equals(targetNode) && neighbourLink.Weight < dist)
                {
                    link = neighbourLink;
                    dist = neighbour.Equals(targetNode) ? link.Weight : neighbourDist;
                }
            }

            if (link == null && oldDist == null)
            {
                //Case 5 + 6
                return(false);
            }
            if (link != null && oldDist == null)
            {
                //1. There was no route originally and one has been found
                UpdateRoutes(targetNode, link.OtherEnd(Node), link, dist);
                changes.Add("Distance Vector added route to " + targetNode.Name + " via " + link.OtherEnd(Node).Name + " with distance " + Math.Round(dist, 2) + ".");
            }
            else if (link == null && oldDist != null)
            {
                //3. The target can no longer be reached but used to be reachable
                lock (distanceVector) {
                    distanceVector.Remove(target);
                    RemoveRoute(DV.DV_NAME, target);
                    changes.Add("Distance Vector removed route to " + targetNode.Name + ". " + oldDist.Hop.Name + " is no longer a valid first hop and no other route was found.");
                }
            }
            else if (oldDist != null && !link.Equals(oldDist.Link))
            {
                //2. There is a new, shorter route along a different link
                UpdateRoutes(targetNode, link.OtherEnd(Node), link, dist);
                changes.Add("Distance Vector changed route to " + targetNode.Name + " from " + oldDist.Hop.Name + " to " + link.OtherEnd(Node).Name + " with distance " + Math.Round(dist, 2) + ".");
            }
            else if (oldDist != null && link.Equals(oldDist.Link) && dist != oldDist.Dist)
            {
                //4. The original route is still shortest but is now a different length
                UpdateRoutes(targetNode, link.OtherEnd(Node), link, dist);
                changes.Add("Distance Vector changed weight of route to " + targetNode.Name + " from " + Math.Round(oldDist.Dist, 2) + " to " + Math.Round(dist, 2) + ".");
            }
            else
            {
                return(false);
            }

            return(true);
        }