Traffic simulation patch
This commit is contained in:
parent
a35eea8878
commit
91c809e05c
22 changed files with 1595 additions and 83 deletions
|
@ -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,10 +344,13 @@ 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;
|
||||||
|
if ( recordMessageData )
|
||||||
|
{
|
||||||
originElement.message = msgData;
|
originElement.message = msgData;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if ( rc.nogomatch )
|
if ( rc.nogomatch )
|
||||||
{
|
{
|
||||||
cost = -1;
|
cost = -1;
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
|
@ -46,13 +46,14 @@ 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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
if ( isFinalLink || bestPath.cost + bestPath.airdistance <= maxTotalCost + 10 )
|
bestPath.airdistance = trafficSim ? path.airdistance : ( isFinalLink ? 0 : nextNode.calcDistance( endPos ) );
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
87
brouter-core/src/main/java/btools/router/SearchBoundary.java
Normal file
87
brouter-core/src/main/java/btools/router/SearchBoundary.java
Normal 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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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 );
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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 );
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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];
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
|
@ -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" ) );
|
||||||
|
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" ) );
|
wplist.add( readPosition( args, 3, "to" ) );
|
||||||
RoutingEngine re = new RoutingEngine( "mytrack", "mylog", args[0], wplist, readRoutingContext(args) );
|
re = new RoutingEngine( "mytrack", "mylog", args[0], wplist, readRoutingContext(args) );
|
||||||
re.doRun( 0 );
|
re.doRun( 0 );
|
||||||
|
}
|
||||||
if ( re.getErrorMessage() != null )
|
if ( re.getErrorMessage() != null )
|
||||||
{
|
{
|
||||||
System.out.println( re.getErrorMessage() );
|
System.out.println( re.getErrorMessage() );
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
||||||
|
|
|
@ -119,4 +119,9 @@ public class FrozenLongMap<V> extends CompactLongMap<V>
|
||||||
{
|
{
|
||||||
return flv;
|
return flv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long[] getKeyArray()
|
||||||
|
{
|
||||||
|
return faid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
464
brouter-util/src/main/java/btools/util/Raster2Png.java
Normal file
464
brouter-util/src/main/java/btools/util/Raster2Png.java
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
125
misc/profiles2/car-traffic_analysis.brf
Normal file
125
misc/profiles2/car-traffic_analysis.brf
Normal 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
7
misc/profiles2/dummy.brf
Normal 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
|
201
misc/profiles2/fastbike-lowtraffic.brf
Normal file
201
misc/profiles2/fastbike-lowtraffic.brf
Normal 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
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue