/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: AStarRegionNode.java
* Written by: Christian Harnisch, Ingo Besenfelder, Michael Neumann (Team 3)
*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
*
* Electric(tm) is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Electric(tm) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.tool.routing.experimentalAStar3.algorithm;
import java.util.ArrayList;
import java.util.HashSet;
import com.sun.electric.tool.routing.experimentalAStar3.concurrency.RoutingMain;
import com.sun.electric.tool.routing.experimentalAStar3.goal.SimpleGoal;
import com.sun.electric.tool.routing.experimentalAStar3.machine.AStarMachine;
import com.sun.electric.tool.routing.experimentalAStar3.machine.AStarMachineFast;
import com.sun.electric.tool.routing.experimentalAStar3.map.FieldMap;
import com.sun.electric.tool.routing.experimentalAStar3.memorymanager.AStarNodeObjectPool;
/**
* An AStarRegionNode represents one layer of one region in the global region
* map.
*
* @author Ingo Besenfelder
* @author Christian Harnisch
*
*/
public class AStarRegionNode extends AStarNodeBase<AStarRegionNode>
{
/**
* is used for checking blockages and giving the router a clean map to route
* on.
*/
public FieldMap<AStarNode> routingMap;
/**
* this map contains all nodes that are created during capacity calculation.
* there is a seperate map for each horizontal and vertical calculation. this
* map should not be asked for blockages as they can change during runtime,
* but won't be updated here after initializing this RegionNode.
*/
private FieldMap<AStarNode> hMap;
private FieldMap<AStarNode> vMap;
protected int hCap;
protected int vCap;
private ArrayList<Integer> hPaths = new ArrayList<Integer>();
private ArrayList<Integer> vPaths = new ArrayList<Integer>();
private HashSet<AStarNode> hPortals = new HashSet<AStarNode>();
public HashSet<AStarNode> vPortals = new HashSet<AStarNode>();
public int height;
public int width;
/* Dirty flags: Tells if the capacity of the region should be recalculated. */
private boolean horizontalDirty = true;
private boolean verticalDirty = true;
private AStarNode entryPoint;
private AStarNode exitPoint;
/**
* needed for special case: start/endpoint is within this region, which has no
* capacity (it happens!). Then the capacity must NOT be asked to be !=0
* (which usually is a required condition to walk in a specific direction).
*/
private boolean isStartRegion = false;
private boolean isGoalRegion = false;
public void setAsStartRegion(boolean isStartRegion)
{
this.isStartRegion = isStartRegion;
}
public void setAsGoalRegion(boolean isGoalRegion)
{
this.isGoalRegion = isGoalRegion;
}
public boolean isTerminalRegion()
{
return this.isStartRegion || this.isGoalRegion;
}
public AStarRegionNode()
{
}
/**
* This class expects that (0,0) is in the upper left corner of the map.<br/>
* <br/>
* The capacity is calculated from x = 0 to x = <code>width</code>-1 and y = 0
* to y = <code>height</code>-1. <br/>
* <br/>
* Since we calculate two different capacities (horizontal and vertical), the
* map cannot contain the found paths directly (because then it would fail to
* calculate the second capacity), so it offers them in two lists: <br/>
* Both lists (<code>hPaths</code> and <code>vPaths</code>) contain lists of
* <code>AStarNodes</code> connected by their <code>origin</code>-pointer
*
* @param map The sub-map of the cell this AStarRegionNode represents a layer
* from.
* @param layer The layer this AStarRegionNode represents
* @param height
* @param width
*/
public AStarRegionNode(FieldMap<AStarNode> map, int width, int height)
{
this.routingMap = map;
this.height = height;
this.width = width;
}
public AStarRegionNode(FieldMap<AStarNode> map, int width, int height, int x, int y, int z)
{
this.routingMap = map;
this.height = height;
this.width = width;
this.x = x;
this.y = y;
this.z = z;
}
/**
* Returns the number of wires that can successfully be routed through this
* section of the cell horizontally.
*
* @return Number of possible horizontal wires.
*/
public int getHorizontalCapacity()
{
if (this.horizontalDirty)
{
this.hCap = calculateCapacity(false);
fillUpCapacityPathNumbers(false);
this.horizontalDirty = false;
}
return this.hCap;
}
/**
* Returns the number of wires that can successfully be routed through this
* section of the cell vertically.
*
* @return Number of possible vertical wires.
*/
public int getVerticalCapacity()
{
if (this.verticalDirty)
{
this.vCap = calculateCapacity(true);
fillUpCapacityPathNumbers(true);
this.verticalDirty = false;
}
return this.vCap;
}
/**
* Calculates and returns the number of wires that can successfully be routed
* through this section of the cell, horizontally or vertically.
*
* @param calcVertical <code>true</code> if the vertical capacity should be
* calculated, <code>false</code> otherwise.
* @return Number of possible wires in the given direction.
*/
private int calculateCapacity(boolean calcVertical)
{
FieldMap<AStarNode> capMap;
if (calcVertical)
{
this.vPaths.clear();
capMap = this.getMap(true);
}
else
{
this.hPaths.clear();
capMap = this.getMap(false);
}
byte commingFrom;
final byte LEFT = 0;
final byte BOTTOM = 1;
final byte RIGHT = 2;
final byte TOP = 3;
// Start at (0,0) for horizontal, (0,this.height-1) for vertical
int x = 0;
int y = calcVertical ? 0 : this.height - 1;
// find path from left to right
int k = 0;
commingFrom = calcVertical ? TOP : LEFT;
while ((!calcVertical && y > 0) || (calcVertical && x < this.width))
{
x = 0;
y = calcVertical ? 0 : this.height - 1;
k++;
if (calcVertical)
while (routingMap.isTileBlocked(x, y, 0) || capMap.nodeAt(x, y, 0).getVerticalCapacityPathNumber() != 0
|| !isPortal(x, y, true))
{
x++;
if (x >= this.width)
return k - 1;
}
else
while (routingMap.isTileBlocked(x, y, 0) || capMap.nodeAt(x, y, 0).getHorizontalCapacityPathNumber() != 0
|| !isPortal(x, y, false))
{
y--;
if (y < 0)
return k - 1;
}
AStarNode origin = capMap.nodeAt(x, y, 0);
if (calcVertical)
origin.setVerticalCapacityPathNumber(k);
else
origin.setHorizontalCapacityPathNumber(k);
while ((!calcVertical && x < this.width && y >= -1 && (x == 0 || !this.isPortal(x, y, false)))
|| (calcVertical && x < this.width && y <= this.height - 1 && (y == 0 || !this.isPortal(x, y, true))))
{
switch (commingFrom)
{
case LEFT:
if (!routingMap.isTileBlocked(x, y + 1, 0))
if (calcVertical ? capMap.nodeAt(x, y + 1, 0).getVerticalCapacityPathNumber() == 0 : capMap.nodeAt(x, y + 1, 0)
.getHorizontalCapacityPathNumber() == 0)
{
y++;
AStarNode oldOrigin = origin;
origin = capMap.nodeAt(x, y, 0);
origin.initialize(oldOrigin, 0, 0, 0, x, y, 0);
if (calcVertical)
origin.setVerticalCapacityPathNumber(k);
else
origin.setHorizontalCapacityPathNumber(k);
commingFrom = TOP;
break;
}
if (!routingMap.isTileBlocked(x + 1, y, 0))
if (calcVertical ? capMap.nodeAt(x + 1, y, 0).getVerticalCapacityPathNumber() == 0 : capMap.nodeAt(x + 1, y, 0)
.getHorizontalCapacityPathNumber() == 0)
{
x++;
AStarNode oldOrigin = origin;
origin = capMap.nodeAt(x, y, 0);
origin.initialize(oldOrigin, 0, 0, 0, x, y, 0);
if (calcVertical)
origin.setVerticalCapacityPathNumber(k);
else
origin.setHorizontalCapacityPathNumber(k);
commingFrom = LEFT;
break;
}
if (!routingMap.isTileBlocked(x, y - 1, 0))
if (calcVertical ? capMap.nodeAt(x, y - 1, 0).getVerticalCapacityPathNumber() == 0 : capMap.nodeAt(x, y - 1, 0)
.getHorizontalCapacityPathNumber() == 0)
{
y--;
AStarNode oldOrigin = origin;
origin = capMap.nodeAt(x, y, 0);
origin.initialize(oldOrigin, 0, 0, 0, x, y, 0);
if (calcVertical)
origin.setVerticalCapacityPathNumber(k);
else
origin.setHorizontalCapacityPathNumber(k);
commingFrom = BOTTOM;
break;
}
x--; // move one step back and start backtracking
// start moving back with opposite direction
commingFrom = RIGHT;
origin = traceBack(capMap.nodeAt(x, y, 0), calcVertical);
if (origin != null) // another way is possible
{
x = origin.getX();
y = origin.getY();
if (origin.origin != null)
{ // is valid node, so start
// from here
int oX = origin.origin.getX();
int oY = origin.origin.getY();
if (oX < x)
commingFrom = LEFT;
if (oX > x)
commingFrom = RIGHT;
if (oY > y)
commingFrom = BOTTOM;
if (oY < y)
commingFrom = TOP;
}
else
// must be beginning node (0,0) => Start again
commingFrom = LEFT;
}
else
return k - 1;
break;
case BOTTOM:
if (!routingMap.isTileBlocked(x + 1, y, 0))
if (calcVertical ? capMap.nodeAt(x + 1, y, 0).getVerticalCapacityPathNumber() == 0 : capMap.nodeAt(x + 1, y, 0)
.getHorizontalCapacityPathNumber() == 0)
{
x++;
AStarNode oldOrigin = origin;
origin = capMap.nodeAt(x, y, 0);
origin.initialize(oldOrigin, 0, 0, 0, x, y, 0);
if (calcVertical)
origin.setVerticalCapacityPathNumber(k);
else
origin.setHorizontalCapacityPathNumber(k);
commingFrom = LEFT;
break;
}
if (y == this.height)
return k - 1;
if (!routingMap.isTileBlocked(x, y - 1, 0))
if (calcVertical ? capMap.nodeAt(x, y - 1, 0).getVerticalCapacityPathNumber() == 0 : capMap.nodeAt(x, y - 1, 0)
.getHorizontalCapacityPathNumber() == 0)
{
y--;
AStarNode oldOrigin = origin;
origin = capMap.nodeAt(x, y, 0);
origin.initialize(oldOrigin, 0, 0, 0, x, y, 0);
if (calcVertical)
origin.setVerticalCapacityPathNumber(k);
else
origin.setHorizontalCapacityPathNumber(k);
commingFrom = BOTTOM;
break;
}
if (!routingMap.isTileBlocked(x - 1, y, 0))
if (calcVertical ? capMap.nodeAt(x - 1, y, 0).getVerticalCapacityPathNumber() == 0 : capMap.nodeAt(x - 1, y, 0)
.getHorizontalCapacityPathNumber() == 0)
{
x--;
AStarNode oldOrigin = origin;
origin = capMap.nodeAt(x, y, 0);
origin.initialize(oldOrigin, 0, 0, 0, x, y, 0);
if (calcVertical)
origin.setVerticalCapacityPathNumber(k);
else
origin.setHorizontalCapacityPathNumber(k);
commingFrom = RIGHT;
break;
}
y++; // move one step back and start backtracking
// start moving back with opposite direction
commingFrom = TOP;
origin = traceBack(capMap.nodeAt(x, y, 0), calcVertical);
if (origin != null) // another way is possible
{
x = origin.getX();
y = origin.getY();
if (origin.origin != null)
{ // is valid node, so start
// from here
int oX = origin.origin.getX();
int oY = origin.origin.getY();
if (oX < x)
commingFrom = LEFT;
if (oX > x)
commingFrom = RIGHT;
if (oY > y)
commingFrom = BOTTOM;
if (oY < y)
commingFrom = TOP;
}
else
// must be beginning node (0,0) => Start again
commingFrom = LEFT;
}
else
return k - 1;
break;
case RIGHT:
if (!routingMap.isTileBlocked(x, y - 1, 0))
if (calcVertical ? capMap.nodeAt(x, y - 1, 0).getVerticalCapacityPathNumber() == 0 : capMap.nodeAt(x, y - 1, 0)
.getHorizontalCapacityPathNumber() == 0)
{
y--;
AStarNode oldOrigin = origin;
origin = capMap.nodeAt(x, y, 0);
origin.initialize(oldOrigin, 0, 0, 0, x, y, 0);
if (calcVertical)
origin.setVerticalCapacityPathNumber(k);
else
origin.setHorizontalCapacityPathNumber(k);
commingFrom = BOTTOM;
break;
}
if (!routingMap.isTileBlocked(x - 1, y, 0))
if (calcVertical ? capMap.nodeAt(x - 1, y, 0).getVerticalCapacityPathNumber() == 0 : capMap.nodeAt(x - 1, y, 0)
.getHorizontalCapacityPathNumber() == 0)
{
x--;
AStarNode oldOrigin = origin;
origin = capMap.nodeAt(x, y, 0);
origin.initialize(oldOrigin, 0, 0, 0, x, y, 0);
if (calcVertical)
origin.setVerticalCapacityPathNumber(k);
else
origin.setHorizontalCapacityPathNumber(k);
commingFrom = RIGHT;
break;
}
if (!routingMap.isTileBlocked(x, y + 1, 0))
if (calcVertical ? capMap.nodeAt(x, y + 1, 0).getVerticalCapacityPathNumber() == 0 : capMap.nodeAt(x, y + 1, 0)
.getHorizontalCapacityPathNumber() == 0)
{
y++;
AStarNode oldOrigin = origin;
origin = capMap.nodeAt(x, y, 0);
origin.initialize(oldOrigin, 0, 0, 0, x, y, 0);
if (calcVertical)
origin.setVerticalCapacityPathNumber(k);
else
origin.setHorizontalCapacityPathNumber(k);
commingFrom = TOP;
break;
}
x++; // move one step back and start backtracking
// start moving back with opposite direction
commingFrom = LEFT;
origin = traceBack(capMap.nodeAt(x, y, 0), calcVertical);
if (origin != null) // another way is possible
{
x = origin.getX();
y = origin.getY();
if (origin.origin != null)
{ // is valid node, so start
// from here
int oX = origin.origin.getX();
int oY = origin.origin.getY();
if (oX < x)
commingFrom = LEFT;
if (oX > x)
commingFrom = RIGHT;
if (oY > y)
commingFrom = BOTTOM;
if (oY < y)
commingFrom = TOP;
}
else
// must be beginning node (0,0) => Start again
commingFrom = LEFT;
}
else
return k - 1;
break;
case TOP:
if (!routingMap.isTileBlocked(x - 1, y, 0))
if (calcVertical ? capMap.nodeAt(x - 1, y, 0).getVerticalCapacityPathNumber() == 0 : capMap.nodeAt(x - 1, y, 0)
.getHorizontalCapacityPathNumber() == 0)
{
x--;
AStarNode oldOrigin = origin;
origin = capMap.nodeAt(x, y, 0);
origin.initialize(oldOrigin, 0, 0, 0, x, y, 0);
if (calcVertical)
origin.setVerticalCapacityPathNumber(k);
else
origin.setHorizontalCapacityPathNumber(k);
commingFrom = RIGHT;
break;
}
if (!routingMap.isTileBlocked(x, y + 1, 0))
if (calcVertical ? capMap.nodeAt(x, y + 1, 0).getVerticalCapacityPathNumber() == 0 : capMap.nodeAt(x, y + 1, 0)
.getHorizontalCapacityPathNumber() == 0)
{
y++;
AStarNode oldOrigin = origin;
origin = capMap.nodeAt(x, y, 0);
origin.initialize(oldOrigin, 0, 0, 0, x, y, 0);
if (calcVertical)
origin.setVerticalCapacityPathNumber(k);
else
origin.setHorizontalCapacityPathNumber(k);
commingFrom = TOP;
break;
}
if (!routingMap.isTileBlocked(x + 1, y, 0))
if (calcVertical ? capMap.nodeAt(x + 1, y, 0).getVerticalCapacityPathNumber() == 0 : capMap.nodeAt(x + 1, y, 0)
.getHorizontalCapacityPathNumber() == 0)
{
x++;
AStarNode oldOrigin = origin;
origin = capMap.nodeAt(x, y, 0);
origin.initialize(oldOrigin, 0, 0, 0, x, y, 0);
if (calcVertical)
origin.setVerticalCapacityPathNumber(k);
else
origin.setHorizontalCapacityPathNumber(k);
commingFrom = LEFT;
break;
}
y--; // move one step back and start backtracking
// start moving back with opposite direction
commingFrom = BOTTOM;
origin = traceBack(capMap.nodeAt(x, y, 0), calcVertical);
if (origin != null) // another way is possible
{
x = origin.getX();
y = origin.getY();
if (origin.origin != null)
{ // is valid node, so start
// from here
int oX = origin.origin.getX();
int oY = origin.origin.getY();
if (oX < x)
commingFrom = LEFT;
if (oX > x)
commingFrom = RIGHT;
if (oY > y)
commingFrom = BOTTOM;
if (oY < y)
commingFrom = TOP;
}
else
// must be beginning node (0,0) => Start again
commingFrom = LEFT;
}
else
return k - 1;
break;
}
}
// add path to path list
// List<AStarNode> path = new ArrayList<AStarNode>();
// AStarNode pathNode = origin;
// while (pathNode != null)
// {
// path.add(pathNode);
// pathNode = pathNode.origin;
// }
if (calcVertical)
this.vPaths.add(k);
else
this.hPaths.add(k);
}
return k;
}
private void fillUpCapacityPathNumbers(boolean calcVertical)
{
if (calcVertical)
{
// fill up path numbers in vertical portals
for (int x = 0; x < this.width; x++)
{
int pathNumber = 0;
// search from top to bottom
int y = 0;
if (isPortal(x, y, true) && this.getMap(true).nodeAt(x, y, 0).getVerticalCapacityPathNumber() == 0)
{
while (y < this.height)
{
if (this.routingMap.isTileBlocked(x, y, 0))
break;
pathNumber = this.getMap(true).nodeAt(x, y, 0).getVerticalCapacityPathNumber();
if (pathNumber != 0)
break;
y++;
}
if (y != 0 && y != this.height && !this.routingMap.isTileBlocked(x, y, 0))
{
this.getMap(true).nodeAt(x, 0, 0).setVerticalCapacityPathNumber(pathNumber);
}
}
// search from bottom to top
y = this.height - 1;
if (isPortal(x, y, true) && this.getMap(true).nodeAt(x, y, 0).getVerticalCapacityPathNumber() == 0)
{
while (y >= 0)
{
if (this.routingMap.isTileBlocked(x, y, 0))
break;
pathNumber = this.getMap(true).nodeAt(x, y, 0).getVerticalCapacityPathNumber();
if (pathNumber != 0)
break;
y--;
}
if (y != this.height - 1 && y != -1 && !this.routingMap.isTileBlocked(x, y, 0))
{
this.getMap(true).nodeAt(x, this.height - 1, 0).setVerticalCapacityPathNumber(pathNumber);
}
}
}
}
else
{
// fill up path numbers in horizontal portals
for (int y = 0; y < this.height; y++)
{
int pathNumber = 0;
// search from west to east
int x = 0;
if (isPortal(x, y, true) && this.getMap(false).nodeAt(x, y, 0).getHorizontalCapacityPathNumber() == 0)
{
while (x < this.width)
{
if (this.routingMap.isTileBlocked(x, y, 0))
break;
pathNumber = this.getMap(false).nodeAt(x, y, 0).getHorizontalCapacityPathNumber();
if (pathNumber != 0)
break;
x++;
}
if (x != 0 && x != this.width && !this.routingMap.isTileBlocked(x, y, 0))
{
this.getMap(false).nodeAt(0, y, 0).setHorizontalCapacityPathNumber(pathNumber);
}
}
// search from east to west
x = this.width - 1;
if (isPortal(x, y, true) && this.getMap(false).nodeAt(x, y, 0).getHorizontalCapacityPathNumber() == 0)
{
while (x >= 0)
{
if (this.routingMap.isTileBlocked(x, y, 0))
break;
pathNumber = this.getMap(false).nodeAt(x, y, 0).getHorizontalCapacityPathNumber();
if (pathNumber != 0)
break;
x--;
}
if (x != this.width - 1 && x != -1 && !this.routingMap.isTileBlocked(x, y, 0))
{
this.getMap(false).nodeAt(this.width - 1, y, 0).setHorizontalCapacityPathNumber(pathNumber);
}
}
}
}
}
protected boolean isPortal(int x, int y, boolean vertical)
{
if (this.routingMap.isTileBlocked(x, y, 0))
{
AStarNode nodeAt = this.routingMap.nodeAt(x, y, 0);
this.vPortals.remove(nodeAt);
this.hPortals.remove(nodeAt);
return false;
}
if (vertical)
return this.vPortals.contains(routingMap.nodeAt(x, y, 0));
return this.hPortals.contains(routingMap.nodeAt(x, y, 0));
}
public void setPortal(int x, int y, boolean vertical)
{
if (vertical)
this.vPortals.add(routingMap.nodeAt(x, y, 0));
else
this.hPortals.add(routingMap.nodeAt(x, y, 0));
}
public boolean isPortalWithPath(int x, int y, boolean calcVertical)
{
if (this.routingMap.isTileBlocked(x, y, 0))
{
AStarNode nodeAt = this.routingMap.nodeAt(x, y, 0);
this.vPortals.remove(nodeAt);
this.hPortals.remove(nodeAt);
return false;
}
if (!this.isPortal(x, y, calcVertical))
return false;
if (this.isTerminalRegion())
{
AStarNode to = this.isGoalRegion ? this.getExitPoint() : this.getEntryPoint();
AStarMachine<AStarNode> machine = new AStarMachineFast(new AStarNodeObjectPool());
AStarGoalBase<AStarNode> goal = new SimpleGoal();
goal.setMaximumRevolutions(RoutingMain.MAX_REVOLUTIONS);
machine.setUpSearchSpace(this.routingMap, goal);
if (machine.findPath(x, y, 0, to.getX(), to.getY(), 0) != null)
return true;
// System.out.println("Could not find path to portal in TerminalRegion ("
// + this.getX() + "/" + this.getY() + ") from (" + x
// + "," + y + ") to (" + to.getX() + "," + to.getY() + ")");
// this.print();
}
if (calcVertical)
return this.vPaths.contains(this.getMap(true).nodeAt(x, y, 0).getVerticalCapacityPathNumber());
return this.hPaths.contains(this.getMap(false).nodeAt(x, y, 0).getHorizontalCapacityPathNumber());
}
private AStarNode traceBack(AStarNode currentNode, boolean calcVertical)
{
int x;
int y;
AStarNode result = currentNode;
if (calcVertical)
{
FieldMap<AStarNode> map = this.getMap(true);
while (result != null)
{
x = result.getX();
y = result.getY();
if ((this.routingMap.isTileBlocked(x, y + 1, 0) || map.nodeAt(x, y + 1, 0).getVerticalCapacityPathNumber() > 0)
&& (this.routingMap.isTileBlocked(x, y - 1, 0) || map.nodeAt(x, y - 1, 0).getVerticalCapacityPathNumber() > 0)
&& (this.routingMap.isTileBlocked(x + 1, y, 0) || map.nodeAt(x + 1, y, 0).getVerticalCapacityPathNumber() > 0)
&& (this.routingMap.isTileBlocked(x - 1, y, 0) || map.nodeAt(x - 1, y, 0).getVerticalCapacityPathNumber() > 0))
{
result = result.origin; // might be null if first Node of
// path =>
// still
// correct
}
else
break;
}
}
else
{
FieldMap<AStarNode> map = this.getMap(false);
while (result != null)
{
x = result.getX();
y = result.getY();
if ((this.routingMap.isTileBlocked(x, y + 1, 0) || map.nodeAt(x, y + 1, 0).getHorizontalCapacityPathNumber() > 0)
&& (this.routingMap.isTileBlocked(x, y - 1, 0) || map.nodeAt(x, y - 1, 0).getHorizontalCapacityPathNumber() > 0)
&& (this.routingMap.isTileBlocked(x + 1, y, 0) || map.nodeAt(x + 1, y, 0).getHorizontalCapacityPathNumber() > 0)
&& (this.routingMap.isTileBlocked(x - 1, y, 0) || map.nodeAt(x - 1, y, 0).getHorizontalCapacityPathNumber() > 0))
{
result = result.origin; // might be null if first Node of
// path =>
// still
// correct
}
else
break;
}
}
return result;
}
/**
* removes a path from the path list. Should be called when node was actually
* used by detailed routing.
*
* @param pathNumber
* @param vertical
*/
public void removePathForNode(int x, int y)
{
if (this.vPaths.remove(Integer.valueOf(this.getMap(true).nodeAt(x, y, 0).getVerticalCapacityPathNumber())))
this.vCap--;
if (this.hPaths.remove(Integer.valueOf(this.getMap(false).nodeAt(x, y, 0).getHorizontalCapacityPathNumber())))
this.hCap--;
}
/*
* (non-Javadoc)
*
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
public int compareTo(AStarRegionNode o)
{
return this.getTotalCost() - o.getTotalCost();
}
public FieldMap<AStarNode> getMap(boolean vertical)
{
if (vertical)
if (this.vMap == null)
return this.vMap = (FieldMap<AStarNode>) this.routingMap.clone();
else
return this.vMap;
else if (this.hMap == null)
return this.hMap = (FieldMap<AStarNode>) this.routingMap.clone();
else
return this.hMap;
}
public boolean isTileBlocked(int x, int y)
{
return this.routingMap.isTileBlocked(x, y, 0);
}
public AStarNode getEntryPoint()
{
return this.entryPoint;
}
public void setEntryPoint(AStarNode node)
{
this.entryPoint = node;
}
public AStarNode getExitPoint()
{
return this.exitPoint;
}
public void setExitPoint(AStarNode node)
{
this.exitPoint = node;
}
public void print()
{
String string = "";
for (int y = 0; y < this.height; y++)
{
for (int x = 0; x < this.width; x++)
{
String value = "";
if (this.getEntryPoint() != null && this.getEntryPoint().equals(this.getMap(true).nodeAt(x, y, 0)))
value = "E";
else if (this.isTileBlocked(x, y))
value = "X";
else
value = "_";
if (this.isPortal(x, y, true) || this.isPortal(x, y, false))
value = "P" + value;
else
value += "_";
string += "[" + value + "]";
}
string += "\n";
}
System.out.println(string);
}
}