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); } }
void printResults(RoutingContext ctx, LatLon start, LatLon end, List<RouteSegmentResult> result) { float completeTime = 0; float completeDistance = 0; for (RouteSegmentResult r : result) { completeTime += r.getSegmentTime(); completeDistance += r.getDistance(); } println("ROUTE : "); double startLat = start.getLatitude(); double startLon = start.getLongitude(); double endLat = end.getLatitude(); double endLon = end.getLongitude(); StringBuilder add = new StringBuilder(); add.append("loadedTiles = \"").append(ctx.loadedTiles).append("\" "); add.append("visitedSegments = \"").append(ctx.visitedSegments).append("\" "); add.append("complete_distance = \"").append(completeDistance).append("\" "); add.append("complete_time = \"").append(completeTime).append("\" "); add.append("routing_time = \"").append(ctx.routingTime).append("\" "); println( MessageFormat.format( "<test regions=\"\" description=\"\" best_percent=\"\" vehicle=\"{4}\" \n" + " start_lat=\"{0}\" start_lon=\"{1}\" target_lat=\"{2}\" target_lon=\"{3}\" {5} >", startLat + "", startLon + "", endLat + "", endLon + "", ctx.config.routerName, add.toString())); if (PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST) { for (RouteSegmentResult res : result) { String name = res.getObject().getName(); String ref = res.getObject().getRef(); if (name == null) { name = ""; } if (ref != null) { name += " (" + ref + ") "; } StringBuilder additional = new StringBuilder(); additional.append("time = \"").append(res.getSegmentTime()).append("\" "); additional.append("name = \"").append(name).append("\" "); // float ms = res.getSegmentSpeed(); float ms = res.getObject().getMaximumSpeed(); if (ms > 0) { additional .append("maxspeed = \"") .append(ms * 3.6f) .append("\" ") .append(res.getObject().getHighway()) .append(" "); } additional.append("distance = \"").append(res.getDistance()).append("\" "); if (res.getTurnType() != null) { additional.append("turn = \"").append(res.getTurnType()).append("\" "); additional .append("turn_angle = \"") .append(res.getTurnType().getTurnAngle()) .append("\" "); if (res.getTurnType().getLanes() != null) { additional .append("lanes = \"") .append(Arrays.toString(res.getTurnType().getLanes())) .append("\" "); } } additional.append("start_bearing = \"").append(res.getBearingBegin()).append("\" "); additional.append("end_bearing = \"").append(res.getBearingEnd()).append("\" "); additional.append("description = \"").append(res.getDescription()).append("\" "); println( MessageFormat.format( "\t<segment id=\"{0}\" start=\"{1}\" end=\"{2}\" {3}/>", (res.getObject().getId()) + "", res.getStartPointIndex() + "", res.getEndPointIndex() + "", additional.toString())); } } println("</test>"); }