From 7b1a43647cd05ff88b6f9721c0da9e2efad55689 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Thu, 7 Jun 2012 23:32:25 +0200 Subject: [PATCH] Route index reader --- .../binary/BinaryMapRouteReaderAdapter.java | 221 +++++++++++++++++- .../preparation/BinaryMapIndexWriter.java | 2 +- .../data/preparation/IndexRouteCreator.java | 8 - 3 files changed, 221 insertions(+), 10 deletions(-) diff --git a/DataExtractionOSM/src/net/osmand/binary/BinaryMapRouteReaderAdapter.java b/DataExtractionOSM/src/net/osmand/binary/BinaryMapRouteReaderAdapter.java index 1c65ef583c..1c248135bf 100644 --- a/DataExtractionOSM/src/net/osmand/binary/BinaryMapRouteReaderAdapter.java +++ b/DataExtractionOSM/src/net/osmand/binary/BinaryMapRouteReaderAdapter.java @@ -1,8 +1,12 @@ package net.osmand.binary; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import net.osmand.LogUtil; +import net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox; +import net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule; import org.apache.commons.logging.Log; @@ -12,13 +16,86 @@ import com.google.protobuf.WireFormat; public class BinaryMapRouteReaderAdapter { private static final Log LOG = LogUtil.getLog(BinaryMapRouteReaderAdapter.class); + public static class RouteTypeRule { + private final static int ACCESS = 1; + private final static int ONEWAY = 2; + private final static int HIGHWAY_TYPE = 3; + private final static int MAXSPEED = 4; + private final String t; + private final String v; + private int intValue; + private float floatValue; + private int type; + + public RouteTypeRule(String t, String v) { + this.t = t.intern(); + this.v = v == null? null : v.intern(); + analyze(); + } + + public int onewayDirection(){ + if(type == ONEWAY){ + return intValue; + } + return 0; + } + + public float maxSpeed(){ + if(type == MAXSPEED){ + return floatValue; + } + return -1; + } + + public String highwayRoad(){ + if(type == HIGHWAY_TYPE){ + return v; + } + return null; + } + + private void analyze() { + if(t.equalsIgnoreCase("oneway")){ + type = ONEWAY; + if("-1".equals(v)) { + intValue = -1; + } else if("1".equals(v) || "yes".equals(v)) { + intValue = 1; + } + intValue = 0; + } else if(t.equalsIgnoreCase("highway") && v != null){ + type = HIGHWAY_TYPE; + } else if(t.startsWith("access") && v != null){ + type = ACCESS; + } else if(t.equalsIgnoreCase("maxspeed") && v != null){ + floatValue = -1; + int i = 0; + while(i < v.length() && Character.isDigit(v.charAt(i))) { + i++; + } + if(i > 0) { + floatValue = Integer.parseInt(v.substring(0, i)); + floatValue *= 3.6; // km/h -> m/s + if(v.contains("mph")) { + floatValue *= 1.6; + } + } + + } + + } + } + public static class RouteRegion extends BinaryIndexPart { - double leftLongitude; double rightLongitude; double topLatitude; double bottomLatitude; + int regionsRead; + + List subregions = new ArrayList(); + List routeEncodingRules = new ArrayList(); public double getLeftLongitude() { return leftLongitude; @@ -35,6 +112,56 @@ public class BinaryMapRouteReaderAdapter { public double getBottomLatitude() { return bottomLatitude; } + + public RouteTypeRule quickGetEncodingRule(int id) { + return routeEncodingRules.get(id); + } + + public void initRouteEncodingRule(int id, String tags, String val) { + while(routeEncodingRules.size() <= id) { + routeEncodingRules.add(null); + } + routeEncodingRules.set(id, new RouteTypeRule(tags, val)); + } + + public List getSubregions(){ + return subregions; + } + } + + public static class RouteSubregion { + private final static int INT_SIZE = 4; + public final RouteRegion routeReg; + public RouteSubregion(RouteRegion routeReg) { + this.routeReg = routeReg; + } + public RouteSubregion(RouteSubregion parentReg) { + this.routeReg = parentReg.routeReg; + this.left = parentReg.left; + this.right = parentReg.right; + this.top = parentReg.top; + this.bottom = parentReg.bottom; + + } + public int length; + public int filePointer; + public int left; + public int right; + public int top; + public int bottom; + public int shiftToData; + public List subregions = null; + + public int getEstimatedSize(){ + int shallow = 7 * INT_SIZE + 4 + 4/*list*/; + if (subregions != null) { + shallow += 8; + for (RouteSubregion s : subregions) { + shallow += s.getEstimatedSize(); + } + } + return shallow; + } } private CodedInputStreamRAF codedIS; @@ -55,6 +182,7 @@ public class BinaryMapRouteReaderAdapter { protected void readRouteIndex(RouteRegion region) throws IOException { + int routeEncodingRule =1; while(true){ int t = codedIS.readTag(); int tag = WireFormat.getTagFieldNumber(t); @@ -64,6 +192,97 @@ public class BinaryMapRouteReaderAdapter { case OsmandOdb.OsmAndRoutingIndex.NAME_FIELD_NUMBER : region.name = codedIS.readString(); break; + case OsmandOdb.OsmAndRoutingIndex.RULES_FIELD_NUMBER: { + int len = codedIS.readInt32(); + int oldLimit = codedIS.pushLimit(len); + readRouteEncodingRule(region, routeEncodingRule++); + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + codedIS.popLimit(oldLimit); + } break; + case OsmandOdb.OsmAndRoutingIndex.ROOTBOXES_FIELD_NUMBER : { + RouteSubregion subregion = new RouteSubregion(region); + subregion.length = readInt(); + subregion.filePointer = codedIS.getTotalBytesRead(); + int oldLimit = codedIS.pushLimit(subregion.length); + readRouteTree(subregion, true); + region.getSubregions().add(subregion); + codedIS.popLimit(oldLimit); + codedIS.seek(subregion.filePointer + subregion.length); + } break; + + default: + skipUnknownField(t); + break; + } + } + } + + private RouteSubregion readRouteTree(RouteSubregion routeTree, boolean readChildren) throws IOException { + if(readChildren) { + routeTree.subregions = new ArrayList(); + } + routeTree.routeReg.regionsRead++; + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return routeTree; + case RouteDataBox.LEFT_FIELD_NUMBER : + routeTree.left += codedIS.readSInt32(); + break; + case RouteDataBox.RIGHT_FIELD_NUMBER : + routeTree.right += codedIS.readSInt32(); + break; + case RouteDataBox.TOP_FIELD_NUMBER : + routeTree.top += codedIS.readSInt32(); + break; + case RouteDataBox.BOTTOM_FIELD_NUMBER : + routeTree.bottom += codedIS.readSInt32(); + break; + case RouteDataBox.SHIFTTODATA_FIELD_NUMBER : + routeTree.shiftToData = readInt(); + break; + case RouteDataBox.BOXES_FIELD_NUMBER : + if(readChildren){ + RouteSubregion subregion = new RouteSubregion(routeTree); + subregion.length = readInt(); + subregion.filePointer = codedIS.getTotalBytesRead(); + int oldLimit = codedIS.pushLimit(subregion.length); + readRouteTree(subregion, readChildren); + routeTree.subregions.add(subregion); + codedIS.popLimit(oldLimit); + codedIS.seek(subregion.filePointer + subregion.length); + } else { + skipUnknownField(t); + } + break; + default: + skipUnknownField(t); + break; + } + } + } + + private void readRouteEncodingRule(RouteRegion index, int id) throws IOException { + String tags = null; + String val = null; + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + index.initRouteEncodingRule(id, tags, val); + return; + case RouteEncodingRule.VALUE_FIELD_NUMBER : + val = codedIS.readString().intern(); + break; + case RouteEncodingRule.TAG_FIELD_NUMBER : + tags = codedIS.readString().intern(); + break; + case RouteEncodingRule.ID_FIELD_NUMBER : + id = codedIS.readUInt32(); + break; default: skipUnknownField(t); break; diff --git a/DataExtractionOSM/src/net/osmand/data/preparation/BinaryMapIndexWriter.java b/DataExtractionOSM/src/net/osmand/data/preparation/BinaryMapIndexWriter.java index deeb958945..e1bef8970e 100644 --- a/DataExtractionOSM/src/net/osmand/data/preparation/BinaryMapIndexWriter.java +++ b/DataExtractionOSM/src/net/osmand/data/preparation/BinaryMapIndexWriter.java @@ -199,7 +199,7 @@ public class BinaryMapIndexWriter { codedOutStream.writeTag(OsmandOdb.OsmAndStructure.ROUTINGINDEX_FIELD_NUMBER, WireFormat.WIRETYPE_FIXED32_LENGTH_DELIMITED); preserveInt32Size(); if (name != null) { - codedOutStream.writeString(OsmandOdb.OsmAndMapIndex.NAME_FIELD_NUMBER, name); + codedOutStream.writeString(OsmandOdb.OsmAndRoutingIndex.NAME_FIELD_NUMBER, name); } } diff --git a/DataExtractionOSM/src/net/osmand/data/preparation/IndexRouteCreator.java b/DataExtractionOSM/src/net/osmand/data/preparation/IndexRouteCreator.java index 6c01dd55f5..4e71acb350 100644 --- a/DataExtractionOSM/src/net/osmand/data/preparation/IndexRouteCreator.java +++ b/DataExtractionOSM/src/net/osmand/data/preparation/IndexRouteCreator.java @@ -13,30 +13,22 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import net.osmand.Algoritms; -import net.osmand.IProgress; import net.osmand.binary.OsmandOdb.IdTable; -import net.osmand.binary.OsmandOdb.MapData; -import net.osmand.binary.OsmandOdb.MapDataBlock; import net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock; import net.osmand.binary.OsmandOdb.RestrictionData; import net.osmand.binary.OsmandOdb.RestrictionData.Builder; import net.osmand.binary.OsmandOdb.RouteData; -import net.osmand.data.Boundary; -import net.osmand.data.MapAlgorithms; import net.osmand.data.preparation.BinaryMapIndexWriter.RoutePointToWrite; import net.osmand.osm.Entity; import net.osmand.osm.Entity.EntityId; import net.osmand.osm.Entity.EntityType; import net.osmand.osm.MapRenderingTypes; -import net.osmand.osm.MapRenderingTypes.MapRulType; import net.osmand.osm.MapRoutingTypes; import net.osmand.osm.MapRoutingTypes.MapRouteType; import net.osmand.osm.MapUtils;