add reading of incomplete routes. Add cache - work in progress

This commit is contained in:
MadWasp79 2020-05-13 15:09:30 +03:00
parent 8e56faabd1
commit 7699e2061c
5 changed files with 192 additions and 42 deletions

View file

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

View file

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

View file

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

View file

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

View file

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