Route index reader

This commit is contained in:
Victor Shcherb 2012-06-07 23:32:25 +02:00
parent 2c8117f738
commit 7b1a43647c
3 changed files with 221 additions and 10 deletions

View file

@ -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<RouteSubregion> subregions = new ArrayList<RouteSubregion>();
List<RouteTypeRule> routeEncodingRules = new ArrayList<BinaryMapRouteReaderAdapter.RouteTypeRule>();
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<RouteSubregion> 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<RouteSubregion> 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<BinaryMapRouteReaderAdapter.RouteSubregion>();
}
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;

View file

@ -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);
}
}

View file

@ -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;