/** * 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 Harald Mueller * Copyright (C) 2010 Kai Krueger */ package net.sharenav.osmToShareNav; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Vector; import net.sharenav.osmToShareNav.model.Bounds; import net.sharenav.osmToShareNav.model.Hash; import net.sharenav.osmToShareNav.model.Node; import net.sharenav.osmToShareNav.model.Relation; import net.sharenav.osmToShareNav.model.Storage; import net.sharenav.osmToShareNav.model.TurnRestriction; import net.sharenav.osmToShareNav.model.Way; import net.sharenav.osmToShareNav.Configuration; import java.text.DecimalFormat; import java.util.Map; public abstract class OsmParser { private static class NodeHash implements Hash<Node, Node> { @Override public int getHashCode(Node k) { return (int) k.id; } @Override public boolean equals(Node k, Node t) { return k.id == t.id; } } private static class Id2EntityHash implements Hash<Long, Node> { @Override public int getHashCode(Long k) { return (int)k.longValue(); } @Override public boolean equals(Long k, Node t) { return t.id == k.longValue(); } } /** * Maps id to already read nodes. Key: Long Value: Node */ //protected HashMap<Long, Node> nodes = new HashMap<Long, Node>(80000, 0.60f); private Storage<Node> nodesStorage = new Storage<Node>(new NodeHash()); protected Map<Long, Node> nodes = nodesStorage.foreignKey(new Id2EntityHash()); protected Vector<Node> nodes2 = null; protected HashMap<Long, Way> ways = new HashMap<Long, Way>(); protected HashMap<Long, Relation> relations = new HashMap<Long, Relation>(); protected HashMap<Long, TurnRestriction> turnRestrictions = new HashMap<Long, TurnRestriction>(); protected ArrayList<TurnRestriction> turnRestrictionsWithViaWays = new ArrayList<TurnRestriction>(); private Node[] delayingNodes; public int trafficSignalCount = 0; private Vector<Bounds> bounds = null; public Configuration configuration; protected int wayIns; /** * @param i * InputStream from which planet file is read */ public OsmParser(InputStream i) { System.out.println(parserType() + " parser started..."); configuration = new Configuration(); init(i); } /** * @param i * InputStream from which planet file is read * @param c * Configuration which supplies the bounds */ public OsmParser(InputStream i, Configuration c) { this.configuration = c; this.bounds = c.getBounds(); if (c.verbose >= 0) { System.out.println(parserType() + " parser with bounds started..."); } init(i); } protected abstract String parserType(); protected abstract void init(InputStream i); protected boolean nodeInArea(float lat, float lon) { boolean inBound = false; if (configuration.getArea() != null && configuration.getArea().contains(lat, lon)) { inBound = true; } if (bounds != null && bounds.size() != 0) { for (Bounds b : bounds) { if (b.isIn(lat, lon)) { inBound = true; break; } } } if ((bounds == null || bounds.size() == 0) && configuration.getArea() == null) { inBound = true; } return inBound; } /** * @param viaNodeOrWayRef * @param turnRestriction */ public void addTurnRestriction(long viaNodeOrWayRef, TurnRestriction turnRestriction) { if (!turnRestrictions.containsKey(new Long(viaNodeOrWayRef))) { turnRestrictions.put(new Long(viaNodeOrWayRef), turnRestriction); // System.out.println("Put turn restrictions at " + // viaNodeOrWayRef); } else { TurnRestriction baseTurnRestriction = (TurnRestriction) turnRestrictions .get(new Long(viaNodeOrWayRef)); while (baseTurnRestriction.nextTurnRestrictionAtThisNode != null) { baseTurnRestriction = baseTurnRestriction.nextTurnRestrictionAtThisNode; } baseTurnRestriction.nextTurnRestrictionAtThisNode = turnRestriction; // System.out.println("Multiple turn restrictions at " + // viaNodeOrWayRef); } } /** * @param w */ public void addWay(Way w) { // polish.api.bigstyles // If oneway=-1, reverse the way if (w.isOneWayMinusOne()) { //System.out.println("Reversing a oneway=-1 way, orig: " + w); Way tmp_w = new Way(w, true); w = tmp_w; w.setAttribute("oneway","yes"); //System.out.println("Reversed a oneway=-1 way, result: " + w); } short t = w.getType(configuration); /** * We seem to have a bit of a mess with respect to type -1 and 0. Both * are used to indicate invalid type it seems. */ if (w.isValid() /* && t > 0 */) { w.trimPath(); w.determineWayRouteModes(); if (w.isAccessForAnyRouting()) { LegendParser.tileScaleLevelContainsRoutableWays[w.getZoomlevel(configuration)] = true; } if (ways.get(w.id) != null) { /** * This way is already in data storage. This results from * splitting a single osm way into severals ShareNav ways. We can * simply invent an id in this case, as we currently don't use * them for anything other than checking if an id is valid for * use in relations */ ways.put(new Long(-1 * wayIns), w); } else { ways.put(w.id, w); } wayIns++; } } /** * @param r */ public void addRelation(Relation r) { relations.put(r.id, r); } /** * @param w */ public void addNode(Node n) { // polish.api.bigstyles short t = n.getType(configuration); /** * We seem to have a bit of a mess with respect to type -1 and 0. Both * are used to indicate invalid type it seems. */ if (true /* n.isValid() * && t > 0 */) { //w.determineWayRouteModes(); if (nodes.get(n.id) != null) { System.out.println ("Error: couldn't store node, already there, id: " + n.id); } else { nodes.put(n.id, n); } } } public void removeWay(Way w) { ways.remove(w.id); } public Collection<Node> getNodes() { if (nodes == null) { return nodes2; } else { return nodes.values(); } } /** * WARNING: This function may return null, after dropHashMap has been called * @return */ public Map<Long,Node> getNodeHashMap() { return nodes; } public Collection<Way> getWays() { return ways.values(); } public Collection<Relation> getRelations() { return relations.values(); } public HashMap<Long, TurnRestriction> getTurnRestrictionHashMap() { return turnRestrictions; } public Node[] getDelayingNodes() { return delayingNodes; } public void freeUpDelayingNodes() { delayingNodes = null; } public void setDelayingNodes(Node[] nodes) { delayingNodes = nodes; } public ArrayList<TurnRestriction> getTurnRestrictionsWithViaWays() { return turnRestrictionsWithViaWays; } public HashMap<Long, Way> getWayHashMap() { return ways; } public void removeNodes(Collection<Node> nds) { if (nodes == null) { // This operation appears rather slow, // so try and avoid calling remove nodes once it is in the nodes2 // format nodes2.removeAll(nds); } else { for (Node n : nds) { nodes.remove(new Long(n.id)); } } } /** * */ public void resize() { //System.gc(); //System.out.println("Free memory: " + Runtime.getRuntime().freeMemory()); if (configuration.verbose >= 0) { System.out.println("Resizing nodes HashMap"); } if (nodes == null) { nodes2 = new Vector<Node>(nodes2); } else { //nodes = new HashMap<Long, Node>(nodes); nodesStorage.shrink(0.85f); } relations = new HashMap<Long, Relation>(relations); //System.gc(); //System.out.println("Free memory: " + Runtime.getRuntime().freeMemory()); printMemoryUsage(1); } public void dropHashMap() { nodes2 = new Vector<Node>(nodes.values()); nodes = null; } /** * Print memory usage. * * @param numberOfGarbageLoops * Number of times to call the garbage colector and print the * memory usage again. */ public static void printMemoryUsage(int numberOfGarbageLoops) { DecimalFormat df = new DecimalFormat (",###"); if (Configuration.getConfiguration().verbose >= 0) { System.out.print("---> Used memory: " + df.format((Runtime.getRuntime().totalMemory() - Runtime.getRuntime() .freeMemory()) / 1024) + " KB / " + df.format(Runtime.getRuntime().maxMemory() / 1024) + " KB"); } for (int i = 0; i < numberOfGarbageLoops; i++) { System.gc(); if (Configuration.getConfiguration().verbose >= 0) { System.out.print(" --> gc: " + df.format((Runtime.getRuntime().totalMemory() - Runtime .getRuntime().freeMemory()) / 1024) + " KB"); } try { if (i + 1 < numberOfGarbageLoops) { Thread.sleep(100); } } catch (InterruptedException ex) { } } System.out.println(""); } }