// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.plugins.JunctionChecker.converting; import org.openstreetmap.josm.plugins.JunctionChecker.datastructure.Channel; import org.openstreetmap.josm.plugins.JunctionChecker.datastructure.ChannelDiGraph; import org.openstreetmap.josm.plugins.JunctionChecker.datastructure.OSMGraph; import org.openstreetmap.josm.plugins.JunctionChecker.datastructure.OSMNode; import org.openstreetmap.josm.plugins.JunctionChecker.datastructure.OSMWay; /** * erstellt einen ChannelDigraphen aus einem OSMGraphen * @author Jörg Possin */ public class ChannelDigraphBuilder { private final ChannelDiGraph digraph; private final OSMGraph osmgraph; private final OSMWay[] osmways; private Channel newChannel = new Channel(); private final NodesConnectionProducer ncp; // Variable wird für die IDs der neu erstellten Ways benötigt, die // Hinrichtung bekommt den des ursprungs-Way, die Rückrichtung // eine fiktive negative (OSM-XML-Standard für neue, noch nicht in der DB // gespeicherte Entities) private int newid = 1; private TurnRestrictionChecker trchecker; Channel backChannel; public ChannelDigraphBuilder(OSMGraph osmgraph) { //Nodesbeziehungen erstellen ncp = new NodesConnectionProducer(osmgraph); ncp.produceNodesConnections(); digraph = new ChannelDiGraph(); this.osmways = osmgraph.getWays(); digraph.setBbbottom(osmgraph.getBbbottom()); digraph.setBbleft(osmgraph.getBbleft()); digraph.setBbright(osmgraph.getBbright()); digraph.setBbtop(osmgraph.getBbtop()); this.osmgraph = osmgraph; } private void setNewWayID(Channel channel) { channel.setNewid(newid); newid++; } /** * Hilfemethode zur Erstellung eines Channels * @param fromNode fromNode des zu erstellenden Channels * @param toNode toNode des zu erstellnenden Channels * @param way ein zu dem Channel gehörender Way */ private Channel createChannel(OSMNode fromNode, OSMNode toNode, OSMWay way) { newChannel = new Channel(); newChannel.setFromNode(fromNode); newChannel.setToNode(toNode); setNewWayID(newChannel); digraph.addChannel(newChannel); fromNode.addOutgoingChannel(newChannel); newChannel.addWay(way); return newChannel; } private void createBackChannel(OSMNode fromNode, OSMNode toNode, OSMWay way, Channel channel) { backChannel = new Channel(); backChannel = createChannel(fromNode, toNode, way); backChannel.setBackChannelID(channel.getNewid()); channel.setBackChannelID(backChannel.getNewid()); } /** * erzeugt den Digraphen */ private void buildChannels(OSMWay way, boolean oneway) { Channel tempChannel = new Channel(); OSMNode lastUsedNode = way.getFromNode(); OSMNode[] nodes = way.getNodes(); /* * log.debug("Way mit ID " + way.getId() + " , startnode: " + * way.getFromNode().getId() + " , EndNode: " + way.getToNode().getId() * + " wird bearbeitet."); */ // alle Knoten eines ways durchgehen for (int i = 1; i < nodes.length; i++) { // nur wenn der aktuelle Knoten mehr als einen Vorgänger/Nachfolger // hat, wird in die if-Abfrage gesprungen und ein neuer Channel mit //mit dem aktuell betrachtetem Node als Endnode erzeugt if (nodes[i].getPredNodeList().size() > 1 || nodes[i].getSuccNodeList().size() > 1) { tempChannel = createChannel(lastUsedNode, nodes[i], way); // bei Nichteinbahnstraße wird Channel in die andere Richtung // erzeugt if (oneway == false) { createBackChannel(nodes[i], lastUsedNode, way, tempChannel); } lastUsedNode = nodes[i]; // wenn der betrachtete Knoten keine Nachfolger hat, ist ein // Straßenende erreicht. Auch in diesem Fall muß ein Channel erzeugt werden } else if (nodes[i].getSuccNodeList().size() == 0) { tempChannel = createChannel(lastUsedNode, nodes[i], way); // Rückrichtung wird nur erzeugt, wenn der OSM-Way keine Einbahnstraße ist if (oneway == false) { createBackChannel(nodes[i], lastUsedNode, way, tempChannel); } // eine Straße besteht aus 2 Ways, obwohl eigentlich eine reicht // tritt z.b. bei einer brücke auf, brücke wird neuer channel //TODO: kann an dieser stelle das erzeugen von pseudo-channels verhindert werden? // Idee: speichern eines flags, um diese erzeugten Channels zu markieren. aus diesen informationen // später den CHannel löschen!!! } else if (i == nodes.length - 1 && nodes[i].getSuccNodeList().size() == 1) { // damit ist ein Channel gefunden, und wird mit Werten gefüllt tempChannel = createChannel(lastUsedNode, nodes[i], way); // bei Nichteinbahnstraße wird Channel in die andere Richtung // erzeugt if (oneway == false) { createBackChannel(nodes[i], lastUsedNode, way, tempChannel); } lastUsedNode = nodes[i]; } } } /** * baut den ChannelDigraph */ public void buildChannelDigraph() { // alle Wege eines OSMGraphen durchgehen for (int i = 0; i < osmways.length; i++) { buildChannels(osmways[i], osmways[i].isOneWay()); } trchecker = new TurnRestrictionChecker(osmgraph, digraph); trchecker.createLeadsTo(); PseudoChannelRemover pcr = new PseudoChannelRemover(digraph); //überflüssige Channels entfernen pcr.removePseudoChannels(); } public ChannelDiGraph getDigraph() { return digraph; } public void setNewid(int newid) { this.newid = newid; } public int getNewid() { return newid; } }