From 7699e2061c75bcf13697145f79f1522c5f40ec79 Mon Sep 17 00:00:00 2001 From: MadWasp79 Date: Wed, 13 May 2020 15:09:30 +0300 Subject: [PATCH] add reading of incomplete routes. Add cache - work in progress --- .../osmand/binary/BinaryMapIndexReader.java | 12 ++- .../BinaryMapTransportReaderAdapter.java | 89 ++++++++++++++++++- .../osmand/data/IncompleteTransportRoute.java | 50 +++++++++++ .../java/net/osmand/data/TransportRoute.java | 4 + .../osmand/router/TransportRoutePlanner.java | 79 ++++++++-------- 5 files changed, 192 insertions(+), 42 deletions(-) create mode 100644 OsmAnd-java/src/main/java/net/osmand/data/IncompleteTransportRoute.java diff --git a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapIndexReader.java b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapIndexReader.java index 5fedfc8eae..4ddb58377a 100644 --- a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapIndexReader.java +++ b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapIndexReader.java @@ -19,6 +19,7 @@ import net.osmand.binary.BinaryMapPoiReaderAdapter.PoiRegion; import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteSubregion; import net.osmand.binary.BinaryMapTransportReaderAdapter.TransportIndex; +import net.osmand.binary.OsmandOdb.IncompleteTransportRoute; import net.osmand.binary.OsmandOdb.MapDataBlock; import net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox; import net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule; @@ -54,6 +55,7 @@ import java.io.InputStreamReader; import java.io.RandomAccessFile; import java.io.Reader; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; @@ -110,7 +112,8 @@ public class BinaryMapIndexReader { /*private*/ List routingIndexes = new ArrayList(); /*private*/ List indexes = new ArrayList(); - private final TLongObjectHashMap incompleteRoutes = new TLongObjectHashMap(); + private final TLongObjectHashMap incompleteRoutes = + new TLongObjectHashMap(); protected CodedInputStream codedIS; @@ -225,7 +228,7 @@ public class BinaryMapIndexReader { ind.filePointer = codedIS.getTotalBytesRead(); if (transportAdapter != null) { oldLimit = codedIS.pushLimit(ind.length); - transportAdapter.readTransportIndex(ind); + transportAdapter.readTransportIndex(ind, incompleteRoutes); codedIS.popLimit(oldLimit); transportIndexes.add(ind); indexes.add(ind); @@ -2633,9 +2636,12 @@ public class BinaryMapIndexReader { } } - public int[] getIncompleteRoutesPointers(long id) { + public net.osmand.data.IncompleteTransportRoute getIncompleteRoutePointers(long id) { return incompleteRoutes.get(id); } + public Collection getIncompleteRoutes() { + return incompleteRoutes.valueCollection(); + } } diff --git a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapTransportReaderAdapter.java b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapTransportReaderAdapter.java index bf3a217306..617bf46f07 100644 --- a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapTransportReaderAdapter.java +++ b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapTransportReaderAdapter.java @@ -1,15 +1,20 @@ package net.osmand.binary; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import com.google.protobuf.CodedInputStream; import com.google.protobuf.WireFormat; +import gnu.trove.list.array.TLongArrayList; import gnu.trove.map.hash.TIntObjectHashMap; +import gnu.trove.map.hash.TLongObjectHashMap; import net.osmand.binary.BinaryMapIndexReader.SearchRequest; +import net.osmand.binary.OsmandOdb.IncompleteTransportRoute; import net.osmand.data.TransportSchedule; import net.osmand.data.TransportStop; import net.osmand.data.TransportStopExit; @@ -43,6 +48,8 @@ public class BinaryMapTransportReaderAdapter { int stopsFileOffset = 0; int stopsFileLength = 0; + int incompleteRoutesOffset = 0; + int incompleteRoutesLength = 0; public String getPartName() { return "Transport"; @@ -67,7 +74,8 @@ public class BinaryMapTransportReaderAdapter { public int getBottom() { return bottom; } - + + IndexStringTable stringTable = null; } @@ -79,7 +87,7 @@ public class BinaryMapTransportReaderAdapter { } - protected void readTransportIndex(TransportIndex ind) throws IOException { + protected void readTransportIndex(TransportIndex ind, TLongObjectHashMap incompleteRoutes) throws IOException { while(true){ int t = codedIS.readTag(); int tag = WireFormat.getTagFieldNumber(t); @@ -108,6 +116,16 @@ public class BinaryMapTransportReaderAdapter { ind.stringTable = st; codedIS.seek(st.length + st.fileOffset); break; + case OsmandOdb.OsmAndTransportIndex.INCOMPLETEROUTES_FIELD_NUMBER : + TIntObjectHashMap stab = new TIntObjectHashMap(); + ind.incompleteRoutesLength = codedIS.readRawVarint32(); + ind.incompleteRoutesOffset = codedIS.getTotalBytesRead(); + int oldl = codedIS.pushLimit(ind.incompleteRoutesLength); + //may be we should start caching stringTable in advance? + readIncompleteRoutesList(incompleteRoutes, ind.incompleteRoutesLength, ind.incompleteRoutesOffset, stab); + codedIS.popLimit(oldl); + break; + default: skipUnknownField(t); break; @@ -240,6 +258,73 @@ public class BinaryMapTransportReaderAdapter { return ((char) i)+""; } + private void readIncompleteRoutesList(TLongObjectHashMap incompleteRoutes, + int length, int offset, TIntObjectHashMap stringTable) throws IOException { + codedIS.seek(offset); + + List irs = new ArrayList<>(); + boolean end = false; + while (!end) { + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + end = true; + break; + case OsmandOdb.IncompleteTransportRoutes.ROUTES_FIELD_NUMBER: + int l = codedIS.readRawVarint32(); + int olds = codedIS.pushLimit(l); + net.osmand.data.IncompleteTransportRoute ir = readIncompleteRoute(stringTable); + incompleteRoutes.put(ir.getRouteId(), ir); + codedIS.popLimit(olds); + break; + default: + skipUnknownField(t); + break; + } + + } + + } + + public net.osmand.data.IncompleteTransportRoute readIncompleteRoute(TIntObjectHashMap stringTable) throws IOException { + net.osmand.data.IncompleteTransportRoute dataObject = new net.osmand.data.IncompleteTransportRoute(); + boolean end = false; + while(!end){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + end = true; + break; + case OsmandOdb.IncompleteTransportRoute.ID_FIELD_NUMBER : + dataObject.setRouteId(codedIS.readUInt64()); + break; + case OsmandOdb.IncompleteTransportRoute.ROUTEREF_FIELD_NUMBER : + dataObject.setRouteOffset(codedIS.readRawVarint32()); + break; + case OsmandOdb.IncompleteTransportRoute.OPERATOR_FIELD_NUMBER : + dataObject.setOperator(regStr(stringTable)); + break; + case OsmandOdb.IncompleteTransportRoute.REF_FIELD_NUMBER : + dataObject.setRef(regStr(stringTable)); + break; + case OsmandOdb.IncompleteTransportRoute.TYPE_FIELD_NUMBER : + dataObject.setType(regStr(stringTable)); + break; + case OsmandOdb.IncompleteTransportRoute.MISSINGSTOPS_FIELD_NUMBER : +//// dataObject.getMissingStops().add(codedIS.readSInt32()); //skip for now + skipUnknownField(t); + break; + default: + skipUnknownField(t); + break; + } + } + + return dataObject; + } + public net.osmand.data.TransportRoute getTransportRoute(int filePointer, TIntObjectHashMap stringTable, boolean onlyDescription) throws IOException { codedIS.seek(filePointer); diff --git a/OsmAnd-java/src/main/java/net/osmand/data/IncompleteTransportRoute.java b/OsmAnd-java/src/main/java/net/osmand/data/IncompleteTransportRoute.java new file mode 100644 index 0000000000..eb84be3453 --- /dev/null +++ b/OsmAnd-java/src/main/java/net/osmand/data/IncompleteTransportRoute.java @@ -0,0 +1,50 @@ +package net.osmand.data; + +import gnu.trove.list.array.TIntArrayList; + +public class IncompleteTransportRoute { + private long routeId; + private int routeOffset = -1; + private String operator; + private String type; + private String ref; +// private TIntArrayList missingStops; //not needed + public long getRouteId() { + return routeId; + } + public void setRouteId(long routeId) { + this.routeId = routeId; + } + public int getRouteOffset() { + return routeOffset; + } + public void setRouteOffset(int routeOffset) { + this.routeOffset = routeOffset; + } + public String getOperator() { + return operator; + } + public void setOperator(String operator) { + this.operator = operator; + } + public String getType() { + return type; + } + public void setType(String type) { + this.type = type; + } + public String getRef() { + return ref; + } + public void setRef(String ref) { + this.ref = ref; + } +// public TIntArrayList getMissingStops() { +// return missingStops; +// } +// public void setMissingStops(TIntArrayList missingStops) { +// this.missingStops = missingStops; +// } + + +} \ No newline at end of file diff --git a/OsmAnd-java/src/main/java/net/osmand/data/TransportRoute.java b/OsmAnd-java/src/main/java/net/osmand/data/TransportRoute.java index ff49525665..251bb6b867 100644 --- a/OsmAnd-java/src/main/java/net/osmand/data/TransportRoute.java +++ b/OsmAnd-java/src/main/java/net/osmand/data/TransportRoute.java @@ -63,6 +63,10 @@ public class TransportRoute extends MapObject { return combined; } + public boolean isIncomplete() { + return forwardStops.get(0).isMissingStop() || forwardStops.get(forwardStops.size()-1).isMissingStop(); + } + public void setCombined(boolean combined) { this.combined = combined; } diff --git a/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutePlanner.java b/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutePlanner.java index b0c1ffcb1e..4be06795ac 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutePlanner.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutePlanner.java @@ -23,6 +23,7 @@ import net.osmand.NativeLibrary; import net.osmand.binary.BinaryIndexPart; import net.osmand.binary.BinaryMapIndexReader; import net.osmand.binary.BinaryMapIndexReader.SearchRequest; +import net.osmand.data.IncompleteTransportRoute; import net.osmand.data.LatLon; import net.osmand.data.QuadRect; import net.osmand.data.TransportRoute; @@ -707,7 +708,7 @@ public class TransportRoutePlanner { public RouteCalculationProgress calculationProgress; public TLongObjectHashMap visitedSegments = new TLongObjectHashMap(); public TransportRoutingConfiguration cfg; - public TLongObjectHashMap combinedRoutes = new TLongObjectHashMap(); + public TLongObjectHashMap combinedRoutesCache = new TLongObjectHashMap(); public Map> missingStopsCache = new HashMap>(); public TLongObjectHashMap> quadTree; @@ -926,55 +927,31 @@ public class TransportRoutePlanner { } private TransportRoute getCombinedRoute(TransportRoute route, String fileName) throws IOException { - if (!route.getForwardStops().get(0).isMissingStop() && !route.getForwardStops().get(route.getForwardStops().size()-1).isMissingStop()) { + if (!route.isIncomplete()) { return route; } - TransportRoute c = combinedRoutes.get(route.getId()); + TransportRoute c = combinedRoutesCache.get(route.getId()); if (c == null) { c = combineRoute(route, fileName); - combinedRoutes.put(route.getId(), c); + combinedRoutesCache.put(route.getId(), c); } return c; } - private TIntObjectHashMap findIncompleteRouteParts(TransportRoute baseRoute, String fileName) throws IOException { - int ptrs[]; - TIntObjectHashMap res = new TIntObjectHashMap(); - TIntObjectHashMap localRes = new TIntObjectHashMap(); -// TODO check if valid comparsion by filename - for (BinaryMapIndexReader bmir: routeMap.keySet()) { - if (!bmir.getFile().getName().equals(fileName)) { - /** - * What about situation when one route has several parts in map? - * MB check all readers and then sort it out? - * - * Should I check if those routes already loaded? But they shouldn't, - * else we will already had a combined route and never get there! - */ - localRes.clear(); - ptrs = bmir.getIncompleteRoutesPointers(baseRoute.getId()); - if (ptrs != null && ptrs.length > 0) { - localRes = bmir.getTransportRoutes(ptrs); - - res.putAll(localRes); - } - } - } - return res; - } - - private TransportRoute combineRoute(TransportRoute route, String fileName) throws IOException { TransportRoute cr = new TransportRoute(route, true); - TIntObjectHashMap res = findIncompleteRouteParts(route, fileName); -// for () { - //TODO check for duplicates and subsets - //TODO connect in right order + Collection res = findIncompleteRouteParts(route, fileName); + List stops = route.getForwardStops(); + List ways = route.getForwardWays(); + for (TransportRoute tr : res.valueCollection()) { -// } + //TODO check for duplicates and subsets + //TODO connect routes in right order (stops/ways) + + } // TransportRoute missingPart; // if (route.getForwardStops().get(0).isMissingStop()) { // missingPart = loadMissingTransportRoute( @@ -995,6 +972,35 @@ public class TransportRoutePlanner { return cr; } + private Collection findIncompleteRouteParts(TransportRoute baseRoute, String fileName) throws IOException { + IncompleteTransportRoute ptr; + TIntObjectHashMap res = new TIntObjectHashMap(); + TIntObjectHashMap localRes = new TIntObjectHashMap(); +// TODO check if valid comparison by filename + for (BinaryMapIndexReader bmir: routeMap.keySet()) { + if (!bmir.getFile().getName().equals(fileName)) { + /** + * What about situation when one route has several parts in map? + * MB check all readers and then sort it out? + * + * Should I check if those routes already loaded? But they shouldn't, + * else we will already had a combined route and never get there! + */ + localRes.clear(); + ptr = bmir.getIncompleteRoutePointers(baseRoute.getId()); + if (ptr!= null && ptr.getRouteOffset() != -1) { + localRes = bmir.getTransportRoutes(new int[] {ptr.getRouteOffset()}); + + res.putAll(localRes); + } + } + } + return res.valueCollection(); + } + + + + private TransportRoute loadMissingTransportRoute(int sx, int sy, TransportRoute route) throws IOException { @@ -1239,5 +1245,4 @@ public class TransportRoutePlanner { } return stops; } - }