Пример #1
0
        protected bool TraceBackForPath(INodeWrapper <T> startingNode)
        {
            result.Clear();
            NodeWrapperEx <T> nodeWrapper = startingNode as NodeWrapperEx <T>;

            if (nodeWrapper == null || nodeWrapper.g == float.PositiveInfinity)
            {
                return(false);
            }

            while (!nodeWrapper.node.Equals(endingNode))
            {
                NodeWrapperEx <T> previous = default;
                foreach (var nei in context.GetGraphData().CollectNeighbor(nodeWrapper.node).Select(n => context.GetOrCreateNode(n)))
                {
                    if (previous == null || nei.g < previous.g)
                    {
                        previous = nei;
                    }
                }

                result.Add(nodeWrapper.node);
                nodeWrapper = previous;
            }
            result.Add(nodeWrapper.node);

            return(true);
        }
Пример #2
0
        protected Vector2 CalculateKey(NodeWrapperEx <T> nodeWrapper)
        {
            float k2 = Mathf.Min(nodeWrapper.g, nodeWrapper.rhs);
            float k1 = k2 + nodeWrapper.h + km;

            return(new Vector2(k1, k2));
        }
Пример #3
0
        private void UpdateNode(NodeWrapperEx <T> nodeWrapper)
        {
            if (nodeWrapper.node.Equals(endingNode))
            {
            }
            else
            {
                // 更新这些节点的 previous
                var neighbors = context.GetGraphData().CollectNeighbor(nodeWrapper.node).Select(n => context.GetOrCreateNode(n));
                nodeWrapper.rhs = CalculateRHS(nodeWrapper);
            }

            if (nodeWrapper.GetConsistency() == NodeConsistency.Consistent)
            {
                context.openList.Remove(nodeWrapper);
            }
            else
            {
                nodeWrapper.h   = CalculateH(nodeWrapper);
                nodeWrapper.key = CalculateKey(nodeWrapper);

                if (context.openList.Contains(nodeWrapper))
                {
                    context.openList.Update(nodeWrapper);
                }
                else
                {
                    context.openList.Enqueue(nodeWrapper);
                }
            }
        }
Пример #4
0
        public NodeWrapperEx <T> GetOrCreateNode(T nodeData)
        {
            if (!nodeMapping.TryGetValue(nodeData, out NodeWrapperEx <T> nodeWrapperEx))
            {
                nodeWrapperEx = new NodeWrapperEx <T>(nodeData);
                nodeMapping.Add(nodeData, nodeWrapperEx);
            }

            return(nodeWrapperEx);
        }
Пример #5
0
        public NodeWrapperEx <T> TryGetNode(T nodeData)
        {
            NodeWrapperEx <T> node = null;

            if (this.nodeMapping.TryGetValue(nodeData, out node))
            {
                return(node);
            }

            return(null);
        }
Пример #6
0
        public int CompareTo(NodeWrapperEx <T> other)
        {
            Vector2 ko = other.key;

            if (key.x != ko.x)
            {
                return(key.x.CompareTo(ko.x));
            }

            if (key.y != ko.y)
            {
                return(key.y.CompareTo(ko.y));
            }

            return(Comparer <T> .Default.Compare(node, other.node));
        }
Пример #7
0
        public void NotifyNodeDataModified(T nodeData)
        {
            if (state == PathfindingState.Found || state == PathfindingState.Failed)
            {
                state = PathfindingState.Finding;

                //NodeWrapperEx<T> endingNodeWrapper = context.GetOrCreateNode(this.endingNode);
                //endingNodeWrapper.g = float.PositiveInfinity;
                //endingNodeWrapper.rhs = float.PositiveInfinity;
                //endingNodeWrapper.h = 0;
                //endingNodeWrapper.key = CalculateKey(endingNodeWrapper);
                //if (context.openList.Contains(endingNodeWrapper))
                //{
                //    context.openList.Remove(endingNodeWrapper);
                //}
            }

            NodeWrapperEx <T> nodeWrapper = this.context.GetOrCreateNode(nodeData);

            nodeWrapper.rhs = CalculateRHS(nodeWrapper);

            if (nodeWrapper.GetConsistency() == NodeConsistency.Overconsistent)
            {
                nodeWrapper.g = nodeWrapper.rhs;
            }
            else
            {
                nodeWrapper.g = float.PositiveInfinity;
                UpdateNode(nodeWrapper);
            }

            var neighbors = context.GetGraphData().CollectNeighbor(nodeData).Select(n => context.GetOrCreateNode(n));

            foreach (var nei in neighbors)
            {
                UpdateNode(nei);
            }
        }
