From 15dd1f30f1874189bfbb31a98cbf253c2446cd3b Mon Sep 17 00:00:00 2001 From: afischerdev Date: Sun, 19 Feb 2023 13:45:47 +0100 Subject: [PATCH] add rework vh process and add post process --- .../src/main/java/btools/router/OsmTrack.java | 4 +- .../btools/router/VoiceHintProcessor.java | 135 +++++++++++++++--- 2 files changed, 122 insertions(+), 17 deletions(-) diff --git a/brouter-core/src/main/java/btools/router/OsmTrack.java b/brouter-core/src/main/java/btools/router/OsmTrack.java index abd2b07..2896b9d 100644 --- a/brouter-core/src/main/java/btools/router/OsmTrack.java +++ b/brouter-core/src/main/java/btools/router/OsmTrack.java @@ -1080,7 +1080,9 @@ public final class OsmTrack { VoiceHintProcessor vproc = new VoiceHintProcessor(rc.turnInstructionCatchingRange, rc.turnInstructionRoundabouts); List results = vproc.process(inputs); - for (VoiceHint hint : results) { + double minDistance = getMinDistance(); + List < VoiceHint > resultsLast = vproc.postProcess(results, rc.turnInstructionCatchingRange, minDistance); + for (VoiceHint hint: resultsLast) { voiceHints.list.add(hint); } diff --git a/brouter-core/src/main/java/btools/router/VoiceHintProcessor.java b/brouter-core/src/main/java/btools/router/VoiceHintProcessor.java index 7ae23a7..d7ac010 100644 --- a/brouter-core/src/main/java/btools/router/VoiceHintProcessor.java +++ b/brouter-core/src/main/java/btools/router/VoiceHintProcessor.java @@ -9,18 +9,22 @@ import java.util.ArrayList; import java.util.List; public final class VoiceHintProcessor { - private double catchingRange; // range to catch angles and merge turns + + double SIGNIFICANT_ANGLE = 22.5; + double INTERNAL_CATCHING_RANGE = 2.; + + // private double catchingRange; // range to catch angles and merge turns private boolean explicitRoundabouts; public VoiceHintProcessor(double catchingRange, boolean explicitRoundabouts) { - this.catchingRange = catchingRange; + // this.catchingRange = catchingRange; this.explicitRoundabouts = explicitRoundabouts; } private float sumNonConsumedWithinCatchingRange(List inputs, int offset) { double distance = 0.; float angle = 0.f; - while (offset >= 0 && distance < catchingRange) { + while (offset >= 0 && distance < INTERNAL_CATCHING_RANGE) { VoiceHint input = inputs.get(offset--); if (input.turnAngleConsumed) { break; @@ -60,6 +64,10 @@ public final class VoiceHintProcessor { for (int hintIdx = 0; hintIdx < inputs.size(); hintIdx++) { VoiceHint input = inputs.get(hintIdx); + if (input.cmd == VoiceHint.BL) { + results.add(input); + continue; + } float turnAngle = input.goodWay.turnangle; distance += input.goodWay.linkdist; int currentPrio = input.goodWay.getPrio(); @@ -67,6 +75,7 @@ public final class VoiceHintProcessor { int minPrio = Math.min(oldPrio, currentPrio); boolean isLink2Highway = input.oldWay.isLinktType() && !input.goodWay.isLinktType(); + boolean isHighway2Link = !input.oldWay.isLinktType() && input.goodWay.isLinktType(); if (input.oldWay.isRoundabout()) { roundAboutTurnAngle += sumNonConsumedWithinCatchingRange(inputs, hintIdx); @@ -101,14 +110,18 @@ public final class VoiceHintProcessor { float minAngle = 180.f; float minAbsAngeRaw = 180.f; + boolean isBadwayLink = false; + if (input.badWays != null) { for (MessageData badWay : input.badWays) { int badPrio = badWay.getPrio(); float badTurn = badWay.turnangle; + if (badWay.isLinktType()) { + isBadwayLink = true; + } + boolean isBadHighway2Link = !input.oldWay.isLinktType() && badWay.isLinktType(); - boolean isHighway2Link = !input.oldWay.isLinktType() && badWay.isLinktType(); - - if (badPrio > maxPrioAll && !isHighway2Link) { + if (badPrio > maxPrioAll && !isBadHighway2Link) { maxPrioAll = badPrio; } @@ -140,12 +153,17 @@ public final class VoiceHintProcessor { } } - boolean hasSomethingMoreStraight = Math.abs(turnAngle) - minAbsAngeRaw > 20.; + boolean hasSomethingMoreStraight = (Math.abs(turnAngle) - minAbsAngeRaw) > 20.; // unconditional triggers are all junctions with // - higher detour prios than the minimum route prio (except link->highway junctions) // - or candidate detours with higher prio then the route exit leg - boolean unconditionalTrigger = hasSomethingMoreStraight || (maxPrioAll > minPrio && !isLink2Highway) || (maxPrioCandidates > currentPrio); + boolean unconditionalTrigger = hasSomethingMoreStraight || + (maxPrioAll > minPrio && !isLink2Highway) || + (maxPrioCandidates > currentPrio) || + VoiceHint.is180DegAngle(turnAngle) || + (!isHighway2Link && isBadwayLink && Math.abs(turnAngle) > 5.f) || + (isHighway2Link && !isBadwayLink && Math.abs(turnAngle) < 5.f); // conditional triggers (=real turning angle required) are junctions // with candidate detours equal in priority than the route exit leg @@ -158,11 +176,13 @@ public final class VoiceHintProcessor { input.needsRealTurn = (!unconditionalTrigger) && isStraight; // check for KR/KL - if (maxAngle < turnAngle && maxAngle > turnAngle - 45.f - (turnAngle > 0.f ? turnAngle : 0.f)) { - input.cmd = VoiceHint.KR; - } - if (minAngle > turnAngle && minAngle < turnAngle + 45.f - (turnAngle < 0.f ? turnAngle : 0.f)) { - input.cmd = VoiceHint.KL; + if (Math.abs(turnAngle) > 5.) { // don't use to small angles + if (maxAngle < turnAngle && maxAngle > turnAngle - 45.f - (Math.max(turnAngle, 0.f))) { + input.cmd = VoiceHint.KR; + } + if (minAngle > turnAngle && minAngle < turnAngle + 45.f - (Math.min(turnAngle, 0.f))) { + input.cmd = VoiceHint.KL; + } } input.angle = sumNonConsumedWithinCatchingRange(inputs, hintIdx); @@ -170,7 +190,7 @@ public final class VoiceHintProcessor { distance = 0.; results.add(input); } - if (results.size() > 0 && distance < catchingRange) { + if (results.size() > 0 && distance < INTERNAL_CATCHING_RANGE) { //catchingRange results.get(results.size() - 1).angle += sumNonConsumedWithinCatchingRange(inputs, hintIdx); } } @@ -185,10 +205,10 @@ public final class VoiceHintProcessor { if (hint.cmd == 0) { hint.calcCommand(); } - if (!(hint.needsRealTurn && hint.cmd == VoiceHint.C)) { + if (!(hint.needsRealTurn && (hint.cmd == VoiceHint.C || hint.cmd == VoiceHint.BL))) { double dist = hint.distanceToNext; // sum up other hints within the catching range (e.g. 40m) - while (dist < catchingRange && i > 0) { + while (dist < INTERNAL_CATCHING_RANGE && i > 0) { VoiceHint h2 = results.get(i - 1); dist = h2.distanceToNext; hint.distanceToNext += dist; @@ -207,9 +227,92 @@ public final class VoiceHintProcessor { } hint.calcCommand(); results2.add(hint); + } else if (hint.cmd == VoiceHint.BL) { + results2.add(hint); + } else { + if (results2.size() > 0) + results2.get(results2.size() - 1).distanceToNext += hint.distanceToNext; } } return results2; } + public List postProcess(List inputs, double catchingRange, double minRange) { + List results = new ArrayList(); + double distance = 0; + VoiceHint inputLast = null; + ArrayList tmpList = new ArrayList<>(); + for (int hintIdx = 0; hintIdx < inputs.size(); hintIdx++) { + VoiceHint input = inputs.get(hintIdx); + + if (input.cmd == VoiceHint.C && !input.goodWay.isLinktType()) { + int badWayPrio = 0; + for (MessageData md : input.badWays) { + badWayPrio = Math.max(badWayPrio, md.getPrio()); + } + if (input.goodWay.getPrio() < badWayPrio) { + results.add(input); + } else { + if (inputLast != null) { // when drop add distance to last + inputLast.distanceToNext += input.distanceToNext; + } + continue; + } + } else { + if (input.distanceToNext < catchingRange) { + double dist = input.distanceToNext; + float angles = input.angle; + int i = 1; + boolean save = true; + tmpList.clear(); + while (dist < catchingRange && hintIdx + i < inputs.size()) { + VoiceHint h2 = inputs.get(hintIdx + i); + dist += h2.distanceToNext; + angles += h2.angle; + if (VoiceHint.is180DegAngle(input.angle) || VoiceHint.is180DegAngle(h2.angle)) { // u-turn, 180 degree + save = true; + break; + } else if (Math.abs(angles) > 180 - SIGNIFICANT_ANGLE) { // u-turn, collects e.g. two left turns in range + input.angle = angles; + input.calcCommand(); + input.distanceToNext += h2.distanceToNext; + save = true; + hintIdx++; + break; + } else if (Math.abs(angles) < SIGNIFICANT_ANGLE && input.distanceToNext < minRange) { + input.angle = angles; + input.calcCommand(); + input.distanceToNext += h2.distanceToNext; + save = true; + hintIdx++; + break; + } else if (Math.abs(input.angle) > SIGNIFICANT_ANGLE) { + tmpList.add(h2); + hintIdx++; + } else if (dist > catchingRange) { // distance reached + break; + } else { + if (inputLast != null) { // when drop add distance to last + inputLast.distanceToNext += input.distanceToNext; + } + save = false; + } + i++; + } + if (save) { + results.add(input); // add when last + if (tmpList.size() > 0) { // add when something in stock + results.addAll(tmpList); + hintIdx += tmpList.size() - 1; + } + } + } else { + results.add(input); + } + inputLast = input; + } + } + return results; + } + }