add reading of incomplete routes. Add cache - work in progress
This commit is contained in:
parent
8e56faabd1
commit
7699e2061c
5 changed files with 192 additions and 42 deletions
|
@ -19,6 +19,7 @@ import net.osmand.binary.BinaryMapPoiReaderAdapter.PoiRegion;
|
||||||
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion;
|
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion;
|
||||||
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteSubregion;
|
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteSubregion;
|
||||||
import net.osmand.binary.BinaryMapTransportReaderAdapter.TransportIndex;
|
import net.osmand.binary.BinaryMapTransportReaderAdapter.TransportIndex;
|
||||||
|
import net.osmand.binary.OsmandOdb.IncompleteTransportRoute;
|
||||||
import net.osmand.binary.OsmandOdb.MapDataBlock;
|
import net.osmand.binary.OsmandOdb.MapDataBlock;
|
||||||
import net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox;
|
import net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox;
|
||||||
import net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule;
|
import net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule;
|
||||||
|
@ -54,6 +55,7 @@ import java.io.InputStreamReader;
|
||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -110,7 +112,8 @@ public class BinaryMapIndexReader {
|
||||||
/*private*/ List<RouteRegion> routingIndexes = new ArrayList<RouteRegion>();
|
/*private*/ List<RouteRegion> routingIndexes = new ArrayList<RouteRegion>();
|
||||||
/*private*/ List<BinaryIndexPart> indexes = new ArrayList<BinaryIndexPart>();
|
/*private*/ List<BinaryIndexPart> indexes = new ArrayList<BinaryIndexPart>();
|
||||||
|
|
||||||
private final TLongObjectHashMap<int[]> incompleteRoutes = new TLongObjectHashMap<int[]>();
|
private final TLongObjectHashMap<net.osmand.data.IncompleteTransportRoute> incompleteRoutes =
|
||||||
|
new TLongObjectHashMap<net.osmand.data.IncompleteTransportRoute>();
|
||||||
|
|
||||||
protected CodedInputStream codedIS;
|
protected CodedInputStream codedIS;
|
||||||
|
|
||||||
|
@ -225,7 +228,7 @@ public class BinaryMapIndexReader {
|
||||||
ind.filePointer = codedIS.getTotalBytesRead();
|
ind.filePointer = codedIS.getTotalBytesRead();
|
||||||
if (transportAdapter != null) {
|
if (transportAdapter != null) {
|
||||||
oldLimit = codedIS.pushLimit(ind.length);
|
oldLimit = codedIS.pushLimit(ind.length);
|
||||||
transportAdapter.readTransportIndex(ind);
|
transportAdapter.readTransportIndex(ind, incompleteRoutes);
|
||||||
codedIS.popLimit(oldLimit);
|
codedIS.popLimit(oldLimit);
|
||||||
transportIndexes.add(ind);
|
transportIndexes.add(ind);
|
||||||
indexes.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);
|
return incompleteRoutes.get(id);
|
||||||
}
|
}
|
||||||
|
public Collection<net.osmand.data.IncompleteTransportRoute> getIncompleteRoutes() {
|
||||||
|
return incompleteRoutes.valueCollection();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,20 @@
|
||||||
package net.osmand.binary;
|
package net.osmand.binary;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.google.protobuf.CodedInputStream;
|
import com.google.protobuf.CodedInputStream;
|
||||||
import com.google.protobuf.WireFormat;
|
import com.google.protobuf.WireFormat;
|
||||||
|
|
||||||
|
import gnu.trove.list.array.TLongArrayList;
|
||||||
import gnu.trove.map.hash.TIntObjectHashMap;
|
import gnu.trove.map.hash.TIntObjectHashMap;
|
||||||
|
import gnu.trove.map.hash.TLongObjectHashMap;
|
||||||
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
|
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
|
||||||
|
import net.osmand.binary.OsmandOdb.IncompleteTransportRoute;
|
||||||
import net.osmand.data.TransportSchedule;
|
import net.osmand.data.TransportSchedule;
|
||||||
import net.osmand.data.TransportStop;
|
import net.osmand.data.TransportStop;
|
||||||
import net.osmand.data.TransportStopExit;
|
import net.osmand.data.TransportStopExit;
|
||||||
|
@ -43,6 +48,8 @@ public class BinaryMapTransportReaderAdapter {
|
||||||
|
|
||||||
int stopsFileOffset = 0;
|
int stopsFileOffset = 0;
|
||||||
int stopsFileLength = 0;
|
int stopsFileLength = 0;
|
||||||
|
int incompleteRoutesOffset = 0;
|
||||||
|
int incompleteRoutesLength = 0;
|
||||||
|
|
||||||
public String getPartName() {
|
public String getPartName() {
|
||||||
return "Transport";
|
return "Transport";
|
||||||
|
@ -67,7 +74,8 @@ public class BinaryMapTransportReaderAdapter {
|
||||||
public int getBottom() {
|
public int getBottom() {
|
||||||
return bottom;
|
return bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IndexStringTable stringTable = null;
|
IndexStringTable stringTable = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +87,7 @@ public class BinaryMapTransportReaderAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void readTransportIndex(TransportIndex ind) throws IOException {
|
protected void readTransportIndex(TransportIndex ind, TLongObjectHashMap<net.osmand.data.IncompleteTransportRoute> incompleteRoutes) throws IOException {
|
||||||
while(true){
|
while(true){
|
||||||
int t = codedIS.readTag();
|
int t = codedIS.readTag();
|
||||||
int tag = WireFormat.getTagFieldNumber(t);
|
int tag = WireFormat.getTagFieldNumber(t);
|
||||||
|
@ -108,6 +116,16 @@ public class BinaryMapTransportReaderAdapter {
|
||||||
ind.stringTable = st;
|
ind.stringTable = st;
|
||||||
codedIS.seek(st.length + st.fileOffset);
|
codedIS.seek(st.length + st.fileOffset);
|
||||||
break;
|
break;
|
||||||
|
case OsmandOdb.OsmAndTransportIndex.INCOMPLETEROUTES_FIELD_NUMBER :
|
||||||
|
TIntObjectHashMap<String> stab = new TIntObjectHashMap<String>();
|
||||||
|
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:
|
default:
|
||||||
skipUnknownField(t);
|
skipUnknownField(t);
|
||||||
break;
|
break;
|
||||||
|
@ -240,6 +258,73 @@ public class BinaryMapTransportReaderAdapter {
|
||||||
return ((char) i)+"";
|
return ((char) i)+"";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void readIncompleteRoutesList(TLongObjectHashMap<net.osmand.data.IncompleteTransportRoute> incompleteRoutes,
|
||||||
|
int length, int offset, TIntObjectHashMap<String> stringTable) throws IOException {
|
||||||
|
codedIS.seek(offset);
|
||||||
|
|
||||||
|
List<net.osmand.data.IncompleteTransportRoute> 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<String> 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<String> stringTable,
|
public net.osmand.data.TransportRoute getTransportRoute(int filePointer, TIntObjectHashMap<String> stringTable,
|
||||||
boolean onlyDescription) throws IOException {
|
boolean onlyDescription) throws IOException {
|
||||||
codedIS.seek(filePointer);
|
codedIS.seek(filePointer);
|
||||||
|
|
|
@ -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;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -63,6 +63,10 @@ public class TransportRoute extends MapObject {
|
||||||
return combined;
|
return combined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isIncomplete() {
|
||||||
|
return forwardStops.get(0).isMissingStop() || forwardStops.get(forwardStops.size()-1).isMissingStop();
|
||||||
|
}
|
||||||
|
|
||||||
public void setCombined(boolean combined) {
|
public void setCombined(boolean combined) {
|
||||||
this.combined = combined;
|
this.combined = combined;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import net.osmand.NativeLibrary;
|
||||||
import net.osmand.binary.BinaryIndexPart;
|
import net.osmand.binary.BinaryIndexPart;
|
||||||
import net.osmand.binary.BinaryMapIndexReader;
|
import net.osmand.binary.BinaryMapIndexReader;
|
||||||
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
|
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
|
||||||
|
import net.osmand.data.IncompleteTransportRoute;
|
||||||
import net.osmand.data.LatLon;
|
import net.osmand.data.LatLon;
|
||||||
import net.osmand.data.QuadRect;
|
import net.osmand.data.QuadRect;
|
||||||
import net.osmand.data.TransportRoute;
|
import net.osmand.data.TransportRoute;
|
||||||
|
@ -707,7 +708,7 @@ public class TransportRoutePlanner {
|
||||||
public RouteCalculationProgress calculationProgress;
|
public RouteCalculationProgress calculationProgress;
|
||||||
public TLongObjectHashMap<TransportRouteSegment> visitedSegments = new TLongObjectHashMap<TransportRouteSegment>();
|
public TLongObjectHashMap<TransportRouteSegment> visitedSegments = new TLongObjectHashMap<TransportRouteSegment>();
|
||||||
public TransportRoutingConfiguration cfg;
|
public TransportRoutingConfiguration cfg;
|
||||||
public TLongObjectHashMap<TransportRoute> combinedRoutes = new TLongObjectHashMap<TransportRoute>();
|
public TLongObjectHashMap<TransportRoute> combinedRoutesCache = new TLongObjectHashMap<TransportRoute>();
|
||||||
public Map<TransportStop, List<TransportRoute>> missingStopsCache = new HashMap<TransportStop, List<TransportRoute>>();
|
public Map<TransportStop, List<TransportRoute>> missingStopsCache = new HashMap<TransportStop, List<TransportRoute>>();
|
||||||
|
|
||||||
public TLongObjectHashMap<List<TransportRouteSegment>> quadTree;
|
public TLongObjectHashMap<List<TransportRouteSegment>> quadTree;
|
||||||
|
@ -926,55 +927,31 @@ public class TransportRoutePlanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
private TransportRoute getCombinedRoute(TransportRoute route, String fileName) throws IOException {
|
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;
|
return route;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransportRoute c = combinedRoutes.get(route.getId());
|
TransportRoute c = combinedRoutesCache.get(route.getId());
|
||||||
|
|
||||||
if (c == null) {
|
if (c == null) {
|
||||||
c = combineRoute(route, fileName);
|
c = combineRoute(route, fileName);
|
||||||
combinedRoutes.put(route.getId(), c);
|
combinedRoutesCache.put(route.getId(), c);
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TIntObjectHashMap<TransportRoute> findIncompleteRouteParts(TransportRoute baseRoute, String fileName) throws IOException {
|
|
||||||
int ptrs[];
|
|
||||||
TIntObjectHashMap<TransportRoute> res = new TIntObjectHashMap<TransportRoute>();
|
|
||||||
TIntObjectHashMap<TransportRoute> localRes = new TIntObjectHashMap<TransportRoute>();
|
|
||||||
// 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 {
|
private TransportRoute combineRoute(TransportRoute route, String fileName) throws IOException {
|
||||||
TransportRoute cr = new TransportRoute(route, true);
|
TransportRoute cr = new TransportRoute(route, true);
|
||||||
TIntObjectHashMap<TransportRoute> res = findIncompleteRouteParts(route, fileName);
|
Collection<TransportRoute> res = findIncompleteRouteParts(route, fileName);
|
||||||
// for () {
|
List<TransportStop> stops = route.getForwardStops();
|
||||||
//TODO check for duplicates and subsets
|
List<Way> ways = route.getForwardWays();
|
||||||
//TODO connect in right order
|
for (TransportRoute tr : res.valueCollection()) {
|
||||||
|
|
||||||
// }
|
//TODO check for duplicates and subsets
|
||||||
|
//TODO connect routes in right order (stops/ways)
|
||||||
|
|
||||||
|
}
|
||||||
// TransportRoute missingPart;
|
// TransportRoute missingPart;
|
||||||
// if (route.getForwardStops().get(0).isMissingStop()) {
|
// if (route.getForwardStops().get(0).isMissingStop()) {
|
||||||
// missingPart = loadMissingTransportRoute(
|
// missingPart = loadMissingTransportRoute(
|
||||||
|
@ -995,6 +972,35 @@ public class TransportRoutePlanner {
|
||||||
return cr;
|
return cr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Collection<TransportRoute> findIncompleteRouteParts(TransportRoute baseRoute, String fileName) throws IOException {
|
||||||
|
IncompleteTransportRoute ptr;
|
||||||
|
TIntObjectHashMap<TransportRoute> res = new TIntObjectHashMap<TransportRoute>();
|
||||||
|
TIntObjectHashMap<TransportRoute> localRes = new TIntObjectHashMap<TransportRoute>();
|
||||||
|
// 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 {
|
private TransportRoute loadMissingTransportRoute(int sx, int sy, TransportRoute route) throws IOException {
|
||||||
|
@ -1239,5 +1245,4 @@ public class TransportRoutePlanner {
|
||||||
}
|
}
|
||||||
return stops;
|
return stops;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue