diff --git a/brouter-core/src/main/java/btools/router/OsmPath.java b/brouter-core/src/main/java/btools/router/OsmPath.java index c76089b..4a42b0c 100644 --- a/brouter-core/src/main/java/btools/router/OsmPath.java +++ b/brouter-core/src/main/java/btools/router/OsmPath.java @@ -139,7 +139,10 @@ abstract class OsmPath implements OsmLinkHolder protected void addAddionalPenalty(OsmTrack refTrack, boolean detailMode, OsmPath origin, OsmLink link, RoutingContext rc ) { byte[] description = link.descriptionBitmap; - if ( description == null ) throw new IllegalArgumentException( "null description for: " + link ); + if ( description == null ) + { + return; // could be a beeline path + } boolean recordTransferNodes = detailMode || rc.countTraffic; diff --git a/brouter-core/src/main/java/btools/router/RoutingContext.java b/brouter-core/src/main/java/btools/router/RoutingContext.java index 3e207fd..204a072 100644 --- a/brouter-core/src/main/java/btools/router/RoutingContext.java +++ b/brouter-core/src/main/java/btools/router/RoutingContext.java @@ -16,6 +16,7 @@ import btools.expressions.BExpressionContextNode; import btools.expressions.BExpressionContextWay; import btools.mapaccess.GeometryDecoder; import btools.mapaccess.OsmLink; +import btools.mapaccess.OsmNode; import btools.util.CheapAngleMeter; import btools.util.CheapRuler; @@ -191,6 +192,7 @@ public final class RoutingContext public List poipoints; public List nogopoints = null; + private List nogopoints_all = null; // full list not filtered for wayoints-in-nogos private List keepnogopoints = null; private OsmNodeNamed pendingEndpoint = null; @@ -258,14 +260,29 @@ public final class RoutingContext } } - public void cleanNogolist( List waypoints ) + /** + * restore the full nogolist previously saved by cleanNogoList + */ + public void restoreNogoList() { + nogopoints = nogopoints_all; + } + + /** + * clean the nogolist (previoulsy saved by saveFullNogolist()) + * by removing nogos with waypoints within + * + * @return true if all wayoints are all in the same (full-weigth) nogo area (triggering bee-line-mode) + */ + public void cleanNogoList( List waypoints ) + { + nogopoints_all = nogopoints; if ( nogopoints == null ) return; List nogos = new ArrayList(); for( OsmNodeNamed nogo : nogopoints ) { boolean goodGuy = true; - for( OsmNodeNamed wp : waypoints ) + for( OsmNode wp : waypoints ) { if ( wp.calcDistance( nogo ) < nogo.radius && (!(nogo instanceof OsmNogoPolygon) @@ -274,7 +291,6 @@ public final class RoutingContext : ((OsmNogoPolygon)nogo).isOnPolyline(wp.ilon, wp.ilat)))) { goodGuy = false; - break; } } if ( goodGuy ) nogos.add( nogo ); @@ -282,6 +298,31 @@ public final class RoutingContext nogopoints = nogos.isEmpty() ? null : nogos; } + public boolean allInOneNogo( List waypoints ) + { + if ( nogopoints == null ) return false; + boolean allInTotal = false; + for( OsmNodeNamed nogo : nogopoints ) + { + boolean allIn = Double.isNaN( nogo.nogoWeight ); + for( OsmNode wp : waypoints ) + { + int dist = wp.calcDistance( nogo ); + if ( dist < nogo.radius + && (!(nogo instanceof OsmNogoPolygon) + || (((OsmNogoPolygon)nogo).isClosed + ? ((OsmNogoPolygon)nogo).isWithin(wp.ilon, wp.ilat) + : ((OsmNogoPolygon)nogo).isOnPolyline(wp.ilon, wp.ilat)))) + { + continue; + } + allIn = false; + } + allInTotal |= allIn; + } + return allInTotal; + } + public long[] getNogoChecksums() { long[] cs = new long[3]; diff --git a/brouter-core/src/main/java/btools/router/RoutingEngine.java b/brouter-core/src/main/java/btools/router/RoutingEngine.java index 9fcea0b..1f9c99b 100644 --- a/brouter-core/src/main/java/btools/router/RoutingEngine.java +++ b/brouter-core/src/main/java/btools/router/RoutingEngine.java @@ -151,9 +151,6 @@ public class RoutingEngine extends Thread { try { - // delete nogos with waypoints in them - routingContext.cleanNogolist( waypoints ); - startTime = System.currentTimeMillis(); long startTime0 = startTime; this.maxRunningTime = maxRunningTime; @@ -459,6 +456,29 @@ public class RoutingEngine extends Thread } private OsmTrack searchTrack( MatchedWaypoint startWp, MatchedWaypoint endWp, OsmTrack nearbyTrack, OsmTrack refTrack ) + { + // remove nogos with waypoints inside + try + { + List wpts2 = new ArrayList(); + wpts2.add( startWp.waypoint ); + wpts2.add( endWp.waypoint ); + boolean calcBeeline = routingContext.allInOneNogo(wpts2); + + if ( !calcBeeline ) return searchRoutedTrack( startWp, endWp, nearbyTrack, refTrack ); + + // we want a beeline-segment + OsmPath path = routingContext.createPath( new OsmLink( null, startWp.crosspoint ) ); + path = routingContext.createPath( path, new OsmLink( startWp.crosspoint, endWp.crosspoint ), null, false ); + return compileTrack( path, false ); + } + finally + { + routingContext.restoreNogoList(); + } + } + + private OsmTrack searchRoutedTrack( MatchedWaypoint startWp, MatchedWaypoint endWp, OsmTrack nearbyTrack, OsmTrack refTrack ) { OsmTrack track = null; double[] airDistanceCostFactors = new double[]{ routingContext.pass1coefficient, routingContext.pass2coefficient }; @@ -650,6 +670,11 @@ public class RoutingEngine extends Thread { try { + List wpts2 = new ArrayList(); + if ( startWp != null ) wpts2.add( startWp.waypoint ); + if ( endWp != null ) wpts2.add( endWp.waypoint ); + routingContext.cleanNogoList(wpts2); + boolean detailed = guideTrack != null; resetCache( detailed ); nodesCache.nodesMap.cleanupMode = detailed ? 0 : ( routingContext.considerTurnRestrictions ? 2 : 1 ); @@ -657,6 +682,7 @@ public class RoutingEngine extends Thread } finally { + routingContext.restoreNogoList(); nodesCache.clean( false ); // clean only non-virgin caches } }