Support via restriction properly #5709

This commit is contained in:
Victor Shcherb 2018-07-25 22:48:43 +02:00
parent 6f9faa3097
commit 22e9fe318a
3 changed files with 99 additions and 29 deletions

View file

@ -24,6 +24,7 @@ import net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox;
import net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule; import net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule;
import net.osmand.binary.OsmandOdb.RestrictionData; import net.osmand.binary.OsmandOdb.RestrictionData;
import net.osmand.binary.OsmandOdb.RouteData; import net.osmand.binary.OsmandOdb.RouteData;
import net.osmand.binary.RouteDataObject.RestrictionInfo;
import net.osmand.util.MapUtils; import net.osmand.util.MapUtils;
import net.osmand.util.OpeningHoursParser; import net.osmand.util.OpeningHoursParser;
@ -329,6 +330,7 @@ public class BinaryMapRouteReaderAdapter {
rdo.pointsY = o.pointsY; rdo.pointsY = o.pointsY;
rdo.id = o.id; rdo.id = o.id;
rdo.restrictions = o.restrictions; rdo.restrictions = o.restrictions;
rdo.restrictionsVia = o.restrictionsVia;
if (o.types != null) { if (o.types != null) {
rdo.types = new int[o.types.length]; rdo.types = new int[o.types.length];
@ -649,7 +651,7 @@ public class BinaryMapRouteReaderAdapter {
} }
} }
private void readRouteTreeData(RouteSubregion routeTree, TLongArrayList idTables, private void readRouteTreeData(RouteSubregion routeTree, TLongArrayList idTables,
TLongObjectHashMap<TLongArrayList> restrictions) throws IOException { TLongObjectHashMap<RestrictionInfo> restrictions) throws IOException {
routeTree.dataObjects = new ArrayList<RouteDataObject>(); routeTree.dataObjects = new ArrayList<RouteDataObject>();
idTables.clear(); idTables.clear();
restrictions.clear(); restrictions.clear();
@ -659,17 +661,24 @@ public class BinaryMapRouteReaderAdapter {
int tag = WireFormat.getTagFieldNumber(t); int tag = WireFormat.getTagFieldNumber(t);
switch (tag) { switch (tag) {
case 0: case 0:
TLongObjectIterator<TLongArrayList> it = restrictions.iterator(); TLongObjectIterator<RestrictionInfo> it = restrictions.iterator();
while (it.hasNext()) { while (it.hasNext()) {
it.advance(); it.advance();
int from = (int) it.key(); int from = (int) it.key();
RouteDataObject fromr = routeTree.dataObjects.get(from); RouteDataObject fromr = routeTree.dataObjects.get(from);
fromr.restrictions = new long[it.value().size()]; fromr.restrictions = new long[it.value().length()];
RestrictionInfo val = it.value();
for (int k = 0; k < fromr.restrictions.length; k++) { for (int k = 0; k < fromr.restrictions.length; k++) {
int to = (int) (it.value().get(k) >> RouteDataObject.RESTRICTION_SHIFT); if(val != null) {
long valto = (idTables.get(to) << RouteDataObject.RESTRICTION_SHIFT) | ((long) it.value().get(k) & RouteDataObject.RESTRICTION_MASK); long via = 0;
fromr.restrictions[k] = valto; if(val.viaWay != 0) {
via = idTables.get((int)val.viaWay);
}
fromr.setRestriction(k, idTables.get((int)val.toWay), val.type, via);
}
val = val.next;
} }
// fromr.restrictionsVia = new
} }
for (RouteDataObject o : routeTree.dataObjects) { for (RouteDataObject o : routeTree.dataObjects) {
if (o != null) { if (o != null) {
@ -728,33 +737,37 @@ public class BinaryMapRouteReaderAdapter {
case RouteDataBlock.RESTRICTIONS_FIELD_NUMBER : case RouteDataBlock.RESTRICTIONS_FIELD_NUMBER :
length = codedIS.readRawVarint32(); length = codedIS.readRawVarint32();
oldLimit = codedIS.pushLimit(length); oldLimit = codedIS.pushLimit(length);
RestrictionInfo ri = new RestrictionInfo();
long from = 0; long from = 0;
long to = 0;
long type = 0;
idLoop : while(true){ idLoop : while(true){
int ts = codedIS.readTag(); int ts = codedIS.readTag();
int tags = WireFormat.getTagFieldNumber(ts); int tags = WireFormat.getTagFieldNumber(ts);
switch (tags) { switch (tags) {
case 0: case 0:
break idLoop; break idLoop;
case RestrictionData.FROM_FIELD_NUMBER : case RestrictionData.FROM_FIELD_NUMBER:
from = codedIS.readInt32(); from = codedIS.readInt32();
break; break;
case RestrictionData.TO_FIELD_NUMBER : case RestrictionData.TO_FIELD_NUMBER:
to = codedIS.readInt32(); ri.toWay = codedIS.readInt32();
break; break;
case RestrictionData.TYPE_FIELD_NUMBER : case RestrictionData.TYPE_FIELD_NUMBER:
type = codedIS.readInt32(); ri.type = codedIS.readInt32();
break;
case RestrictionData.VIA_FIELD_NUMBER:
ri.viaWay = codedIS.readInt32();
break; break;
default: default:
skipUnknownField(ts); skipUnknownField(ts);
break; break;
} }
} }
if(!restrictions.containsKey(from)) { RestrictionInfo prev = restrictions.get(from);
restrictions.put(from, new TLongArrayList()); if(prev != null) {
prev.next = ri;
} else {
restrictions.put(from, ri);
} }
restrictions.get(from).add((to << RouteDataObject.RESTRICTION_SHIFT) + type);
codedIS.popLimit(oldLimit); codedIS.popLimit(oldLimit);
break; break;
case RouteDataBlock.STRINGTABLE_FIELD_NUMBER : case RouteDataBlock.STRINGTABLE_FIELD_NUMBER :
@ -886,7 +899,7 @@ public class BinaryMapRouteReaderAdapter {
public List<RouteDataObject> loadRouteRegionData(RouteSubregion rs) throws IOException { public List<RouteDataObject> loadRouteRegionData(RouteSubregion rs) throws IOException {
TLongArrayList idMap = new TLongArrayList(); TLongArrayList idMap = new TLongArrayList();
TLongObjectHashMap<TLongArrayList> restrictionMap = new TLongObjectHashMap<TLongArrayList>(); TLongObjectHashMap<RestrictionInfo> restrictionMap = new TLongObjectHashMap<RestrictionInfo>();
if (rs.dataObjects == null) { if (rs.dataObjects == null) {
codedIS.seek(rs.filePointer + rs.shiftToData); codedIS.seek(rs.filePointer + rs.shiftToData);
int limit = codedIS.readRawVarint32(); int limit = codedIS.readRawVarint32();
@ -909,7 +922,7 @@ public class BinaryMapRouteReaderAdapter {
} }
}); });
TLongArrayList idMap = new TLongArrayList(); TLongArrayList idMap = new TLongArrayList();
TLongObjectHashMap<TLongArrayList> restrictionMap = new TLongObjectHashMap<TLongArrayList>(); TLongObjectHashMap<RestrictionInfo> restrictionMap = new TLongObjectHashMap<RestrictionInfo>();
for (RouteSubregion rs : toLoad) { for (RouteSubregion rs : toLoad) {
if (rs.dataObjects == null) { if (rs.dataObjects == null) {
codedIS.seek(rs.filePointer + rs.shiftToData); codedIS.seek(rs.filePointer + rs.shiftToData);

View file

@ -6,11 +6,11 @@ import gnu.trove.map.hash.TIntObjectHashMap;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.Arrays; import java.util.Arrays;
import net.osmand.Location;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteTypeRule; import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteTypeRule;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils; import net.osmand.util.MapUtils;
import net.osmand.Location;
import net.sf.junidecode.Junidecode; import net.sf.junidecode.Junidecode;
@ -26,6 +26,7 @@ public class RouteDataObject {
public int[] pointsX; public int[] pointsX;
public int[] pointsY; public int[] pointsY;
public long[] restrictions; public long[] restrictions;
public long[] restrictionsVia;
public int[][] pointTypes; public int[][] pointTypes;
public String[][] pointNames; public String[][] pointNames;
public int[][] pointNameTypes; public int[][] pointNameTypes;
@ -58,6 +59,7 @@ public class RouteDataObject {
this.types = copy.types; this.types = copy.types;
this.names = copy.names; this.names = copy.names;
this.restrictions = copy.restrictions; this.restrictions = copy.restrictions;
this.restrictionsVia = copy.restrictionsVia;
this.pointTypes = copy.pointTypes; this.pointTypes = copy.pointTypes;
this.pointNames = copy.pointNames; this.pointNames = copy.pointNames;
this.pointNameTypes = copy.pointNameTypes; this.pointNameTypes = copy.pointNameTypes;
@ -77,6 +79,7 @@ public class RouteDataObject {
boolean equals = true; boolean equals = true;
equals = equals && Arrays.equals(this.restrictions, thatObj.restrictions); equals = equals && Arrays.equals(this.restrictions, thatObj.restrictions);
equals = equals && Arrays.equals(this.restrictionsVia, thatObj.restrictionsVia);
if (equals) { if (equals) {
if (this.types == null || thatObj.types == null) { if (this.types == null || thatObj.types == null) {
@ -395,10 +398,23 @@ public class RouteDataObject {
return (int) (restrictions[i] & RESTRICTION_MASK); return (int) (restrictions[i] & RESTRICTION_MASK);
} }
public long getRawRestriction(int i) { public RestrictionInfo getRestrictionInfo(int k) {
return restrictions[i]; RestrictionInfo ri = new RestrictionInfo();
ri.toWay = getRestrictionId(k);
ri.type = getRestrictionType(k);
if(restrictionsVia != null && k < restrictionsVia.length) {
ri.viaWay = restrictionsVia[k];
}
return null;
} }
public long getRestrictionVia(int i) {
if(restrictionsVia != null && restrictionsVia.length > i) {
return restrictionsVia[i];
}
return 0;
}
public long getRestrictionId(int i) { public long getRestrictionId(int i) {
return restrictions[i] >> RESTRICTION_SHIFT; return restrictions[i] >> RESTRICTION_SHIFT;
} }
@ -832,4 +848,40 @@ public class RouteDataObject {
return MessageFormat.format("Road id {0} name {1} ref {2}", (getId() / 64) + "", name == null ? "" : name, return MessageFormat.format("Road id {0} name {1} ref {2}", (getId() / 64) + "", name == null ? "" : name,
rf == null ? "" : rf); rf == null ? "" : rf);
} }
public static class RestrictionInfo {
public int type;
public long toWay;
public long viaWay;
public RestrictionInfo next; // optional to simulate linked list
public int length() {
if(next == null) {
return 1;
}
return next.length() + 1;
}
}
public void setRestriction(int k, long to, int type, long viaWay) {
long valto = (to << RouteDataObject.RESTRICTION_SHIFT) | ((long) type & RouteDataObject.RESTRICTION_MASK);
restrictions[k] = valto;
if(viaWay != 0) {
setRestrictionVia(k, viaWay);
}
}
public void setRestrictionVia(int k, long viaWay) {
if(restrictionsVia != null) {
long[] nrestrictionsVia = new long[Math.max(k + 1, restrictions.length)];
System.arraycopy(restrictions, 0, nrestrictionsVia, 0, restrictions.length);
restrictionsVia = nrestrictionsVia;
} else {
restrictionsVia = new long[k + 1];
}
restrictionsVia[k] = viaWay;
}
} }

View file

@ -623,16 +623,17 @@ public class BinaryRoutePlanner {
} }
ctx.segmentsToVisitPrescripted.clear(); ctx.segmentsToVisitPrescripted.clear();
ctx.segmentsToVisitNotForbidden.clear(); ctx.segmentsToVisitNotForbidden.clear();
processRestriction(ctx, inputNext, reverseWay, false, road); processRestriction(ctx, inputNext, reverseWay, 0, road);
if (parent != null) { if (parent != null) {
processRestriction(ctx, inputNext, reverseWay, true, parent.getRoad()); processRestriction(ctx, inputNext, reverseWay, road.id, parent.getRoad());
} }
return true; return true;
} }
protected void processRestriction(RoutingContext ctx, RouteSegment inputNext, boolean reverseWay, boolean via, protected void processRestriction(RoutingContext ctx, RouteSegment inputNext, boolean reverseWay, long viaId,
RouteDataObject road) { RouteDataObject road) {
boolean via = viaId != 0;
RouteSegment next = inputNext; RouteSegment next = inputNext;
boolean exclusiveRestriction = false; boolean exclusiveRestriction = false;
while (next != null) { while (next != null) {
@ -640,8 +641,10 @@ public class BinaryRoutePlanner {
if (!reverseWay) { if (!reverseWay) {
for (int i = 0; i < road.getRestrictionLength(); i++) { for (int i = 0; i < road.getRestrictionLength(); i++) {
if (road.getRestrictionId(i) == next.road.id) { if (road.getRestrictionId(i) == next.road.id) {
type = road.getRestrictionType(i); if(!via || road.getRestrictionVia(i) == viaId) {
break; type = road.getRestrictionType(i);
break;
}
} }
} }
} else { } else {
@ -649,8 +652,10 @@ public class BinaryRoutePlanner {
int rt = next.road.getRestrictionType(i); int rt = next.road.getRestrictionType(i);
long restrictedTo = next.road.getRestrictionId(i); long restrictedTo = next.road.getRestrictionId(i);
if (restrictedTo == road.id) { if (restrictedTo == road.id) {
type = rt; if(!via || next.road.getRestrictionVia(i) == viaId) {
break; type = rt;
break;
}
} }
// Check if there is restriction only to the other than current road // Check if there is restriction only to the other than current road