private TurnType processRoundaboutTurn( List<RouteSegmentResult> result, int i, boolean leftSide, RouteSegmentResult prev, RouteSegmentResult rr) { int exit = 1; RouteSegmentResult last = rr; for (int j = i; j < result.size(); j++) { RouteSegmentResult rnext = result.get(j); last = rnext; if (rnext.getObject().roundabout()) { boolean plus = rnext.getStartPointIndex() < rnext.getEndPointIndex(); int k = rnext.getStartPointIndex(); if (j == i) { k = plus ? k + 1 : k - 1; } while (k != rnext.getEndPointIndex()) { if (rnext.getAttachedRoutes(k).size() > 0) { exit++; } k = plus ? k + 1 : k - 1; } } else { break; } } // combine all roundabouts TurnType t = TurnType.valueOf("EXIT" + exit, leftSide); t.setTurnAngle((float) MapUtils.degreesDiff(last.getBearingBegin(), prev.getBearingEnd())); return t; }
private TurnType getTurnInfo(List<RouteSegmentResult> result, int i, boolean leftSide) { if (i == 0) { return TurnType.valueOf(TurnType.C, false); } RouteSegmentResult prev = result.get(i - 1); if (prev.getObject().roundabout()) { // already analyzed! return null; } RouteSegmentResult rr = result.get(i); if (rr.getObject().roundabout()) { return processRoundaboutTurn(result, i, leftSide, prev, rr); } TurnType t = null; if (prev != null) { boolean noAttachedRoads = rr.getAttachedRoutes(rr.getStartPointIndex()).size() == 0; // add description about turn double mpi = MapUtils.degreesDiff(prev.getBearingEnd(), rr.getBearingBegin()); if (noAttachedRoads) { // TODO VICTOR : look at the comment inside direction route // double begin = rr.getObject().directionRoute(rr.getStartPointIndex(), // rr.getStartPointIndex() < // rr.getEndPointIndex(), 25); // mpi = MapUtils.degreesDiff(prev.getBearingEnd(), begin); } if (mpi >= TURN_DEGREE_MIN) { if (mpi < 60) { t = TurnType.valueOf(TurnType.TSLL, leftSide); } else if (mpi < 120) { t = TurnType.valueOf(TurnType.TL, leftSide); } else if (mpi < 135 || leftSide) { t = TurnType.valueOf(TurnType.TSHL, leftSide); } else { t = TurnType.valueOf(TurnType.TU, leftSide); } } else if (mpi < -TURN_DEGREE_MIN) { if (mpi > -60) { t = TurnType.valueOf(TurnType.TSLR, leftSide); } else if (mpi > -120) { t = TurnType.valueOf(TurnType.TR, leftSide); } else if (mpi > -135 || !leftSide) { t = TurnType.valueOf(TurnType.TSHR, leftSide); } else { t = TurnType.valueOf(TurnType.TU, leftSide); } } else { t = attachKeepLeftInfoAndLanes(leftSide, prev, rr, t); } if (t != null) { t.setTurnAngle((float) -mpi); } } return t; }
private TurnType attachKeepLeftInfoAndLanes( boolean leftSide, RouteSegmentResult prev, RouteSegmentResult rr, TurnType t) { // keep left/right int[] lanes = null; boolean kl = false; boolean kr = false; List<RouteSegmentResult> attachedRoutes = rr.getAttachedRoutes(rr.getStartPointIndex()); int ls = prev.getObject().getLanes(); if (ls >= 0 && prev.getObject().getOneway() == 0) { ls = (ls + 1) / 2; } int left = 0; int right = 0; boolean speak = false; int speakPriority = Math.max( highwaySpeakPriority(prev.getObject().getHighway()), highwaySpeakPriority(rr.getObject().getHighway())); if (attachedRoutes != null) { for (RouteSegmentResult rs : attachedRoutes) { double ex = MapUtils.degreesDiff(rs.getBearingBegin(), rr.getBearingBegin()); double mpi = Math.abs(MapUtils.degreesDiff(prev.getBearingEnd(), rs.getBearingBegin())); int rsSpeakPriority = highwaySpeakPriority(rs.getObject().getHighway()); if (rsSpeakPriority != MAX_SPEAK_PRIORITY || speakPriority == MAX_SPEAK_PRIORITY) { if ((ex < TURN_DEGREE_MIN || mpi < TURN_DEGREE_MIN) && ex >= 0) { kl = true; int lns = rs.getObject().getLanes(); if (rs.getObject().getOneway() == 0) { lns = (lns + 1) / 2; } if (lns > 0) { right += lns; } speak = speak || rsSpeakPriority <= speakPriority; } else if ((ex > -TURN_DEGREE_MIN || mpi < TURN_DEGREE_MIN) && ex <= 0) { kr = true; int lns = rs.getObject().getLanes(); if (rs.getObject().getOneway() == 0) { lns = (lns + 1) / 2; } if (lns > 0) { left += lns; } speak = speak || rsSpeakPriority <= speakPriority; } } } } if (kr && left == 0) { left = 1; } else if (kl && right == 0) { right = 1; } int current = rr.getObject().getLanes(); if (rr.getObject().getOneway() == 0) { current = (current + 1) / 2; } if (current <= 0) { current = 1; } if (ls >= 0 /*&& current + left + right >= ls*/) { lanes = new int[current + left + right]; ls = current + left + right; for (int it = 0; it < ls; it++) { if (it < left || it >= left + current) { lanes[it] = 0; } else { lanes[it] = 1; } } // sometimes links are if ((current <= left + right) && (left > 1 || right > 1)) { speak = true; } } if (kl) { t = TurnType.valueOf(TurnType.KL, leftSide); t.setSkipToSpeak(!speak); } else if (kr) { t = TurnType.valueOf(TurnType.KR, leftSide); t.setSkipToSpeak(!speak); } if (t != null && lanes != null) { t.setLanes(lanes); } return t; }
private void calculateTimeSpeedAndAttachRoadSegments( 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); double distOnRoadToPass = 0; double speed = ctx.getRouter().defineSpeed(road); if (speed == 0) { speed = ctx.getRouter().getMinDefaultSpeed(); } boolean plus = rr.getStartPointIndex() < rr.getEndPointIndex(); int next; double distance = 0; 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); } 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; } distOnRoadToPass += d / speed + obstacle; List<RouteSegmentResult> attachedRoutes = rr.getAttachedRoutes(next); if (next != rr.getEndPointIndex() && !rr.getObject().roundabout() && attachedRoutes != null) { float before = rr.getBearing(next, !plus); float after = rr.getBearing(next, plus); 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.setSegmentTime((float) distOnRoadToPass); rr.setSegmentSpeed((float) speed); rr.setDistance((float) distance); rr.setEndPointIndex(next); result.add(i + 1, split); i++; // switch current segment to the splitted rr = split; distOnRoadToPass = 0; distance = 0; } } } // 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); } }