예제 #1
0
        /*
         *  Alter NavigationNodeLinks by restoring NavigationLinks following the rule dictated by p_navigationLinkAlterationMethod (see ENavigationLinkRemovalMethod for more).
         *  - NavigationNodeLinks are restored from the NavigationGraphSnapshot.
         */
        public static void restoreNavigationLinksFromSnapshot(NavigationGraph p_navigationGraph, ENavigationLinkAlterationMethod p_navigationLinkAlterationMethod, NavigationNode p_involvedNode)
        {
            switch (p_navigationLinkAlterationMethod)
            {
            case ENavigationLinkAlterationMethod.TO:

                // We have to :
                //    * copy NavigationLinks going to the p_involvedNode (retrieved from snapshot)
                //    * add NavigationLinks coming from NavigationNodes that goes to the p_involvedNode
                List <NavigationLink> l_linksThatPointsTowardsInvolvedNode = p_navigationGraph.NodeLinksIndexedByEndNode[p_involvedNode];
                l_linksThatPointsTowardsInvolvedNode.Clear();
                l_linksThatPointsTowardsInvolvedNode.AddRange(p_navigationGraph.NavigationGraphSnapshot.NodeLinksIndexedByEndNode[p_involvedNode]);

                for (int i = 0; i < l_linksThatPointsTowardsInvolvedNode.Count; i++)
                {
                    NavigationLink l_linkTo = l_linksThatPointsTowardsInvolvedNode[i];

                    var l_linksFrom_snapshot_enumerator = p_navigationGraph.NavigationGraphSnapshot.NodeLinksIndexedByStartNode[l_linkTo.StartNode].GetEnumerator();
                    while (l_linksFrom_snapshot_enumerator.MoveNext())
                    {
                        NavigationLink l_referenceFromLink = l_linksFrom_snapshot_enumerator.Current;

                        if (l_referenceFromLink.EndNode == p_involvedNode)
                        {
                            p_navigationGraph.NodeLinksIndexedByStartNode[l_referenceFromLink.StartNode].Add(l_referenceFromLink);
                        }
                    }
                }
                break;
            }
        }
예제 #2
0
 /// <summary>
 /// Because <see cref="NavigationNode.LocalPosition"/> is in <see cref="NavigationGraph"/> local space, all positions must be converted to world space from this component.
 /// As the <see cref="NavigationGraphComponent"/> is the holder of the <see cref="m_navigationGraph"/> it is his role.
 /// </summary>
 /// <returns> <paramref name="p_navigationNode"/> position in world space.</returns>
 public static float3 get_WorldPositionFromNavigationNode(NavigationGraphComponent p_navigationGraphComponent, NavigationNode p_navigationNode)
 {
     return(p_navigationGraphComponent.transform.localToWorldMatrix.MultiplyPoint(p_navigationNode.LocalPosition));
 }
예제 #3
0
 /*
  * Alter NavigationNodeLinks by removing the NavigationLinks following the rule dictated by p_navigationLinkAlterationMethod (see ENavigationLinkRemovalMethod for more).
  */
 public static void removeNavigationLinks(NavigationGraph p_navigationGraph, ENavigationLinkAlterationMethod p_navigationLinkAlterationMethod, NavigationNode p_involvedNode)
 {
     switch (p_navigationLinkAlterationMethod)
     {
     case ENavigationLinkAlterationMethod.TO:
         // We have to :
         //    * gets NavigationLinks going to the p_involvedNode
         //    * clear NavigationLinks coming from NavigationNodes that goes to the p_involvedNode
         //    * clear NavigationLinks going to the p_involvedNode
         List <NavigationLink> l_nodesToList = p_navigationGraph.NodeLinksIndexedByEndNode[p_involvedNode];
         for (int i = 0; i < l_nodesToList.Count; i++)
         {
             NavigationLink        l_linkTo     = l_nodesToList[i];
             List <NavigationLink> l_targetList = p_navigationGraph.NodeLinksIndexedByStartNode[l_linkTo.StartNode];
             l_targetList.Remove(l_linkTo);
         }
         p_navigationGraph.NodeLinksIndexedByEndNode[p_involvedNode].Clear();
         break;
     }
 }
