// License: GPL. For details, see LICENSE file. package public_transport; import java.util.Iterator; import java.util.Objects; import java.util.TreeMap; import java.util.TreeSet; import java.util.Vector; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.data.osm.Node; import org.openstreetmap.josm.data.osm.Way; public class PublicTransportAStar extends AStarAlgorithm { public PublicTransportAStar(Node start, Node end) { super(new NodeVertex(start), new NodeVertex(end)); } public static class NodeVertex extends AStarAlgorithm.Vertex { public NodeVertex(Node node) { this.node = node; } @Override public int compareTo(AStarAlgorithm.Vertex v) { return this.node.compareTo(((NodeVertex) v).node); } @Override public boolean equals(Object o) { if ((NodeVertex) o == null) return false; return node.equals(((NodeVertex) o).node); } @Override public int hashCode() { return Objects.hashCode(node); } public Node node; } public static class PartialWayEdge extends AStarAlgorithm.Edge { public PartialWayEdge(Way way, int beginIndex, int endIndex) { this.way = way; this.beginIndex = beginIndex; this.endIndex = endIndex; } @Override public AStarAlgorithm.Vertex getBegin() { return new NodeVertex(way.getNode(beginIndex)); } @Override public AStarAlgorithm.Vertex getEnd() { return new NodeVertex(way.getNode(endIndex)); } @Override public double getLength() { int min = beginIndex; int max = endIndex; if (endIndex < beginIndex) { min = endIndex; max = beginIndex; } double totalDistance = 0; for (int i = min; i < max; ++i) { totalDistance += way.getNode(i).getCoor().greatCircleDistance(way.getNode(i + 1).getCoor()); } return totalDistance; } public Way way; public int beginIndex; public int endIndex; } @Override public Vector<AStarAlgorithm.Edge> getNeighbors(AStarAlgorithm.Vertex vertex) { if (waysPerNode == null) { waysPerNode = new TreeMap<>(); Iterator<Way> iter = Main.getLayerManager().getEditDataSet().getWays().iterator(); while (iter.hasNext()) { Way way = iter.next(); // Only consider ways that are usable if (!way.isUsable()) continue; // Further tests whether the way is eligible. for (int i = 0; i < way.getNodesCount(); ++i) { if (waysPerNode.get(way.getNode(i)) == null) waysPerNode.put(way.getNode(i), new TreeSet<Way>()); waysPerNode.get(way.getNode(i)).add(way); } } } NodeVertex nodeVertex = (NodeVertex) vertex; System.out.println(nodeVertex.node.getUniqueId()); Vector<AStarAlgorithm.Edge> result = new Vector<>(); // Determine all ways in which nodeVertex.node is contained. Iterator<Way> iter = waysPerNode.get(nodeVertex.node).iterator(); while (iter.hasNext()) { Way way = iter.next(); // Only consider ways that are usable if (!way.isUsable()) continue; // Further tests whether the way is eligible. for (int i = 0; i < way.getNodesCount(); ++i) { if (way.getNode(i).equals(nodeVertex.node)) { if (i > 0) result.add(new PartialWayEdge(way, i, i - 1)); if (i < way.getNodesCount() - 1) result.add(new PartialWayEdge(way, i, i + 1)); } } } return result; } TreeMap<Node, TreeSet<Way>> waysPerNode = null; @Override public double estimateDistance(AStarAlgorithm.Vertex vertex) { NodeVertex nodeVertex = (NodeVertex) vertex; return ((NodeVertex) super.end).node.getCoor() .greatCircleDistance(nodeVertex.node.getCoor()); } }