minor refactoring

This commit is contained in:
Arndt Brenschede 2019-04-17 11:33:07 +02:00
parent 126c104bb3
commit 19e434facb
18 changed files with 138 additions and 115 deletions

View file

@ -5,6 +5,8 @@
*/
package btools.router;
import btools.util.FastMath;
final class KinematicPath extends OsmPath
{
@ -58,7 +60,7 @@ final class KinematicPath extends OsmPath
if ( km.turnAngleDecayLength != 0. ) // process turn-angle slowdown
{
double decayFactor = exp( - dist / km.turnAngleDecayLength );
double decayFactor = FastMath.exp( - dist / km.turnAngleDecayLength );
floatingAngleLeft = (float)( floatingAngleLeft * decayFactor );
floatingAngleRight = (float)( floatingAngleRight * decayFactor );
if ( angle < 0 ) floatingAngleLeft -= (float)angle;

View file

@ -6,7 +6,7 @@
package btools.router;
import btools.mapaccess.OsmNode;
import btools.util.CheapRulerSingleton;
import btools.util.CheapRuler;
public class OsmNodeNamed extends OsmNode
{
@ -26,10 +26,10 @@ public class OsmNodeNamed extends OsmNode
}
public double distanceWithinRadius(int lon1, int lat1, int lon2, int lat2, double totalSegmentLength) {
double[] lonlat2m = CheapRulerSingleton.getLonLatToMeterScales( (lat1 + lat2) >> 1 );
double[] lonlat2m = CheapRuler.getLonLatToMeterScales( (lat1 + lat2) >> 1 );
boolean isFirstPointWithinCircle = CheapRulerSingleton.distance(lon1, lat1, ilon, ilat) < radius;
boolean isLastPointWithinCircle = CheapRulerSingleton.distance(lon2, lat2, ilon, ilat) < radius;
boolean isFirstPointWithinCircle = CheapRuler.distance(lon1, lat1, ilon, ilat) < radius;
boolean isLastPointWithinCircle = CheapRuler.distance(lon2, lat2, ilon, ilat) < radius;
// First point is within the circle
if (isFirstPointWithinCircle) {
// Last point is within the circle
@ -58,7 +58,7 @@ public class OsmNodeNamed extends OsmNode
+ (lat2 - lat1) * (ilat - lat1) * lonlat2m[1] * lonlat2m[1]
) / totalSegmentLength;
// Distance between the initial point and the center of the circle.
double initialToCenter = CheapRulerSingleton.distance(ilon, ilat, lon1, lat1);
double initialToCenter = CheapRuler.distance(ilon, ilat, lon1, lat1);
// Half length of the segment within the circle
double halfDistanceWithin = Math.sqrt(
radius*radius - (

View file

@ -25,7 +25,7 @@ package btools.router;
import java.util.ArrayList;
import java.util.List;
import btools.util.CheapRulerSingleton;
import btools.util.CheapRuler;
public class OsmNogoPolygon extends OsmNodeNamed
{
@ -104,7 +104,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
int cx = (cxmax+cxmin) / 2; // center of circle
int cy = (cymax+cymin) / 2;
double[] lonlat2m = CheapRulerSingleton.getLonLatToMeterScales( cy );
double[] lonlat2m = CheapRuler.getLonLatToMeterScales( cy );
double dlon2m = lonlat2m[0];
double dlat2m = lonlat2m[1];
@ -119,7 +119,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
for (int i = 0; i < points.size(); i++)
{
final Point p = points.get(i);
final double dist = CheapRulerSingleton.distance(p.x, p.y, (int) cx, (int) cy);
final double dist = CheapRuler.distance(p.x, p.y, (int) cx, (int) cy);
if (dist <= rad)
{
continue;
@ -141,7 +141,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
cx += (int)(dd * (p.x - cx) + 0.5); // shift center toward point
cy += (int)(dd * (p.y - cy) + 0.5);
dmax = rad = CheapRulerSingleton.distance(p.x, p.y, (int) cx, (int) cy);
dmax = rad = CheapRuler.distance(p.x, p.y, (int) cx, (int) cy);
i_max = -1;
}
while (true);
@ -357,7 +357,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
) {
// There was a previous match within the polygon and this part of the
// segment is within the polygon.
distance += CheapRulerSingleton.distance(
distance += CheapRuler.distance(
previousIntersectionOnSegment.x, previousIntersectionOnSegment.y,
intersection.x, intersection.y
);
@ -368,12 +368,12 @@ public class OsmNogoPolygon extends OsmNodeNamed
// Segment and edge overlaps
// FIXME: Could probably be done in a smarter way
distance += Math.min(
CheapRulerSingleton.distance(p1.x, p1.y, p2.x, p2.y),
CheapRuler.distance(p1.x, p1.y, p2.x, p2.y),
Math.min(
CheapRulerSingleton.distance(edgePoint1.x, edgePoint1.y, edgePoint2.x, edgePoint2.y),
CheapRuler.distance(edgePoint1.x, edgePoint1.y, edgePoint2.x, edgePoint2.y),
Math.min(
CheapRulerSingleton.distance(p1.x, p1.y, edgePoint2.x, edgePoint2.y),
CheapRulerSingleton.distance(edgePoint1.x, edgePoint1.y, p2.x, p2.y)
CheapRuler.distance(p1.x, p1.y, edgePoint2.x, edgePoint2.y),
CheapRuler.distance(edgePoint1.x, edgePoint1.y, p2.x, p2.y)
)
)
);
@ -387,7 +387,7 @@ public class OsmNogoPolygon extends OsmNodeNamed
&& isWithin(lon2, lat2)
) {
// Last point is within the polygon, add the remaining missing distance.
distance += CheapRulerSingleton.distance(
distance += CheapRuler.distance(
previousIntersectionOnSegment.x, previousIntersectionOnSegment.y,
lon2, lat2
);

View file

@ -12,7 +12,7 @@ import btools.mapaccess.OsmLinkHolder;
import btools.mapaccess.OsmNode;
import btools.mapaccess.OsmTransferNode;
import btools.mapaccess.TurnRestriction;
import btools.util.CheapRulerSingleton;
import btools.util.CheapRuler;
abstract class OsmPath implements OsmLinkHolder
{
@ -251,42 +251,9 @@ abstract class OsmPath implements OsmLinkHolder
// check turn restrictions (n detail mode (=final pass) no TR to not mess up voice hints)
if ( nsection == 0 && rc.considerTurnRestrictions && !detailMode&& !isStartpoint )
{
boolean hasAnyPositive = false;
boolean hasPositive = false;
boolean hasNegative = false;
TurnRestriction tr = sourceNode.firstRestriction;
while( tr != null )
{
if ( ( tr.exceptBikes() && rc.bikeMode ) || tr.exceptMotorcars() && rc.carMode )
{
tr = tr.next;
continue;
}
int fromLon = rc.inverseDirection ? lon2 : lon0;
int fromLat = rc.inverseDirection ? lat2 : lat0;
int toLon = rc.inverseDirection ? lon0 : lon2;
int toLat = rc.inverseDirection ? lat0 : lat2;
if ( tr.fromLon == fromLon && tr.fromLat == fromLat )
{
if ( tr.isPositive )
{
hasAnyPositive = true;
}
if ( tr.toLon == toLon && tr.toLat == toLat )
{
if ( tr.isPositive )
{
hasPositive = true;
}
else
{
hasNegative = true;
}
}
}
tr = tr.next;
}
if ( !hasPositive && ( hasAnyPositive || hasNegative ) )
if ( rc.inverseDirection
? TurnRestriction.isTurnForbidden( sourceNode.firstRestriction, lon2, lat2, lon0, lat0, rc.bikeMode, rc.carMode )
: TurnRestriction.isTurnForbidden( sourceNode.firstRestriction, lon0, lat0, lon2, lat2, rc.bikeMode, rc.carMode ) )
{
cost = -1;
return;
@ -345,8 +312,8 @@ abstract class OsmPath implements OsmLinkHolder
{
if ( rc.startDirectionValid )
{
double dir = rc.startDirection.intValue() * CheapRulerSingleton.DEG_TO_RAD;
double[] lonlat2m = CheapRulerSingleton.getLonLatToMeterScales( (lon0 + lat1) >> 1 );
double dir = rc.startDirection.intValue() * CheapRuler.DEG_TO_RAD;
double[] lonlat2m = CheapRuler.getLonLatToMeterScales( (lon0 + lat1) >> 1 );
lon0 = lon1 - (int) ( 1000. * Math.sin( dir ) / lonlat2m[0] );
lat0 = lat1 - (int) ( 1000. * Math.cos( dir ) / lonlat2m[1] );
}
@ -541,16 +508,4 @@ abstract class OsmPath implements OsmLinkHolder
{
return 0.;
}
protected static double exp( double e )
{
double x = e;
double f = 1.;
while( e < -1. )
{
e += 1.;
f *= 0.367879;
}
return f*( 1. + x*( 1. + x * ( 0.5 + x * ( 0.166667 + 0.0416667 * x) ) ) );
}
}

View file

@ -6,7 +6,7 @@ import java.io.IOException;
import btools.mapaccess.OsmNode;
import btools.mapaccess.OsmPos;
import btools.util.CheapRulerSingleton;
import btools.util.CheapRuler;
/**
* Container for link between two Osm nodes
@ -78,7 +78,7 @@ public class OsmPathElement implements OsmPos
public final int calcDistance( OsmPos p )
{
return (int)(CheapRulerSingleton.distance(ilon, ilat, p.getILon(), p.getILat()) + 1.0 );
return (int)(CheapRuler.distance(ilon, ilat, p.getILon(), p.getILat()) + 1.0 );
}
public OsmPathElement origin;

View file

@ -16,7 +16,7 @@ import btools.expressions.BExpressionContextNode;
import btools.expressions.BExpressionContextWay;
import btools.mapaccess.GeometryDecoder;
import btools.mapaccess.OsmLink;
import btools.util.CheapRulerSingleton;
import btools.util.CheapRuler;
public final class RoutingContext
{
@ -309,7 +309,7 @@ public final class RoutingContext
public int calcDistance( int lon1, int lat1, int lon2, int lat2 )
{
double[] lonlat2m = CheapRulerSingleton.getLonLatToMeterScales( (lat1+lat2) >> 1 );
double[] lonlat2m = CheapRuler.getLonLatToMeterScales( (lat1+lat2) >> 1 );
double dlon2m = lonlat2m[0];
double dlat2m = lonlat2m[1];
double dx = (lon2 - lon1 ) * dlon2m;
@ -419,7 +419,7 @@ public final class RoutingContext
public double calcAngle( int lon0, int lat0, int lon1, int lat1, int lon2, int lat2 )
{
double[] lonlat2m = CheapRulerSingleton.getLonLatToMeterScales( lat1 );
double[] lonlat2m = CheapRuler.getLonLatToMeterScales( lat1 );
double lon2m = lonlat2m[0];
double lat2m = lonlat2m[1];
double dx10 = (lon1 - lon0) * lon2m;

View file

@ -492,16 +492,6 @@ public class RoutingEngine extends Thread
}
// expand hollow link targets and resolve reverse links
private void expandHollowLinkTargets( OsmNode n )
{
for( OsmLink link = n.firstlink; link != null; link = link.getNext( n ) )
{
nodesCache.obtainNonHollowNode( link.getTarget( n ) );
}
}
private OsmTrack searchTrack( MatchedWaypoint startWp, MatchedWaypoint endWp, OsmTrack nearbyTrack, OsmTrack refTrack )
{
OsmTrack track = null;
@ -640,7 +630,7 @@ public class RoutingEngine extends Thread
{
return null;
}
expandHollowLinkTargets( start );
nodesCache.expandHollowLinkTargets( start );
return start;
}

View file

@ -5,11 +5,7 @@
*/
package btools.router;
import btools.mapaccess.OsmLink;
import btools.mapaccess.OsmNode;
import btools.mapaccess.OsmTransferNode;
import btools.mapaccess.TurnRestriction;
import btools.util.CheapRulerSingleton;
import btools.util.FastMath;
final class StdPath extends OsmPath
{
@ -223,7 +219,7 @@ final class StdPath extends OsmPath
{
return 0.;
}
double decayFactor = exp( - dist / 100. );
double decayFactor = FastMath.exp( - dist / 100. );
float new_elevation_buffer = (float)( (elevation_buffer+shift) * decayFactor - shift);
double incline = ( elevation_buffer - new_elevation_buffer ) / dist;
elevation_buffer = new_elevation_buffer;
@ -247,7 +243,7 @@ final class StdPath extends OsmPath
if (rc.footMode || rc.expctxWay.getCostfactor() > 4.9 )
{
// Use Tobler's hiking function for walking sections
speed = 6 * exp(-3.5 * Math.abs( incline + 0.05)) / 3.6;
speed = 6 * FastMath.exp(-3.5 * Math.abs( incline + 0.05)) / 3.6;
}
else if (rc.bikeMode)
{

View file

@ -5,7 +5,7 @@ import java.util.List;
import btools.codec.WaypointMatcher;
import btools.mapaccess.OsmNode;
import btools.mapaccess.OsmNodePairSet;
import btools.util.CheapRulerSingleton;
import btools.util.CheapRuler;
/**
* the WaypointMatcher is feeded by the decoder with geoemtries of ways that are
@ -41,7 +41,7 @@ public final class WaypointMatcherImpl implements WaypointMatcher
{
// todo: bounding-box pre-filter
double[] lonlat2m = CheapRulerSingleton.getLonLatToMeterScales( (lat1+lat2) >> 1 );
double[] lonlat2m = CheapRuler.getLonLatToMeterScales( (lat1+lat2) >> 1 );
double dlon2m = lonlat2m[0];
double dlat2m = lonlat2m[1];

View file

@ -8,15 +8,15 @@ import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import btools.util.CheapRulerSingleton;
import btools.util.CheapRuler;
public class OsmNodeNamedTest {
static int toOsmLon(double lon) {
return (int)( ( lon + 180. ) / CheapRulerSingleton.ILATLNG_TO_LATLNG + 0.5);
return (int)( ( lon + 180. ) / CheapRuler.ILATLNG_TO_LATLNG + 0.5);
}
static int toOsmLat(double lat) {
return (int)( ( lat + 90. ) / CheapRulerSingleton.ILATLNG_TO_LATLNG + 0.5);
return (int)( ( lat + 90. ) / CheapRuler.ILATLNG_TO_LATLNG + 0.5);
}
@Test
@ -36,7 +36,7 @@ public class OsmNodeNamedTest {
lat1 = toOsmLat(48.823822);
lon2 = toOsmLon(2.335018);
lat2 = toOsmLat(48.824105);
double totalSegmentLength = CheapRulerSingleton.distance(lon1, lat1, lon2, lat2);
double totalSegmentLength = CheapRuler.distance(lon1, lat1, lon2, lat2);
assertEquals(
"Works for segment aligned with the nogo center",
2 * node.radius,
@ -65,7 +65,7 @@ public class OsmNodeNamedTest {
// Check distance within radius is correctly computed if a point is inside the circle
lon2 = toOsmLon(2.334495);
lat2 = toOsmLat(48.824045);
totalSegmentLength = CheapRulerSingleton.distance(lon1, lat1, lon2, lat2);
totalSegmentLength = CheapRuler.distance(lon1, lat1, lon2, lat2);
assertEquals(
"Works if last point is within the circle",
17,
@ -77,7 +77,7 @@ public class OsmNodeNamedTest {
lat1 = toOsmLat(48.824045);
lon2 = toOsmLon(2.335018);
lat2 = toOsmLat(48.824105);
totalSegmentLength = CheapRulerSingleton.distance(lon1, lat1, lon2, lat2);
totalSegmentLength = CheapRuler.distance(lon1, lat1, lon2, lat2);
assertEquals(
"Works if first point is within the circle",
9,
@ -89,7 +89,7 @@ public class OsmNodeNamedTest {
lat1 = toOsmLat(48.82402);
lon2 = toOsmLon(2.334587);
lat2 = toOsmLat(48.824061);
totalSegmentLength = CheapRulerSingleton.distance(lon1, lat1, lon2, lat2);
totalSegmentLength = CheapRuler.distance(lon1, lat1, lon2, lat2);
assertEquals(
"Works if both points are within the circle",
25,
@ -106,7 +106,7 @@ public class OsmNodeNamedTest {
lat1 = toOsmLat(48.823822);
lon2 = toOsmLon(2.33431);
lat2 = toOsmLat(48.824027);
totalSegmentLength = CheapRulerSingleton.distance(lon1, lat1, lon2, lat2);
totalSegmentLength = CheapRuler.distance(lon1, lat1, lon2, lat2);
assertEquals(
"Works if both points are on the same side of the circle center",
5,

View file

@ -26,7 +26,7 @@ import org.junit.BeforeClass;
import org.junit.Test;
import btools.router.OsmNogoPolygon.Point;
import btools.util.CheapRulerSingleton;
import btools.util.CheapRuler;
public class OsmNogoPolygonTest {
@ -65,7 +65,7 @@ public class OsmNogoPolygonTest {
@Test
public void testCalcBoundingCircle() {
double[] lonlat2m = CheapRulerSingleton.getLonLatToMeterScales( polygon.ilat );
double[] lonlat2m = CheapRuler.getLonLatToMeterScales( polygon.ilat );
double dlon2m = lonlat2m[0];
double dlat2m = lonlat2m[1];
@ -207,9 +207,9 @@ public class OsmNogoPolygonTest {
lat2 = toOsmLat(48.824091, 0);
assertEquals(
"Should give the correct length if the segment overlaps with an edge of the polygon",
CheapRulerSingleton.distance(lon1, lat1, lon2, lat2),
CheapRuler.distance(lon1, lat1, lon2, lat2),
polygon.distanceWithinPolygon(lon1, lat1, lon2, lat2),
0.05 * CheapRulerSingleton.distance(lon1, lat1, lon2, lat2)
0.05 * CheapRuler.distance(lon1, lat1, lon2, lat2)
);
lon1 = toOsmLon(2.333523, 0);
@ -218,9 +218,9 @@ public class OsmNogoPolygonTest {
lat2 = toOsmLat(48.8239345, 0);
assertEquals(
"Should give the correct length if the segment overlaps with a polyline",
CheapRulerSingleton.distance(lon1, lat1, lon2, lat2),
CheapRuler.distance(lon1, lat1, lon2, lat2),
polyline.distanceWithinPolygon(lon1, lat1, lon2, lat2),
0.05 * CheapRulerSingleton.distance(lon1, lat1, lon2, lat2)
0.05 * CheapRuler.distance(lon1, lat1, lon2, lat2)
);
}
}

View file

@ -8,15 +8,15 @@ import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import btools.util.CheapRulerSingleton;
import btools.util.CheapRuler;
public class RoutingContextTest {
static int toOsmLon(double lon) {
return (int)( ( lon + 180. ) / CheapRulerSingleton.ILATLNG_TO_LATLNG + 0.5);
return (int)( ( lon + 180. ) / CheapRuler.ILATLNG_TO_LATLNG + 0.5);
}
static int toOsmLat(double lat) {
return (int)( ( lat + 90. ) / CheapRulerSingleton.ILATLNG_TO_LATLNG + 0.5);
return (int)( ( lat + 90. ) / CheapRuler.ILATLNG_TO_LATLNG + 0.5);
}
@Test
@ -84,7 +84,7 @@ public class RoutingContextTest {
int lon1 = 8500000;
int lat1 = 49500000;
double[] lonlat2m = CheapRulerSingleton.getLonLatToMeterScales( lat1 );
double[] lonlat2m = CheapRuler.getLonLatToMeterScales( lat1 );
double lon2m = lonlat2m[0];
double lat2m = lonlat2m[1];

View file

@ -230,6 +230,13 @@ public final class NodesCache
}
}
/**
* make sure the given node is non-hollow,
* which means it contains not just the id,
* but also the actual data
*
* @return true if successfull, false if node is still hollow
*/
public boolean obtainNonHollowNode( OsmNode node )
{
if ( !node.isHollow() )
@ -255,6 +262,19 @@ public final class NodesCache
return !node.isHollow();
}
/**
* make sure all link targets of the given node are non-hollow
*/
public void expandHollowLinkTargets( OsmNode n )
{
for( OsmLink link = n.firstlink; link != null; link = link.getNext( n ) )
{
obtainNonHollowNode( link.getTarget( n ) );
}
}
private OsmFile fileForSegment( int lonDegree, int latDegree ) throws Exception
{
int lonMod5 = lonDegree % 5;

View file

@ -8,7 +8,7 @@ package btools.mapaccess;
import btools.codec.MicroCache;
import btools.codec.MicroCache2;
import btools.util.ByteArrayUnifier;
import btools.util.CheapRulerSingleton;
import btools.util.CheapRuler;
import btools.util.IByteArrayUnifier;
public class OsmNode extends OsmLink implements OsmPos
@ -102,7 +102,7 @@ public class OsmNode extends OsmLink implements OsmPos
public final int calcDistance( OsmPos p )
{
return (int)(CheapRulerSingleton.distance(ilon, ilat, p.getILon(), p.getILat()) + 1.0 );
return (int)(CheapRuler.distance(ilon, ilat, p.getILon(), p.getILat()) + 1.0 );
}
public String toString()

View file

@ -28,6 +28,42 @@ public final class TurnRestriction
return ( exceptions & 2 ) != 0;
}
public static boolean isTurnForbidden( TurnRestriction first, int fromLon, int fromLat, int toLon, int toLat, boolean bikeMode, boolean carMode )
{
boolean hasAnyPositive = false;
boolean hasPositive = false;
boolean hasNegative = false;
TurnRestriction tr = first;
while (tr != null)
{
if ( ( tr.exceptBikes() && bikeMode ) || ( tr.exceptMotorcars() && carMode ) )
{
tr = tr.next;
continue;
}
if ( tr.fromLon == fromLon && tr.fromLat == fromLat )
{
if ( tr.isPositive )
{
hasAnyPositive = true;
}
if ( tr.toLon == toLon && tr.toLat == toLat )
{
if ( tr.isPositive )
{
hasPositive = true;
}
else
{
hasNegative = true;
}
}
}
tr = tr.next;
}
return !hasPositive && ( hasAnyPositive || hasNegative );
}
@Override
public String toString()
{

View file

@ -38,7 +38,7 @@ import btools.router.OsmTrack;
import btools.router.RoutingContext;
import btools.router.RoutingEngine;
import btools.router.RoutingHelper;
import btools.util.CheapRulerSingleton;
import btools.util.CheapRuler;
public class BRouterView extends View
{
@ -510,7 +510,7 @@ public class BRouterView extends View
centerLon = ( maxlon + minlon ) / 2;
centerLat = ( maxlat + minlat ) / 2;
double[] lonlat2m = CheapRulerSingleton.getLonLatToMeterScales( centerLat );
double[] lonlat2m = CheapRuler.getLonLatToMeterScales( centerLat );
double dlon2m = lonlat2m[0];
double dlat2m = lonlat2m[1];
double difflon = (maxlon - minlon)*dlon2m;

View file

@ -1,6 +1,6 @@
package btools.util;
public final class CheapRulerSingleton {
public final class CheapRuler {
/**
* Cheap-Ruler Java implementation
* See

View file

@ -0,0 +1,24 @@
package btools.util;
/**
* Some fast approximations to mathematical functions
*
* @author ab
*/
public class FastMath
{
/**
* Approximation to Math.exp for small negative arguments
*/
public static double exp( double e )
{
double x = e;
double f = 1.;
while( e < -1. )
{
e += 1.;
f *= 0.367879;
}
return f*( 1. + x*( 1. + x * ( 0.5 + x * ( 0.166667 + 0.0416667 * x) ) ) );
}
}