Traffic simulation patch

This commit is contained in:
Arndt 2015-08-28 16:39:41 +02:00
parent a35eea8878
commit 91c809e05c
22 changed files with 1595 additions and 83 deletions

View file

@ -5,7 +5,13 @@
*/ */
package btools.router; 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 final class OsmPath implements OsmLinkHolder
{ {
@ -29,6 +35,9 @@ final class OsmPath implements OsmLinkHolder
private OsmNode sourcenode; private OsmNode sourcenode;
private OsmLink link; private OsmLink link;
public OsmPathElement originElement; public OsmPathElement originElement;
public OsmPathElement myElement;
private float traffic;
private OsmLinkHolder nextForLink = null; private OsmLinkHolder nextForLink = null;
@ -44,6 +53,32 @@ final class OsmPath implements OsmLinkHolder
public MessageData message; 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() OsmPath()
{ {
} }
@ -55,23 +90,30 @@ final class OsmPath implements OsmLinkHolder
this.selev = link.targetNode.getSElev(); 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();
this.originElement = new OsmPathElement( origin ); if ( origin.myElement == null )
{
origin.myElement = OsmPathElement.create( origin, rc.countTraffic );
}
this.originElement = origin.myElement;
this.link = link; this.link = link;
this.sourcenode = sourcenode; this.sourcenode = sourcenode;
this.cost = origin.cost; this.cost = origin.cost;
this.ehbd = origin.ehbd; this.ehbd = origin.ehbd;
this.ehbu = origin.ehbu; this.ehbu = origin.ehbu;
this.lastClassifier = origin.lastClassifier; 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() ); if ( link.descriptionBitmap == null ) throw new IllegalArgumentException( "null description for class: " + link.getClass() );
boolean recordTransferNodes = detailMode || rc.countTraffic;
boolean recordMessageData = detailMode;
rc.nogomatch = false; rc.nogomatch = false;
// extract the 3 positions of the first section // extract the 3 positions of the first section
@ -117,10 +159,10 @@ final class OsmPath implements OsmLinkHolder
} }
rc.messageHandler.setCurrentPos( lon2, lat2 ); 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 way description changed, store message
if ( msgData.wayKeyValues != null && !sameData ) if ( recordMessageData && msgData.wayKeyValues != null && !sameData )
{ {
originElement.message = msgData; originElement.message = msgData;
msgData = new MessageData(); msgData = new MessageData();
@ -147,7 +189,7 @@ final class OsmPath implements OsmLinkHolder
{ {
if ( rc.wayfraction > 0. ) 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 else
{ {
@ -160,9 +202,10 @@ final class OsmPath implements OsmLinkHolder
msgData.linkdist += dist; msgData.linkdist += dist;
linkdisttotal += dist; linkdisttotal += dist;
boolean isTrafficBackbone = cost == 0 && rc.expctxWay.getIsTrafficBackbone() > 0.f;
// *** penalty for turning angles // *** penalty for turning angles
if ( origin.originElement != null ) if ( !isTrafficBackbone && origin.originElement != null )
{ {
// penalty proportional to direction change // penalty proportional to direction change
double cos = rc.calcCosAngle( lon0, lat0, lon1, lat1, lon2, lat2 ); 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; cfdown = cfdown == 0.f ? cf : cfdown;
float costfactor = cfup*upweight + cf*(1.f - upweight - downweight) + cfdown*downweight; float costfactor = cfup*upweight + cf*(1.f - upweight - downweight) + cfdown*downweight;
if ( isTrafficBackbone )
{
costfactor = 0.f;
}
float fcost = dist * costfactor + 0.5f; float fcost = dist * costfactor + 0.5f;
if ( costfactor > 9999. || fcost + cost >= 2000000000. ) if ( costfactor > 9999. || fcost + cost >= 2000000000. )
{ {
@ -260,6 +309,12 @@ final class OsmPath implements OsmLinkHolder
int waycost = (int)(fcost); int waycost = (int)(fcost);
cost += waycost; 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 // *** add initial cost if the classifier changed
float newClassifier = rc.expctxWay.getInitialClassifier(); float newClassifier = rc.expctxWay.getInitialClassifier();
if ( newClassifier == 0. ) if ( newClassifier == 0. )
@ -276,7 +331,7 @@ final class OsmPath implements OsmLinkHolder
cost += iicost; cost += iicost;
} }
if ( recordTransferNodes ) if ( recordMessageData )
{ {
msgData.costfactor = costfactor; msgData.costfactor = costfactor;
msgData.lon = lon2; msgData.lon = lon2;
@ -289,9 +344,12 @@ final class OsmPath implements OsmLinkHolder
{ {
if ( recordTransferNodes ) 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.cost = cost;
originElement.message = msgData; if ( recordMessageData )
{
originElement.message = msgData;
}
} }
if ( rc.nogomatch ) if ( rc.nogomatch )
{ {
@ -315,8 +373,10 @@ final class OsmPath implements OsmLinkHolder
if ( recordTransferNodes ) if ( recordTransferNodes )
{ {
originElement = new OsmPathElement( lon2, lat2, ele2, originElement ); originElement = OsmPathElement.create( lon2, lat2, ele2, originElement, rc.countTraffic );
originElement.cost = cost; originElement.cost = cost;
originElement.addTraffic( traffic );
traffic = 0;
} }
lon0 = lon1; lon0 = lon1;
lat0 = lat1; lat0 = lat1;
@ -350,13 +410,15 @@ final class OsmPath implements OsmLinkHolder
cost += iicost; cost += iicost;
if ( recordTransferNodes ) if ( recordMessageData )
{ {
msgData.nodeKeyValues = rc.expctxNode.getKeyValueDescription( nodeAccessGranted, targetNode.nodeDescription ); msgData.nodeKeyValues = rc.expctxNode.getKeyValueDescription( nodeAccessGranted, targetNode.nodeDescription );
} }
} }
if ( recordMessageData )
message = msgData; {
message = msgData;
}
} }

View file

@ -13,7 +13,7 @@ import java.io.IOException;
* @author ab * @author ab
*/ */
public final class OsmPathElement implements OsmPos public class OsmPathElement implements OsmPos
{ {
private int ilat; // latitude private int ilat; // latitude
private int ilon; // longitude private int ilon; // longitude
@ -24,32 +24,32 @@ public final class OsmPathElement implements OsmPos
public int cost; public int cost;
// interface OsmPos // interface OsmPos
public int getILat() public final int getILat()
{ {
return ilat; return ilat;
} }
public int getILon() public final int getILon()
{ {
return ilon; return ilon;
} }
public short getSElev() public final short getSElev()
{ {
return selev; return selev;
} }
public double getElev() public final double getElev()
{ {
return selev / 4.; return selev / 4.;
} }
public long getIdFromPos() public final long getIdFromPos()
{ {
return ((long)ilon)<<32 | ilat; return ((long)ilon)<<32 | ilat;
} }
public int calcDistance( OsmPos p ) public final int calcDistance( OsmPos p )
{ {
double l = (ilat-90000000) * 0.00000001234134; double l = (ilat-90000000) * 0.00000001234134;
double l2 = l*l; double l2 = l*l;
@ -65,27 +65,30 @@ public final class OsmPathElement implements OsmPos
public OsmPathElement origin; public OsmPathElement origin;
// construct a path element from a path // 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; OsmNode n = path.getLink().targetNode;
ilat = n.getILat(); OsmPathElement pe = create( n.getILon(), n.getILat(), path.selev, path.originElement, countTraffic );
ilon = n.getILon(); pe.cost = path.cost;
selev = path.selev; pe.message = path.message;
cost = path.cost; return pe;
origin = path.originElement;
message = path.message;
} }
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; OsmPathElement pe = countTraffic ? new OsmPathElementWithTraffic() : new OsmPathElement();
this.ilat = ilat; pe.ilon = ilon;
this.selev = selev; pe.ilat = ilat;
this.origin = origin; pe.selev = selev;
pe.origin = origin;
return pe;
} }
private OsmPathElement() protected OsmPathElement()
{
}
public void addTraffic( float traffic )
{ {
} }

View file

@ -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;
}
}

View file

@ -32,7 +32,7 @@ public final class OsmTrack
public MatchedWaypoint endPoint; public MatchedWaypoint endPoint;
public long[] nogoChecksums; public long[] nogoChecksums;
private class OsmPathElementHolder private static class OsmPathElementHolder
{ {
public OsmPathElement node; public OsmPathElement node;
public OsmPathElementHolder nextHolder; public OsmPathElementHolder nextHolder;
@ -448,7 +448,7 @@ public final class OsmTrack
idx2 += 6; idx2 += 6;
int idx3 = line.indexOf( '"', idx2 ); int idx3 = line.indexOf( '"', idx2 );
int ilat = (int)((Double.parseDouble( line.substring( idx2, idx3 ) ) + 90. )*1000000. + 0.5); 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(); br.close();

View file

@ -5,11 +5,15 @@
*/ */
package btools.router; package btools.router;
import java.io.DataOutput;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import btools.mapaccess.*; import btools.expressions.BExpressionContext;
import btools.expressions.*; import btools.expressions.BExpressionContextNode;
import btools.expressions.BExpressionContextWay;
import btools.mapaccess.DistanceChecker;
import btools.mapaccess.OsmTransferNode;
public final class RoutingContext implements DistanceChecker public final class RoutingContext implements DistanceChecker
{ {
@ -83,6 +87,14 @@ public final class RoutingContext implements DistanceChecker
buffertime = expctxGlobal.getVariableValue( "buffertime", 120.f ); buffertime = expctxGlobal.getVariableValue( "buffertime", 120.f );
waittimeadjustment = expctxGlobal.getVariableValue( "waittimeadjustment", 0.9f ); waittimeadjustment = expctxGlobal.getVariableValue( "waittimeadjustment", 0.9f );
starttimeoffset = expctxGlobal.getVariableValue( "starttimeoffset", 0.f ); 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(); public RoutingMessageHandler messageHandler = new RoutingMessageHandler();
@ -99,6 +111,18 @@ public final class RoutingContext implements DistanceChecker
public int ilatshortest; public int ilatshortest;
public int ilonshortest; 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<OsmNodeNamed> nogos ) public static void prepareNogoPoints( List<OsmNodeNamed> nogos )
{ {
for( OsmNodeNamed nogo : nogos ) for( OsmNodeNamed nogo : nogos )

View file

@ -46,14 +46,15 @@ public class RoutingEngine extends Thread
private Writer infoLogWriter; private Writer infoLogWriter;
protected RoutingContext routingContext; protected RoutingContext routingContext;
private double airDistanceCostFactor; public double airDistanceCostFactor;
private OsmTrack guideTrack; private OsmTrack guideTrack;
private OsmPathElement matchPath; private OsmPathElement matchPath;
private long startTime; private long startTime;
private long maxRunningTime; private long maxRunningTime;
public SearchBoundary boundary;
public boolean quite = false; public boolean quite = false;
public RoutingEngine( String outfileBase, String logfileBase, String segmentDir, 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() public String cleanOnOOM()
{ {
boolean oom_carsubset_hint = nodesCache == null ? false : nodesCache.oom_carsubset_hint; boolean oom_carsubset_hint = nodesCache == null ? false : nodesCache.oom_carsubset_hint;
@ -504,15 +550,15 @@ public class RoutingEngine extends Thread
return start; 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 // special case: start+end on same segment
if ( sameSegmentSearch ) if ( sameSegmentSearch )
{ {
OsmPath pe = getEndPath( n1, p.getLink(), endWp.crosspoint, endWp.crosspoint ); OsmPath pe = getEndPath( n1, p.getLink(), endPos );
OsmPath pt = getEndPath( n1, p.getLink(), null, endWp.crosspoint ); OsmPath pt = getEndPath( n1, p.getLink(), null );
int costdelta = pt.cost - p.cost; int costdelta = pt.cost - p.cost;
if ( pe.cost >= costdelta ) if ( pe.cost >= costdelta )
{ {
@ -571,7 +617,7 @@ public class RoutingEngine extends Thread
wp.radius = 1e9; wp.radius = 1e9;
OsmPath testPath = new OsmPath( null, startPath, link, null, guideTrack != null, routingContext ); 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 ) if ( wp.radius < minradius )
{ {
bestPath = testPath; 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 try
{ {
@ -619,7 +665,6 @@ public class RoutingEngine extends Thread
int maxTotalCost = 1000000000; int maxTotalCost = 1000000000;
int firstMatchCost = 1000000000; int firstMatchCost = 1000000000;
int firstEstimate = 1000000000;
logInfo( "findtrack with airDistanceCostFactor=" + airDistanceCostFactor ); logInfo( "findtrack with airDistanceCostFactor=" + airDistanceCostFactor );
if (costCuttingTrack != null ) logInfo( "costCuttingTrack.cost=" + costCuttingTrack.cost ); if (costCuttingTrack != null ) logInfo( "costCuttingTrack.cost=" + costCuttingTrack.cost );
@ -628,12 +673,13 @@ public class RoutingEngine extends Thread
int nodesVisited = 0; int nodesVisited = 0;
resetCache(); resetCache();
long endNodeId1 = endWp.node1.getIdFromPos(); long endNodeId1 = endWp == null ? -1L : endWp.node1.getIdFromPos();
long endNodeId2 = endWp.node2.getIdFromPos(); long endNodeId2 = endWp == null ? -1L : endWp.node2.getIdFromPos();
long startNodeId1 = startWp.node1.getIdFromPos(); long startNodeId1 = startWp.node1.getIdFromPos();
long startNodeId2 = startWp.node2.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 ) boolean sameSegmentSearch = ( startNodeId1 == endNodeId1 && startNodeId2 == endNodeId2 )
|| ( startNodeId1 == endNodeId2 && startNodeId2 == endNodeId1 ); || ( startNodeId1 == endNodeId2 && startNodeId2 == endNodeId1 );
@ -642,8 +688,8 @@ public class RoutingEngine extends Thread
OsmNode start2 = getStartNode( startNodeId2 ); OsmNode start2 = getStartNode( startNodeId2 );
if ( start1 == null || start2 == null ) return null; if ( start1 == null || start2 == null ) return null;
OsmPath startPath1 = getStartPath( start1, start2, startWp, endWp, sameSegmentSearch ); OsmPath startPath1 = getStartPath( start1, start2, startWp, endPos, sameSegmentSearch );
OsmPath startPath2 = getStartPath( start2, start1, startWp, endWp, sameSegmentSearch ); OsmPath startPath2 = getStartPath( start2, start1, startWp, endPos, sameSegmentSearch );
// check for an INITIAL match with the cost-cutting-track // check for an INITIAL match with the cost-cutting-track
if ( costCuttingTrack != null ) if ( costCuttingTrack != null )
@ -681,7 +727,11 @@ public class RoutingEngine extends Thread
path = openSet.popLowestKeyValue(); path = openSet.popLowestKeyValue();
} }
if ( path == null ) break; 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 ) if ( matchPath != null && fastPartialRecalc && firstMatchCost < 500 && path.cost > 30L*firstMatchCost )
{ {
@ -728,8 +778,7 @@ public class RoutingEngine extends Thread
+ ( costCuttingTrack.cost - pe.cost ); + ( costCuttingTrack.cost - pe.cost );
if ( costEstimate <= maxTotalCost ) if ( costEstimate <= maxTotalCost )
{ {
if ( matchPath == null ) firstEstimate = costEstimate; matchPath = OsmPathElement.create( path, routingContext.countTraffic );
matchPath = new OsmPathElement( path );
} }
if ( costEstimate < maxTotalCost ) if ( costEstimate < maxTotalCost )
{ {
@ -743,6 +792,7 @@ public class RoutingEngine extends Thread
// recheck cutoff before doing expensive stuff // recheck cutoff before doing expensive stuff
if ( path.cost + path.airdistance > maxTotalCost + 10 ) if ( path.cost + path.airdistance > maxTotalCost + 10 )
{ {
path.unregisterUpTree( routingContext );
continue; continue;
} }
@ -809,8 +859,8 @@ public class RoutingEngine extends Thread
{ {
if ( isFinalLink ) if ( isFinalLink )
{ {
endWp.crosspoint.radius = 1e-5; endPos.radius = 1e-5;
routingContext.setWaypoint( endWp.crosspoint, true ); routingContext.setWaypoint( endPos, true );
} }
OsmPath testPath = new OsmPath( currentNode, otherPath, link, refTrack, guideTrack != null, routingContext ); OsmPath testPath = new OsmPath( currentNode, otherPath, link, refTrack, guideTrack != null, routingContext );
if ( testPath.cost >= 0 && ( bestPath == null || testPath.cost < bestPath.cost ) ) if ( testPath.cost >= 0 && ( bestPath == null || testPath.cost < bestPath.cost ) )
@ -829,13 +879,17 @@ public class RoutingEngine extends Thread
} }
if ( bestPath != null ) 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 // add only if this may beat an existing path for that link
OsmLinkHolder dominator = link.firstlinkholder; OsmLinkHolder dominator = link.firstlinkholder;
while( dominator != null ) while( !trafficSim && dominator != null )
{ {
if ( bestPath.definitlyWorseThan( (OsmPath)dominator, routingContext ) ) if ( bestPath.definitlyWorseThan( (OsmPath)dominator, routingContext ) )
{ {
@ -846,6 +900,11 @@ public class RoutingEngine extends Thread
if ( dominator == null ) if ( dominator == null )
{ {
if ( trafficSim && boundary != null && path.cost == 0 && bestPath.cost > 0 )
{
bestPath.airdistance += boundary.getBoundaryDistance( nextNode );
}
bestPath.treedepth = path.treedepth + 1; bestPath.treedepth = path.treedepth + 1;
link.addLinkHolder( bestPath ); link.addLinkHolder( bestPath );
synchronized( openSet ) synchronized( openSet )
@ -861,7 +920,7 @@ public class RoutingEngine extends Thread
{ {
currentNode.unlinkLink(counterLink); currentNode.unlinkLink(counterLink);
} }
path.unregisterUpTree( routingContext );
} }
return null; return null;
} }
@ -871,6 +930,7 @@ public class RoutingEngine extends Thread
if ( path.cost >= 0 ) if ( path.cost >= 0 )
{ {
openSet.add( path.cost + (int)(path.airdistance*airDistanceCostFactor), path ); 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 ) private OsmTrack compileTrack( OsmPath path, boolean verbose )
{ {
OsmPathElement element = new OsmPathElement( path ); OsmPathElement element = OsmPathElement.create( path, false );
// for final track, cut endnode // for final track, cut endnode
if ( guideTrack != null ) element = element.origin; if ( guideTrack != null ) element = element.origin;

View file

@ -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 );
}
}
}

View file

@ -12,6 +12,7 @@ final class BExpression
private static final int MULTIPLY_EXP = 21; private static final int MULTIPLY_EXP = 21;
private static final int MAX_EXP = 22; private static final int MAX_EXP = 22;
private static final int EQUAL_EXP = 23; 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 SWITCH_EXP = 30;
private static final int ASSIGN_EXP = 31; private static final int ASSIGN_EXP = 31;
@ -105,6 +106,10 @@ final class BExpression
{ {
exp.typ = EQUAL_EXP; exp.typ = EQUAL_EXP;
} }
else if ( "greater".equals( operator ) )
{
exp.typ = GREATER_EXP;
}
else else
{ {
nops = 1; // check unary expressions nops = 1; // check unary expressions
@ -226,6 +231,7 @@ final class BExpression
case MULTIPLY_EXP: return op1.evaluate(ctx) * op2.evaluate(ctx); case MULTIPLY_EXP: return op1.evaluate(ctx) * op2.evaluate(ctx);
case MAX_EXP: return max( 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 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 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 ASSIGN_EXP: return ctx.assign( variableIdx, op1.evaluate(ctx) );
case LOOKUP_EXP: return ctx.getLookupMatch( lookupNameIdx, lookupValueIdxArray ); case LOOKUP_EXP: return ctx.getLookupMatch( lookupNameIdx, lookupValueIdxArray );

View file

@ -11,7 +11,7 @@ package btools.expressions;
public final class BExpressionContextWay extends BExpressionContext public final class BExpressionContextWay extends BExpressionContext
{ {
private static String[] buildInVariables = private static String[] buildInVariables =
{ "costfactor", "turncost", "uphillcostfactor", "downhillcostfactor", "initialcost", "nodeaccessgranted", "initialclassifier" }; { "costfactor", "turncost", "uphillcostfactor", "downhillcostfactor", "initialcost", "nodeaccessgranted", "initialclassifier", "trafficsourcedensity", "istrafficbackbone" };
protected String[] getBuildInVariableNames() protected String[] getBuildInVariableNames()
{ {
@ -25,6 +25,8 @@ public final class BExpressionContextWay extends BExpressionContext
public float getInitialcost() { return getBuildInVariable(4); } public float getInitialcost() { return getBuildInVariable(4); }
public float getNodeAccessGranted() { return getBuildInVariable(5); } public float getNodeAccessGranted() { return getBuildInVariable(5); }
public float getInitialClassifier() { return getBuildInVariable(6); } public float getInitialClassifier() { return getBuildInVariable(6); }
public float getTrafficSourceDensity() { return getBuildInVariable(7); }
public float getIsTrafficBackbone() { return getBuildInVariable(8); }
public BExpressionContextWay( BExpressionMetaData meta ) public BExpressionContextWay( BExpressionMetaData meta )

View file

@ -34,14 +34,12 @@ public class OsmNodeP extends OsmLinkP implements Comparable<OsmNodeP>
*/ */
public short selev; public short selev;
public boolean isBorder = false;
public final static int NO_BRIDGE_BIT = 1; public final static int NO_BRIDGE_BIT = 1;
public final static int NO_TUNNEL_BIT = 2; public final static int NO_TUNNEL_BIT = 2;
public final static int LCN_BIT = 4; public final static int BORDER_BIT = 4;
public final static int CR_BIT = 8; public final static int TRAFFIC_BIT = 8;
public byte wayBits = 0; public byte bits = 0;
// interface OsmPos // interface OsmPos
public int getILat() public int getILat()
@ -57,7 +55,7 @@ public class OsmNodeP extends OsmLinkP implements Comparable<OsmNodeP>
public short getSElev() public short getSElev()
{ {
// if all bridge or all tunnel, elevation=no-data // 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() public double getElev()
@ -247,9 +245,19 @@ public class OsmNodeP extends OsmLinkP implements Comparable<OsmNodeP>
return ((long)ilon)<<32 | ilat; return ((long)ilon)<<32 | ilat;
} }
public boolean isBorderNode()
{
return (bits & BORDER_BIT) != 0;
}
public boolean hasTraffic()
{
return (bits & TRAFFIC_BIT) != 0;
}
public boolean isTransferNode() public boolean isTransferNode()
{ {
return (!isBorder) && _linkCnt() == 2; return (bits & BORDER_BIT) == 0 && _linkCnt() == 2;
} }
private int _linkCnt() private int _linkCnt()

View file

@ -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<OsmTrafficElement> map = new CompactLongMap<OsmTrafficElement>();
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<OsmTrafficElement>( 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 );
}
}

View file

@ -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;
}
}

View file

@ -1,8 +1,12 @@
package btools.mapcreator; package btools.mapcreator;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -31,6 +35,7 @@ import btools.util.LazyArrayOfLists;
public class WayLinker extends MapCreatorBase public class WayLinker extends MapCreatorBase
{ {
private File nodeTilesIn; private File nodeTilesIn;
private File trafficTilesIn;
private File dataTilesOut; private File dataTilesOut;
private File borderFileIn; private File borderFileIn;
@ -39,6 +44,7 @@ public class WayLinker extends MapCreatorBase
private boolean readingBorder; private boolean readingBorder;
private CompactLongMap<OsmNodeP> nodesMap; private CompactLongMap<OsmNodeP> nodesMap;
private OsmTrafficMap trafficMap;
private List<OsmNodeP> nodesList; private List<OsmNodeP> nodesList;
private CompactLongSet borderSet; private CompactLongSet borderSet;
private short lookupVersion; 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 public void process( File nodeTilesIn, File wayTilesIn, File borderFileIn, File lookupFile, File profileFile, File dataTilesOut, String dataTilesSuffix ) throws Exception
{ {
this.nodeTilesIn = nodeTilesIn; this.nodeTilesIn = nodeTilesIn;
this.trafficTilesIn = new File( "traffic" );
this.dataTilesOut = dataTilesOut; this.dataTilesOut = dataTilesOut;
this.borderFileIn = borderFileIn; this.borderFileIn = borderFileIn;
this.dataTilesSuffix = dataTilesSuffix; this.dataTilesSuffix = dataTilesSuffix;
@ -126,6 +133,14 @@ public class WayLinker extends MapCreatorBase
nodesMap = nodesMapFrozen; nodesMap = nodesMapFrozen;
nodesList = nodesMapFrozen.getValueList(); 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 @Override
@ -135,7 +150,7 @@ public class WayLinker extends MapCreatorBase
n.ilon = data.ilon; n.ilon = data.ilon;
n.ilat = data.ilat; n.ilat = data.ilat;
n.selev = data.selev; n.selev = data.selev;
n.isBorder = readingBorder;
if ( readingBorder || (!borderSet.contains( data.nid )) ) if ( readingBorder || (!borderSet.contains( data.nid )) )
{ {
nodesMap.fastPut( data.nid, n ); nodesMap.fastPut( data.nid, n );
@ -143,6 +158,7 @@ public class WayLinker extends MapCreatorBase
if ( readingBorder ) if ( readingBorder )
{ {
n.bits |= OsmNodeP.BORDER_BIT;
borderSet.fastAdd( data.nid ); borderSet.fastAdd( data.nid );
return; return;
} }
@ -160,6 +176,7 @@ public class WayLinker extends MapCreatorBase
public void nextWay( WayData way ) throws Exception public void nextWay( WayData way ) throws Exception
{ {
byte[] description = abUnifier.unify( way.description ); byte[] description = abUnifier.unify( way.description );
int lastTraffic = 0;
// filter according to profile // filter according to profile
expctxWay.evaluate( false, description, null ); expctxWay.evaluate( false, description, null );
@ -183,11 +200,20 @@ public class WayLinker extends MapCreatorBase
if ( n1 != null && n2 != null && n1 != n2 ) if ( n1 != null && n2 != null && n1 != n2 )
{ {
OsmLinkP link = n2.createLink( n1 ); 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; link.descriptionBitmap = description;
} }
if ( n2 != null ) if ( n2 != null )
{ {
n2.wayBits |= wayBits; n2.bits |= wayBits;
} }
} }
} }
@ -197,6 +223,7 @@ public class WayLinker extends MapCreatorBase
{ {
nodesMap = null; nodesMap = null;
borderSet = null; borderSet = null;
trafficMap = null;
byte[] abBuf = new byte[1024*1024]; byte[] abBuf = new byte[1024*1024];
byte[] abBuf2 = new byte[10*1024*1024]; byte[] abBuf2 = new byte[10*1024*1024];

View file

@ -339,7 +339,7 @@ time0 = minutes0 * 60000L;
{ {
System.out.println( "trip=" + current ); System.out.println( "trip=" + current );
OsmNodeP node = current.getTargetNode(); 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); track.addNode(pe);
if ( nextNode != null ) if ( nextNode != null )

View file

@ -1,5 +1,8 @@
package btools.server; package btools.server;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -7,6 +10,7 @@ import java.util.List;
import btools.router.OsmNodeNamed; import btools.router.OsmNodeNamed;
import btools.router.RoutingContext; import btools.router.RoutingContext;
import btools.router.RoutingEngine; import btools.router.RoutingEngine;
import btools.router.SearchBoundary;
public class BRouter public class BRouter
{ {
@ -84,7 +88,7 @@ public class BRouter
} }
System.exit(0); System.exit(0);
} }
System.out.println("BRouter 1.0 / 01062014 / abrensch"); System.out.println("BRouter 1.2 / 04042015 / abrensch");
if ( args.length < 6 ) if ( args.length < 6 )
{ {
System.out.println("Find routes in an OSM map"); System.out.println("Find routes in an OSM map");
@ -93,9 +97,37 @@ public class BRouter
} }
List<OsmNodeNamed> wplist = new ArrayList<OsmNodeNamed>(); List<OsmNodeNamed> wplist = new ArrayList<OsmNodeNamed>();
wplist.add( readPosition( args, 1, "from" ) ); wplist.add( readPosition( args, 1, "from" ) );
wplist.add( readPosition( args, 3, "to" ) ); RoutingEngine re = null;
RoutingEngine re = new RoutingEngine( "mytrack", "mylog", args[0], wplist, readRoutingContext(args) ); if ( "seed".equals( args[3] ) )
re.doRun( 0 ); {
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 ) if ( re.getErrorMessage() != null )
{ {
System.out.println( re.getErrorMessage() ); System.out.println( re.getErrorMessage() );

View file

@ -13,6 +13,7 @@ import java.util.List;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.TreeMap; import java.util.TreeMap;
import btools.memrouter.TwinRoutingEngine;
import btools.router.OsmNodeNamed; import btools.router.OsmNodeNamed;
import btools.router.OsmTrack; import btools.router.OsmTrack;
import btools.router.RoutingContext; import btools.router.RoutingContext;
@ -101,7 +102,7 @@ public class RouteServer extends Thread
RoutingContext rc = handler.readRoutingContext(); RoutingContext rc = handler.readRoutingContext();
List<OsmNodeNamed> wplist = handler.readWayPointList(); List<OsmNodeNamed> 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.quite = true;
cr.doRun( maxRunningTime ); cr.doRun( maxRunningTime );

View file

@ -119,4 +119,9 @@ public class FrozenLongMap<V> extends CompactLongMap<V>
{ {
return flv; return flv;
} }
public long[] getKeyArray()
{
return faid;
}
} }

View file

@ -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<nRows; i++ )
{
int ir = i + startRow;
for( int ic=0; ic<width; ic++ )
{
pixels[ i*width + ic ] = imagePixels[ ir*width + ic];
}
}
}
private int pseudoLog( short sval )
{
int val = 30 + sval;
if ( val < 0 ) { val = 0; }
if ( val > 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;
}
}

View file

@ -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

7
misc/profiles2/dummy.brf Normal file
View file

@ -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

View file

@ -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

View file

@ -1,5 +1,5 @@
---lookupversion:10 ---lookupversion:10
---minorversion:4 ---minorversion:5
---readvarlength ---readvarlength
---context:way ---context:way
@ -498,6 +498,14 @@ ramp:wheelchair;0000000439 no
ramp:luggage;0000000162 no ramp:luggage;0000000162 no
ramp:luggage;0000000054 yes automatic manual 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 ---context:node
highway;0001314954 bus_stop highway;0001314954 bus_stop