private void BuildClusterNodeIntraEdges(AbstractionLayer layer) { foreach (var c in layer.Clusters.Values) { foreach (var cn in c.ClusterNodes.Values) { calculateDistInnerClusterNodes(cn, c); } } }
private void BuildClusterConnections(AbstractionLayer layer) { foreach (var cnode in layer.Clusters) { var neighbors = getHPAClusterNeighbors(cnode.Value); foreach (var n in neighbors) { cnode.Value.AddNeighbor(n.ID, n); n.AddNeighbor(cnode.Key, cnode.Value); } } }
private void BuildHPAClusters() { HierarchicalGraph.Clear(); hpaWatch = new Stopwatch(); hpaWatch.Start(); AbstractionLayer layer = new AbstractionLayer(0, new List <Cluster>()); //we make 10 x 10 clusters , from the upper left to the lower right. if (gMap.Width >= 20 && gMap.Height >= 20) { HPACsize = 10; int i = 0; int j = 0; for (j = 0; j <= gMap.Height / HPACsize; ++j) { for (i = 0; i < gMap.Width; i += HPACsize) { CreateHPACluster(layer, i, j); } } } else //otherwise, we divide the map to 4 clusters by the size of width / 2 x height / 2 { int i = 0; int j = 0; HPACsize = (gMap.Width % 2 == 0 ? gMap.Width / 2 : gMap.Width / 2 + 1); for (j = 0; j <= gMap.Height / HPACsize; ++j) { for (i = 0; i < gMap.Width; i += HPACsize) { CreateHPACluster(layer, i, j); } } } HierarchicalGraph.Add(layer.ID, layer); BuildClusterConnections(layer); BuildClusterNodes(layer); BuildClusterNodeIntraEdges(layer); hpaWatch.Stop(); }
private void BuildClusterNodes(AbstractionLayer layer) { foreach (var c in layer.Clusters) { //for every cluster, we look at its OuterNodes - all 4 sides. //We look at the neighboring nodes. If they are traversable, //we start tracking an entrance. We expand an entrance as long as both the neighboring nodes //are traversable. If one of them is not, we stop, look at the number of entrances and //dependng on its size, create the corresponding number of cluster nodes. foreach (var side in c.Value.OuterNodes) { Cluster neighbor; List <Tuple <int, int> > possibleEntrances = new List <Tuple <int, int> >(); switch (side.Key) { case 'U': //get the upper neighbor neighbor = c.Value.GetNeighbor('U'); if (neighbor == null) { continue; } //now we start tracking entrances between these clusters. possibleEntrances = new List <Tuple <int, int> >(); foreach (var n in side.Value) { int id = n - gMap.Width; if (gMap.Nodes[n].IsTraversable() && gMap.Nodes[id].IsTraversable()) { //ITEM1 is the Cluster node, ITEM2 is the NEIGHBOR cluster node possibleEntrances.Add(Tuple.Create(n, id)); } else { //there is an obstacle on either side of the outer nodes. //get the number of items in hte possibleEntrances and create the cluster Nodes. //after that, clear the possibleEntrances list and continue; if (possibleEntrances.Count > 0) { if (possibleEntrances.Count < 5) { //make a single entrance in the middle. //the FIRST tuple item is the node of 'c' and the second item is the node of neighbor Tuple <int, int> entrance = possibleEntrances[possibleEntrances.Count / 2]; createClusterNodes(c.Value, neighbor, entrance); possibleEntrances.Clear(); } else if (possibleEntrances.Count >= 5 && possibleEntrances.Count < 7) //the continuous entrance length is higher than/equal to 5 { //we create two entrances in this case, one on the start and one on the end. Tuple <int, int> entrance1 = possibleEntrances[0]; Tuple <int, int> entrance2 = possibleEntrances[possibleEntrances.Count - 1]; createClusterNodes(c.Value, neighbor, entrance1, entrance2); possibleEntrances.Clear(); } else //>=7 { //we create two entrances in this case - the first one column from the start, //the second one column from the end Tuple <int, int> entrance1 = possibleEntrances[2]; Tuple <int, int> entrance2 = possibleEntrances[possibleEntrances.Count - 3]; createClusterNodes(c.Value, neighbor, entrance1, entrance2); possibleEntrances.Clear(); } } } } if (possibleEntrances.Count > 0) { if (possibleEntrances.Count < 5) { //make a single entrance in the middle. //the FIRST tuple item is the node of 'c' and the second item is the node of neighbor Tuple <int, int> entrance = possibleEntrances[possibleEntrances.Count / 2]; createClusterNodes(c.Value, neighbor, entrance); possibleEntrances.Clear(); } else if (possibleEntrances.Count >= 5 && possibleEntrances.Count < 7) { //we create two entrances in this case, one on the start and one on the end. Tuple <int, int> entrance1 = possibleEntrances[0]; Tuple <int, int> entrance2 = possibleEntrances[possibleEntrances.Count - 1]; createClusterNodes(c.Value, neighbor, entrance1, entrance2); possibleEntrances.Clear(); } else //>= 7 { //we create two entrances in this case - the first one column from the start, //the second one column from the end Tuple <int, int> entrance1 = possibleEntrances[2]; Tuple <int, int> entrance2 = possibleEntrances[possibleEntrances.Count - 3]; createClusterNodes(c.Value, neighbor, entrance1, entrance2); possibleEntrances.Clear(); } } break; case 'R': //get the neighbor on the right neighbor = c.Value.GetNeighbor('R'); if (neighbor == null) { continue; } //now we start tracking entrances between these clusters. possibleEntrances = new List <Tuple <int, int> >(); foreach (var n in side.Value) { int id = n + 1; if (gMap.Nodes[n].IsTraversable() && gMap.Nodes[id].IsTraversable() && ((GridMap)gMap).SameRow(n, id)) { //ITEM1 is the Cluster node, ITEM2 is the NEIGHBOR cluster node possibleEntrances.Add(Tuple.Create(n, id)); } else { //there is an obstacle on either side of the outer nodes. //get the number of items in hte possibleEntrances and create the cluster Nodes. //after that, clear the possibleEntrances list and continue; if (possibleEntrances.Count > 0) { if (possibleEntrances.Count < 5) { //make a single entrance in the middle. //the FIRST tuple item is the node of 'c' and the second item is the node of neighbor Tuple <int, int> entrance = possibleEntrances[possibleEntrances.Count / 2]; createClusterNodes(c.Value, neighbor, entrance); possibleEntrances.Clear(); } else if (possibleEntrances.Count >= 5 && possibleEntrances.Count < 7) //the continuous entrance length is higher than/equal to 5 { //we create two entrances in this case, one on the start and one on the end. Tuple <int, int> entrance1 = possibleEntrances[0]; Tuple <int, int> entrance2 = possibleEntrances[possibleEntrances.Count - 1]; createClusterNodes(c.Value, neighbor, entrance1, entrance2); possibleEntrances.Clear(); } else //>=7 { //we create two entrances in this case - the first one column from the start, //the second one column from the end Tuple <int, int> entrance1 = possibleEntrances[2]; Tuple <int, int> entrance2 = possibleEntrances[possibleEntrances.Count - 3]; createClusterNodes(c.Value, neighbor, entrance1, entrance2); possibleEntrances.Clear(); } } } } if (possibleEntrances.Count > 0) { if (possibleEntrances.Count < 5) { //make a single entrance in the middle. //the FIRST tuple item is the node of 'c' and the second item is the node of neighbor Tuple <int, int> entrance = possibleEntrances[possibleEntrances.Count / 2]; createClusterNodes(c.Value, neighbor, entrance); possibleEntrances.Clear(); } else if (possibleEntrances.Count >= 5 && possibleEntrances.Count < 7) { //we create two entrances in this case, one on the start and one on the end. Tuple <int, int> entrance1 = possibleEntrances[0]; Tuple <int, int> entrance2 = possibleEntrances[possibleEntrances.Count - 1]; createClusterNodes(c.Value, neighbor, entrance1, entrance2); possibleEntrances.Clear(); } else //>= 7 { //we create two entrances in this case - the first one column from the start, //the second one column from the end Tuple <int, int> entrance1 = possibleEntrances[2]; Tuple <int, int> entrance2 = possibleEntrances[possibleEntrances.Count - 3]; createClusterNodes(c.Value, neighbor, entrance1, entrance2); possibleEntrances.Clear(); } } break; } } } }
public void CreateHPACluster(AbstractionLayer layer, int columnPos, int rowPos) { Cluster c = new Cluster(layer.LastAssignedClusterID); layer.LastAssignedClusterID++; HashSet <int> innerNodes = new HashSet <int>(); Dictionary <char, OuterNodeArea> outerNodes = new Dictionary <char, OuterNodeArea> { { 'U', new OuterNodeArea() }, { 'D', new OuterNodeArea() }, { 'L', new OuterNodeArea() }, { 'R', new OuterNodeArea() }, }; int startY = rowPos * HPACsize * gMap.Width; int endY = startY == 0 ? HPACsize * gMap.Width : startY + gMap.Width * HPACsize; int startX = columnPos; int endX = columnPos + HPACsize; //non-inclusive for (int j = startY; j < endY; j += gMap.Width) { for (int i = startX; i < endX; ++i) { if (gMap.Nodes.ContainsKey(i + j)) { gMap.Nodes[i + j].HPAClusterParent = c.ID; innerNodes.Add(i + j); if (j == startY || i == startX || i == endX - 1 || j + gMap.Width >= endY) { char direction = 'D'; //default init if (j == startY) //first row. 'U' outer node { direction = 'U'; } else if (i == startX) //first column. 'L' node { direction = 'L'; } else if (i == endX - 1) //last column. 'R' node { direction = 'R'; } else //j + gMap.Width >= endY. last row. 'D' node { direction = 'D'; } outerNodes[direction].Add(i + j); } } } } if (innerNodes.Count != 0 && outerNodes.Count != 0) { c.SetInnerNodes(innerNodes); c.SetOuterNodes(outerNodes); layer.Clusters.Add(c.ID, c); } else { //do not add the cluster to layer; decrease the ID layer.LastAssignedClusterID--; } }