예제 #4
0
 /// <summary>
 /// Checks if the <paramref name="p_requestedNode1"/> and <paramref name="p_requestedNode2"/> have a direct <see cref="NavigationLink"/> connection.
 /// The checked <see cref="NavigationLink"/> is oriented from <paramref name="p_requestedNode1"/> to <paramref name="p_requestedNode2"/>.
 /// </summary>
 public static bool areNavigationNodesNeighbors(NavigationGraph p_navigationGraph, NavigationNode p_requestedNode1, NavigationNode p_requestedNode2, NavigationGraphFlag p_navigationGraphFlag)
 {
     foreach (NavigationNode l_reachableNavigationNode in getReachableNeighborNavigationNodes(p_navigationGraph, p_requestedNode1, p_navigationGraphFlag))
     {
         if (l_reachableNavigationNode == p_requestedNode2)
         {
             return(true);
         }
     }
     return(false);
 }
예제 #5
0
        /// <summary>
        /// Find all NavigationNodes that the <paramref name="p_requestedNode"/> can travel to and have direct <see cref="NavigationLink"/> between them.
        /// - "Reachable" : Means that it exists a path between the <paramref name="p_requestedNode"/> and the returned NavigationNode
        /// - "Neighbor" : Means that the <paramref name="p_requestedNode"/> and the returned NavigationNode have a direct NavigationLink between them.
        /// </summary>
        public static IEnumerable <NavigationNode> getReachableNeighborNavigationNodes(NavigationGraph p_navigationGraph, NavigationNode p_requestedNode, NavigationGraphFlag p_navigationGraphFlag)
        {
            var l_navigationLinksGoingFromTheRequestedNode = NavigationGraph.get_nodeLinksIndexedByStartNode(p_navigationGraph, p_navigationGraphFlag)[p_requestedNode];

            var l_navigationLinksGoingFromTheRequestedNodeEnumerator = l_navigationLinksGoingFromTheRequestedNode.GetEnumerator();

            while (l_navigationLinksGoingFromTheRequestedNodeEnumerator.MoveNext())
            {
                yield return(l_navigationLinksGoingFromTheRequestedNodeEnumerator.Current.EndNode);
            }
        }
예제 #6
0
 public static void prepareForCalculation(CalculatePathRequest p_request, NavigationGraph p_navigationGraph, NavigationNode p_beginNode, NavigationNode p_endNode,
                                          PathCalculationParameters p_pathCalculationParameters)
 {
     p_request.NavigationGraph           = p_navigationGraph;
     p_request.BeginNode                 = p_beginNode;
     p_request.EndNode                   = p_endNode;
     p_request.PathCalculationParameters = p_pathCalculationParameters;
 }
예제 #7
0
        /// <summary>
        /// Path calculation is a recursive algorithm that try all possibilities of <see cref="NavigationLink"/> from the <paramref name="p_beginNode"/> to reach the <paramref name="p_endNode"/>.
        /// These possibilities are ordered by a score (see <see cref="NavigationNodePathTraversalCalculations"/> for details) that represents the "difficulty" to reach the destination.
        /// The combinaison of <see cref="NavigationLink"/> that leads to the lower score is the resulting path.
        /// </summary>
        public static void CalculatePath(CalculatePathRequest p_request)
        {
            if (p_request.BeginNode != null && p_request.EndNode != null)
            {
                if (p_request.BeginNode == p_request.EndNode)
                {
                    p_request.ResultPath.NavigationNodesTraversalCalculations[p_request.BeginNode] = NavigationNodePathTraversalCalculations.build();
                    return;
                }

                NavigationNode l_currentEvaluatedNode = p_request.BeginNode;
                bool           l_isFirstTimeInLoop    = true;

                while (l_currentEvaluatedNode != null && l_currentEvaluatedNode != p_request.EndNode)
                {
                    // If this is not the start, we find the next current node to pick
                    if (!l_isFirstTimeInLoop)
                    {
                        l_currentEvaluatedNode = pickNextCurrentNodeToCalculate(p_request.ResultPath.NavigationNodesTraversalCalculations, p_request.NodesElligibleForNextCurrent);
                    }
                    else
                    {
                        l_isFirstTimeInLoop = false;
                        NavigationNodePathTraversalCalculations l_pathTraversalCaluclation = NavigationNodePathTraversalCalculations.build();
                        l_pathTraversalCaluclation.CalculationMadeFrom = l_currentEvaluatedNode;
                        p_request.ResultPath.NavigationNodesTraversalCalculations[l_currentEvaluatedNode] = l_pathTraversalCaluclation;
                        p_request.NodesElligibleForNextCurrent.Add(l_currentEvaluatedNode);
                    }

                    if (l_currentEvaluatedNode != null)
                    {
                        // For the current node, we evaluate the score of it's neighbors

                        // The current evaluated node is no more ellisible because it has just been traversed by the algorithm
                        p_request.NodesElligibleForNextCurrent.Remove(l_currentEvaluatedNode);

                        // If the current evaluated node has links
                        if (p_request.NavigationGraph.NodeLinksIndexedByStartNode.ContainsKey(l_currentEvaluatedNode))
                        {
                            List <NavigationLink> l_evaluatedNavigationLinks = p_request.NavigationGraph.NodeLinksIndexedByStartNode[l_currentEvaluatedNode];
                            for (int i = 0; i < l_evaluatedNavigationLinks.Count; i++)
                            {
                                NavigationLink l_link = l_evaluatedNavigationLinks[i];

                                // We calculate the score as if the linked node is traversed.
                                NavigationNodePathTraversalCalculations l_currentCalculation = p_request.ResultPath.NavigationNodesTraversalCalculations[l_currentEvaluatedNode];
                                float l_calculatedPathScore = simulateNavigationLinkTraversal(ref l_currentCalculation, ref l_link);

                                // If the neighbor has not already been calculated
                                if (!p_request.ResultPath.NavigationNodesTraversalCalculations.ContainsKey(l_link.EndNode))
                                {
                                    NavigationNode l_linkEndNode = l_link.EndNode;

                                    NavigationNodePathTraversalCalculations l_linkNodeCalculations = NavigationNodePathTraversalCalculations.build();
                                    updatePathScore(ref l_linkNodeCalculations, l_calculatedPathScore, l_currentEvaluatedNode);
                                    calculateHeuristicScore(ref l_linkNodeCalculations, l_linkEndNode, p_request.EndNode, p_request.PathCalculationParameters.HeurisitcDistanceWeight);
                                    p_request.ResultPath.NavigationNodesTraversalCalculations[l_linkEndNode] = l_linkNodeCalculations;

                                    p_request.NodesElligibleForNextCurrent.Add(l_linkEndNode);
                                }
                                // Else, we update score calculations only if the current calculated score is lower than the previous one.
                                // This means we have found a less costly path.
                                else
                                {
                                    NavigationNode l_linkEndNode = l_link.EndNode;

                                    NavigationNodePathTraversalCalculations l_linkNodeCalculations = p_request.ResultPath.NavigationNodesTraversalCalculations[l_linkEndNode];
                                    updatePathScore(ref l_linkNodeCalculations, l_calculatedPathScore, l_currentEvaluatedNode);
                                    p_request.ResultPath.NavigationNodesTraversalCalculations[l_linkEndNode] = l_linkNodeCalculations;
                                }
                            }
                        }
                    }
                }

                // calculating final path by going to the start by taking "CalculationMadeFrom" nodes
                if (l_currentEvaluatedNode != null)
                {
                    p_request.ResultPath.NavigationNodes.Add(l_currentEvaluatedNode);

                    NavigationNodePathTraversalCalculations l_navigationNodePathTraversalCalculations = p_request.ResultPath.NavigationNodesTraversalCalculations[l_currentEvaluatedNode];
                    p_request.ResultPath.PathCost = NavigationNodePathTraversalCalculations.calculateTotalScore(ref l_navigationNodePathTraversalCalculations);


                    while (l_currentEvaluatedNode != p_request.BeginNode)
                    {
                        NavigationNode l_parent = p_request.ResultPath.NavigationNodesTraversalCalculations[l_currentEvaluatedNode].CalculationMadeFrom;
                        if (l_parent != null)
                        {
                            p_request.ResultPath.NavigationNodes.Add(l_parent);
                            l_currentEvaluatedNode = l_parent;
                        }
                        else
                        {
                            l_currentEvaluatedNode = p_request.BeginNode;
                        }
                    }

                    p_request.ResultPath.NavigationNodes.Reverse();
                }
            }
        }