use of net.osmand.binary.RouteDataObject in project Osmand by osmandapp.
the class RoutingContext method loadTileData.
public void loadTileData(int x31, int y31, int zoomAround, final List<RouteDataObject> toFillIn) {
int t = config.ZOOM_TO_LOAD_TILES - zoomAround;
int coordinatesShift = (1 << (31 - config.ZOOM_TO_LOAD_TILES));
if (t <= 0) {
t = 1;
coordinatesShift = (1 << (31 - zoomAround));
} else {
t = 1 << t;
}
TLongHashSet ts = new TLongHashSet();
long now = System.nanoTime();
for (int i = -t; i <= t; i++) {
for (int j = -t; j <= t; j++) {
ts.add(getRoutingTile(x31 + i * coordinatesShift, y31 + j * coordinatesShift, 0, OPTION_IN_MEMORY_LOAD));
}
}
TLongIterator it = ts.iterator();
TLongObjectHashMap<RouteDataObject> excludeDuplications = new TLongObjectHashMap<RouteDataObject>();
while (it.hasNext()) {
getAllObjects(it.next(), toFillIn, excludeDuplications);
}
timeToFindInitialSegments += (System.nanoTime() - now);
}
use of net.osmand.binary.RouteDataObject in project Osmand by osmandapp.
the class BinaryRoutePlanner method checkIfOppositeSegmentWasVisited.
private boolean checkIfOppositeSegmentWasVisited(final RoutingContext ctx, boolean reverseWaySearch, PriorityQueue<RouteSegment> graphSegments, RouteSegment segment, TLongObjectHashMap<RouteSegment> oppositeSegments, int segmentPoint, float segmentDist, float obstaclesTime) {
RouteDataObject road = segment.getRoad();
long opp = calculateRoutePointId(road, segment.isPositive() ? segmentPoint - 1 : segmentPoint, !segment.isPositive());
if (oppositeSegments.containsKey(opp)) {
RouteSegment opposite = oppositeSegments.get(opp);
RouteSegment to = reverseWaySearch ? getParentDiffId(segment) : getParentDiffId(opposite);
RouteSegment from = !reverseWaySearch ? getParentDiffId(segment) : getParentDiffId(opposite);
if (checkViaRestrictions(from, to)) {
FinalRouteSegment frs = new FinalRouteSegment(road, segmentPoint);
float distStartObstacles = segment.distanceFromStart + calculateTimeWithObstacles(ctx, road, segmentDist, obstaclesTime);
frs.setParentRoute(segment);
frs.setParentSegmentEnd(segmentPoint);
frs.reverseWaySearch = reverseWaySearch;
frs.distanceFromStart = opposite.distanceFromStart + distStartObstacles;
frs.distanceToEnd = 0;
frs.opposite = opposite;
graphSegments.add(frs);
if (TRACE_ROUTING) {
printRoad(" >> Final segment : ", frs, reverseWaySearch);
}
return true;
}
}
return false;
}
use of net.osmand.binary.RouteDataObject in project Osmand by osmandapp.
the class BinaryRoutePlanner method processRouteSegment.
@SuppressWarnings("unused")
private void processRouteSegment(final RoutingContext ctx, boolean reverseWaySearch, PriorityQueue<RouteSegment> graphSegments, TLongObjectHashMap<RouteSegment> visitedSegments, RouteSegment segment, TLongObjectHashMap<RouteSegment> oppositeSegments, boolean doNotAddIntersections) throws IOException {
final RouteDataObject road = segment.road;
boolean initDirectionAllowed = checkIfInitialMovementAllowedOnSegment(ctx, reverseWaySearch, visitedSegments, segment, road);
if (TEST_SPECIFIC && road.getId() >> 6 == TEST_ID) {
printRoad(" ! " + +segment.distanceFromStart + " ", segment, reverseWaySearch);
}
boolean directionAllowed = initDirectionAllowed;
if (!directionAllowed) {
if (TRACE_ROUTING) {
println(" >> Already visited");
}
return;
}
// Go through all point of the way and find ways to continue
// ! Actually there is small bug when there is restriction to move forward on the way (it doesn't take into account)
float obstaclesTime = 0;
float segmentDist = 0;
// +/- diff from middle point
short segmentPoint = segment.getSegmentStart();
boolean[] processFurther = new boolean[1];
RouteSegment previous = segment;
boolean dir = segment.isPositive();
while (directionAllowed) {
// mark previous interval as visited and move to next intersection
short prevInd = segmentPoint;
if (dir) {
segmentPoint++;
} else {
segmentPoint--;
}
if (segmentPoint < 0 || segmentPoint >= road.getPointsLength()) {
directionAllowed = false;
continue;
}
// store <segment> in order to not have unique <segment, direction> in visitedSegments
visitedSegments.put(calculateRoutePointId(segment.getRoad(), segment.isPositive() ? segmentPoint - 1 : segmentPoint, segment.isPositive()), previous != null ? previous : segment);
final int x = road.getPoint31XTile(segmentPoint);
final int y = road.getPoint31YTile(segmentPoint);
final int prevx = road.getPoint31XTile(prevInd);
final int prevy = road.getPoint31YTile(prevInd);
if (x == prevx && y == prevy) {
continue;
}
// 2. calculate point and try to load neighbor ways if they are not loaded
segmentDist += squareRootDist(x, y, prevx, prevy);
// 2.1 calculate possible obstacle plus time
double obstacle = ctx.getRouter().defineRoutingObstacle(road, segmentPoint);
if (obstacle < 0) {
directionAllowed = false;
continue;
}
double heightObstacle = ctx.getRouter().defineHeightObstacle(road, !reverseWaySearch ? prevInd : segmentPoint, !reverseWaySearch ? segmentPoint : prevInd);
if (heightObstacle < 0) {
directionAllowed = false;
continue;
}
boolean alreadyVisited = checkIfOppositeSegmentWasVisited(ctx, reverseWaySearch, graphSegments, segment, oppositeSegments, segmentPoint, segmentDist, obstaclesTime);
obstaclesTime += obstacle;
obstaclesTime += heightObstacle;
if (alreadyVisited) {
directionAllowed = false;
continue;
}
// correct way of handling precalculatedRouteDirection
if (ctx.precalculatedRouteDirection != null) {
// long nt = System.nanoTime();
// float devDistance = ctx.precalculatedRouteDirection.getDeviationDistance(x, y);
// // 1. linear method
// segmentDist = segmentDist * (1 + devDistance / ctx.config.DEVIATION_RADIUS);
// // 2. exponential method
// segmentDist = segmentDist * (float) Math.pow(1.5, devDistance / 500);
// 3. next by method
// segmentDist = devDistance ;
// ctx.timeNanoToCalcDeviation += (System.nanoTime() - nt);
}
// could be expensive calculation
// 3. get intersected ways
final RouteSegment roadNext = ctx.loadRouteSegment(x, y, ctx.config.memoryLimitation - ctx.memoryOverhead);
float distStartObstacles = segment.distanceFromStart + calculateTimeWithObstacles(ctx, road, segmentDist, obstaclesTime);
if (ctx.precalculatedRouteDirection != null && ctx.precalculatedRouteDirection.isFollowNext()) {
// reset to f
// distStartObstacles = 0;
// more precise but slower
distStartObstacles = ctx.precalculatedRouteDirection.getDeviationDistance(x, y) / ctx.getRouter().getMaxDefaultSpeed();
}
// We don't check if there are outgoing connections
previous = processIntersections(ctx, graphSegments, visitedSegments, distStartObstacles, segment, segmentPoint, roadNext, reverseWaySearch, doNotAddIntersections, processFurther);
if (!processFurther[0]) {
directionAllowed = false;
continue;
}
}
if (initDirectionAllowed && ctx.visitor != null) {
ctx.visitor.visitSegment(segment, segmentPoint, true);
}
}
use of net.osmand.binary.RouteDataObject in project Osmand by osmandapp.
the class RouteResultPreparation method calculateTimeSpeed.
private void calculateTimeSpeed(RoutingContext ctx, List<RouteSegmentResult> result) throws IOException {
// for Naismith
boolean usePedestrianHeight = ((((GeneralRouter) ctx.getRouter()).getProfile() == GeneralRouterProfile.PEDESTRIAN) && ((GeneralRouter) ctx.getRouter()).getHeightObstacles());
for (int i = 0; i < result.size(); i++) {
RouteSegmentResult rr = result.get(i);
RouteDataObject road = rr.getObject();
double distOnRoadToPass = 0;
double speed = ctx.getRouter().defineVehicleSpeed(road);
if (speed == 0) {
speed = ctx.getRouter().getMinDefaultSpeed();
} else {
if (speed > 15) {
// decrease speed proportionally from 15ms=50kmh -
// reference speed 30ms=108kmh - 7kmh
speed = speed - ((speed - 15f) / (30f - 15f) * 2f);
}
}
boolean plus = rr.getStartPointIndex() < rr.getEndPointIndex();
int next;
double distance = 0;
// for Naismith
float prevHeight = -99999.0f;
float[] heightDistanceArray = null;
if (usePedestrianHeight) {
road.calculateHeightArray();
heightDistanceArray = road.heightDistanceArray;
}
for (int j = rr.getStartPointIndex(); j != rr.getEndPointIndex(); j = next) {
next = plus ? j + 1 : j - 1;
double d = measuredDist(road.getPoint31XTile(j), road.getPoint31YTile(j), road.getPoint31XTile(next), road.getPoint31YTile(next));
distance += d;
double obstacle = ctx.getRouter().defineObstacle(road, j);
if (obstacle < 0) {
obstacle = 0;
}
// this is time in seconds
distOnRoadToPass += d / speed + obstacle;
// for Naismith
if (usePedestrianHeight) {
int heightIndex = 2 * j + 1;
if (heightDistanceArray != null && heightIndex < heightDistanceArray.length) {
float height = heightDistanceArray[heightIndex];
if (prevHeight != -99999.0f) {
float heightDiff = height - prevHeight;
if (heightDiff > 0) {
// ascent only
// Naismith's rule: add 1 hour per every 600m of ascent
distOnRoadToPass += heightDiff * 6.0f;
}
}
prevHeight = height;
}
}
}
// last point turn time can be added
// if(i + 1 < result.size()) { distOnRoadToPass += ctx.getRouter().calculateTurnTime(); }
rr.setSegmentTime((float) distOnRoadToPass);
rr.setSegmentSpeed((float) speed);
rr.setDistance((float) distance);
}
}
use of net.osmand.binary.RouteDataObject in project Osmand by osmandapp.
the class RouteResultPreparation method splitRoadsAndAttachRoadSegments.
private void splitRoadsAndAttachRoadSegments(RoutingContext ctx, List<RouteSegmentResult> result) throws IOException {
for (int i = 0; i < result.size(); i++) {
if (ctx.checkIfMemoryLimitCritical(ctx.config.memoryLimitation)) {
ctx.unloadUnusedTiles(ctx.config.memoryLimitation);
}
RouteSegmentResult rr = result.get(i);
RouteDataObject road = rr.getObject();
checkAndInitRouteRegion(ctx, road);
boolean plus = rr.getStartPointIndex() < rr.getEndPointIndex();
int next;
for (int j = rr.getStartPointIndex(); j != rr.getEndPointIndex(); j = next) {
next = plus ? j + 1 : j - 1;
if (j == rr.getStartPointIndex()) {
attachRoadSegments(ctx, result, i, j, plus);
}
if (next != rr.getEndPointIndex()) {
attachRoadSegments(ctx, result, i, next, plus);
}
List<RouteSegmentResult> attachedRoutes = rr.getAttachedRoutes(next);
boolean tryToSplit = next != rr.getEndPointIndex() && !rr.getObject().roundabout() && attachedRoutes != null;
if (rr.getDistance(next, plus) == 0) {
// same point will be processed next step
tryToSplit = false;
}
if (tryToSplit) {
// avoid small zigzags
float before = rr.getBearing(next, !plus);
float after = rr.getBearing(next, plus);
if (rr.getDistance(next, plus) < 5) {
after = before + 180;
} else if (rr.getDistance(next, !plus) < 5) {
before = after - 180;
}
boolean straight = Math.abs(MapUtils.degreesDiff(before + 180, after)) < TURN_DEGREE_MIN;
boolean isSplit = false;
// split if needed
for (RouteSegmentResult rs : attachedRoutes) {
double diff = MapUtils.degreesDiff(before + 180, rs.getBearingBegin());
if (Math.abs(diff) <= TURN_DEGREE_MIN) {
isSplit = true;
} else if (!straight && Math.abs(diff) < 100) {
isSplit = true;
}
}
if (isSplit) {
int endPointIndex = rr.getEndPointIndex();
RouteSegmentResult split = new RouteSegmentResult(rr.getObject(), next, endPointIndex);
split.copyPreattachedRoutes(rr, Math.abs(next - rr.getStartPointIndex()));
rr.setEndPointIndex(next);
result.add(i + 1, split);
i++;
// switch current segment to the splitted
rr = split;
}
}
}
}
}
Aggregations