/** * This file is part of OSM2ShareNav * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * * Copyright (C) 2007 2008 Harald Mueller * */ package net.sharenav.osmToShareNav; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Vector; import net.sharenav.osmToShareNav.model.Connection; import net.sharenav.osmToShareNav.model.Node; import net.sharenav.osmToShareNav.model.RouteNode; import net.sharenav.osmToShareNav.model.TravelMode; import net.sharenav.osmToShareNav.model.TravelModes; import net.sharenav.osmToShareNav.model.TurnRestriction; import net.sharenav.osmToShareNav.model.Way; import net.sharenav.osmToShareNav.model.WayDescription; import net.sharenav.osmToShareNav.tools.FileTools; /** * @author hmueller * */ public class RouteData { private OsmParser parser; private String path; private Configuration config; public Map<Long, RouteNode> nodes = new HashMap<Long, RouteNode>(); public RouteData(OsmParser parser, String path) { super(); this.parser = parser; this.path = path; } public void create(Configuration config) { if (config.sourceIsApk) { this.path = this.path + "/assets"; } this.config = config; // reset connectedLineCount for each Node to 0 for (Node n:parser.getNodes()) { n.resetConnectedLineCount(); } boolean neverTrafficSignalsRouteNode = false; // count all connections for all nodes for (Way w:parser.getWays()) { if (! w.isAccessForAnyRouting()) { continue; } // mark nodes in tunnels / on bridges / on motorways to not get later marked as traffic signal delay route node by nearby traffic signals WayDescription wayDesc = config.getWayDesc(w.type); neverTrafficSignalsRouteNode = (w.isBridge() || w.isTunnel() || (wayDesc.isMotorway() && !wayDesc.isHighwayLink()) ); Node lastNode = null; for (Node n:w.getNodes()) { n.incConnectedLineCount(); if (lastNode != null) { n.incConnectedLineCount(); } lastNode = n; if (neverTrafficSignalsRouteNode) { n.markAsNeverTrafficSignalsRouteNode(); //System.out.println("Mark to never become a traffic signal delay route node: " + n.toString()); } } if (lastNode != null) { lastNode.decConnectedLineCount(); } } for (Way w:parser.getWays()) { if (!w.isAccessForAnyRouting()) { continue; } addConnections(w.getNodes(), w); } if (config.verbose >= 0) { System.out.println("Created " + nodes.size() + " route nodes."); } createIds(); calculateTurnRestrictions(); } /** * calculate turn restrictions */ private void calculateTurnRestrictions() { resolveViaWays(); if (config.verbose >= 0) { System.out.println("info: Calculating turn restrictions"); } int numTurnRestrictions = 0; for (RouteNode n: nodes.values()) { TurnRestriction turn = (TurnRestriction) parser.getTurnRestrictionHashMap().get(new Long(n.node.id)); while (turn != null) { Way restrictionFromWay = parser.getWayHashMap().get(new Long(turn.fromWayRef)); // skip if restrictionFromWay is not in available wayData if (restrictionFromWay == null) { System.out.println(" no fromWay"); turn = turn.nextTurnRestrictionAtThisNode; continue; } // skip if restrictionToWay is not in available wayData Way restrictionToWay = parser.getWayHashMap().get(new Long(turn.toWayRef)); if (restrictionToWay == null) { System.out.println(" no toWay"); turn = turn.nextTurnRestrictionAtThisNode; continue; } turn.viaRouteNode = n; turn.viaLat = n.node.lat; turn.viaLon = n.node.lon; turn.affectedTravelModes = TravelModes.applyTurnRestrictionsTravelModes; // search the from way for the RouteNode connected to the viaWay RouteNode nViaFrom = n; if (turn.isViaTypeWay()) { nViaFrom = turn.additionalViaRouteNodes[0]; } //System.out.println(turn.toString(parser.getWayHashMap())); int numFromConnections = 0; long lastId = -1; for (Connection c:nViaFrom.getConnectedFrom()) { // TODO: Strange: there are sometimes multiple connections connecting to the same node, filter those out by checking lastId /* [ sharenav-Bugs-3159017 ] Can't parse turn restriction * rather than only checking if the restrictionFromWay contains the from node * compare the travel length on the way between from node and via node * with the connection length to make more sure this is the right connection * with the via way * FIXME: we need to check for the right connection with this workaround * for not having to store the way in the connection, otherwise we could check for c.way == restrictionWay */ if (getDistOnWay(restrictionFromWay, nViaFrom.node, c.from.node) == c.length && c.from.id != lastId) { turn.fromRouteNode = c.from; numFromConnections++; lastId = c.from.id; } } if (numFromConnections != 1) { if (restrictionFromWay.isAccessForRoutingInAnyTurnRestrictionTravelMode()) { System.out.println("warning: ignoring map data: Can't parse turn restriction: " + numFromConnections + " from_connections matched for: " + turn.toString(parser.getWayHashMap())); if (numFromConnections == 0) { System.out.println("warning: ignoring map data: Reason may be: from/to swapped on oneways or a gap between viaNode and fromWay"); } else { System.out.println("warning: ignoring map data: Reason may be: fromWay not split at via member"); turn.fromRouteNode = null; // make the turn restriction incomplete so it won't get passed to ShareNav } for (Connection c:nViaFrom.getConnectedFrom()) { if (restrictionFromWay.containsNode(c.from.node)) { System.out.println(" FromNode: " + c.from.node.id); } } System.out.println("warning: ignoring map data: URL for via node: " + n.node.toUrl()); } } // search the RouteNode following the viaRouteNode on the toWay int numToConnections = 0; lastId = -1; for (Connection c:n.getConnected()) { /* FIXME: we do not store the way in the connection, otherwise we could check for c.way == restrictionWay */ if (getDistOnWay(restrictionToWay, n.node, c.to.node) == c.length && c.to.id != lastId) { // TODO: Strange: there are sometimes multiple connections connecting to the same node, filter those out by checking lastId turn.toRouteNode = c.to; numToConnections++; lastId = c.to.id; } } if (numToConnections != 1) { if (restrictionToWay.isAccessForRoutingInAnyTurnRestrictionTravelMode()) { System.out.println("warning: ignoring map data: Can't parse turn restriction: " + numToConnections + " to_connections matched for: " + turn.toString(parser.getWayHashMap())); if (numToConnections == 0) { System.out.println("warning: ignoring map data: Reason may be: from/to swapped on oneways or a gap between viaNode and toWay"); } else { System.out.println("warning: ignoring map data: Reason may be: toWay not split at via member"); turn.toRouteNode = null; // make the turn restriction incomplete so it won't get passed to ShareNav } for (Connection c:n.getConnected()) { if (restrictionToWay.containsNode(c.to.node)) { System.out.println("warning: ignoring map data: ToNode: " + c.to.node.id); } } System.out.println("warning: ignoring map data: URL for via node: " + n.node.toUrl()); } } if (numFromConnections == 1 && numToConnections == 1) { numTurnRestrictions++; } turn = turn.nextTurnRestrictionAtThisNode; } } if (config.verbose >= 0) { System.out.println("info: " + numTurnRestrictions + " turn restrictions valid"); } } /** * Resolve viaWays to route nodes */ private void resolveViaWays() { int numViaWaysResolved = 0; if (config.verbose >= 0) { System.out.println("info: Resolving " + parser.getTurnRestrictionsWithViaWays().size() + " viaWays for turn restrictions"); } for (TurnRestriction turn: parser.getTurnRestrictionsWithViaWays()) { Way restrictionFromWay = parser.getWayHashMap().get(new Long(turn.fromWayRef)); // skip if restrictionFromWay is not in available wayData if (restrictionFromWay == null) { continue; } // skip if restrictionToWay is not in available wayData Way restrictionToWay = parser.getWayHashMap().get(new Long(turn.toWayRef)); if (restrictionToWay == null) { continue; } // skip if restrictionViaWay is not in available wayData Way restrictionViaWay = parser.getWayHashMap().get(new Long(turn.viaWayRef)); if (restrictionViaWay == null) { continue; } ArrayList<RouteNode> viaWayRouteNodes = restrictionViaWay.getAllRouteNodesOnTheWay(); // if it's a circle way remove the first viaRouteNode if (viaWayRouteNodes.size()>0 && viaWayRouteNodes.get(0).id == viaWayRouteNodes.get(viaWayRouteNodes.size() -1 ).id) { viaWayRouteNodes.remove(0); } ArrayList<RouteNode> additionalViaRouteNodesCache = new ArrayList<RouteNode>(); int startEntry = 0; // find the index of the element crossing the fromWay (start entry) for (RouteNode n:viaWayRouteNodes) { if (restrictionFromWay.containsNode(n.node)) { // this is where viaWay and fromWay are connected additionalViaRouteNodesCache.add(n); // and becomes the first entry in the additionalViaRouteNode array if (config.verbose >= 0) { System.out.println("info: Resolved viaWay x fromWay to node " + n.node.id); } break; } startEntry++; } // find the index of the element crossing the toWay (the end entry) int endEntry = 0; RouteNode rn = null; // the direction to fill in the remaining viaRouteNodes into the array so the result is ordered with route nodes from the fromWay to the toWay exclusively int direction = 1; for (int i = startEntry; i < viaWayRouteNodes.size() * 2; i++) { // use index with modulo because of circle ways in roundabouts rn = viaWayRouteNodes.get(i % viaWayRouteNodes.size()); if (restrictionToWay.containsNode(rn.node)) { turn.viaRouteNode = rn; endEntry = i % viaWayRouteNodes.size(); if (i == endEntry || restrictionViaWay.isOneWay()) { direction = 1; } else { direction = -1; } if (config.verbose >= 0) { System.out.println("info: Resolved viaWay x toWay to node " + rn.node.id); } break; } else { } } // fill in routeNodes between start and end entry if (turn.viaRouteNode != null && additionalViaRouteNodesCache.size() != 0) { // fill in the remaining viaRouteNodes into the array so the result is ordered with route nodes from the fromWay to the toWay exclusively for (int i = startEntry + direction; i != startEntry && i % viaWayRouteNodes.size() != endEntry; i += direction) { // use index with modulo because of circle ways in roundabouts i %= viaWayRouteNodes.size(); // System.out.println(i + " " + startEntry + " " + endEntry + " dir " + direction ); rn = viaWayRouteNodes.get(i); additionalViaRouteNodesCache.add(rn); } // transfer the route nodes from the ArrayList to the additionalViaRouteNodes array turn.additionalViaRouteNodes = new RouteNode[additionalViaRouteNodesCache.size()]; for (int i=0; i < turn.additionalViaRouteNodes.length; i++) { turn.additionalViaRouteNodes[i] = additionalViaRouteNodesCache.get(i); } if (config.verbose >= 0) { System.out.println("info: viaRouteNodes on viaWay " + restrictionViaWay.toUrl() + ":"); } if (config.verbose >= 0) { for (RouteNode n:turn.additionalViaRouteNodes) { if (n != null && n.node != null) { System.out.println("info: " + n.node.toUrl()); } else { if (n == null) { System.out.println("info: n is null"); } else { System.out.println("info: n.node is null"); } continue; } } System.out.println("info: " + turn.viaRouteNode.node.toUrl()); } // add the resolved viaWay turn restriction to its viaRouteNode parser.addTurnRestriction(new Long(turn.viaRouteNode.node.id), turn); numViaWaysResolved++; } else { System.out.println(" WARNING: Could not resolve viaRouteNodes"); System.out.println(" for viaWay " + restrictionViaWay.toUrl()); if ( turn.additionalViaRouteNodes == null) { System.out.println(" viaWay " + restrictionFromWay.toUrl() + " does not end at start of toWay"); } else if (turn.additionalViaRouteNodes[0] == null) { System.out.println(" fromWay " + restrictionFromWay.toUrl() + " is not connected"); } if (turn.viaRouteNode == null) { System.out.println(" toWay " + restrictionToWay.toUrl() + " is not connected"); } } } if (config.verbose >= 0) { System.out.println(" " + numViaWaysResolved + " viaWays resolved"); } parser.getTurnRestrictionsWithViaWays().clear(); } /** * @param w * @param n1 - a node on the way * @param n2 - another node on the way * @return distance for travelling from n1 to n2 on w or -1 if no match */ private int getDistOnWay(Way w, Node n1, Node n2) { boolean startNodeFound = false; Node lastNode = null; int dist = 0; for (Node n:w.getNodes()) { if (startNodeFound) { dist += MyMath.dist(lastNode, n); if (n.id == n1.id || n.id == n2.id) { return dist; } } if (n.id == n1.id || n.id == n2.id) { // start measuring distance startNodeFound = true; } lastNode = n; } return -1; } /** * @param nl */ // TODO: explain private void addConnections(List<Node> nl, Way w) { RouteNode from = null; int lastIndex = nl.size(); Node lastNode = null; int thisIndex = 0; int dist = 0; int count = 0; byte bearing = 0; for (Node n:nl) { thisIndex++; if (from == null) { lastNode = n; from = getRouteNode(n); count++; dist = 0; } else { dist += MyMath.dist(lastNode, n); count++; if (count == 2) { bearing = MyMath.bearing_start(lastNode, n); } if (thisIndex == lastIndex || (n.getConnectedLineCount() != 2)) { RouteNode next = getRouteNode(n); byte endBearing = MyMath.bearing_start(lastNode, n); addConnection(from, next, dist, w, bearing, endBearing); from = next; dist = 0; count = 1; } lastNode = n; } } nl = new ArrayList<Node>(); } /** * @param l */ private RouteNode getRouteNode(Node n) { RouteNode routeNode; if (! nodes.containsKey(n.id)) { routeNode = new RouteNode(n); n.routeNode = routeNode; } else { routeNode = nodes.get(n.id); } return routeNode; } /** * @param from * @param f * @param dist * @param routeNode */ private void addConnection(RouteNode from, RouteNode to, int dist, Way w, byte bs, byte be) { /** travel modes with no barrier detected */ int noBarrierTravelModes = 0xFFFFFFFF; byte againstDirectionTravelModes = 0; // create an array of routing times with an entry for each travel mode int times[] = new int[TravelModes.travelModeCount]; for (int i = 0; i < TravelModes.travelModeCount; i++) { if (w.isAccessForRouting(i)) { /* * Removing route connections because of barriers is disabled for now. * It requires a solution first for too many POIs becoming unreachable * because of barriers before the destination way */ // check for barriers in non-area ways if (config.useBarriers && !w.isArea()) { int a = 0; boolean fromNodeFound = false; boolean toNodeFound = false; for (Iterator<Node> si = w.path.iterator(); si.hasNext();) { Node t = si.next(); if (from.node.id == t.id /* && a != 0 && si.hasNext() */) { fromNodeFound = true; } if (to.node.id == t.id /* && a != 0 && si.hasNext() */) { toNodeFound = true; } if ( ( (fromNodeFound && !toNodeFound) || (toNodeFound && !fromNodeFound) ) && t.isBarrier() ) { if (t.isAccessPermittedOrForbiddenFor(i) <= 0) { // if (noBarrierTravelModes == 0xFFFFFFFF) { // System.out.println("Barrier found on " + w.toString() + " at \n" + t.toUrl()); // } // System.out.println(" affects route mode " + i); noBarrierTravelModes &= ~(1 << i); break; } } a++; } } TravelMode tm = TravelModes.getTravelMode(i); if (w.isExplicitArea()) { tm.numAreaCrossConnections++; } tm.numOneWayConnections++; float speed = w.getRoutingSpeed(i); float time = dist * 10.0f / speed; times[i] = (int)time; boolean bicycleOppositeDirection = (tm.travelModeFlags & TravelMode.BICYLE_OPPOSITE_EXCEPTIONS) > 0 && w.isOppositeDirectionForBicycleAllowed(); // you can go against the direction of the way if it's not a oneway or an against direction rule applies if ( !w.isRoundabout() // FIXME: workaround to never route against direction in roundabouts, not even walk because we have no routing instruction for this && ( ! w.isOneWay() || (tm.travelModeFlags & TravelMode.AGAINST_ALL_ONEWAYS) > 0 || bicycleOppositeDirection ) ) { againstDirectionTravelModes |= (1<<i); if (bicycleOppositeDirection) { tm.numBicycleOppositeConnections++; } } } else { times[i] = 0; } } boolean allBarriered = true; for (int i = 0; i < TravelModes.travelModeCount; i++) { if ( (noBarrierTravelModes & (1<<i)) > 0) { allBarriered = false; } } if (allBarriered) { // System.out.println("Connection barriered for all route modes"); // avoid to create a connection that cannot be travelled in any route mode return; } nodes.put(from.node.id, from); nodes.put(to.node.id, to); Connection c = new Connection(to, dist, times, bs, be, w); c.connTravelModes &= noBarrierTravelModes; // disable connection for travelmodes that are barriered from.addConnected(c); to.addConnectedFrom(c); // roundabouts don't need to be explicitly tagged as oneways in OSM according to http://wiki.openstreetmap.org/wiki/Tag:junction%3Droundabout if (againstDirectionTravelModes != 0 ) { // add connection in the other direction as well, if this is no oneWay // TODO: explain Doesn't this add duplicates when addconnection() is called later on with from and to exchanged or does this not happen? Connection cr = new Connection(from, dist, times, MyMath.inverseBearing(be), MyMath.inverseBearing(bs), w); cr.from = to; to.addConnected(cr); from.addConnectedFrom(cr); // flag connections useable for travel modes you can go against the ways direction cr.connTravelModes = againstDirectionTravelModes; cr.connTravelModes &= noBarrierTravelModes; // disable connection for travelmodes that are barriered cr.connTravelModes |= w.wayTravelModes & (Connection.CONNTYPE_MAINSTREET_NET | Connection.CONNTYPE_MOTORWAY | Connection.CONNTYPE_TRUNK_OR_PRIMARY); for (int i=0; i < TravelModes.travelModeCount; i++) { if ( (againstDirectionTravelModes & (1<<i)) != 0 ) { TravelMode tm = TravelModes.getTravelMode(i); tm.numDualConnections++; tm.numOneWayConnections--; } } } // need only for debugging not for live c.from = from; } @Deprecated public boolean isRelevant(Node n) { int count = 0; // for (Line l:parser.lines.values()) { // if (n.id == l.from.id) { // count++; // } // if (n.id == l.to.id) { // count++; // } // } if (count == 2) { return false; } else { return true; } } private void createIds() { int id = 1; for (RouteNode n: nodes.values()) { n.id = id++; } } public void optimise() { // System.out.println("Optimizing route data"); // System.out.println("RouteNodes for optimise " + nodes.size()); // ArrayList<RouteNode> removeNodes = new ArrayList<RouteNode>(); // for (RouteNode n:nodes.values()) { // // find nodes that are only a point between to nodes without // // any junction. This test does not cover one ways // // for normal ways the second connection will removed // if (n.connected.size() == 2 && n.connectedFrom.size() == 2) { // Connection c1 = n.connected.get(0); // RouteNode n1 = c1.to; // Connection c2 = null; // Connection c3 = n.connected.get(1); // RouteNode n2 = c3.to; // Connection c4 = null; // for (Connection ct:n.connectedFrom) { // if (ct.from == n2 ) { // c2 = ct; // } // if (ct.from == n1) { // c4 = ct; // } // } // if (c2 != null && c4 != null) { // if (c2.to != n) { // System.out.println("c2.to != n"); // } // if (c4.to != n) { // System.out.println("c4.to != n"); // } // if (c1.to != c4.from) { // System.out.println("c1.to != c4.from"); // } // if (c2.from != c3.to) { // System.out.println("c2.from != c3.to"); // } // c2.endBearing = c1.endBearing; // c2.time += c1.time; // c2.length += c1.length; // c2.to = c1.to; // c3.from = c1.to; // c3.startBearing = MyMath.inversBearing(c1.endBearing); // c3.time += c1.time; // c3.length += c1.length; // n1.connectedFrom.remove(c1); // n1.connected.remove(c4); // n1.connectedFrom.add(c2); // n1.connected.add(c3); // connections.remove(c1); // connections.remove(c4); // removeNodes.add(n); // } // // } // // for one ways // if (n.connected.size() == 1 && n.connectedFrom.size() == 1) { // Connection c1 = n.connected.get(0); // RouteNode n1 = c1.to; // Connection c2 = n.connectedFrom.get(0); // RouteNode n2 = c2.from; // if (n2 != n1) { // c2.endBearing = c1.endBearing; // c2.time += c1.time; // c2.length += c1.length; // c2.to = c1.to; // n1.connectedFrom.remove(c1); // n1.connectedFrom.add(c2); // n.connected.remove(c1); // n.connectedFrom.remove(c2); // connections.remove(c1); // removeNodes.add(n); // // } // } // } // System.out.println("Removed " + removeNodes.size() + " RouteNodes due to optimization"); // for (RouteNode n:removeNodes) { // n.node.routeNode = null; // nodes.remove(n.node.id); // } } /** * normaly not used, only for test * @param args */ public static void main(String[] args) { try { Configuration conf = new Configuration(args); FileInputStream fr = new FileInputStream("/Massenspeicher/myStreetMap0.5.osm"); // FileInputStream fr = new FileInputStream("/Massenspeicher/planet-070725.osm"); OxParser parser = new OxParser(fr, conf); System.out.println("Read nodes " + parser.getNodes().size()); System.out.println("Read ways " + parser.getNodes().size()); new CleanUpData(parser, conf); RouteData rd = new RouteData(parser, ""); rd.create(conf); int rid = 10000; // for (RouteNode r:rd.nodes.values()) { // r.node.renumberdId=rid++; // } rid = 1; rd.optimise(); for (RouteNode r:rd.nodes.values()) { r.node.renumberdId = rid++; } // rd.write("/Temp"); System.out.println("RelNodes contain " + rd.nodes.size()); //System.out.println("Connections contain " + rd.connections.size()); RouteNode start = rd.nodes.get(new Long(1955808)); System.out.println("Start " + start); // RouteNode dest = rd.nodes.get(new Long(25844378)); // RouteNode dest = rd.nodes.get(new Long(33141402)); // RouteNode dest = rd.nodes.get(new Long(28380647)); // System.out.println("Destination " + dest); // AStar2 astar = new AStar2(); // Vector<Connection> solve = astar.solve(start, dest); // System.out.println("\n\nSolution:"); PrintWriter fo = new PrintWriter("/Massenspeicher/routetestErg.osm"); // exportResultOSM(fo, rd, solve); fo = new PrintWriter("/Massenspeicher/routetestConnections.osm"); exportResultOSM(fo, rd, null); } catch (FileNotFoundException e) { e.printStackTrace(); } } /** * @param fo * @param rd * @param solve */ private static void exportResultOSM(PrintWriter fo, RouteData rd, Vector<Connection> solve) { fo.write("<?xml version='1.0' encoding='UTF-8'?>\n"); fo.write("<osm version='0.5' generator='JOSM'>\n"); for (RouteNode r:rd.nodes.values()) { fo.write("<node id='" + r.node.renumberdId); fo.write("' timestamp='2007-02-15 10:32:17' visible='true' lat='" + r.node.lat); fo.write("' lon='" + r.node.lon + "'>\n"); fo.write(" <tag k='connectCount' v='" + r.node.getConnectedLineCount() + "'/>\n"); fo.write(" <tag k='connectTo' v='"); for (Connection c:r.getConnected()) { fo.write("," + c.to.node.renumberdId); } fo.write("'/>\n"); fo.write(" <tag k='connectFrom' v='"); for (Connection c:r.getConnectedFrom()) { fo.write("," + c.from.node.renumberdId); } fo.write("'/>\n"); fo.write("</node>\n"); } int id = 1; for (RouteNode r:rd.nodes.values()) { for (Connection c:r.getConnected()) { fo.write("<way id='" + id++ + "' timestamp='2007-02-14 23:41:43' visible='true' >\n"); fo.write(" <nd ref='" + c.from.node.renumberdId + "'/>\n"); fo.write(" <nd ref='" + c.to.node.renumberdId + "'/>\n"); fo.write(" <tag k='name' v='laenge=" + c.length + "' />\n"); System.out.println("RouteData.exportResultOSM(): only first route mode"); fo.write(" <tag k='time' v='" + c.times[0] + "' />\n"); fo.write(" <tag k='bs' v='" + c.startBearing * 2 + "' />\n"); fo.write(" <tag k='be' v='" + c.endBearing * 2 + "' />\n"); fo.write("</way>\n"); } } // RouteNode last = null; // Connection lastCon = null; // int lb = 0; // if (solve != null) { // for (Connection c:solve) { // if (last == null) { // last = c.to; // lastCon = c; // lb = c.endBearing; // } else { // System.out.println(c.printTurn(lastCon)); // fo.write("<segment id='" + id++ + "' timestamp='2007-02-14 23:41:43' visible='true' from='" + // last.node.renumberdId // + "' to='" // + c.to.node.renumberdId // + "'>\n"); // fo.write(" <tag k='length' v='" + c.length + "' />\n"); // fo.write(" <tag k='time' v='" + c.time + "' />\n"); // fo.write(" <tag k='bs' v='" + c.startBearing * 2 + "' />\n"); // fo.write(" <tag k='be' v='" + c.endBearing * 2 + "' />\n"); // fo.write("</segment>\n"); // last = c.to; // lastCon = c; // } // } // } fo.write("</osm>"); fo.close(); } /** * @param zl * @param fid * @param nodes2 * @throws FileNotFoundException */ public void write(int zl, int fid, Collection<Node> nodes2) throws FileNotFoundException { FileOutputStream fo = FileTools.createFileOutputStream(path + "/t" + zl +"/"+ fid + ".d"); DataOutputStream tds = new DataOutputStream(fo); for (Node n: nodes2) { if (nodes.containsKey(n.id)) { RouteNode rn = nodes.get(n.id); } } } // /** // * deprecated but still used by routeTiles // * @param canonicalPath // * @throws IOException // */ // @Deprecated // public void write(String canonicalPath) throws IOException { // DataOutputStream nodeStream = new DataOutputStream(new FileOutputStream(canonicalPath + "/rn.d")); // File f = new File(canonicalPath + "/rc"); // f.mkdir(); //// DataOutputStream connStream = new DataOutputStream(new FileOutputStream(canonicalPath + "/rc.d")); // int[] connectionIndex = new int[nodes.size()]; // int i = 0; // for (RouteNode rde : nodes.values()) { // rde.node.renumberdId = i++; // rde.id = rde.node.renumberdId; // } // i = 0; // nodeStream.writeInt(nodes.size()); // for (RouteNode rde : nodes.values()) { // connectionIndex[i++] = nodeStream.size(); // nodeStream.writeFloat(MyMath.degToRad(rde.node.lat)); // nodeStream.writeFloat(MyMath.degToRad(rde.node.lon)); // nodeStream.writeInt(rde.node.renumberdId); // System.out.println("id=" + rde.node.renumberdId); // nodeStream.writeByte(rde.connected.size()); // DataOutputStream connStream = new DataOutputStream(new FileOutputStream(canonicalPath + "/" + rde.node.renumberdId + ".d")); // for (Connection c : rde.connected) { // connStream.writeInt(c.to.node.renumberdId); // System.out.println("RouteData.write(): only first route mode"); // connStream.writeShort((int) c.times[0]); // only first route mode // connStream.writeShort((int) c.length); // connStream.writeByte(c.startBearing); // connStream.writeByte(c.endBearing); // } // connStream.close(); // } //// System.out.println("size " + ro.size()); // nodeStream.close(); // DataOutputStream indexStream = new DataOutputStream(new FileOutputStream(canonicalPath + "/rd.idx")); // for (int il : connectionIndex) { // indexStream.write(il); // } // indexStream.close(); // } /** Remember traffic signals nodes in own array so they can be removed by CleanupData * (traffic signals nodes must not be marked as used because otherwise they are written to the bundle/map) */ public void rememberDelayingNodes() { Node[] delayingNodes = new Node[parser.trafficSignalCount]; int i = 0; for (Node n:parser.getNodes()) { if (n.isTrafficSignals()) { delayingNodes[i++] = n; } } parser.setDelayingNodes(delayingNodes); } }