Traffic simulation patch

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

View file

@ -5,7 +5,13 @@
*/
package btools.router;
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;
}
}

View file

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

View file

@ -0,0 +1,78 @@
package btools.router;
import java.io.IOException;
/**
* Extension to OsmPathElement to count traffic load
*
* @author ab
*/
public final class OsmPathElementWithTraffic extends OsmPathElement
{
private int registerCount;
private float farTraffic;
private float nearTraffic;
public void register()
{
if ( registerCount++ == 0 )
{
if ( origin instanceof OsmPathElementWithTraffic )
{
OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic)origin;
ot.register();
ot.farTraffic += farTraffic;
ot.nearTraffic += nearTraffic;
farTraffic = 0;
nearTraffic = 0;
}
}
}
@Override
public void addTraffic( float traffic )
{
this.farTraffic += traffic;
this.nearTraffic += traffic;
}
// unregister from origin if our registercount is 0, else do nothing
public static double maxtraffic = 0.;
public boolean unregister( RoutingContext rc ) throws IOException
{
if ( --registerCount == 0 )
{
if ( origin instanceof OsmPathElementWithTraffic )
{
OsmPathElementWithTraffic ot = (OsmPathElementWithTraffic)origin;
int costdelta = cost-ot.cost;
ot.farTraffic += farTraffic*Math.exp(-costdelta/rc.farTrafficDecayLength);
ot.nearTraffic += nearTraffic*Math.exp(-costdelta/rc.nearTrafficDecayLength);
if ( costdelta > 0 && farTraffic > maxtraffic ) maxtraffic = farTraffic;
int t2 = cost == ot.cost ? -1 : (int)(rc.farTrafficWeight*farTraffic + rc.nearTrafficWeight*nearTraffic);
if ( t2 > 4000 || t2 == -1 )
{
// System.out.println( "unregistered: " + this + " origin=" + ot + " farTraffic =" + farTraffic + " nearTraffic =" + nearTraffic + " cost=" + cost );
if ( rc.trafficOutputStream != null )
{
rc.trafficOutputStream.writeLong( getIdFromPos());
rc.trafficOutputStream.writeLong( ot.getIdFromPos());
rc.trafficOutputStream.writeInt( t2 );
}
}
farTraffic = 0;
nearTraffic = 0;
}
return true;
}
return false;
}
}

View file

@ -32,7 +32,7 @@ public final class OsmTrack
public MatchedWaypoint endPoint;
public 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();

View file

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

View file

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

View file

@ -0,0 +1,87 @@
/**
* static helper class for handling datafiles
*
* @author ab
*/
package btools.router;
import btools.mapaccess.OsmNode;
public final class SearchBoundary
{
private int minlon0;
private int minlat0;
private int maxlon0;
private int maxlat0;
private int minlon;
private int minlat;
private int maxlon;
private int maxlat;
private int radius;
private OsmNode p;
int direction;
public SearchBoundary( OsmNode n, int radius, int direction )
{
this.radius = radius;
this.direction = direction;
p = new OsmNode( n.ilon, n.ilat );
int lon = (n.ilon / 5000000 ) * 5000000;
int lat = (n.ilat / 5000000 ) * 5000000;
minlon0 = lon - 5000000;
minlat0 = lat - 5000000;
maxlon0 = lon + 10000000;
maxlat0 = lat + 10000000;
minlon = lon - 1000000;
minlat = lat - 1000000;
maxlon = lon + 6000000;
maxlat = lat + 6000000;
}
public static String getFileName( OsmNode n )
{
int lon = (n.ilon / 5000000 ) * 5000000;
int lat = (n.ilat / 5000000 ) * 5000000;
int dlon = lon / 1000000 -180;
int dlat = lat / 1000000 - 90;
String slon = dlon < 0 ? "W" + (-dlon) : "E" + dlon;
String slat = dlat < 0 ? "S" + (-dlat) : "N" + dlat;
return slon + "_" + slat + ".trf";
}
public boolean isInBoundary( OsmNode n, int cost )
{
if ( radius > 0 )
{
return n.calcDistance( p ) < radius;
}
if ( cost == 0 )
{
return n.ilon > minlon0 && n.ilon < maxlon0 && n.ilat > minlat0 && n.ilat < maxlat0;
}
return n.ilon > minlon && n.ilon < maxlon && n.ilat > minlat && n.ilat < maxlat;
}
public int getBoundaryDistance( OsmNode n )
{
switch( direction )
{
case 0: return n.calcDistance( new OsmNode( n.ilon, minlat ) );
case 1: return n.calcDistance( new OsmNode( minlon, n.ilat ) );
case 2: return n.calcDistance( new OsmNode( n.ilon, maxlat ) );
case 3: return n.calcDistance( new OsmNode( maxlon, n.ilat ) );
default: throw new IllegalArgumentException( "undefined direction: "+ direction );
}
}
}