Пример #8
0
        public void NotifyNodeDataModified(T nodeData)
        {
            if (state != PathfindingState.Finding)
            {
                throw new InvalidOperationException();
            }

            km = km + HeuristicFunc(oldStartingNode, currentNode);
            oldStartingNode = currentNode;

            NodeWrapperEx <T> nodeWrapper = this.context.GetOrCreateNode(nodeData);

            nodeWrapper.g   = float.PositiveInfinity;
            nodeWrapper.rhs = float.PositiveInfinity;
            UpdateNode(nodeWrapper);

            var neighbors = context.GetGraphData().CollectNeighbor(nodeData).Select(n => context.GetOrCreateNode(n));

            foreach (var nei in neighbors)
            {
                UpdateNode(nei);
            }
        }
Пример #9
0
        public PathfindingState Step()
        {
            if (state == PathfindingState.Initialized)
            {
                state = PathfindingState.Finding;

                NodeWrapperEx <T> startingNodeWrapper = context.GetOrCreateNode(this.startingNode);
                startingNodeWrapper.g   = float.PositiveInfinity;
                startingNodeWrapper.rhs = float.PositiveInfinity;
                startingNodeWrapper.h   = 0;
                startingNodeWrapper.key = CalculateKey(startingNodeWrapper);

                NodeWrapperEx <T> endingNodeWrapper = context.GetOrCreateNode(this.endingNode);
                endingNodeWrapper.g   = float.PositiveInfinity;
                endingNodeWrapper.rhs = 0;
                endingNodeWrapper.h   = 0;
                endingNodeWrapper.key = CalculateKey(endingNodeWrapper);

                context.openList.Enqueue(endingNodeWrapper);

                return(state);
            }

            if (state != PathfindingState.Finding)
            {
                throw new Exception($"Unexpected state {state}");
            }

            NodeWrapperEx <T> first = context.openList.TryDequeue();

            if (first == null)
            {
                // 寻路失败
                state = PathfindingState.Failed;
                TraceBackForPath(null);
                return(state);
            }

            NodeWrapperEx <T> startingNodeWrapper0 = context.GetOrCreateNode(startingNode);

            startingNodeWrapper0.key = CalculateKey(startingNodeWrapper0);
            if (startingNodeWrapper0.GetConsistency() == NodeConsistency.Consistent &&
                first.CompareTo(startingNodeWrapper0) >= 0)
            {
                // 终点局部一致
                // 此时有一条有效路径
                // state = PathfindingState.Found;
                // TraceBackForPath(startingNodeWrapper0);
                if (MoveAgent())
                {
                    state = PathfindingState.Found;
                }

                return(state);
            }

            Vector2 keyOld = first.key;
            Vector2 key    = CalculateKey(first);

            if (keyOld.x < key.x && keyOld.y < key.y)
            {
                first.key = key;
                context.openList.Enqueue(first);
            }
            else
            {
                if (first.GetConsistency() == NodeConsistency.Overconsistent)
                {
                    // 障碍被清除 或者cost变低
                    first.g = first.rhs;
                }
                else
                {
                    first.g = float.PositiveInfinity;
                    UpdateNode(first);
                }

                var neighbors = context.GetGraphData().CollectNeighbor(first.node).Select(n => context.GetOrCreateNode(n));
                foreach (NodeWrapperEx <T> nei in neighbors)
                {
                    UpdateNode(nei);
                }
            }

            return(state);
        }
Пример #10
0
        protected float CalculateRHS(NodeWrapperEx <T> nodeWrapper)
        {
            var neighbors = context.GetGraphData().CollectNeighbor(nodeWrapper.node).Select(n => context.GetOrCreateNode(n));

            return(neighbors.Select(nei => nei.g + HeuristicFunc(nei.node, nodeWrapper.node) * (1 + nodeWrapper.node.cost)).Min());
        }
Пример #11
0
 protected float CalculateH(NodeWrapperEx <T> nodeWrapper)
 {
     return(HeuristicFunc(nodeWrapper.node, this.startingNode));
 }