List of usage examples for org.apache.commons.collections.buffer PriorityBuffer isEmpty
public boolean isEmpty()
From source file:de._13ducks.cor.game.server.movement.SectorPathfinder.java
public static synchronized List<Node> findPath(SimplePosition start, SimplePosition target, FreePolygon startSector, MovementMap moveMap) { if (start == null || target == null) { System.out.println("FixMe: SPathfinder, irregular call: " + start + "-->" + target); return null; }//from w ww. j a va 2 s. c o m FreePolygon targetSector = moveMap.containingPoly(target.x(), target.y()); if (targetSector == null) { // Ziel ungltig abbrechen System.out.println("Irregular target. Aborting"); return null; } FakeNode startNode = new FakeNode(start.x(), start.y(), startSector); Node targetNode = new FakeNode(target.x(), target.y(), targetSector); targetNode.addPolygon(targetSector); // Der Startknoten muss die Member seines Polys kennen startNode.setReachableNodes(computeDirectReachable(startNode, startSector)); // Der Zielknoten muss den Membern seines Polys bekannt sein // Die Movement-Map darf aber nicht verndert werden. Des halb mssen einige Aufrufe intern abgefangen werden und das reingedoktert werden. List<Node> preTargetNodes = Arrays.asList(computeDirectReachable(targetNode, targetSector)); PriorityBuffer open = new PriorityBuffer(); // Liste fr entdeckte Knoten LinkedHashSet<Node> containopen = new LinkedHashSet<Node>(); // Auch fr entdeckte Knoten, hiermit kann viel schneller festgestellt werden, ob ein bestimmter Knoten schon enthalten ist. LinkedHashSet<Node> closed = new LinkedHashSet<Node>(); // Liste fr fertig bearbeitete Knoten double cost_t = 0; //Movement Kosten (gerade 5, diagonal 7, wird spter festgelegt) startNode.setCost(0); //Kosten fr das Startfeld (von dem aus berechnet wird) sind natrlich 0 open.add(startNode); //Startfeld in die openlist containopen.add(startNode); targetNode.setParent(null); //"Vorgngerfeld" vom Zielfeld noch nicht bekannt for (int j = 0; j < 40000; j++) { //Anzahl der maximalen Durchlufe, bis Wegfindung aufgibt if (open.isEmpty()) { //Abbruch, wenn openlist leer ist => es gibt keinen Weg return null; } // Sortieren nicht mehr ntig, PriorityBuffer bewahrt die Felder in der Reihenfolge ihrer Priority - also dem F-Wert auf Node current = (Node) open.remove(); //der Eintrag aus der openlist mit dem niedrigesten F-Wert rausholen und gleich lschen containopen.remove(current); if (current.equals(targetNode)) { //Abbruch, weil Weg von Start nach Ziel gefunden wurde targetNode.setParent(current.getParent()); //"Vorgngerfeld" von Ziel bekannt break; } // Aus der open wurde current bereits gelscht, jetzt in die closed verschieben closed.add(current); List<Node> neighbors = computeNeighbors(current, targetNode, preTargetNodes); for (Node node : neighbors) { if (closed.contains(node)) { continue; } // Kosten dort hin berechnen cost_t = current.movementCostTo(node); if (containopen.contains(node)) { //Wenn sich der Knoten in der openlist befindet, muss berechnet werden, ob es einen krzeren Weg gibt if (current.getCost() + cost_t < node.getCost()) { //krzerer Weg gefunden? node.setCost(current.getCost() + cost_t); //-> Wegkosten neu berechnen node.setValF(node.getCost() + node.getHeuristic()); //F-Wert, besteht aus Wegkosten vom Start + Luftlinie zum Ziel node.setParent(current); //aktuelles Feld wird zum Vorgngerfeld } } else { node.setCost(current.getCost() + cost_t); node.setHeuristic(Math.sqrt(Math.pow(Math.abs((targetNode.getX() - node.getX())), 2) + Math.pow(Math.abs((targetNode.getY() - node.getY())), 2))); // geschtzte Distanz zum Ziel //Die Zahl am Ende der Berechnung ist der Aufwand der Wegsuche //5 ist schnell, 4 normal, 3 dauert lange node.setParent(current); // Parent ist die RogPosition, von dem der aktuelle entdeckt wurde node.setValF(node.getCost() + node.getHeuristic()); //F-Wert, besteht aus Wegkosten vom Start aus + Luftlinie zum Ziel open.add(node); // in openlist hinzufgen containopen.add(node); } } } if (targetNode.getParent() == null) { //kein Weg gefunden return null; } ArrayList<Node> pathrev = new ArrayList<Node>(); //Pfad aus parents erstellen, von Ziel nach Start while (!targetNode.equals(startNode)) { pathrev.add(targetNode); targetNode = targetNode.getParent(); } pathrev.add(startNode); ArrayList<Node> path = new ArrayList<Node>(); //Pfad umkehren, sodass er von Start nach Ziel ist for (int k = pathrev.size() - 1; k >= 0; k--) { path.add(pathrev.get(k)); } // Der folgende Algorithmus braucht Polygon-Infos, diese also hier einfgen startNode.addPolygon(startSector); targetNode.addPolygon(targetSector); /** * An dieser Stelle muss der Weg nocheinmal berarbeitet werden. * Es kann nmlich durch neue Tweaks sein, dass dies die Knoten nicht direkt * verbunden sind (also keinen gemeinsamen Polygon haben) * Das tritt z.B. bei der Start- und Zieleinsprungpunkt-Variierung auf. */ for (int i = 0; i < path.size() - 1; i++) { Node n1 = path.get(i); Node n2 = path.get(i + 1); FreePolygon commonSector = commonSector(n1, n2); if (commonSector == null) { // Das hier ist der interessante Fall, die beiden Knoten sind nicht direkt verbunden, es muss ein Zwischenknoten eingefgt werden: // Dessen Punkt suchen Edge direct = new Edge(n1, n2); Node newNode = null; // Die Polygone von n1 durchprobieren for (FreePolygon currentPoly : n1.getPolygons()) { List<Edge> edges = currentPoly.calcEdges(); for (Edge testedge : edges) { // Gibts da einen Schnitt? SimplePosition intersection = direct.intersectionWithEndsNotAllowed(testedge); if (intersection != null) { // Kandidat fr den nchsten Polygon FreePolygon nextPoly = null; // Kante gefunden // Von dieser Kante die Enden suchen nextPoly = getOtherPoly(testedge.getStart(), testedge.getEnd(), currentPoly); newNode = intersection.toNode(); newNode.addPolygon(currentPoly); newNode.addPolygon(nextPoly); break; } } if (newNode != null) { break; } } if (newNode == null) { // Das drfte nicht passieren, der Weg ist legal gefunden worden, muss also eigentlich existieren System.out.println("[Pathfinder][ERROR]: Cannot insert Nodes into route, aborting!"); return null; } else { path.add(i + 1, newNode); } } } return path; //Pfad zurckgeben }