/// <summary> /// 恢复寻路新增节点导致的变化 /// </summary> private void RestoreNodeBackup(HierarchicalMap map, int nodeId, NodeBackup backup) { AbstractGraph graph = map.AbstractGraph; AbstractNode node = graph.GetNode(nodeId); //恢复节点的级别 node.Level = backup.Level; //恢复相关的边 graph.RemoveEdgeFromAndToNode(nodeId); foreach (var edge in backup.Edges) { int targetNodeId = edge.TargetNodeId; var targetNode = map.GetAbstractNode(targetNodeId); AbstractEdge abstractEdge = HPADemo.Instance.CreateEdge(node.Pos, targetNode.Pos, edge.Level, edge.IsInterEdge); abstractEdge.Init(targetNodeId, edge.Cost, edge.Level, edge.IsInterEdge); abstractEdge.SetInnerLowerLevelPath(edge.InnerLowerLevelPath); graph.AddEdge(nodeId, abstractEdge); edge.InnerLowerLevelPath?.Reverse(); abstractEdge = HPADemo.Instance.CreateEdge(targetNode.Pos, node.Pos, edge.Level, edge.IsInterEdge); abstractEdge.Init(nodeId, edge.Cost, edge.Level, edge.IsInterEdge); abstractEdge.SetInnerLowerLevelPath(edge.InnerLowerLevelPath); graph.AddEdge(targetNodeId, abstractEdge); } m_backupDict.Remove(nodeId); }
// insert a new node, such as start or target, to the abstract graph and // returns the id of the newly created node in the abstract graph // x and y are the positions where I want to put the node private Id <AbstractNode> InsertNodeIntoHierarchicalMap(HierarchicalMap map, Id <ConcreteNode> concreteNodeId, Position pos) { // If the node already existed (for instance, it was the an entrance point already // existing in the graph, we need to keep track of the previous status in order // to be able to restore it once we delete this STAL if (map.ConcreteNodeIdToAbstractNodeIdMap.ContainsKey(concreteNodeId)) { var existingAbstractNodeId = map.ConcreteNodeIdToAbstractNodeIdMap[concreteNodeId]; var nodeBackup = new NodeBackup( map.AbstractGraph.GetNodeInfo(existingAbstractNodeId).Level, map.GetNodeEdges(concreteNodeId)); nodeBackups[existingAbstractNodeId] = nodeBackup; return(map.ConcreteNodeIdToAbstractNodeIdMap[concreteNodeId]); } var cluster = map.FindClusterForPosition(pos); // create global entrance var abstractNodeId = Id <AbstractNode> .From(map.NrNodes); var entrance = cluster.AddEntrance(abstractNodeId, new Position(pos.X - cluster.Origin.X, pos.Y - cluster.Origin.Y)); cluster.UpdatePathsForLocalEntrance(entrance); map.ConcreteNodeIdToAbstractNodeIdMap[concreteNodeId] = abstractNodeId; var info = new AbstractNodeInfo( abstractNodeId, 1, cluster.Id, pos, concreteNodeId); map.AbstractGraph.AddNode(abstractNodeId, info); foreach (var entrancePoint in cluster.EntrancePoints) { if (cluster.AreConnected(abstractNodeId, entrancePoint.AbstractNodeId)) { map.AddEdge( entrancePoint.AbstractNodeId, abstractNodeId, cluster.GetDistance(entrancePoint.AbstractNodeId, abstractNodeId)); map.AddEdge( abstractNodeId, entrancePoint.AbstractNodeId, cluster.GetDistance(abstractNodeId, entrancePoint.AbstractNodeId)); } } return(abstractNodeId); }
/// <summary> /// 插入节点到Cluster内,并构建相关节点和边到图中 /// </summary> private int InsertAbstractNodeInClusterLevel(HierarchicalMap map, Vector2Int concretePos) { AbstractNode abstractNode = map.GetAbstractNode(concretePos); //如果要插入的位置已经存在节点,则保存相关信息,以便之后删除时恢复 if (abstractNode != null) { NodeBackup backup = new NodeBackup(abstractNode.Level, abstractNode.Edges.Values.ToList()); if (m_backupDict.ContainsKey(abstractNode.Id)) { Debug.LogError("已经存在一个NodeBackup,逻辑上出错了"); } m_backupDict[abstractNode.Id] = backup; return(abstractNode.Id); } //把节点插入到Cluster内 int abstractId = map.NodeCount(); var cluster = map.FindClusterForPosition(concretePos); var entrance = cluster.AddEntrancePoint(abstractId, m_concreteMap.Get(concretePos)); cluster.AddIntraEdgesData(entrance); //把节点插入到图中 abstractNode = HPADemo.Instance.CreateAbstractNode(1, concretePos); abstractNode.Init(abstractId, 1, cluster.Id, concretePos); map.AddAbstractNode(abstractNode); map.AbstractGraph.AddNode(abstractNode); //把该节点相关的边插入到图中 foreach (var otherEntrance in cluster.EntrancePoints) { if (cluster.IsConnected(abstractId, otherEntrance.AbstractId)) { float distance = cluster.Distance(abstractId, otherEntrance.AbstractId); AbstractEdge edge = HPADemo.Instance.CreateEdge(concretePos, otherEntrance.ConcreteNode.Pos, 1, false); edge.Init(otherEntrance.AbstractId, distance, 1, false); map.AbstractGraph.AddEdge(abstractId, edge); edge = HPADemo.Instance.CreateEdge(otherEntrance.ConcreteNode.Pos, concretePos, 1, false); edge.Init(abstractId, distance, 1, false); map.AbstractGraph.AddEdge(otherEntrance.AbstractId, edge); } } return(abstractId); }