/** * This program * - reads an *.osm from stdin * - writes 45*30 degree node tiles + a way file + a rel file * * @author ab */ package btools.mapcreator; import java.io.BufferedOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Map; import btools.expressions.BExpressionContextNode; import btools.expressions.BExpressionContextWay; import btools.expressions.BExpressionMetaData; public class OsmCutter extends MapCreatorBase { private long recordCnt; private long nodesParsed; private long waysParsed; private long relsParsed; private long changesetsParsed; private DataOutputStream wayDos; private DataOutputStream cyclewayDos; private DataOutputStream restrictionsDos; public WayCutter wayCutter; public RestrictionCutter restrictionCutter; public NodeFilter nodeFilter; private DatabasePseudoTagProvider dbPseudoTagProvider; public static void main(String[] args) throws Exception { System.out.println("*** OsmCutter: cut an osm map in node-tiles + a way file"); if (args.length != 6 && args.length != 7) { System.out.println("usage: bzip2 -dc | java OsmCutter "); System.out.println("or : java OsmCutter "); return; } new OsmCutter().process( new File(args[0]) , new File(args[1]) , new File(args[2]) , new File(args[3]) , new File(args[4]) , new File(args[5]) , args.length > 6 ? new File(args[6]) : null ); } private BExpressionContextWay _expctxWay; private BExpressionContextNode _expctxNode; public void process(File lookupFile, File outTileDir, File wayFile, File relFile, File resFile, File profileFile, File mapFile) throws Exception { if (!lookupFile.exists()) { throw new IllegalArgumentException("lookup-file: " + lookupFile + " does not exist"); } BExpressionMetaData meta = new BExpressionMetaData(); _expctxWay = new BExpressionContextWay(meta); _expctxNode = new BExpressionContextNode(meta); meta.readMetaData(lookupFile); _expctxWay.parseFile(profileFile, "global"); this.outTileDir = outTileDir; if (!outTileDir.isDirectory()) throw new RuntimeException("out tile directory " + outTileDir + " does not exist"); wayDos = wayFile == null ? null : new DataOutputStream(new BufferedOutputStream(new FileOutputStream(wayFile))); cyclewayDos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(relFile))); if (resFile != null) { restrictionsDos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(resFile))); } // read the osm map into memory long t0 = System.currentTimeMillis(); new OsmParser().readMap(mapFile, this, this, this); long t1 = System.currentTimeMillis(); System.out.println("parsing time (ms) =" + (t1 - t0)); // close all files closeTileOutStreams(); if (wayDos != null) { wayDos.close(); } cyclewayDos.close(); if (restrictionsDos != null) { restrictionsDos.close(); } // System.out.println( "-------- way-statistics -------- " ); // _expctxWayStat.dumpStatistics(); // System.out.println( "-------- node-statistics -------- " ); // _expctxNodeStat.dumpStatistics(); System.out.println(statsLine()); } private void checkStats() { if ((++recordCnt % 100000) == 0) System.out.println(statsLine()); } private String statsLine() { return "records read: " + recordCnt + " nodes=" + nodesParsed + " ways=" + waysParsed + " rels=" + relsParsed + " changesets=" + changesetsParsed; } public void setJdbcUrl(String url) { dbPseudoTagProvider = new DatabasePseudoTagProvider(url); } @Override public void nextNode(NodeData n) throws Exception { nodesParsed++; checkStats(); if (n.getTagsOrNull() != null) { int[] lookupData = _expctxNode.createNewLookupData(); for (Map.Entry e : n.getTagsOrNull().entrySet()) { _expctxNode.addLookupValue(e.getKey(), e.getValue(), lookupData); // _expctxNodeStat.addLookupValue( key, value, null ); } n.description = _expctxNode.encode(lookupData); } // write node to file int tileIndex = getTileIndex(n.ilon, n.ilat); if (tileIndex >= 0) { n.writeTo(getOutStreamForTile(tileIndex)); if (wayCutter != null) { wayCutter.nextNode(n); } } } private void generatePseudoTags(Map map) { // add pseudo.tags for concrete:lanes and concrete:plates String concrete = null; for (Map.Entry e : map.entrySet()) { String key = e.getKey(); if ("concrete".equals(key)) { return; } if ("surface".equals(key)) { String value = e.getValue(); if (value.startsWith("concrete:")) { concrete = value.substring("concrete:".length()); } } } if (concrete != null) { map.put("concrete", concrete); } } @Override public void nextWay(WayData w) throws Exception { waysParsed++; checkStats(); // encode tags if (w.getTagsOrNull() == null) return; int[] lookupData = _expctxWay.createNewLookupData(); for (String key : w.getTagsOrNull().keySet()) { String value = w.getTag(key); _expctxWay.addLookupValue(key, value.replace(' ', '_'), lookupData); } w.description = _expctxWay.encode(lookupData); if (w.description == null) return; // filter according to profile _expctxWay.evaluate(false, w.description); boolean ok = _expctxWay.getCostfactor() < 10000.; _expctxWay.evaluate(true, w.description); ok |= _expctxWay.getCostfactor() < 10000.; if (!ok) return; if (dbPseudoTagProvider != null) { dbPseudoTagProvider.addTags(w.wid, w.getTagsOrNull()); } generatePseudoTags(w.getTagsOrNull()); if (wayDos != null) { w.writeTo(wayDos); } if (wayCutter != null) { wayCutter.nextWay(w); } if (nodeFilter != null) { nodeFilter.nextWay(w); } } @Override public void nextRelation(RelationData r) throws IOException { relsParsed++; checkStats(); String route = r.getTag("route"); // filter out non-cycle relations if (route == null) { return; } String network = r.getTag("network"); if (network == null) network = ""; String state = r.getTag("state"); if (state == null) state = ""; writeId(cyclewayDos, r.rid); cyclewayDos.writeUTF(route); cyclewayDos.writeUTF(network); cyclewayDos.writeUTF(state); for (int i = 0; i < r.ways.size(); i++) { long wid = r.ways.get(i); writeId(cyclewayDos, wid); } writeId(cyclewayDos, -1); } @Override public void nextRestriction(RelationData r, long fromWid, long toWid, long viaNid) throws Exception { String type = r.getTag("type"); if (type == null || !"restriction".equals(type)) { return; } short exceptions = 0; String except = r.getTag("except"); if (except != null) { exceptions |= toBit("bicycle", 0, except); exceptions |= toBit("motorcar", 1, except); exceptions |= toBit("agricultural", 2, except); exceptions |= toBit("forestry", 2, except); exceptions |= toBit("psv", 3, except); exceptions |= toBit("hgv", 4, except); } for (String restrictionKey : r.getTagsOrNull().keySet()) { if (!(restrictionKey.equals("restriction") || restrictionKey.startsWith("restriction:"))) { continue; } String restriction = r.getTag(restrictionKey); RestrictionData res = new RestrictionData(); res.restrictionKey = restrictionKey; res.restriction = restriction; res.exceptions = exceptions; res.fromWid = fromWid; res.toWid = toWid; res.viaNid = viaNid; if (restrictionsDos != null) { res.writeTo(restrictionsDos); } if (restrictionCutter != null) { restrictionCutter.nextRestriction(res); } } } private static short toBit(String tag, int bitpos, String s) { return (short) (s.indexOf(tag) < 0 ? 0 : 1 << bitpos); } private int getTileIndex(int ilon, int ilat) { int lon = ilon / 45000000; int lat = ilat / 30000000; if (lon < 0 || lon > 7 || lat < 0 || lat > 5) { System.out.println("warning: ignoring illegal pos: " + ilon + "," + ilat); return -1; } return lon * 6 + lat; } protected String getNameForTile(int tileIndex) { int lon = (tileIndex / 6) * 45 - 180; int lat = (tileIndex % 6) * 30 - 90; String slon = lon < 0 ? "W" + (-lon) : "E" + lon; String slat = lat < 0 ? "S" + (-lat) : "N" + lat; return slon + "_" + slat + ".ntl"; } }