From 91c809e05c88cf0c1378d353c73b9819bf29c540 Mon Sep 17 00:00:00 2001 From: Arndt Date: Fri, 28 Aug 2015 16:39:41 +0200 Subject: [PATCH] Traffic simulation patch --- .../src/main/java/btools/router/OsmPath.java | 96 +++- .../java/btools/router/OsmPathElement.java | 45 +- .../router/OsmPathElementWithTraffic.java | 78 +++ .../src/main/java/btools/router/OsmTrack.java | 4 +- .../java/btools/router/RoutingContext.java | 28 +- .../java/btools/router/RoutingEngine.java | 108 +++- .../java/btools/router/SearchBoundary.java | 87 ++++ .../java/btools/expressions/BExpression.java | 6 + .../expressions/BExpressionContextWay.java | 4 +- .../main/java/btools/mapcreator/OsmNodeP.java | 22 +- .../java/btools/mapcreator/OsmTrafficMap.java | 158 ++++++ .../btools/mapcreator/TrafficData2Png.java | 154 ++++++ .../java/btools/mapcreator/WayLinker.java | 31 +- .../btools/memrouter/ScheduledRouter.java | 2 +- .../src/main/java/btools/server/BRouter.java | 40 +- .../main/java/btools/server/RouteServer.java | 3 +- .../main/java/btools/util/FrozenLongMap.java | 5 + .../src/main/java/btools/util/Raster2Png.java | 464 ++++++++++++++++++ misc/profiles2/car-traffic_analysis.brf | 125 +++++ misc/profiles2/dummy.brf | 7 + misc/profiles2/fastbike-lowtraffic.brf | 201 ++++++++ misc/profiles2/lookups.dat | 10 +- 22 files changed, 1595 insertions(+), 83 deletions(-) create mode 100644 brouter-core/src/main/java/btools/router/OsmPathElementWithTraffic.java create mode 100644 brouter-core/src/main/java/btools/router/SearchBoundary.java create mode 100644 brouter-map-creator/src/main/java/btools/mapcreator/OsmTrafficMap.java create mode 100644 brouter-map-creator/src/main/java/btools/mapcreator/TrafficData2Png.java create mode 100644 brouter-util/src/main/java/btools/util/Raster2Png.java create mode 100644 misc/profiles2/car-traffic_analysis.brf create mode 100644 misc/profiles2/dummy.brf create mode 100644 misc/profiles2/fastbike-lowtraffic.brf diff --git a/brouter-core/src/main/java/btools/router/OsmPath.java b/brouter-core/src/main/java/btools/router/OsmPath.java index 7cc4824..32fd056 100644 --- a/brouter-core/src/main/java/btools/router/OsmPath.java +++ b/brouter-core/src/main/java/btools/router/OsmPath.java @@ -5,7 +5,13 @@ */ package btools.router; -import btools.mapaccess.*; +import java.io.IOException; +import java.util.ArrayList; + +import btools.mapaccess.OsmLink; +import btools.mapaccess.OsmLinkHolder; +import btools.mapaccess.OsmNode; +import btools.mapaccess.OsmTransferNode; final class OsmPath implements OsmLinkHolder { @@ -29,6 +35,9 @@ final class OsmPath implements OsmLinkHolder private OsmNode sourcenode; private OsmLink link; public OsmPathElement originElement; + public OsmPathElement myElement; + + private float traffic; private OsmLinkHolder nextForLink = null; @@ -44,6 +53,32 @@ final class OsmPath implements OsmLinkHolder public MessageData message; + public void unregisterUpTree( RoutingContext rc ) + { + try + { + OsmPathElement pe = originElement; + while( pe instanceof OsmPathElementWithTraffic && ((OsmPathElementWithTraffic)pe).unregister(rc) ) + { + pe = pe.origin; + } + } + catch( IOException ioe ) + { + throw new RuntimeException( ioe ); + } + } + + public void registerUpTree() + { + if ( originElement instanceof OsmPathElementWithTraffic ) + { + OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic)originElement; + ot.register(); + ot.addTraffic( traffic ); + } + } + OsmPath() { } @@ -55,23 +90,30 @@ final class OsmPath implements OsmLinkHolder this.selev = link.targetNode.getSElev(); } - OsmPath( OsmNode sourcenode, OsmPath origin, OsmLink link, OsmTrack refTrack, boolean recordTransferNodes, RoutingContext rc ) + OsmPath( OsmNode sourcenode, OsmPath origin, OsmLink link, OsmTrack refTrack, boolean detailMode, RoutingContext rc ) { this(); - this.originElement = new OsmPathElement( origin ); + if ( origin.myElement == null ) + { + origin.myElement = OsmPathElement.create( origin, rc.countTraffic ); + } + this.originElement = origin.myElement; this.link = link; this.sourcenode = sourcenode; this.cost = origin.cost; this.ehbd = origin.ehbd; this.ehbu = origin.ehbu; this.lastClassifier = origin.lastClassifier; - addAddionalPenalty(refTrack, recordTransferNodes, origin, link, rc ); + addAddionalPenalty(refTrack, detailMode, origin, link, rc ); } - private void addAddionalPenalty(OsmTrack refTrack, boolean recordTransferNodes, OsmPath origin, OsmLink link, RoutingContext rc ) + private void addAddionalPenalty(OsmTrack refTrack, boolean detailMode, OsmPath origin, OsmLink link, RoutingContext rc ) { if ( link.descriptionBitmap == null ) throw new IllegalArgumentException( "null description for class: " + link.getClass() ); - + + boolean recordTransferNodes = detailMode || rc.countTraffic; + boolean recordMessageData = detailMode; + rc.nogomatch = false; // extract the 3 positions of the first section @@ -117,10 +159,10 @@ final class OsmPath implements OsmLinkHolder } rc.messageHandler.setCurrentPos( lon2, lat2 ); - boolean sameData = rc.expctxWay.evaluate( link.counterLinkWritten, description, rc.messageHandler ); + boolean sameData = rc.expctxWay.evaluate( rc.inverseDirection ^ link.counterLinkWritten, description, rc.messageHandler ); // if way description changed, store message - if ( msgData.wayKeyValues != null && !sameData ) + if ( recordMessageData && msgData.wayKeyValues != null && !sameData ) { originElement.message = msgData; msgData = new MessageData(); @@ -147,7 +189,7 @@ final class OsmPath implements OsmLinkHolder { if ( rc.wayfraction > 0. ) { - originElement = new OsmPathElement( rc.ilonshortest, rc.ilatshortest, ele2, null ); + originElement = OsmPathElement.create( rc.ilonshortest, rc.ilatshortest, ele2, null, rc.countTraffic ); } else { @@ -160,9 +202,10 @@ final class OsmPath implements OsmLinkHolder msgData.linkdist += dist; linkdisttotal += dist; + boolean isTrafficBackbone = cost == 0 && rc.expctxWay.getIsTrafficBackbone() > 0.f; // *** penalty for turning angles - if ( origin.originElement != null ) + if ( !isTrafficBackbone && origin.originElement != null ) { // penalty proportional to direction change double cos = rc.calcCosAngle( lon0, lat0, lon1, lat1, lon2, lat2 ); @@ -251,6 +294,12 @@ final class OsmPath implements OsmLinkHolder cfdown = cfdown == 0.f ? cf : cfdown; float costfactor = cfup*upweight + cf*(1.f - upweight - downweight) + cfdown*downweight; + + if ( isTrafficBackbone ) + { + costfactor = 0.f; + } + float fcost = dist * costfactor + 0.5f; if ( costfactor > 9999. || fcost + cost >= 2000000000. ) { @@ -260,6 +309,12 @@ final class OsmPath implements OsmLinkHolder int waycost = (int)(fcost); cost += waycost; + // calculate traffic + { + int minDist = (int)rc.trafficSourceMinDist; + int cost2 = cost < minDist ? minDist : cost; + traffic += dist*rc.expctxWay.getTrafficSourceDensity()*Math.pow(cost2/10000.f,rc.trafficSourceExponent); + } // *** add initial cost if the classifier changed float newClassifier = rc.expctxWay.getInitialClassifier(); if ( newClassifier == 0. ) @@ -276,7 +331,7 @@ final class OsmPath implements OsmLinkHolder cost += iicost; } - if ( recordTransferNodes ) + if ( recordMessageData ) { msgData.costfactor = costfactor; msgData.lon = lon2; @@ -289,9 +344,12 @@ final class OsmPath implements OsmLinkHolder { if ( recordTransferNodes ) { - originElement = new OsmPathElement( rc.ilonshortest, rc.ilatshortest, ele2, originElement ); + originElement = OsmPathElement.create( rc.ilonshortest, rc.ilatshortest, ele2, originElement, rc.countTraffic ); originElement.cost = cost; - originElement.message = msgData; + if ( recordMessageData ) + { + originElement.message = msgData; + } } if ( rc.nogomatch ) { @@ -315,8 +373,10 @@ final class OsmPath implements OsmLinkHolder if ( recordTransferNodes ) { - originElement = new OsmPathElement( lon2, lat2, ele2, originElement ); + originElement = OsmPathElement.create( lon2, lat2, ele2, originElement, rc.countTraffic ); originElement.cost = cost; + originElement.addTraffic( traffic ); + traffic = 0; } lon0 = lon1; lat0 = lat1; @@ -350,13 +410,15 @@ final class OsmPath implements OsmLinkHolder cost += iicost; - if ( recordTransferNodes ) + if ( recordMessageData ) { msgData.nodeKeyValues = rc.expctxNode.getKeyValueDescription( nodeAccessGranted, targetNode.nodeDescription ); } } - - message = msgData; + if ( recordMessageData ) + { + message = msgData; + } } diff --git a/brouter-core/src/main/java/btools/router/OsmPathElement.java b/brouter-core/src/main/java/btools/router/OsmPathElement.java index 7a13be1..f382479 100644 --- a/brouter-core/src/main/java/btools/router/OsmPathElement.java +++ b/brouter-core/src/main/java/btools/router/OsmPathElement.java @@ -13,7 +13,7 @@ import java.io.IOException; * @author ab */ -public final class OsmPathElement implements OsmPos +public class OsmPathElement implements OsmPos { private int ilat; // latitude private int ilon; // longitude @@ -24,32 +24,32 @@ public final class OsmPathElement implements OsmPos public int cost; // interface OsmPos - public int getILat() + public final int getILat() { return ilat; } - public int getILon() + public final int getILon() { return ilon; } - public short getSElev() + public final short getSElev() { return selev; } - public double getElev() + public final double getElev() { return selev / 4.; } - public long getIdFromPos() + public final long getIdFromPos() { return ((long)ilon)<<32 | ilat; } - public int calcDistance( OsmPos p ) + public final int calcDistance( OsmPos p ) { double l = (ilat-90000000) * 0.00000001234134; double l2 = l*l; @@ -65,27 +65,30 @@ public final class OsmPathElement implements OsmPos public OsmPathElement origin; // construct a path element from a path - public OsmPathElement( OsmPath path ) + public static final OsmPathElement create( OsmPath path, boolean countTraffic ) { OsmNode n = path.getLink().targetNode; - ilat = n.getILat(); - ilon = n.getILon(); - selev = path.selev; - cost = path.cost; - - origin = path.originElement; - message = path.message; + OsmPathElement pe = create( n.getILon(), n.getILat(), path.selev, path.originElement, countTraffic ); + pe.cost = path.cost; + pe.message = path.message; + return pe; } - public OsmPathElement( int ilon, int ilat, short selev, OsmPathElement origin ) + public static final OsmPathElement create( int ilon, int ilat, short selev, OsmPathElement origin, boolean countTraffic ) { - this.ilon = ilon; - this.ilat = ilat; - this.selev = selev; - this.origin = origin; + OsmPathElement pe = countTraffic ? new OsmPathElementWithTraffic() : new OsmPathElement(); + pe.ilon = ilon; + pe.ilat = ilat; + pe.selev = selev; + pe.origin = origin; + return pe; } - private OsmPathElement() + protected OsmPathElement() + { + } + + public void addTraffic( float traffic ) { } diff --git a/brouter-core/src/main/java/btools/router/OsmPathElementWithTraffic.java b/brouter-core/src/main/java/btools/router/OsmPathElementWithTraffic.java new file mode 100644 index 0000000..aa8cb5a --- /dev/null +++ b/brouter-core/src/main/java/btools/router/OsmPathElementWithTraffic.java @@ -0,0 +1,78 @@ +package btools.router; + +import java.io.IOException; + + +/** + * Extension to OsmPathElement to count traffic load + * + * @author ab + */ + +public final class OsmPathElementWithTraffic extends OsmPathElement +{ + private int registerCount; + private float farTraffic; + private float nearTraffic; + + public void register() + { + if ( registerCount++ == 0 ) + { + if ( origin instanceof OsmPathElementWithTraffic ) + { + OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic)origin; + ot.register(); + ot.farTraffic += farTraffic; + ot.nearTraffic += nearTraffic; + farTraffic = 0; + nearTraffic = 0; + } + } + } + + @Override + public void addTraffic( float traffic ) + { + this.farTraffic += traffic; + this.nearTraffic += traffic; + } + + // unregister from origin if our registercount is 0, else do nothing + +public static double maxtraffic = 0.; + + public boolean unregister( RoutingContext rc ) throws IOException + { + if ( --registerCount == 0 ) + { + if ( origin instanceof OsmPathElementWithTraffic ) + { + OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic)origin; + + int costdelta = cost-ot.cost; + ot.farTraffic += farTraffic*Math.exp(-costdelta/rc.farTrafficDecayLength); + ot.nearTraffic += nearTraffic*Math.exp(-costdelta/rc.nearTrafficDecayLength); + +if ( costdelta > 0 && farTraffic > maxtraffic ) maxtraffic = farTraffic; + + int t2 = cost == ot.cost ? -1 : (int)(rc.farTrafficWeight*farTraffic + rc.nearTrafficWeight*nearTraffic); + + if ( t2 > 4000 || t2 == -1 ) + { + // System.out.println( "unregistered: " + this + " origin=" + ot + " farTraffic =" + farTraffic + " nearTraffic =" + nearTraffic + " cost=" + cost ); + if ( rc.trafficOutputStream != null ) + { + rc.trafficOutputStream.writeLong( getIdFromPos()); + rc.trafficOutputStream.writeLong( ot.getIdFromPos()); + rc.trafficOutputStream.writeInt( t2 ); + } + } + farTraffic = 0; + nearTraffic = 0; + } + return true; + } + return false; + } +} diff --git a/brouter-core/src/main/java/btools/router/OsmTrack.java b/brouter-core/src/main/java/btools/router/OsmTrack.java index e89c0c8..e8a2242 100644 --- a/brouter-core/src/main/java/btools/router/OsmTrack.java +++ b/brouter-core/src/main/java/btools/router/OsmTrack.java @@ -32,7 +32,7 @@ public final class OsmTrack public MatchedWaypoint endPoint; public long[] nogoChecksums; - private class OsmPathElementHolder + private static class OsmPathElementHolder { public OsmPathElement node; public OsmPathElementHolder nextHolder; @@ -448,7 +448,7 @@ public final class OsmTrack idx2 += 6; int idx3 = line.indexOf( '"', idx2 ); int ilat = (int)((Double.parseDouble( line.substring( idx2, idx3 ) ) + 90. )*1000000. + 0.5); - nodes.add( new OsmPathElement( ilon, ilat, (short)0, null ) ); + nodes.add( OsmPathElement.create( ilon, ilat, (short)0, null, false ) ); } } br.close(); diff --git a/brouter-core/src/main/java/btools/router/RoutingContext.java b/brouter-core/src/main/java/btools/router/RoutingContext.java index bdd3eca..67b548f 100644 --- a/brouter-core/src/main/java/btools/router/RoutingContext.java +++ b/brouter-core/src/main/java/btools/router/RoutingContext.java @@ -5,11 +5,15 @@ */ package btools.router; +import java.io.DataOutput; import java.util.ArrayList; import java.util.List; -import btools.mapaccess.*; -import btools.expressions.*; +import btools.expressions.BExpressionContext; +import btools.expressions.BExpressionContextNode; +import btools.expressions.BExpressionContextWay; +import btools.mapaccess.DistanceChecker; +import btools.mapaccess.OsmTransferNode; public final class RoutingContext implements DistanceChecker { @@ -83,6 +87,14 @@ public final class RoutingContext implements DistanceChecker buffertime = expctxGlobal.getVariableValue( "buffertime", 120.f ); waittimeadjustment = expctxGlobal.getVariableValue( "waittimeadjustment", 0.9f ); starttimeoffset = expctxGlobal.getVariableValue( "starttimeoffset", 0.f ); + + farTrafficWeight = expctxGlobal.getVariableValue( "farTrafficWeight", 2.f ); + nearTrafficWeight = expctxGlobal.getVariableValue( "nearTrafficWeight", 2.f ); + farTrafficDecayLength = expctxGlobal.getVariableValue( "farTrafficDecayLength", 30000.f ); + nearTrafficDecayLength = expctxGlobal.getVariableValue( "nearTrafficDecayLength", 3000.f ); + trafficDirectionFactor = expctxGlobal.getVariableValue( "trafficDirectionFactor", 0.9f ); + trafficSourceExponent = expctxGlobal.getVariableValue( "trafficSourceExponent", -0.7f ); + trafficSourceMinDist = expctxGlobal.getVariableValue( "trafficSourceMinDist", 3000.f ); } public RoutingMessageHandler messageHandler = new RoutingMessageHandler(); @@ -99,6 +111,18 @@ public final class RoutingContext implements DistanceChecker public int ilatshortest; public int ilonshortest; + public boolean countTraffic; + public boolean inverseDirection; + public DataOutput trafficOutputStream; + + public double farTrafficWeight; + public double nearTrafficWeight; + public double farTrafficDecayLength; + public double nearTrafficDecayLength; + public double trafficDirectionFactor; + public double trafficSourceExponent; + public double trafficSourceMinDist; + public static void prepareNogoPoints( List nogos ) { for( OsmNodeNamed nogo : nogos ) diff --git a/brouter-core/src/main/java/btools/router/RoutingEngine.java b/brouter-core/src/main/java/btools/router/RoutingEngine.java index 579d9df..4370535 100644 --- a/brouter-core/src/main/java/btools/router/RoutingEngine.java +++ b/brouter-core/src/main/java/btools/router/RoutingEngine.java @@ -46,14 +46,15 @@ public class RoutingEngine extends Thread private Writer infoLogWriter; protected RoutingContext routingContext; - private double airDistanceCostFactor; + public double airDistanceCostFactor; private OsmTrack guideTrack; private OsmPathElement matchPath; private long startTime; private long maxRunningTime; - + public SearchBoundary boundary; + public boolean quite = false; public RoutingEngine( String outfileBase, String logfileBase, String segmentDir, @@ -231,6 +232,51 @@ public class RoutingEngine extends Thread } } + public void doSearch() + { + try + { + MatchedWaypoint seedPoint = matchNodeForPosition( waypoints.get(0) ); + routingContext.countTraffic = true; + + findTrack( "seededSearch", seedPoint, null, null, null, false ); + } + catch( IllegalArgumentException e) + { + errorMessage = e.getMessage(); + logInfo( "Exception (linksProcessed=" + linksProcessed + ": " + errorMessage ); + } + catch( Exception e) + { + errorMessage = e instanceof IllegalArgumentException ? e.getMessage() : e.toString(); + logInfo( "Exception (linksProcessed=" + linksProcessed + ": " + errorMessage ); + e.printStackTrace(); + } + catch( Error e) + { + String hint = cleanOnOOM(); + errorMessage = e.toString() + hint; + logInfo( "Error (linksProcessed=" + linksProcessed + ": " + errorMessage ); + e.printStackTrace(); + } + finally + { + if ( nodesCache != null ) + { + nodesCache.close(); + nodesCache = null; + } + openSet.clear(); + finished = true; // this signals termination to outside + + if ( infoLogWriter != null ) + { + try { infoLogWriter.close(); } catch( Exception e ) {} + infoLogWriter = null; + } + } + } + public String cleanOnOOM() { boolean oom_carsubset_hint = nodesCache == null ? false : nodesCache.oom_carsubset_hint; @@ -504,15 +550,15 @@ public class RoutingEngine extends Thread return start; } - private OsmPath getStartPath( OsmNode n1, OsmNode n2, MatchedWaypoint mwp, MatchedWaypoint endWp, boolean sameSegmentSearch ) + private OsmPath getStartPath( OsmNode n1, OsmNode n2, MatchedWaypoint mwp, OsmNodeNamed endPos, boolean sameSegmentSearch ) { - OsmPath p = getStartPath( n1, n2, mwp.waypoint, endWp.crosspoint ); + OsmPath p = getStartPath( n1, n2, mwp.waypoint, endPos ); // special case: start+end on same segment if ( sameSegmentSearch ) { - OsmPath pe = getEndPath( n1, p.getLink(), endWp.crosspoint, endWp.crosspoint ); - OsmPath pt = getEndPath( n1, p.getLink(), null, endWp.crosspoint ); + OsmPath pe = getEndPath( n1, p.getLink(), endPos ); + OsmPath pt = getEndPath( n1, p.getLink(), null ); int costdelta = pt.cost - p.cost; if ( pe.cost >= costdelta ) { @@ -571,7 +617,7 @@ public class RoutingEngine extends Thread wp.radius = 1e9; OsmPath testPath = new OsmPath( null, startPath, link, null, guideTrack != null, routingContext ); - testPath.airdistance = nextNode.calcDistance( endPos ); + testPath.airdistance = endPos == null ? 0 : nextNode.calcDistance( endPos ); if ( wp.radius < minradius ) { bestPath = testPath; @@ -593,7 +639,7 @@ public class RoutingEngine extends Thread } } - private OsmPath getEndPath( OsmNode n1, OsmLink link, OsmNodeNamed wp, OsmNode endPos ) + private OsmPath getEndPath( OsmNode n1, OsmLink link, OsmNodeNamed wp ) { try { @@ -619,7 +665,6 @@ public class RoutingEngine extends Thread int maxTotalCost = 1000000000; int firstMatchCost = 1000000000; - int firstEstimate = 1000000000; logInfo( "findtrack with airDistanceCostFactor=" + airDistanceCostFactor ); if (costCuttingTrack != null ) logInfo( "costCuttingTrack.cost=" + costCuttingTrack.cost ); @@ -628,12 +673,13 @@ public class RoutingEngine extends Thread int nodesVisited = 0; resetCache(); - long endNodeId1 = endWp.node1.getIdFromPos(); - long endNodeId2 = endWp.node2.getIdFromPos(); + long endNodeId1 = endWp == null ? -1L : endWp.node1.getIdFromPos(); + long endNodeId2 = endWp == null ? -1L : endWp.node2.getIdFromPos(); long startNodeId1 = startWp.node1.getIdFromPos(); long startNodeId2 = startWp.node2.getIdFromPos(); - OsmNode endPos = endWp.crosspoint; + OsmNodeNamed startPos = startWp.crosspoint; + OsmNodeNamed endPos = endWp == null ? null : endWp.crosspoint; boolean sameSegmentSearch = ( startNodeId1 == endNodeId1 && startNodeId2 == endNodeId2 ) || ( startNodeId1 == endNodeId2 && startNodeId2 == endNodeId1 ); @@ -642,8 +688,8 @@ public class RoutingEngine extends Thread OsmNode start2 = getStartNode( startNodeId2 ); if ( start1 == null || start2 == null ) return null; - OsmPath startPath1 = getStartPath( start1, start2, startWp, endWp, sameSegmentSearch ); - OsmPath startPath2 = getStartPath( start2, start1, startWp, endWp, sameSegmentSearch ); + OsmPath startPath1 = getStartPath( start1, start2, startWp, endPos, sameSegmentSearch ); + OsmPath startPath2 = getStartPath( start2, start1, startWp, endPos, sameSegmentSearch ); // check for an INITIAL match with the cost-cutting-track if ( costCuttingTrack != null ) @@ -681,7 +727,11 @@ public class RoutingEngine extends Thread path = openSet.popLowestKeyValue(); } if ( path == null ) break; - if ( path.airdistance == -1 ) continue; + if ( path.airdistance == -1 ) + { + path.unregisterUpTree( routingContext ); + continue; + } if ( matchPath != null && fastPartialRecalc && firstMatchCost < 500 && path.cost > 30L*firstMatchCost ) { @@ -728,8 +778,7 @@ public class RoutingEngine extends Thread + ( costCuttingTrack.cost - pe.cost ); if ( costEstimate <= maxTotalCost ) { - if ( matchPath == null ) firstEstimate = costEstimate; - matchPath = new OsmPathElement( path ); + matchPath = OsmPathElement.create( path, routingContext.countTraffic ); } if ( costEstimate < maxTotalCost ) { @@ -743,6 +792,7 @@ public class RoutingEngine extends Thread // recheck cutoff before doing expensive stuff if ( path.cost + path.airdistance > maxTotalCost + 10 ) { + path.unregisterUpTree( routingContext ); continue; } @@ -809,8 +859,8 @@ public class RoutingEngine extends Thread { if ( isFinalLink ) { - endWp.crosspoint.radius = 1e-5; - routingContext.setWaypoint( endWp.crosspoint, true ); + endPos.radius = 1e-5; + routingContext.setWaypoint( endPos, true ); } OsmPath testPath = new OsmPath( currentNode, otherPath, link, refTrack, guideTrack != null, routingContext ); if ( testPath.cost >= 0 && ( bestPath == null || testPath.cost < bestPath.cost ) ) @@ -829,13 +879,17 @@ public class RoutingEngine extends Thread } if ( bestPath != null ) { - bestPath.airdistance = isFinalLink ? 0 : nextNode.calcDistance( endPos ); + boolean trafficSim = endPos == null; + + bestPath.airdistance = trafficSim ? path.airdistance : ( isFinalLink ? 0 : nextNode.calcDistance( endPos ) ); - if ( isFinalLink || bestPath.cost + bestPath.airdistance <= maxTotalCost + 10 ) + boolean inRadius = boundary == null || boundary.isInBoundary( nextNode, bestPath.cost ); + + if ( inRadius && ( isFinalLink || bestPath.cost + bestPath.airdistance <= maxTotalCost + 10 ) ) { // add only if this may beat an existing path for that link OsmLinkHolder dominator = link.firstlinkholder; - while( dominator != null ) + while( !trafficSim && dominator != null ) { if ( bestPath.definitlyWorseThan( (OsmPath)dominator, routingContext ) ) { @@ -846,6 +900,11 @@ public class RoutingEngine extends Thread if ( dominator == null ) { + if ( trafficSim && boundary != null && path.cost == 0 && bestPath.cost > 0 ) + { + bestPath.airdistance += boundary.getBoundaryDistance( nextNode ); + } + bestPath.treedepth = path.treedepth + 1; link.addLinkHolder( bestPath ); synchronized( openSet ) @@ -861,7 +920,7 @@ public class RoutingEngine extends Thread { currentNode.unlinkLink(counterLink); } - + path.unregisterUpTree( routingContext ); } return null; } @@ -871,6 +930,7 @@ public class RoutingEngine extends Thread if ( path.cost >= 0 ) { openSet.add( path.cost + (int)(path.airdistance*airDistanceCostFactor), path ); + path.registerUpTree(); } } @@ -902,7 +962,7 @@ public class RoutingEngine extends Thread private OsmTrack compileTrack( OsmPath path, boolean verbose ) { - OsmPathElement element = new OsmPathElement( path ); + OsmPathElement element = OsmPathElement.create( path, false ); // for final track, cut endnode if ( guideTrack != null ) element = element.origin; diff --git a/brouter-core/src/main/java/btools/router/SearchBoundary.java b/brouter-core/src/main/java/btools/router/SearchBoundary.java new file mode 100644 index 0000000..f40aec1 --- /dev/null +++ b/brouter-core/src/main/java/btools/router/SearchBoundary.java @@ -0,0 +1,87 @@ +/** + * static helper class for handling datafiles + * + * @author ab + */ +package btools.router; + +import btools.mapaccess.OsmNode; + + +public final class SearchBoundary +{ + + private int minlon0; + private int minlat0; + private int maxlon0; + private int maxlat0; + + private int minlon; + private int minlat; + private int maxlon; + private int maxlat; + private int radius; + private OsmNode p; + + int direction; + + public SearchBoundary( OsmNode n, int radius, int direction ) + { + this.radius = radius; + this.direction = direction; + + p = new OsmNode( n.ilon, n.ilat ); + + int lon = (n.ilon / 5000000 ) * 5000000; + int lat = (n.ilat / 5000000 ) * 5000000; + + minlon0 = lon - 5000000; + minlat0 = lat - 5000000; + maxlon0 = lon + 10000000; + maxlat0 = lat + 10000000; + + minlon = lon - 1000000; + minlat = lat - 1000000; + maxlon = lon + 6000000; + maxlat = lat + 6000000; + } + + public static String getFileName( OsmNode n ) + { + int lon = (n.ilon / 5000000 ) * 5000000; + int lat = (n.ilat / 5000000 ) * 5000000; + + int dlon = lon / 1000000 -180; + int dlat = lat / 1000000 - 90; + + String slon = dlon < 0 ? "W" + (-dlon) : "E" + dlon; + String slat = dlat < 0 ? "S" + (-dlat) : "N" + dlat; + return slon + "_" + slat + ".trf"; + } + + public boolean isInBoundary( OsmNode n, int cost ) + { + if ( radius > 0 ) + { + return n.calcDistance( p ) < radius; + } + if ( cost == 0 ) + { + return n.ilon > minlon0 && n.ilon < maxlon0 && n.ilat > minlat0 && n.ilat < maxlat0; + } + return n.ilon > minlon && n.ilon < maxlon && n.ilat > minlat && n.ilat < maxlat; + } + + public int getBoundaryDistance( OsmNode n ) + { + switch( direction ) + { + case 0: return n.calcDistance( new OsmNode( n.ilon, minlat ) ); + case 1: return n.calcDistance( new OsmNode( minlon, n.ilat ) ); + case 2: return n.calcDistance( new OsmNode( n.ilon, maxlat ) ); + case 3: return n.calcDistance( new OsmNode( maxlon, n.ilat ) ); + default: throw new IllegalArgumentException( "undefined direction: "+ direction ); + } + } + +} diff --git a/brouter-expressions/src/main/java/btools/expressions/BExpression.java b/brouter-expressions/src/main/java/btools/expressions/BExpression.java index 9f889d2..beb9b53 100644 --- a/brouter-expressions/src/main/java/btools/expressions/BExpression.java +++ b/brouter-expressions/src/main/java/btools/expressions/BExpression.java @@ -12,6 +12,7 @@ final class BExpression private static final int MULTIPLY_EXP = 21; private static final int MAX_EXP = 22; private static final int EQUAL_EXP = 23; + private static final int GREATER_EXP = 24; private static final int SWITCH_EXP = 30; private static final int ASSIGN_EXP = 31; @@ -105,6 +106,10 @@ final class BExpression { exp.typ = EQUAL_EXP; } + else if ( "greater".equals( operator ) ) + { + exp.typ = GREATER_EXP; + } else { nops = 1; // check unary expressions @@ -226,6 +231,7 @@ final class BExpression case MULTIPLY_EXP: return op1.evaluate(ctx) * op2.evaluate(ctx); case MAX_EXP: return max( op1.evaluate(ctx), op2.evaluate(ctx) ); case EQUAL_EXP: return op1.evaluate(ctx) == op2.evaluate(ctx) ? 1.f : 0.f; + case GREATER_EXP: return op1.evaluate(ctx) > op2.evaluate(ctx) ? 1.f : 0.f; case SWITCH_EXP: return op1.evaluate(ctx) != 0.f ? op2.evaluate(ctx) : op3.evaluate(ctx); case ASSIGN_EXP: return ctx.assign( variableIdx, op1.evaluate(ctx) ); case LOOKUP_EXP: return ctx.getLookupMatch( lookupNameIdx, lookupValueIdxArray ); diff --git a/brouter-expressions/src/main/java/btools/expressions/BExpressionContextWay.java b/brouter-expressions/src/main/java/btools/expressions/BExpressionContextWay.java index c1116d9..703172d 100644 --- a/brouter-expressions/src/main/java/btools/expressions/BExpressionContextWay.java +++ b/brouter-expressions/src/main/java/btools/expressions/BExpressionContextWay.java @@ -11,7 +11,7 @@ package btools.expressions; public final class BExpressionContextWay extends BExpressionContext { private static String[] buildInVariables = - { "costfactor", "turncost", "uphillcostfactor", "downhillcostfactor", "initialcost", "nodeaccessgranted", "initialclassifier" }; + { "costfactor", "turncost", "uphillcostfactor", "downhillcostfactor", "initialcost", "nodeaccessgranted", "initialclassifier", "trafficsourcedensity", "istrafficbackbone" }; protected String[] getBuildInVariableNames() { @@ -25,6 +25,8 @@ public final class BExpressionContextWay extends BExpressionContext public float getInitialcost() { return getBuildInVariable(4); } public float getNodeAccessGranted() { return getBuildInVariable(5); } public float getInitialClassifier() { return getBuildInVariable(6); } + public float getTrafficSourceDensity() { return getBuildInVariable(7); } + public float getIsTrafficBackbone() { return getBuildInVariable(8); } public BExpressionContextWay( BExpressionMetaData meta ) diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java b/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java index 4433f7f..a95c53f 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java @@ -34,14 +34,12 @@ public class OsmNodeP extends OsmLinkP implements Comparable */ public short selev; - public boolean isBorder = false; - public final static int NO_BRIDGE_BIT = 1; public final static int NO_TUNNEL_BIT = 2; - public final static int LCN_BIT = 4; - public final static int CR_BIT = 8; + public final static int BORDER_BIT = 4; + public final static int TRAFFIC_BIT = 8; - public byte wayBits = 0; + public byte bits = 0; // interface OsmPos public int getILat() @@ -57,7 +55,7 @@ public class OsmNodeP extends OsmLinkP implements Comparable public short getSElev() { // if all bridge or all tunnel, elevation=no-data - return ( wayBits & NO_BRIDGE_BIT ) == 0 || ( wayBits & NO_TUNNEL_BIT ) == 0 ? Short.MIN_VALUE : selev; + return ( bits & NO_BRIDGE_BIT ) == 0 || ( bits & NO_TUNNEL_BIT ) == 0 ? Short.MIN_VALUE : selev; } public double getElev() @@ -247,9 +245,19 @@ public class OsmNodeP extends OsmLinkP implements Comparable return ((long)ilon)<<32 | ilat; } + public boolean isBorderNode() + { + return (bits & BORDER_BIT) != 0; + } + + public boolean hasTraffic() + { + return (bits & TRAFFIC_BIT) != 0; + } + public boolean isTransferNode() { - return (!isBorder) && _linkCnt() == 2; + return (bits & BORDER_BIT) == 0 && _linkCnt() == 2; } private int _linkCnt() diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/OsmTrafficMap.java b/brouter-map-creator/src/main/java/btools/mapcreator/OsmTrafficMap.java new file mode 100644 index 0000000..8b417ce --- /dev/null +++ b/brouter-map-creator/src/main/java/btools/mapcreator/OsmTrafficMap.java @@ -0,0 +1,158 @@ +/** + * Container for link between two Osm nodes (pre-pocessor version) + * + * @author ab + */ +package btools.mapcreator; + +import java.io.BufferedInputStream; +import java.io.DataInputStream; +import java.io.EOFException; +import java.io.File; +import java.io.FileInputStream; + +import btools.util.CompactLongMap; +import btools.util.FrozenLongMap; + + +public class OsmTrafficMap +{ + int minLon; + int minLat; + int maxLon; + int maxLat; + + public static class OsmTrafficElement + { + public long node2; + public int traffic; + public OsmTrafficElement next; + } + + private CompactLongMap map = new CompactLongMap(); + + public long[] load( File file, int minLon, int minLat, int maxLon, int maxLat, boolean includeMotorways ) throws Exception + { + this.minLon = minLon; + this.minLat = minLat; + this.maxLon = maxLon; + this.maxLat = maxLat; + + int trafficElements = 0; + DataInputStream is = new DataInputStream( new BufferedInputStream( new FileInputStream( file ) ) ); + try + { + for(;;) + { + long n1 = is.readLong(); + long n2 = is.readLong(); + int traffic = is.readInt(); + if ( traffic == -1 && !includeMotorways ) + { + continue; + } + if ( isInsideBounds( n1 ) || isInsideBounds( n2 ) ) + { + if ( addElement( n1, n2, traffic ) ) + { + trafficElements++; + } + } + } + } + catch( EOFException eof ) {} + finally{ is.close(); } + + FrozenLongMap fmap = new FrozenLongMap( map ); + map = fmap; + System.out.println( "read traffic-elements: " + trafficElements ); + return fmap.getKeyArray(); + } + + + public boolean addElement( long n1, long n2, int traffic ) + { + OsmTrafficElement e = getElement( n1, n2 ); + if ( e == null ) + { + e = new OsmTrafficElement(); + e.node2 = n2; + e.traffic = traffic; + + OsmTrafficElement e0 = map.get( n1 ); + if ( e0 != null ) + { + while( e0.next != null ) + { + e0 = e0.next; + } + e0.next = e; + } + else + { + map.fastPut( n1, e ); + } + return true; + } + e.traffic = e.traffic == -1 || traffic == -1 ? -1 : e.traffic + traffic; + return false; + } + + private boolean isInsideBounds( long id ) + { + int ilon = (int)(id >> 32); + int ilat = (int)(id & 0xffffffff); + + return ilon >= minLon && ilon < maxLon && ilat >= minLat && ilat < maxLat; + } + + public int getTrafficClass( long n1, long n2 ) + { + int traffic1 = getTraffic( n1, n2 ); + int traffic2 = getTraffic( n2, n1 ); + int traffic = traffic1 == -1 || traffic2 == -1 ? -1 : traffic1 > traffic2 ? traffic1 : traffic2; + return getTrafficClassForTraffic( traffic ); + } + + public int getTrafficClassForTraffic( int traffic ) + { + if ( traffic < 0 ) return -1; + if ( traffic < 20000 ) return 0; + if ( traffic < 40000 ) return 1; + if ( traffic < 80000 ) return 2; + if ( traffic < 160000 ) return 3; + if ( traffic < 320000 ) return 4; + if ( traffic < 640000 ) return 5; + if ( traffic <1280000 ) return 6; + return 7; + } + + private int getTraffic( long n1, long n2 ) + { + OsmTrafficElement e = getElement( n1, n2 ); + return e == null ? 0 : e.traffic; + } + + public void freeze() + { + } + + private OsmTrafficElement getElement( long n1, long n2 ) + { + OsmTrafficElement e = map.get( n1 ); + while( e != null ) + { + if ( e.node2 == n2 ) + { + return e; + } + e = e.next; + } + return null; + } + + public OsmTrafficElement getElement( long n ) + { + return map.get( n ); + } +} diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/TrafficData2Png.java b/brouter-map-creator/src/main/java/btools/mapcreator/TrafficData2Png.java new file mode 100644 index 0000000..9f7ba24 --- /dev/null +++ b/brouter-map-creator/src/main/java/btools/mapcreator/TrafficData2Png.java @@ -0,0 +1,154 @@ +package btools.mapcreator; + +import java.io.BufferedOutputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; + +import btools.util.Raster2Png; + +public class TrafficData2Png +{ + private static int minLon; + private static int minLat; + private static int maxLon; + private static int maxLat; + private static int ncols; + private static int nrows; + private static int[] pixels; + + public static void main( String[] args) throws Exception + { + if ( args.length == 8 ) + { + doConvert( args[0], args[1], + Double.parseDouble( args[2] ), Double.parseDouble( args[3] ), Double.parseDouble( args[4] ), Double.parseDouble( args[5] ), + Integer.parseInt( args[6] ), Integer.parseInt( args[7] ) ); + } + else if ( args.length == 4 ) + { + int lon0 = Integer.parseInt( args[0] ); + int lat0 = Integer.parseInt( args[1] ); + String inputFile = "traffic/E" + lon0 + "_N" + lat0 + ".trf"; + for( int lon = lon0; lon < lon0+5; lon++ ) + for( int lat = lat0; lat < lat0+5; lat++ ) + { + String imageFile = "traffic_pics/E" + lon + "_N" + lat + ".png"; + System.out.println( "file=" + inputFile + " image=" + imageFile ); + doConvert( inputFile, imageFile, lon, lat, lon+1, lat+1, Integer.parseInt( args[2] ), Integer.parseInt( args[3] ) ); + } + } + + } + + public static void doConvert( String inputFile, String imageFile, double lon0, double lat0, double lon1, double lat1, + int cols, int rows ) throws Exception + { + OsmTrafficMap trafficMap = new OsmTrafficMap(); + minLon = (int)(lon0 * 1000000 + 180000000); + maxLon = (int)(lon1 * 1000000 + 180000000); + minLat = (int)(lat0 * 1000000 + 90000000); + maxLat = (int)(lat1 * 1000000 + 90000000); + ncols = cols; + nrows = rows; + + long[] keys = trafficMap.load( new File( inputFile ), minLon, minLat, maxLon, maxLat, true ); + + pixels = new int[cols*rows]; + + int[] tclasses = new int[] { 1,2,3,4,5,6,7, -1 }; + for( int tclass : tclasses ) + { + for(long key : keys ) + { + OsmTrafficMap.OsmTrafficElement e = trafficMap.getElement(key ); + while( e != null ) + { + long key2 = e.node2; + e = e.next; + int trafficClass = trafficMap.getTrafficClass( key, key2 ); + if ( trafficClass != tclass ) continue; + + int[] from = getImagePosition( key ); + int[] to = getImagePosition( key2 ); + + int rgb = 0; + if ( trafficClass == -1 ) rgb = 0x0000ff; // blue + else if ( trafficClass == 1 ) rgb = 0x404040; // dark grey + else if ( trafficClass == 2 ) rgb = 0xa0a0a0; // light grey + else if ( trafficClass == 3 ) rgb = 0x00ff00; // green + else if ( trafficClass == 4 ) rgb = 0xf4e500; // yellow + else if ( trafficClass == 5 ) rgb = 0xf18e1c; // orange + else if ( trafficClass == 6 ) rgb = 0xe32322; // red + else if ( trafficClass == 7 ) rgb = 0xc0327d; // pink + if ( rgb != 0 ) + { + drawLine( from, to, rgb ); + } + } + } + } + + + Raster2Png r2p = new Raster2Png( Raster2Png.FILTER_NONE, 6, cols, rows, pixels ); + byte[] png = r2p.pngEncode( ); + + System.out.println( "got png of size: " + png.length ); + DataOutputStream dos = new DataOutputStream( new BufferedOutputStream( new FileOutputStream( imageFile ) ) ); + dos.write(png); + dos.close(); + } + + private static void drawLine( int[] from, int[] to, int rgb ) + { + int ix = from[0]; + int iy = from[1]; + int ixx = to[0]; + int iyy = to[1]; + + int sx = ixx > ix ? 1 : -1; + int sy = iyy > iy ? 1 : -1; + + int dx = (ixx-ix)*sx; + int dy = (iyy-iy)*sy; + + int sum = 0; + + for(;;) + { + drawPixel( ix, iy, rgb ); + if ( ix == ixx && iy == iyy ) break; + + if ( Math.abs( sum+dx ) < Math.abs( sum-dy ) ) + { + iy+= sy; + sum += dx; + } + else + { + ix+= sx; + sum -= dy; + } + } + } + + private static void drawPixel( int ix, int iy, int rgb ) + { + if ( ix >= 0 && ix < ncols && iy >= 0 && iy < nrows ) + { + pixels[ (nrows-1-iy)*ncols + ix ] = rgb; + } + } + + private static int[] getImagePosition( long key ) + { + int ilon = (int)(key >> 32); + int ilat = (int)(key & 0xffffffff); + double lonDelta = maxLon-minLon; + double latDelta = maxLat-minLat; + int[] res = new int[2]; + res[0] = (int)( ( (ilon-minLon)/lonDelta ) *ncols ); + res[1] = (int)( ( (ilat-minLat)/latDelta ) *nrows ); + return res; + } +} diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java b/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java index eedf1e9..fca9173 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java @@ -1,8 +1,12 @@ package btools.mapcreator; +import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; import java.io.DataOutputStream; +import java.io.EOFException; import java.io.File; +import java.io.FileInputStream; import java.io.RandomAccessFile; import java.util.Collections; import java.util.List; @@ -31,6 +35,7 @@ import btools.util.LazyArrayOfLists; public class WayLinker extends MapCreatorBase { private File nodeTilesIn; + private File trafficTilesIn; private File dataTilesOut; private File borderFileIn; @@ -39,6 +44,7 @@ public class WayLinker extends MapCreatorBase private boolean readingBorder; private CompactLongMap nodesMap; + private OsmTrafficMap trafficMap; private List nodesList; private CompactLongSet borderSet; private short lookupVersion; @@ -77,6 +83,7 @@ public class WayLinker extends MapCreatorBase public void process( File nodeTilesIn, File wayTilesIn, File borderFileIn, File lookupFile, File profileFile, File dataTilesOut, String dataTilesSuffix ) throws Exception { this.nodeTilesIn = nodeTilesIn; + this.trafficTilesIn = new File( "traffic" ); this.dataTilesOut = dataTilesOut; this.borderFileIn = borderFileIn; this.dataTilesSuffix = dataTilesSuffix; @@ -126,6 +133,14 @@ public class WayLinker extends MapCreatorBase nodesMap = nodesMapFrozen; nodesList = nodesMapFrozen.getValueList(); } + + // read a traffic-file, if any + File trafficFile = fileFromTemplate( wayfile, trafficTilesIn, "trf" ); + if ( trafficFile.exists() ) + { + trafficMap = new OsmTrafficMap(); + trafficMap.load( trafficFile, minLon, minLat, minLon + 5000000, minLat + 5000000, false ); + } } @Override @@ -135,7 +150,7 @@ public class WayLinker extends MapCreatorBase n.ilon = data.ilon; n.ilat = data.ilat; n.selev = data.selev; - n.isBorder = readingBorder; + if ( readingBorder || (!borderSet.contains( data.nid )) ) { nodesMap.fastPut( data.nid, n ); @@ -143,6 +158,7 @@ public class WayLinker extends MapCreatorBase if ( readingBorder ) { + n.bits |= OsmNodeP.BORDER_BIT; borderSet.fastAdd( data.nid ); return; } @@ -160,6 +176,7 @@ public class WayLinker extends MapCreatorBase public void nextWay( WayData way ) throws Exception { byte[] description = abUnifier.unify( way.description ); + int lastTraffic = 0; // filter according to profile expctxWay.evaluate( false, description, null ); @@ -183,11 +200,20 @@ public class WayLinker extends MapCreatorBase if ( n1 != null && n2 != null && n1 != n2 ) { OsmLinkP link = n2.createLink( n1 ); + + int traffic = trafficMap == null ? 0 : trafficMap.getTrafficClass( n1.getIdFromPos(), n2.getIdFromPos() ); + if ( traffic != lastTraffic ) + { + expctxWay.decode( description ); + expctxWay.addLookupValue( "estimated_traffic_class", traffic == 0 ? 0 : traffic + 1 ); + description = abUnifier.unify( expctxWay.encode() ); + lastTraffic = traffic; + } link.descriptionBitmap = description; } if ( n2 != null ) { - n2.wayBits |= wayBits; + n2.bits |= wayBits; } } } @@ -197,6 +223,7 @@ public class WayLinker extends MapCreatorBase { nodesMap = null; borderSet = null; + trafficMap = null; byte[] abBuf = new byte[1024*1024]; byte[] abBuf2 = new byte[10*1024*1024]; diff --git a/brouter-mem-router/src/main/java/btools/memrouter/ScheduledRouter.java b/brouter-mem-router/src/main/java/btools/memrouter/ScheduledRouter.java index 30cff22..06d79f0 100644 --- a/brouter-mem-router/src/main/java/btools/memrouter/ScheduledRouter.java +++ b/brouter-mem-router/src/main/java/btools/memrouter/ScheduledRouter.java @@ -339,7 +339,7 @@ time0 = minutes0 * 60000L; { System.out.println( "trip=" + current ); OsmNodeP node = current.getTargetNode(); - OsmPathElement pe = new OsmPathElement(node.ilon, node.ilat, node.selev, null ); + OsmPathElement pe = OsmPathElement.create(node.ilon, node.ilat, node.selev, null, false ); track.addNode(pe); if ( nextNode != null ) diff --git a/brouter-server/src/main/java/btools/server/BRouter.java b/brouter-server/src/main/java/btools/server/BRouter.java index c5dc022..87bb2d4 100644 --- a/brouter-server/src/main/java/btools/server/BRouter.java +++ b/brouter-server/src/main/java/btools/server/BRouter.java @@ -1,5 +1,8 @@ package btools.server; +import java.io.BufferedOutputStream; +import java.io.DataOutputStream; +import java.io.FileOutputStream; import java.net.URLDecoder; import java.util.ArrayList; import java.util.List; @@ -7,6 +10,7 @@ import java.util.List; import btools.router.OsmNodeNamed; import btools.router.RoutingContext; import btools.router.RoutingEngine; +import btools.router.SearchBoundary; public class BRouter { @@ -84,7 +88,7 @@ public class BRouter } System.exit(0); } - System.out.println("BRouter 1.0 / 01062014 / abrensch"); + System.out.println("BRouter 1.2 / 04042015 / abrensch"); if ( args.length < 6 ) { System.out.println("Find routes in an OSM map"); @@ -93,9 +97,37 @@ public class BRouter } List wplist = new ArrayList(); wplist.add( readPosition( args, 1, "from" ) ); - wplist.add( readPosition( args, 3, "to" ) ); - RoutingEngine re = new RoutingEngine( "mytrack", "mylog", args[0], wplist, readRoutingContext(args) ); - re.doRun( 0 ); + RoutingEngine re = null; + if ( "seed".equals( args[3] ) ) + { + int searchRadius = Integer.parseInt( args[4] ); // if = 0 search a 5x5 square + + String filename = SearchBoundary.getFileName( wplist.get(0) ); + DataOutputStream dos = new DataOutputStream( new BufferedOutputStream( new FileOutputStream( "traffic/" + filename ) ) ); + + for( int direction = 0; direction < 8; direction++ ) + { + RoutingContext rc = readRoutingContext(args); + SearchBoundary boundary = new SearchBoundary( wplist.get(0), searchRadius, direction/2 ); + rc.trafficOutputStream = dos; + rc.inverseDirection = (direction & 1 ) != 0; + re = new RoutingEngine( "mytrack", "mylog", args[0], wplist, rc ); + re.boundary = boundary; + re.airDistanceCostFactor = rc.trafficDirectionFactor; + re.doSearch(); + if ( re.getErrorMessage() != null ) + { + break; + } + } + dos.close(); + } + else + { + wplist.add( readPosition( args, 3, "to" ) ); + re = new RoutingEngine( "mytrack", "mylog", args[0], wplist, readRoutingContext(args) ); + re.doRun( 0 ); + } if ( re.getErrorMessage() != null ) { System.out.println( re.getErrorMessage() ); diff --git a/brouter-server/src/main/java/btools/server/RouteServer.java b/brouter-server/src/main/java/btools/server/RouteServer.java index 01abf05..95394be 100644 --- a/brouter-server/src/main/java/btools/server/RouteServer.java +++ b/brouter-server/src/main/java/btools/server/RouteServer.java @@ -13,6 +13,7 @@ import java.util.List; import java.util.StringTokenizer; import java.util.TreeMap; +import btools.memrouter.TwinRoutingEngine; import btools.router.OsmNodeNamed; import btools.router.OsmTrack; import btools.router.RoutingContext; @@ -101,7 +102,7 @@ public class RouteServer extends Thread RoutingContext rc = handler.readRoutingContext(); List wplist = handler.readWayPointList(); - cr = new RoutingEngine( null, null, serviceContext.segmentDir, wplist, rc ); + cr = new TwinRoutingEngine( null, null, serviceContext.segmentDir, wplist, rc ); cr.quite = true; cr.doRun( maxRunningTime ); diff --git a/brouter-util/src/main/java/btools/util/FrozenLongMap.java b/brouter-util/src/main/java/btools/util/FrozenLongMap.java index b308173..ff53e3a 100644 --- a/brouter-util/src/main/java/btools/util/FrozenLongMap.java +++ b/brouter-util/src/main/java/btools/util/FrozenLongMap.java @@ -119,4 +119,9 @@ public class FrozenLongMap extends CompactLongMap { return flv; } + + public long[] getKeyArray() + { + return faid; + } } diff --git a/brouter-util/src/main/java/btools/util/Raster2Png.java b/brouter-util/src/main/java/btools/util/Raster2Png.java new file mode 100644 index 0000000..775e497 --- /dev/null +++ b/brouter-util/src/main/java/btools/util/Raster2Png.java @@ -0,0 +1,464 @@ +package btools.util; + +import java.io.*; +import java.util.zip.*; + +public class Raster2Png extends Object { + + /** Constant specifying that alpha channel should be encoded. */ + public static final boolean ENCODE_ALPHA = true; + + /** Constant specifying that alpha channel should not be encoded. */ + public static final boolean NO_ALPHA = false; + + /** Constants for filter (NONE) */ + public static final int FILTER_NONE = 0; + + /** Constants for filter (SUB) */ + public static final int FILTER_SUB = 1; + + /** Constants for filter (UP) */ + public static final int FILTER_UP = 2; + + /** Constants for filter (LAST) */ + public static final int FILTER_LAST = 2; + + /** IHDR tag. */ + protected static final byte IHDR[] = {73, 72, 68, 82}; + + /** IDAT tag. */ + protected static final byte IDAT[] = {73, 68, 65, 84}; + + /** IEND tag. */ + protected static final byte IEND[] = {73, 69, 78, 68}; + + /** The png bytes. */ + protected byte[] pngBytes; + + /** The prior row. */ + protected byte[] priorRow; + + /** The left bytes. */ + protected byte[] leftBytes; + + /** The width. */ + protected int width, height; + + /** The byte position. */ + protected int bytePos, maxPos; + + protected int[] imagePixels; + + /** CRC. */ + protected CRC32 crc = new CRC32(); + + /** The CRC value. */ + protected long crcValue; + + /** The filter type. */ + protected int filter; + + /** The bytes-per-pixel. */ + protected int bytesPerPixel; + + /** The compression level. */ + protected int compressionLevel; + + private boolean encodeAlpha = false; + + /** + * Class constructor specifying filter to use and compression level. + * + * @param whichFilter 0=none, 1=sub, 2=up + * @param compLevel 0..9 + */ + public Raster2Png(int whichFilter, int compLevel, int width, int height, int[] imagePixels ) { + this.width = width; + this.height = height; + this.imagePixels = imagePixels; + + setFilter(whichFilter); + + if (compLevel >= 0 && compLevel <= 9) { + this.compressionLevel = compLevel; + } + } + + /** + * Creates an array of bytes that is the PNG equivalent of the current image, specifying + * whether to encode alpha or not. + * + * @param encodeAlpha boolean false=no alpha, true=encode alpha + * @return an array of bytes, or null if there was a problem + */ + public byte[] pngEncode() { + byte[] pngIdBytes = {-119, 80, 78, 71, 13, 10, 26, 10}; + + if (imagePixels == null) { + return null; + } + + /* + * start with an array that is big enough to hold all the pixels + * (plus filter bytes), and an extra 200 bytes for header info + */ + pngBytes = new byte[((width + 1) * height * 3) + 200]; + + /* + * keep track of largest byte written to the array + */ + maxPos = 0; + + bytePos = writeBytes(pngIdBytes, 0); + //hdrPos = bytePos; + writeHeader(); + //dataPos = bytePos; + if (writeImageData()) { + writeEnd(); + pngBytes = resizeByteArray(pngBytes, maxPos); + } + else { + pngBytes = null; + } + return pngBytes; + } + + /** + * Set the filter to use + * + * @param whichFilter from constant list + */ + public void setFilter(int whichFilter) { + this.filter = FILTER_NONE; + if (whichFilter <= FILTER_LAST) { + this.filter = whichFilter; + } + } + + /** + * Set the compression level to use + * + * @param level 0 through 9 + */ + public void setCompressionLevel(int level) { + if (level >= 0 && level <= 9) { + this.compressionLevel = level; + } + } + + /** + * Increase or decrease the length of a byte array. + * + * @param array The original array. + * @param newLength The length you wish the new array to have. + * @return Array of newly desired length. If shorter than the + * original, the trailing elements are truncated. + */ + protected byte[] resizeByteArray(byte[] array, int newLength) { + byte[] newArray = new byte[newLength]; + int oldLength = array.length; + + System.arraycopy(array, 0, newArray, 0, Math.min(oldLength, newLength)); + return newArray; + } + + /** + * Write an array of bytes into the pngBytes array. + * Note: This routine has the side effect of updating + * maxPos, the largest element written in the array. + * The array is resized by 1000 bytes or the length + * of the data to be written, whichever is larger. + * + * @param data The data to be written into pngBytes. + * @param offset The starting point to write to. + * @return The next place to be written to in the pngBytes array. + */ + protected int writeBytes(byte[] data, int offset) { + maxPos = Math.max(maxPos, offset + data.length); + if (data.length + offset > pngBytes.length) { + pngBytes = resizeByteArray(pngBytes, pngBytes.length + Math.max(1000, data.length)); + } + System.arraycopy(data, 0, pngBytes, offset, data.length); + return offset + data.length; + } + + /** + * Write an array of bytes into the pngBytes array, specifying number of bytes to write. + * Note: This routine has the side effect of updating + * maxPos, the largest element written in the array. + * The array is resized by 1000 bytes or the length + * of the data to be written, whichever is larger. + * + * @param data The data to be written into pngBytes. + * @param nBytes The number of bytes to be written. + * @param offset The starting point to write to. + * @return The next place to be written to in the pngBytes array. + */ + protected int writeBytes(byte[] data, int nBytes, int offset) { + maxPos = Math.max(maxPos, offset + nBytes); + if (nBytes + offset > pngBytes.length) { + pngBytes = resizeByteArray(pngBytes, pngBytes.length + Math.max(1000, nBytes)); + } + System.arraycopy(data, 0, pngBytes, offset, nBytes); + return offset + nBytes; + } + + /** + * Write a two-byte integer into the pngBytes array at a given position. + * + * @param n The integer to be written into pngBytes. + * @param offset The starting point to write to. + * @return The next place to be written to in the pngBytes array. + */ + protected int writeInt2(int n, int offset) { + byte[] temp = {(byte) ((n >> 8) & 0xff), (byte) (n & 0xff)}; + return writeBytes(temp, offset); + } + + /** + * Write a four-byte integer into the pngBytes array at a given position. + * + * @param n The integer to be written into pngBytes. + * @param offset The starting point to write to. + * @return The next place to be written to in the pngBytes array. + */ + protected int writeInt4(int n, int offset) { + byte[] temp = {(byte) ((n >> 24) & 0xff), + (byte) ((n >> 16) & 0xff), + (byte) ((n >> 8) & 0xff), + (byte) (n & 0xff)}; + return writeBytes(temp, offset); + } + + /** + * Write a single byte into the pngBytes array at a given position. + * + * @param b The integer to be written into pngBytes. + * @param offset The starting point to write to. + * @return The next place to be written to in the pngBytes array. + */ + protected int writeByte(int b, int offset) { + byte[] temp = {(byte) b}; + return writeBytes(temp, offset); + } + + /** + * Write a PNG "IHDR" chunk into the pngBytes array. + */ + protected void writeHeader() { + int startPos; + + startPos = bytePos = writeInt4(13, bytePos); + bytePos = writeBytes(IHDR, bytePos); + bytePos = writeInt4(width, bytePos); + bytePos = writeInt4(height, bytePos); + bytePos = writeByte(8, bytePos); // bit depth + bytePos = writeByte((encodeAlpha) ? 6 : 2, bytePos); // direct model + bytePos = writeByte(0, bytePos); // compression method + bytePos = writeByte(0, bytePos); // filter method + bytePos = writeByte(0, bytePos); // no interlace + crc.reset(); + crc.update(pngBytes, startPos, bytePos - startPos); + crcValue = crc.getValue(); + bytePos = writeInt4((int) crcValue, bytePos); + } + + /** + * Perform "sub" filtering on the given row. + * Uses temporary array leftBytes to store the original values + * of the previous pixels. The array is 16 bytes long, which + * will easily hold two-byte samples plus two-byte alpha. + * + * @param pixels The array holding the scan lines being built + * @param startPos Starting position within pixels of bytes to be filtered. + * @param width Width of a scanline in pixels. + */ + protected void filterSub(byte[] pixels, int startPos, int width) { + int i; + int offset = bytesPerPixel; + int actualStart = startPos + offset; + int nBytes = width * bytesPerPixel; + int leftInsert = offset; + int leftExtract = 0; + + for (i = actualStart; i < startPos + nBytes; i++) { + leftBytes[leftInsert] = pixels[i]; + pixels[i] = (byte) ((pixels[i] - leftBytes[leftExtract]) % 256); + leftInsert = (leftInsert + 1) % 0x0f; + leftExtract = (leftExtract + 1) % 0x0f; + } + } + + /** + * Perform "up" filtering on the given row. + * Side effect: refills the prior row with current row + * + * @param pixels The array holding the scan lines being built + * @param startPos Starting position within pixels of bytes to be filtered. + * @param width Width of a scanline in pixels. + */ + protected void filterUp(byte[] pixels, int startPos, int width) { + int i, nBytes; + byte currentByte; + + nBytes = width * bytesPerPixel; + + for (i = 0; i < nBytes; i++) { + currentByte = pixels[startPos + i]; + pixels[startPos + i] = (byte) ((pixels[startPos + i] - priorRow[i]) % 256); + priorRow[i] = currentByte; + } + } + + /** + * Write the image data into the pngBytes array. + * This will write one or more PNG "IDAT" chunks. In order + * to conserve memory, this method grabs as many rows as will + * fit into 32K bytes, or the whole image; whichever is less. + * + * + * @return true if no errors; false if error grabbing pixels + */ + protected boolean writeImageData() { + int rowsLeft = height; // number of rows remaining to write + int startRow = 0; // starting row to process this time through + int nRows; // how many rows to grab at a time + + byte[] scanLines; // the scan lines to be compressed + int scanPos; // where we are in the scan lines + int startPos; // where this line's actual pixels start (used for filtering) + + byte[] compressedLines; // the resultant compressed lines + int nCompressed; // how big is the compressed area? + + //int depth; // color depth ( handle only 8 or 32 ) + +// PixelGrabber pg; + + bytesPerPixel = (encodeAlpha) ? 4 : 3; + + Deflater scrunch = new Deflater(compressionLevel); + ByteArrayOutputStream outBytes = new ByteArrayOutputStream(1024); + + DeflaterOutputStream compBytes = new DeflaterOutputStream(outBytes, scrunch); + try { + while (rowsLeft > 0) { + nRows = Math.min(32767 / (width * (bytesPerPixel + 1)), rowsLeft); + nRows = Math.max( nRows, 1 ); + + int[] pixels = new int[width * nRows]; + + getPixels(startRow, nRows, pixels); + + /* + * Create a data chunk. scanLines adds "nRows" for + * the filter bytes. + */ + scanLines = new byte[width * nRows * bytesPerPixel + nRows]; + + if (filter == FILTER_SUB) { + leftBytes = new byte[16]; + } + if (filter == FILTER_UP) { + priorRow = new byte[width * bytesPerPixel]; + } + + scanPos = 0; + startPos = 1; + for (int i = 0; i < width * nRows; i++) { + if (i % width == 0) { + scanLines[scanPos++] = (byte) filter; + startPos = scanPos; + } + scanLines[scanPos++] = (byte) ((pixels[i] >> 16) & 0xff); + scanLines[scanPos++] = (byte) ((pixels[i] >> 8) & 0xff); + scanLines[scanPos++] = (byte) ((pixels[i]) & 0xff); + if (encodeAlpha) { + scanLines[scanPos++] = (byte) ((pixels[i] >> 24) & 0xff); + } + if ((i % width == width - 1) && (filter != FILTER_NONE)) { + if (filter == FILTER_SUB) { + filterSub(scanLines, startPos, width); + } + if (filter == FILTER_UP) { + filterUp(scanLines, startPos, width); + } + } + } + + /* + * Write these lines to the output area + */ + compBytes.write(scanLines, 0, scanPos); + + startRow += nRows; + rowsLeft -= nRows; + } + compBytes.close(); + + /* + * Write the compressed bytes + */ + compressedLines = outBytes.toByteArray(); + nCompressed = compressedLines.length; + + crc.reset(); + bytePos = writeInt4(nCompressed, bytePos); + bytePos = writeBytes(IDAT, bytePos); + crc.update(IDAT); + bytePos = writeBytes(compressedLines, nCompressed, bytePos); + crc.update(compressedLines, 0, nCompressed); + + crcValue = crc.getValue(); + bytePos = writeInt4((int) crcValue, bytePos); + scrunch.finish(); + return true; + } + catch (IOException e) { + System.err.println(e.toString()); + return false; + } + } + + /** + * Write a PNG "IEND" chunk into the pngBytes array. + */ + protected void writeEnd() { + bytePos = writeInt4(0, bytePos); + bytePos = writeBytes(IEND, bytePos); + crc.reset(); + crc.update(IEND); + crcValue = crc.getValue(); + bytePos = writeInt4((int) crcValue, bytePos); + } + + private void getPixels( int startRow, int nRows, int[] pixels) + { + for( int i=0; i 2000 ) return 255; + int res = 0; + int div = 1; + while ( val > 0 ) + { + int d = val > 127 ? 127 : val; + val -= d; + res += d / div; + div *= 2; + } + return res < 255 ? res : 255; + } + +} diff --git a/misc/profiles2/car-traffic_analysis.brf b/misc/profiles2/car-traffic_analysis.brf new file mode 100644 index 0000000..d267796 --- /dev/null +++ b/misc/profiles2/car-traffic_analysis.brf @@ -0,0 +1,125 @@ +# +# Car-Routing is experimantal !!! +# +# DO NOT USE FOR ACTUAL NAVIGATION +# +# Turn restrictions are missing, leading to wrong routes +# + +---context:global + +assign downhillcost 0 +assign downhillcutoff 0 +assign uphillcost 0 +assign uphillcutoff 0 + +assign validForCars 1 + +assign pass1coefficient 0. +assign pass2coefficient -1 + +---context:way # following code refers to way-tags + + +assign turncost = 0 + +assign initialcost switch route=ferry 20000 0 + + +# +# calculate logical car access +# +assign caraccess + switch motorcar= + switch motor_vehicle= + switch vehicle= + switch access= + switch or highway=motorway highway=motorway_link 1 + switch or highway=trunk highway=trunk_link 1 + switch or highway=primary highway=primary_link 1 + switch or highway=secondary highway=secondary_link 1 + switch or highway=tertiary highway=tertiary_link 1 + switch highway=unclassified 1 + switch route=ferry 1 + switch or highway=residential highway=living_street 1 + switch highway=service 1 + 0 + or access=yes or access=permissive or access=designated access=destination + or vehicle=yes or vehicle=designated vehicle=destination + or motor_vehicle=yes or motor_vehicle=permissive or motor_vehicle=designated motor_vehicle=destination + or motorcar=yes or motorcar=permissive or motorcar=designated motorcar=destination + +assign accesspenalty + switch caraccess + 0 + 10000 + +assign onewaypenalty + switch switch reversedirection=yes + switch oneway= + junction=roundabout + or oneway=yes or oneway=true oneway=1 + oneway=-1 + 10000 + 0.0 + + +assign ispaved or surface=paved or surface=asphalt or surface=concrete surface=paving_stones + + +assign costfactor + + add max onewaypenalty accesspenalty + + switch and highway= not route=ferry 10000 + + switch or highway=motorway highway=motorway_link 1 + switch or highway=trunk highway=trunk_link 1 + switch or highway=primary highway=primary_link 1.2 + switch or highway=secondary highway=secondary_link 1.6 + switch or highway=tertiary highway=tertiary_link 2.0 + switch highway=unclassified 2.5 + switch route=ferry 5.67 + switch highway=bridleway 5 + switch or highway=residential highway=living_street 3.5 + switch highway=service 3.5 + switch or highway=track or highway=road highway=path + switch tracktype=grade1 5 + switch ispaved 5 + 30 + 10000 + +assign trafficsourcedensity = + if highway=residential|living_street then 1 + else if and maxspeed=30|50 highway=tertiary|secondary|primary then 1 + else 0 + +assign istrafficbackbone + if greater costfactor 9999 then false + else if highway=motorway|motorway_link then true + else false + +---context:node # following code refers to node tags + +# +# calculate logical car access to nodes +# +assign caraccess + switch motorcar= + switch motor_vehicle= + switch vehicle= + switch access= + switch barrier=gate 0 + switch barrier=bollard 0 + switch barrier=lift_gate 0 + switch barrier=cycle_barrier 0 + 1 + or access=yes or access=permissive or access=designated access=destination + or vehicle=yes or vehicle=permissive or vehicle=designated vehicle=destination + or motor_vehicle=yes or motor_vehicle=permissive or motor_vehicle=designated motor_vehicle=destination + or motorcar=yes or motorcar=permissive or motorcar=designated motorcar=destination + +assign initialcost + switch caraccess + 0 + 1000000 diff --git a/misc/profiles2/dummy.brf b/misc/profiles2/dummy.brf new file mode 100644 index 0000000..a18162c --- /dev/null +++ b/misc/profiles2/dummy.brf @@ -0,0 +1,7 @@ +---context:global # following code refers to global config +---context:way # following code refers to way-tags + +assign costfactor + switch and highway= not route=ferry 100000 + +---context:node # following code refers to node tags diff --git a/misc/profiles2/fastbike-lowtraffic.brf b/misc/profiles2/fastbike-lowtraffic.brf new file mode 100644 index 0000000..c210b85 --- /dev/null +++ b/misc/profiles2/fastbike-lowtraffic.brf @@ -0,0 +1,201 @@ +# +# A fastbike could be a racing bike or a speed pedelec. +# But also at night or in rainy whether you might want +# to fallback to this one. +# +# Structure is similar to trekking.brf, see this for documenation. +# + +---context:global # following code refers to global config + +# Use the following switches to change behaviour +# (1=yes, 0=no): + +assign consider_elevation 1 # set to 0 to ignore elevation in routing +assign allow_steps 1 # set to 0 to disallow steps +assign allow_ferries 1 # set to 0 to disallow ferries +assign ignore_cycleroutes 0 # set to 1 for better elevation results +assign stick_to_cycleroutes 0 # set to 1 to just follow cycleroutes +assign avoid_unsafe 0 # set to 1 to avoid standard highways + +assign forceSecondaryData 1 + +assign validForBikes 1 + +# the elevation parameters + +assign downhillcost switch consider_elevation 60 0 +assign downhillcutoff 1.5 +assign uphillcost 0 +assign uphillcutoff 1.5 + +---context:way # following code refers to way-tags + +assign any_cycleroute or route_bicycle_icn=yes or route_bicycle_ncn=yes or route_bicycle_rcn=yes route_bicycle_lcn=yes +assign nodeaccessgranted or any_cycleroute lcn=yes + +assign ispaved or surface=paved or surface=asphalt or surface=concrete surface=paving_stones +assign isunpaved not or surface= or ispaved or surface=fine_gravel surface=cobblestone + +assign turncost 90 + +assign initialcost switch route=ferry 10000 0 + +# +# calculate logical bike access +# +assign bikeaccess = + if any_cycleroute then true + else if bicycle= then + ( + if vehicle= then + ( + if access= then not or motorroad=yes highway=footway + else if access=private|no then false + else true + ) + else not vehicle=private|no + ) + else not bicycle=private|no|dismount + +# +# calculate logical foot access +# +assign footaccess = + if bikeaccess then true + else if bicycle=dismount then true + else if foot= then + ( + if access= then not motorroad=yes + else if access=private|no then false + else true + ) + else not foot=private|no + +# +# if not bike-, but foot-acess, just a moderate penalty, +# otherwise access is forbidden +# +assign accesspenalty = + if bikeaccess then 0 + else if footaccess then 6 + else 100000 + +# +# handle one-ways. On primary roads, wrong-oneways should +# be close to forbidden, while on other ways we just add +# 4 to the costfactor (making it at least 5 - you are allowed +# to push your bike) +# +assign oneway + switch oneway= + junction=roundabout + or oneway=yes or oneway=true oneway=1 +assign onewaypenalty + switch switch reversedirection=yes oneway oneway=-1 + switch or cycleway=opposite or cycleway=opposite_lane or cycleway=opposite_track oneway:bicycle=no 0 + switch or highway=primary highway=primary_link 50 + switch or highway=secondary highway=secondary_link 30 + switch or highway=tertiary highway=tertiary_link 20 + 6.0 + 0.0 + +assign hascycleway = not + and ( or cycleway= cycleway=no|none ) and ( or cycleway:left= cycleway:left=no ) ( or cycleway:right= cycleway:right=no ) + +assign trafficpenalty0 = + if highway=primary|primary_link then + ( + if estimated_traffic_class=4 then 0.2 + else if estimated_traffic_class=5 then 0.4 + else if estimated_traffic_class=6|7 then 0.6 + else 0 + ) + else if highway=secondary|secondary_link then + ( + if estimated_traffic_class=3 then 0.2 + else if estimated_traffic_class=4 then 0.4 + else if estimated_traffic_class=5 then 0.6 + else if estimated_traffic_class=6|7 then 1 + else 0 + ) + else if highway=tertiary|tertiary_link then + ( + if estimated_traffic_class=2 then 0.1 + else if estimated_traffic_class=3 then 0.3 + else if estimated_traffic_class=4 then 0.5 + else if estimated_traffic_class=5|6|7 then 1 + else 0 + ) + else 0 + +assign trafficpenalty = + if hascycleway then multiply -1 max -0.3 multiply -1 trafficpenalty0 + else trafficpenalty0 + +assign costfactor + + add max onewaypenalty accesspenalty + add trafficpenalty + + switch and highway= not route=ferry 100000 + + switch or highway=motorway highway=motorway_link 100000 + switch or highway=proposed highway=abandoned 100000 + switch or highway=trunk highway=trunk_link 10 + switch or highway=primary highway=primary_link 1.2 + switch or highway=secondary highway=secondary_link 1.1 + switch or highway=tertiary highway=tertiary_link 1.0 + switch highway=unclassified 1.1 + switch highway=pedestrian 10 + switch highway=steps 1000 + switch route=ferry 5.67 + switch highway=bridleway 5 + switch highway=cycleway|footway 1.3 + switch or highway=residential highway=living_street switch isunpaved 10 1.2 + switch highway=service switch isunpaved 10 1.2 + switch or highway=track or highway=road or highway=path highway=footway + switch tracktype=grade1 switch isunpaved 3 1.2 + switch tracktype=grade2 switch isunpaved 10 3 + switch tracktype=grade3 10.0 + switch tracktype=grade4 20.0 + switch tracktype=grade5 30.0 + switch bicycle=designated 1.3 + switch ispaved 2.0 100.0 + 10.0 + +---context:node # following code refers to node tags + +assign defaultaccess + switch access= + 1 # add default barrier restrictions here! + switch or access=private access=no + 0 + 1 + +assign bikeaccess + or nodeaccessgranted=yes + switch bicycle= + switch vehicle= + defaultaccess + switch or vehicle=private vehicle=no + 0 + 1 + switch or bicycle=private or bicycle=no bicycle=dismount + 0 + 1 + +assign footaccess + or bicycle=dismount + switch foot= + defaultaccess + switch or foot=private foot=no + 0 + 1 + +assign initialcost + switch bikeaccess + 0 + switch footaccess + 300 + 1000000 diff --git a/misc/profiles2/lookups.dat b/misc/profiles2/lookups.dat index 67603f5..8f9b0dd 100644 --- a/misc/profiles2/lookups.dat +++ b/misc/profiles2/lookups.dat @@ -1,5 +1,5 @@ ---lookupversion:10 ----minorversion:4 +---minorversion:5 ---readvarlength ---context:way @@ -498,6 +498,14 @@ ramp:wheelchair;0000000439 no ramp:luggage;0000000162 no ramp:luggage;0000000054 yes automatic manual +estimated_traffic_class;0000000001 1 +estimated_traffic_class;0000000001 2 +estimated_traffic_class;0000000001 3 +estimated_traffic_class;0000000001 4 +estimated_traffic_class;0000000001 5 +estimated_traffic_class;0000000001 6 +estimated_traffic_class;0000000001 7 + ---context:node highway;0001314954 bus_stop