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;
|
||||
|
||||
import btools.mapaccess.*;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import btools.mapaccess.OsmLink;
|
||||
import btools.mapaccess.OsmLinkHolder;
|
||||
import btools.mapaccess.OsmNode;
|
||||
import btools.mapaccess.OsmTransferNode;
|
||||
|
||||
final class OsmPath implements OsmLinkHolder
|
||||
{
|
||||
|
|
@ -29,6 +35,9 @@ final class OsmPath implements OsmLinkHolder
|
|||
private OsmNode sourcenode;
|
||||
private OsmLink link;
|
||||
public OsmPathElement originElement;
|
||||
public OsmPathElement myElement;
|
||||
|
||||
private float traffic;
|
||||
|
||||
private OsmLinkHolder nextForLink = null;
|
||||
|
||||
|
|
@ -44,6 +53,32 @@ final class OsmPath implements OsmLinkHolder
|
|||
|
||||
public MessageData message;
|
||||
|
||||
public void unregisterUpTree( RoutingContext rc )
|
||||
{
|
||||
try
|
||||
{
|
||||
OsmPathElement pe = originElement;
|
||||
while( pe instanceof OsmPathElementWithTraffic && ((OsmPathElementWithTraffic)pe).unregister(rc) )
|
||||
{
|
||||
pe = pe.origin;
|
||||
}
|
||||
}
|
||||
catch( IOException ioe )
|
||||
{
|
||||
throw new RuntimeException( ioe );
|
||||
}
|
||||
}
|
||||
|
||||
public void registerUpTree()
|
||||
{
|
||||
if ( originElement instanceof OsmPathElementWithTraffic )
|
||||
{
|
||||
OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic)originElement;
|
||||
ot.register();
|
||||
ot.addTraffic( traffic );
|
||||
}
|
||||
}
|
||||
|
||||
OsmPath()
|
||||
{
|
||||
}
|
||||
|
|
@ -55,23 +90,30 @@ final class OsmPath implements OsmLinkHolder
|
|||
this.selev = link.targetNode.getSElev();
|
||||
}
|
||||
|
||||
OsmPath( OsmNode sourcenode, OsmPath origin, OsmLink link, OsmTrack refTrack, boolean recordTransferNodes, RoutingContext rc )
|
||||
OsmPath( OsmNode sourcenode, OsmPath origin, OsmLink link, OsmTrack refTrack, boolean detailMode, RoutingContext rc )
|
||||
{
|
||||
this();
|
||||
this.originElement = new OsmPathElement( origin );
|
||||
if ( origin.myElement == null )
|
||||
{
|
||||
origin.myElement = OsmPathElement.create( origin, rc.countTraffic );
|
||||
}
|
||||
this.originElement = origin.myElement;
|
||||
this.link = link;
|
||||
this.sourcenode = sourcenode;
|
||||
this.cost = origin.cost;
|
||||
this.ehbd = origin.ehbd;
|
||||
this.ehbu = origin.ehbu;
|
||||
this.lastClassifier = origin.lastClassifier;
|
||||
addAddionalPenalty(refTrack, recordTransferNodes, origin, link, rc );
|
||||
addAddionalPenalty(refTrack, detailMode, origin, link, rc );
|
||||
}
|
||||
|
||||
private void addAddionalPenalty(OsmTrack refTrack, boolean recordTransferNodes, OsmPath origin, OsmLink link, RoutingContext rc )
|
||||
private void addAddionalPenalty(OsmTrack refTrack, boolean detailMode, OsmPath origin, OsmLink link, RoutingContext rc )
|
||||
{
|
||||
if ( link.descriptionBitmap == null ) throw new IllegalArgumentException( "null description for class: " + link.getClass() );
|
||||
|
||||
|
||||
boolean recordTransferNodes = detailMode || rc.countTraffic;
|
||||
boolean recordMessageData = detailMode;
|
||||
|
||||
rc.nogomatch = false;
|
||||
|
||||
// extract the 3 positions of the first section
|
||||
|
|
@ -117,10 +159,10 @@ final class OsmPath implements OsmLinkHolder
|
|||
}
|
||||
|
||||
rc.messageHandler.setCurrentPos( lon2, lat2 );
|
||||
boolean sameData = rc.expctxWay.evaluate( link.counterLinkWritten, description, rc.messageHandler );
|
||||
boolean sameData = rc.expctxWay.evaluate( rc.inverseDirection ^ link.counterLinkWritten, description, rc.messageHandler );
|
||||
|
||||
// if way description changed, store message
|
||||
if ( msgData.wayKeyValues != null && !sameData )
|
||||
if ( recordMessageData && msgData.wayKeyValues != null && !sameData )
|
||||
{
|
||||
originElement.message = msgData;
|
||||
msgData = new MessageData();
|
||||
|
|
@ -147,7 +189,7 @@ final class OsmPath implements OsmLinkHolder
|
|||
{
|
||||
if ( rc.wayfraction > 0. )
|
||||
{
|
||||
originElement = new OsmPathElement( rc.ilonshortest, rc.ilatshortest, ele2, null );
|
||||
originElement = OsmPathElement.create( rc.ilonshortest, rc.ilatshortest, ele2, null, rc.countTraffic );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -160,9 +202,10 @@ final class OsmPath implements OsmLinkHolder
|
|||
msgData.linkdist += dist;
|
||||
linkdisttotal += dist;
|
||||
|
||||
boolean isTrafficBackbone = cost == 0 && rc.expctxWay.getIsTrafficBackbone() > 0.f;
|
||||
|
||||
// *** penalty for turning angles
|
||||
if ( origin.originElement != null )
|
||||
if ( !isTrafficBackbone && origin.originElement != null )
|
||||
{
|
||||
// penalty proportional to direction change
|
||||
double cos = rc.calcCosAngle( lon0, lat0, lon1, lat1, lon2, lat2 );
|
||||
|
|
@ -251,6 +294,12 @@ final class OsmPath implements OsmLinkHolder
|
|||
cfdown = cfdown == 0.f ? cf : cfdown;
|
||||
|
||||
float costfactor = cfup*upweight + cf*(1.f - upweight - downweight) + cfdown*downweight;
|
||||
|
||||
if ( isTrafficBackbone )
|
||||
{
|
||||
costfactor = 0.f;
|
||||
}
|
||||
|
||||
float fcost = dist * costfactor + 0.5f;
|
||||
if ( costfactor > 9999. || fcost + cost >= 2000000000. )
|
||||
{
|
||||
|
|
@ -260,6 +309,12 @@ final class OsmPath implements OsmLinkHolder
|
|||
int waycost = (int)(fcost);
|
||||
cost += waycost;
|
||||
|
||||
// calculate traffic
|
||||
{
|
||||
int minDist = (int)rc.trafficSourceMinDist;
|
||||
int cost2 = cost < minDist ? minDist : cost;
|
||||
traffic += dist*rc.expctxWay.getTrafficSourceDensity()*Math.pow(cost2/10000.f,rc.trafficSourceExponent);
|
||||
}
|
||||
// *** add initial cost if the classifier changed
|
||||
float newClassifier = rc.expctxWay.getInitialClassifier();
|
||||
if ( newClassifier == 0. )
|
||||
|
|
@ -276,7 +331,7 @@ final class OsmPath implements OsmLinkHolder
|
|||
cost += iicost;
|
||||
}
|
||||
|
||||
if ( recordTransferNodes )
|
||||
if ( recordMessageData )
|
||||
{
|
||||
msgData.costfactor = costfactor;
|
||||
msgData.lon = lon2;
|
||||
|
|
@ -289,9 +344,12 @@ final class OsmPath implements OsmLinkHolder
|
|||
{
|
||||
if ( recordTransferNodes )
|
||||
{
|
||||
originElement = new OsmPathElement( rc.ilonshortest, rc.ilatshortest, ele2, originElement );
|
||||
originElement = OsmPathElement.create( rc.ilonshortest, rc.ilatshortest, ele2, originElement, rc.countTraffic );
|
||||
originElement.cost = cost;
|
||||
originElement.message = msgData;
|
||||
if ( recordMessageData )
|
||||
{
|
||||
originElement.message = msgData;
|
||||
}
|
||||
}
|
||||
if ( rc.nogomatch )
|
||||
{
|
||||
|
|
@ -315,8 +373,10 @@ final class OsmPath implements OsmLinkHolder
|
|||
|
||||
if ( recordTransferNodes )
|
||||
{
|
||||
originElement = new OsmPathElement( lon2, lat2, ele2, originElement );
|
||||
originElement = OsmPathElement.create( lon2, lat2, ele2, originElement, rc.countTraffic );
|
||||
originElement.cost = cost;
|
||||
originElement.addTraffic( traffic );
|
||||
traffic = 0;
|
||||
}
|
||||
lon0 = lon1;
|
||||
lat0 = lat1;
|
||||
|
|
@ -350,13 +410,15 @@ final class OsmPath implements OsmLinkHolder
|
|||
|
||||
cost += iicost;
|
||||
|
||||
if ( recordTransferNodes )
|
||||
if ( recordMessageData )
|
||||
{
|
||||
msgData.nodeKeyValues = rc.expctxNode.getKeyValueDescription( nodeAccessGranted, targetNode.nodeDescription );
|
||||
}
|
||||
}
|
||||
|
||||
message = msgData;
|
||||
if ( recordMessageData )
|
||||
{
|
||||
message = msgData;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import java.io.IOException;
|
|||
* @author ab
|
||||
*/
|
||||
|
||||
public final class OsmPathElement implements OsmPos
|
||||
public class OsmPathElement implements OsmPos
|
||||
{
|
||||
private int ilat; // latitude
|
||||
private int ilon; // longitude
|
||||
|
|
@ -24,32 +24,32 @@ public final class OsmPathElement implements OsmPos
|
|||
public int cost;
|
||||
|
||||
// interface OsmPos
|
||||
public int getILat()
|
||||
public final int getILat()
|
||||
{
|
||||
return ilat;
|
||||
}
|
||||
|
||||
public int getILon()
|
||||
public final int getILon()
|
||||
{
|
||||
return ilon;
|
||||
}
|
||||
|
||||
public short getSElev()
|
||||
public final short getSElev()
|
||||
{
|
||||
return selev;
|
||||
}
|
||||
|
||||
public double getElev()
|
||||
public final double getElev()
|
||||
{
|
||||
return selev / 4.;
|
||||
}
|
||||
|
||||
public long getIdFromPos()
|
||||
public final long getIdFromPos()
|
||||
{
|
||||
return ((long)ilon)<<32 | ilat;
|
||||
}
|
||||
|
||||
public int calcDistance( OsmPos p )
|
||||
public final int calcDistance( OsmPos p )
|
||||
{
|
||||
double l = (ilat-90000000) * 0.00000001234134;
|
||||
double l2 = l*l;
|
||||
|
|
@ -65,27 +65,30 @@ public final class OsmPathElement implements OsmPos
|
|||
public OsmPathElement origin;
|
||||
|
||||
// construct a path element from a path
|
||||
public OsmPathElement( OsmPath path )
|
||||
public static final OsmPathElement create( OsmPath path, boolean countTraffic )
|
||||
{
|
||||
OsmNode n = path.getLink().targetNode;
|
||||
ilat = n.getILat();
|
||||
ilon = n.getILon();
|
||||
selev = path.selev;
|
||||
cost = path.cost;
|
||||
|
||||
origin = path.originElement;
|
||||
message = path.message;
|
||||
OsmPathElement pe = create( n.getILon(), n.getILat(), path.selev, path.originElement, countTraffic );
|
||||
pe.cost = path.cost;
|
||||
pe.message = path.message;
|
||||
return pe;
|
||||
}
|
||||
|
||||
public OsmPathElement( int ilon, int ilat, short selev, OsmPathElement origin )
|
||||
public static final OsmPathElement create( int ilon, int ilat, short selev, OsmPathElement origin, boolean countTraffic )
|
||||
{
|
||||
this.ilon = ilon;
|
||||
this.ilat = ilat;
|
||||
this.selev = selev;
|
||||
this.origin = origin;
|
||||
OsmPathElement pe = countTraffic ? new OsmPathElementWithTraffic() : new OsmPathElement();
|
||||
pe.ilon = ilon;
|
||||
pe.ilat = ilat;
|
||||
pe.selev = selev;
|
||||
pe.origin = origin;
|
||||
return pe;
|
||||
}
|
||||
|
||||
private OsmPathElement()
|
||||
protected OsmPathElement()
|
||||
{
|
||||
}
|
||||
|
||||
public void addTraffic( float traffic )
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 long[] nogoChecksums;
|
||||
|
||||
private class OsmPathElementHolder
|
||||
private static class OsmPathElementHolder
|
||||
{
|
||||
public OsmPathElement node;
|
||||
public OsmPathElementHolder nextHolder;
|
||||
|
|
@ -448,7 +448,7 @@ public final class OsmTrack
|
|||
idx2 += 6;
|
||||
int idx3 = line.indexOf( '"', idx2 );
|
||||
int ilat = (int)((Double.parseDouble( line.substring( idx2, idx3 ) ) + 90. )*1000000. + 0.5);
|
||||
nodes.add( new OsmPathElement( ilon, ilat, (short)0, null ) );
|
||||
nodes.add( OsmPathElement.create( ilon, ilat, (short)0, null, false ) );
|
||||
}
|
||||
}
|
||||
br.close();
|
||||
|
|
|
|||
|
|
@ -5,11 +5,15 @@
|
|||
*/
|
||||
package btools.router;
|
||||
|
||||
import java.io.DataOutput;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import btools.mapaccess.*;
|
||||
import btools.expressions.*;
|
||||
import btools.expressions.BExpressionContext;
|
||||
import btools.expressions.BExpressionContextNode;
|
||||
import btools.expressions.BExpressionContextWay;
|
||||
import btools.mapaccess.DistanceChecker;
|
||||
import btools.mapaccess.OsmTransferNode;
|
||||
|
||||
public final class RoutingContext implements DistanceChecker
|
||||
{
|
||||
|
|
@ -83,6 +87,14 @@ public final class RoutingContext implements DistanceChecker
|
|||
buffertime = expctxGlobal.getVariableValue( "buffertime", 120.f );
|
||||
waittimeadjustment = expctxGlobal.getVariableValue( "waittimeadjustment", 0.9f );
|
||||
starttimeoffset = expctxGlobal.getVariableValue( "starttimeoffset", 0.f );
|
||||
|
||||
farTrafficWeight = expctxGlobal.getVariableValue( "farTrafficWeight", 2.f );
|
||||
nearTrafficWeight = expctxGlobal.getVariableValue( "nearTrafficWeight", 2.f );
|
||||
farTrafficDecayLength = expctxGlobal.getVariableValue( "farTrafficDecayLength", 30000.f );
|
||||
nearTrafficDecayLength = expctxGlobal.getVariableValue( "nearTrafficDecayLength", 3000.f );
|
||||
trafficDirectionFactor = expctxGlobal.getVariableValue( "trafficDirectionFactor", 0.9f );
|
||||
trafficSourceExponent = expctxGlobal.getVariableValue( "trafficSourceExponent", -0.7f );
|
||||
trafficSourceMinDist = expctxGlobal.getVariableValue( "trafficSourceMinDist", 3000.f );
|
||||
}
|
||||
|
||||
public RoutingMessageHandler messageHandler = new RoutingMessageHandler();
|
||||
|
|
@ -99,6 +111,18 @@ public final class RoutingContext implements DistanceChecker
|
|||
public int ilatshortest;
|
||||
public int ilonshortest;
|
||||
|
||||
public boolean countTraffic;
|
||||
public boolean inverseDirection;
|
||||
public DataOutput trafficOutputStream;
|
||||
|
||||
public double farTrafficWeight;
|
||||
public double nearTrafficWeight;
|
||||
public double farTrafficDecayLength;
|
||||
public double nearTrafficDecayLength;
|
||||
public double trafficDirectionFactor;
|
||||
public double trafficSourceExponent;
|
||||
public double trafficSourceMinDist;
|
||||
|
||||
public static void prepareNogoPoints( List<OsmNodeNamed> nogos )
|
||||
{
|
||||
for( OsmNodeNamed nogo : nogos )
|
||||
|
|
|
|||
|
|
@ -46,14 +46,15 @@ public class RoutingEngine extends Thread
|
|||
private Writer infoLogWriter;
|
||||
protected RoutingContext routingContext;
|
||||
|
||||
private double airDistanceCostFactor;
|
||||
public double airDistanceCostFactor;
|
||||
private OsmTrack guideTrack;
|
||||
|
||||
private OsmPathElement matchPath;
|
||||
|
||||
private long startTime;
|
||||
private long maxRunningTime;
|
||||
|
||||
public SearchBoundary boundary;
|
||||
|
||||
public boolean quite = false;
|
||||
|
||||
public RoutingEngine( String outfileBase, String logfileBase, String segmentDir,
|
||||
|
|
@ -231,6 +232,51 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
}
|
||||
|
||||
public void doSearch()
|
||||
{
|
||||
try
|
||||
{
|
||||
MatchedWaypoint seedPoint = matchNodeForPosition( waypoints.get(0) );
|
||||
routingContext.countTraffic = true;
|
||||
|
||||
findTrack( "seededSearch", seedPoint, null, null, null, false );
|
||||
}
|
||||
catch( IllegalArgumentException e)
|
||||
{
|
||||
errorMessage = e.getMessage();
|
||||
logInfo( "Exception (linksProcessed=" + linksProcessed + ": " + errorMessage );
|
||||
}
|
||||
catch( Exception e)
|
||||
{
|
||||
errorMessage = e instanceof IllegalArgumentException ? e.getMessage() : e.toString();
|
||||
logInfo( "Exception (linksProcessed=" + linksProcessed + ": " + errorMessage );
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch( Error e)
|
||||
{
|
||||
String hint = cleanOnOOM();
|
||||
errorMessage = e.toString() + hint;
|
||||
logInfo( "Error (linksProcessed=" + linksProcessed + ": " + errorMessage );
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if ( nodesCache != null )
|
||||
{
|
||||
nodesCache.close();
|
||||
nodesCache = null;
|
||||
}
|
||||
openSet.clear();
|
||||
finished = true; // this signals termination to outside
|
||||
|
||||
if ( infoLogWriter != null )
|
||||
{
|
||||
try { infoLogWriter.close(); } catch( Exception e ) {}
|
||||
infoLogWriter = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String cleanOnOOM()
|
||||
{
|
||||
boolean oom_carsubset_hint = nodesCache == null ? false : nodesCache.oom_carsubset_hint;
|
||||
|
|
@ -504,15 +550,15 @@ public class RoutingEngine extends Thread
|
|||
return start;
|
||||
}
|
||||
|
||||
private OsmPath getStartPath( OsmNode n1, OsmNode n2, MatchedWaypoint mwp, MatchedWaypoint endWp, boolean sameSegmentSearch )
|
||||
private OsmPath getStartPath( OsmNode n1, OsmNode n2, MatchedWaypoint mwp, OsmNodeNamed endPos, boolean sameSegmentSearch )
|
||||
{
|
||||
OsmPath p = getStartPath( n1, n2, mwp.waypoint, endWp.crosspoint );
|
||||
OsmPath p = getStartPath( n1, n2, mwp.waypoint, endPos );
|
||||
|
||||
// special case: start+end on same segment
|
||||
if ( sameSegmentSearch )
|
||||
{
|
||||
OsmPath pe = getEndPath( n1, p.getLink(), endWp.crosspoint, endWp.crosspoint );
|
||||
OsmPath pt = getEndPath( n1, p.getLink(), null, endWp.crosspoint );
|
||||
OsmPath pe = getEndPath( n1, p.getLink(), endPos );
|
||||
OsmPath pt = getEndPath( n1, p.getLink(), null );
|
||||
int costdelta = pt.cost - p.cost;
|
||||
if ( pe.cost >= costdelta )
|
||||
{
|
||||
|
|
@ -571,7 +617,7 @@ public class RoutingEngine extends Thread
|
|||
|
||||
wp.radius = 1e9;
|
||||
OsmPath testPath = new OsmPath( null, startPath, link, null, guideTrack != null, routingContext );
|
||||
testPath.airdistance = nextNode.calcDistance( endPos );
|
||||
testPath.airdistance = endPos == null ? 0 : nextNode.calcDistance( endPos );
|
||||
if ( wp.radius < minradius )
|
||||
{
|
||||
bestPath = testPath;
|
||||
|
|
@ -593,7 +639,7 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
}
|
||||
|
||||
private OsmPath getEndPath( OsmNode n1, OsmLink link, OsmNodeNamed wp, OsmNode endPos )
|
||||
private OsmPath getEndPath( OsmNode n1, OsmLink link, OsmNodeNamed wp )
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -619,7 +665,6 @@ public class RoutingEngine extends Thread
|
|||
|
||||
int maxTotalCost = 1000000000;
|
||||
int firstMatchCost = 1000000000;
|
||||
int firstEstimate = 1000000000;
|
||||
|
||||
logInfo( "findtrack with airDistanceCostFactor=" + airDistanceCostFactor );
|
||||
if (costCuttingTrack != null ) logInfo( "costCuttingTrack.cost=" + costCuttingTrack.cost );
|
||||
|
|
@ -628,12 +673,13 @@ public class RoutingEngine extends Thread
|
|||
int nodesVisited = 0;
|
||||
|
||||
resetCache();
|
||||
long endNodeId1 = endWp.node1.getIdFromPos();
|
||||
long endNodeId2 = endWp.node2.getIdFromPos();
|
||||
long endNodeId1 = endWp == null ? -1L : endWp.node1.getIdFromPos();
|
||||
long endNodeId2 = endWp == null ? -1L : endWp.node2.getIdFromPos();
|
||||
long startNodeId1 = startWp.node1.getIdFromPos();
|
||||
long startNodeId2 = startWp.node2.getIdFromPos();
|
||||
|
||||
OsmNode endPos = endWp.crosspoint;
|
||||
OsmNodeNamed startPos = startWp.crosspoint;
|
||||
OsmNodeNamed endPos = endWp == null ? null : endWp.crosspoint;
|
||||
|
||||
boolean sameSegmentSearch = ( startNodeId1 == endNodeId1 && startNodeId2 == endNodeId2 )
|
||||
|| ( startNodeId1 == endNodeId2 && startNodeId2 == endNodeId1 );
|
||||
|
|
@ -642,8 +688,8 @@ public class RoutingEngine extends Thread
|
|||
OsmNode start2 = getStartNode( startNodeId2 );
|
||||
if ( start1 == null || start2 == null ) return null;
|
||||
|
||||
OsmPath startPath1 = getStartPath( start1, start2, startWp, endWp, sameSegmentSearch );
|
||||
OsmPath startPath2 = getStartPath( start2, start1, startWp, endWp, sameSegmentSearch );
|
||||
OsmPath startPath1 = getStartPath( start1, start2, startWp, endPos, sameSegmentSearch );
|
||||
OsmPath startPath2 = getStartPath( start2, start1, startWp, endPos, sameSegmentSearch );
|
||||
|
||||
// check for an INITIAL match with the cost-cutting-track
|
||||
if ( costCuttingTrack != null )
|
||||
|
|
@ -681,7 +727,11 @@ public class RoutingEngine extends Thread
|
|||
path = openSet.popLowestKeyValue();
|
||||
}
|
||||
if ( path == null ) break;
|
||||
if ( path.airdistance == -1 ) continue;
|
||||
if ( path.airdistance == -1 )
|
||||
{
|
||||
path.unregisterUpTree( routingContext );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( matchPath != null && fastPartialRecalc && firstMatchCost < 500 && path.cost > 30L*firstMatchCost )
|
||||
{
|
||||
|
|
@ -728,8 +778,7 @@ public class RoutingEngine extends Thread
|
|||
+ ( costCuttingTrack.cost - pe.cost );
|
||||
if ( costEstimate <= maxTotalCost )
|
||||
{
|
||||
if ( matchPath == null ) firstEstimate = costEstimate;
|
||||
matchPath = new OsmPathElement( path );
|
||||
matchPath = OsmPathElement.create( path, routingContext.countTraffic );
|
||||
}
|
||||
if ( costEstimate < maxTotalCost )
|
||||
{
|
||||
|
|
@ -743,6 +792,7 @@ public class RoutingEngine extends Thread
|
|||
// recheck cutoff before doing expensive stuff
|
||||
if ( path.cost + path.airdistance > maxTotalCost + 10 )
|
||||
{
|
||||
path.unregisterUpTree( routingContext );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -809,8 +859,8 @@ public class RoutingEngine extends Thread
|
|||
{
|
||||
if ( isFinalLink )
|
||||
{
|
||||
endWp.crosspoint.radius = 1e-5;
|
||||
routingContext.setWaypoint( endWp.crosspoint, true );
|
||||
endPos.radius = 1e-5;
|
||||
routingContext.setWaypoint( endPos, true );
|
||||
}
|
||||
OsmPath testPath = new OsmPath( currentNode, otherPath, link, refTrack, guideTrack != null, routingContext );
|
||||
if ( testPath.cost >= 0 && ( bestPath == null || testPath.cost < bestPath.cost ) )
|
||||
|
|
@ -829,13 +879,17 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
if ( bestPath != null )
|
||||
{
|
||||
bestPath.airdistance = isFinalLink ? 0 : nextNode.calcDistance( endPos );
|
||||
boolean trafficSim = endPos == null;
|
||||
|
||||
bestPath.airdistance = trafficSim ? path.airdistance : ( isFinalLink ? 0 : nextNode.calcDistance( endPos ) );
|
||||
|
||||
if ( isFinalLink || bestPath.cost + bestPath.airdistance <= maxTotalCost + 10 )
|
||||
boolean inRadius = boundary == null || boundary.isInBoundary( nextNode, bestPath.cost );
|
||||
|
||||
if ( inRadius && ( isFinalLink || bestPath.cost + bestPath.airdistance <= maxTotalCost + 10 ) )
|
||||
{
|
||||
// add only if this may beat an existing path for that link
|
||||
OsmLinkHolder dominator = link.firstlinkholder;
|
||||
while( dominator != null )
|
||||
while( !trafficSim && dominator != null )
|
||||
{
|
||||
if ( bestPath.definitlyWorseThan( (OsmPath)dominator, routingContext ) )
|
||||
{
|
||||
|
|
@ -846,6 +900,11 @@ public class RoutingEngine extends Thread
|
|||
|
||||
if ( dominator == null )
|
||||
{
|
||||
if ( trafficSim && boundary != null && path.cost == 0 && bestPath.cost > 0 )
|
||||
{
|
||||
bestPath.airdistance += boundary.getBoundaryDistance( nextNode );
|
||||
}
|
||||
|
||||
bestPath.treedepth = path.treedepth + 1;
|
||||
link.addLinkHolder( bestPath );
|
||||
synchronized( openSet )
|
||||
|
|
@ -861,7 +920,7 @@ public class RoutingEngine extends Thread
|
|||
{
|
||||
currentNode.unlinkLink(counterLink);
|
||||
}
|
||||
|
||||
path.unregisterUpTree( routingContext );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -871,6 +930,7 @@ public class RoutingEngine extends Thread
|
|||
if ( path.cost >= 0 )
|
||||
{
|
||||
openSet.add( path.cost + (int)(path.airdistance*airDistanceCostFactor), path );
|
||||
path.registerUpTree();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -902,7 +962,7 @@ public class RoutingEngine extends Thread
|
|||
|
||||
private OsmTrack compileTrack( OsmPath path, boolean verbose )
|
||||
{
|
||||
OsmPathElement element = new OsmPathElement( path );
|
||||
OsmPathElement element = OsmPathElement.create( path, false );
|
||||
|
||||
// for final track, cut endnode
|
||||
if ( guideTrack != null ) element = element.origin;
|
||||
|
|
|
|||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue