Support via restriction properly #5709
This commit is contained in:
parent
6f9faa3097
commit
22e9fe318a
3 changed files with 99 additions and 29 deletions
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue