Radius are now stored in meters, to easily account for different

radiuses on X and Y axes.
This commit is contained in:
Phyks (Lucas Verney) 2018-12-04 15:54:50 +01:00
parent df9767b65e
commit d621964863
9 changed files with 60 additions and 67 deletions

View file

@ -17,7 +17,7 @@ final class MatchedWaypoint
public OsmNode node2; public OsmNode node2;
public OsmNodeNamed crosspoint; public OsmNodeNamed crosspoint;
public OsmNodeNamed waypoint; public OsmNodeNamed waypoint;
public double radius; public double radius; // radius in meters
public boolean hasUpdate; public boolean hasUpdate;
public void writeToStream( DataOutput dos ) throws IOException public void writeToStream( DataOutput dos ) throws IOException

View file

@ -10,7 +10,7 @@ import btools.mapaccess.OsmNode;
public class OsmNodeNamed extends OsmNode public class OsmNodeNamed extends OsmNode
{ {
public String name; public String name;
public double radius; // radius of nogopoint public double radius; // radius of nogopoint (in meters)
public boolean isNogo = false; public boolean isNogo = false;
@Override @Override

View file

@ -111,28 +111,24 @@ public class OsmNogoPolygon extends OsmNodeNamed
double rad = 0; // radius double rad = 0; // radius
double rad2 = 0; // radius squared; double rad2 = 0; // radius squared;
double dpx = 0; // x-xomponent of vector from center to point double dmax = 0; // length of vector from center to point
double dpy = 0; // y-component
double dmax2 = 0; // squared lenght of vector from center to point
int i_max = -1; int i_max = -1;
do do
{ // now identify the point outside of the circle that has the greatest distance {
// now identify the point outside of the circle that has the greatest distance
for (int i = 0; i < points.size(); i++) for (int i = 0; i < points.size(); i++)
{ {
final Point p = points.get(i); final Point p = points.get(i);
final double dpix = (p.x - cx) * dlon2m; final double dist = CheapRulerSingleton.distance(p.x, p.y, (int) cx, (int) cy);
final double dpiy = (p.y - cy) * dlat2m; if (dist <= rad)
final double dist2 = dpix * dpix + dpiy * dpiy;
if (dist2 <= rad2)
{ {
continue; continue;
} }
if (dist2 > dmax2) if (dist > dmax)
{ {
dmax2 = dist2; // new maximum distance found // new maximum distance found
dpx = dpix / dlon2m; dmax = dist;
dpy = dpiy / dlat2m;
i_max = i; i_max = i;
} }
} }
@ -140,17 +136,13 @@ public class OsmNogoPolygon extends OsmNodeNamed
{ {
break; // leave loop when no point outside the circle is found any more. break; // leave loop when no point outside the circle is found any more.
} }
final double dist = Math.sqrt(dmax2); final double dd = 0.5 * (1 - rad / dmax);
final double dd = 0.5 * (dist - rad) / dist;
cx += (int)(dd * dpx + 0.5); // shift center toward point
cy += (int)(dd * dpy + 0.5);
final Point p = points.get(i_max); // calculate new radius to just include this point final Point p = points.get(i_max); // calculate new radius to just include this point
final double dpix = (p.x - cx) * dlon2m; cx += (int)(dd * (p.x - cx) + 0.5); // shift center toward point
final double dpiy = (p.y - cy) * dlat2m; cy += (int)(dd * (p.y - cy) + 0.5);
dmax2 = rad2 = dpix * dpix + dpiy * dpiy;
rad = Math.sqrt(rad2); dmax = rad = CheapRulerSingleton.distance(p.x, p.y, (int) cx, (int) cy);
i_max = -1; i_max = -1;
} }
while (true); while (true);

View file

@ -346,7 +346,8 @@ abstract class OsmPath implements OsmLinkHolder
if ( rc.startDirectionValid ) if ( rc.startDirectionValid )
{ {
double dir = rc.startDirection.intValue() / CheapRulerSingleton.DEG_TO_RAD; double dir = rc.startDirection.intValue() / CheapRulerSingleton.DEG_TO_RAD;
lon0 = lon1 - (int) ( 1000. * Math.sin( dir ) / rc.getCosLat() ); double coslat = Math.cos(lat1);
lon0 = lon1 - (int) ( 1000. * Math.sin( dir ) / coslat );
lat0 = lat1 - (int) ( 1000. * Math.cos( dir ) ); lat0 = lat1 - (int) ( 1000. * Math.cos( dir ) );
} }
else else

View file

@ -193,7 +193,6 @@ public final class RoutingContext
public Integer startDirection; public Integer startDirection;
public boolean startDirectionValid; public boolean startDirectionValid;
private double coslat;
private double cosangle; private double cosangle;
public boolean nogomatch = false; public boolean nogomatch = false;
public boolean isEndpoint = false; public boolean isEndpoint = false;
@ -248,8 +247,8 @@ public final class RoutingContext
try { ir = Integer.parseInt( s.substring( 4 ) ); } try { ir = Integer.parseInt( s.substring( 4 ) ); }
catch( Exception e ) { /* ignore */ } catch( Exception e ) { /* ignore */ }
} }
// TODO[Phyks] // Radius of the nogo point in meters
nogo.radius = ir / 110984.; // 6378000. / 57.3; nogo.radius = ir;
} }
} }
@ -259,12 +258,10 @@ public final class RoutingContext
List<OsmNodeNamed> nogos = new ArrayList<OsmNodeNamed>(); List<OsmNodeNamed> nogos = new ArrayList<OsmNodeNamed>();
for( OsmNodeNamed nogo : nogopoints ) for( OsmNodeNamed nogo : nogopoints )
{ {
// TODO[Phyks]
int radiusInMeter = (int)(nogo.radius * 111894.);
boolean goodGuy = true; boolean goodGuy = true;
for( OsmNodeNamed wp : waypoints ) for( OsmNodeNamed wp : waypoints )
{ {
if ( wp.calcDistance( nogo ) < radiusInMeter if ( wp.calcDistance( nogo ) < nogo.radius
&& (!(nogo instanceof OsmNogoPolygon) && (!(nogo instanceof OsmNogoPolygon)
|| (((OsmNogoPolygon)nogo).isClosed || (((OsmNogoPolygon)nogo).isClosed
? ((OsmNogoPolygon)nogo).isWithin(wp.ilon, wp.ilat) ? ((OsmNogoPolygon)nogo).isWithin(wp.ilon, wp.ilat)
@ -288,6 +285,7 @@ public final class RoutingContext
OsmNodeNamed nogo = nogopoints.get(i); OsmNodeNamed nogo = nogopoints.get(i);
cs[0] += nogo.ilon; cs[0] += nogo.ilon;
cs[1] += nogo.ilat; cs[1] += nogo.ilat;
// 10 is an arbitrary constant to get sub-integer precision in the checksum
cs[2] += (long) ( nogo.radius*10.); cs[2] += (long) ( nogo.radius*10.);
} }
return cs; return cs;
@ -342,7 +340,7 @@ public final class RoutingContext
if ( s2 > 0. ) if ( s2 > 0. )
{ {
radius = Math.sqrt( s1 < s2 ? r12 : r22 ); radius = Math.sqrt( s1 < s2 ? r12 : r22 );
if ( radius > nogo.radius ) continue; // 20m ^ 2 if ( radius > nogo.radius ) continue;
} }
if ( nogo.isNogo ) if ( nogo.isNogo )
{ {
@ -404,28 +402,23 @@ public final class RoutingContext
return (int)(d + 1.0 ); return (int)(d + 1.0 );
} }
// assumes that calcDistance/calcCosAngle called in sequence, so coslat valid
public double getCosAngle() public double getCosAngle()
{ {
return cosangle; return cosangle;
} }
public double getCosLat()
{
return coslat;
}
public double calcAngle( int lon0, int lat0, int lon1, int lat1, int lon2, int lat2 ) public double calcAngle( int lon0, int lat0, int lon1, int lat1, int lon2, int lat2 )
{ {
double dlat1 = (lat1 - lat0); double[] lonlat2m = CheapRulerSingleton.getLonLatToMeterScales( lat1 );
double dlon1 = (lon1 - lon0) * coslat; double dy10 = (lat1 - lat0) * lonlat2m[1];
double dlat2 = (lat2 - lat1); double dx10 = (lon1 - lon0) * lonlat2m[0];
double dlon2 = (lon2 - lon1) * coslat; double dy21 = (lat2 - lat1) * lonlat2m[1];
double dx21 = (lon2 - lon1) * lonlat2m[0];
double dd = Math.sqrt( (dlat1*dlat1 + dlon1*dlon1)*(dlat2*dlat2 + dlon2*dlon2) ); double dd = Math.sqrt( (dx10*dx10 + dy10*dy10)*(dx21*dx21 + dy21*dy21) );
if ( dd == 0. ) { cosangle = 1.; return 0.; } if ( dd == 0. ) { cosangle = 1.; return 0.; }
double sinp = (dlat1*dlon2 - dlon1*dlat2)/dd; double sinp = (dy10*dy21 - dx10*dx21)/dd;
double cosp = (dlat1*dlat2 + dlon1*dlon2)/dd; double cosp = (dy10*dy21 + dx10*dx21)/dd;
cosangle = cosp; cosangle = cosp;
double p; double p;

View file

@ -25,6 +25,9 @@ public final class SearchBoundary
int direction; int direction;
/**
* @param radius Search radius in meters.
*/
public SearchBoundary( OsmNode n, int radius, int direction ) public SearchBoundary( OsmNode n, int radius, int direction )
{ {
this.radius = radius; this.radius = radius;

View file

@ -33,8 +33,7 @@ public final class WaypointMatcherImpl implements WaypointMatcher
this.islandPairs = islandPairs; this.islandPairs = islandPairs;
for ( MatchedWaypoint mwp : waypoints ) for ( MatchedWaypoint mwp : waypoints )
{ {
// TODO[Phyks] mwp.radius = maxDistance;
mwp.radius = maxDistance * 110984.; // 6378000. / 57.3;
} }
} }
@ -49,6 +48,7 @@ public final class WaypointMatcherImpl implements WaypointMatcher
double dx = ( lon2 - lon1 ) * dlon2m; double dx = ( lon2 - lon1 ) * dlon2m;
double dy = ( lat2 - lat1 ) * dlat2m; double dy = ( lat2 - lat1 ) * dlat2m;
double d = Math.sqrt( dy * dy + dx * dx ); double d = Math.sqrt( dy * dy + dx * dx );
if ( d == 0. ) if ( d == 0. )
return; return;

View file

@ -635,7 +635,9 @@ public class BRouterView extends View
int lat = n.ilat - centerLat; int lat = n.ilat - centerLat;
int x = imgw / 2 + (int) ( scaleLon * lon ); int x = imgw / 2 + (int) ( scaleLon * lon );
int y = imgh / 2 - (int) ( scaleLat * lat ); int y = imgh / 2 - (int) ( scaleLat * lat );
int ir = (int) ( n.radius * 1000000. * scaleLat );
double[] lonlat2m = CheapRulerSingleton.getLonLatToMeterScales( centerLat );
int ir = (int) ( n.radius * scaleLat / lonlat2m[1]);
if ( ir > minradius ) if ( ir > minradius )
{ {
Paint paint = new Paint(); Paint paint = new Paint();
@ -660,7 +662,8 @@ public class BRouterView extends View
private void paintPolygon( Canvas canvas, OsmNogoPolygon p, int minradius ) private void paintPolygon( Canvas canvas, OsmNogoPolygon p, int minradius )
{ {
final int ir = (int) ( p.radius * 1000000. * scaleLat ); double[] lonlat2m = CheapRulerSingleton.getLonLatToMeterScales( centerLat );
final int ir = (int) ( p.radius * scaleLat / lonlat2m[1] );
if ( ir > minradius ) if ( ir > minradius )
{ {
Paint paint = new Paint(); Paint paint = new Paint();

View file

@ -17,10 +17,10 @@ public final class CheapRulerSingleton {
public final static int KILOMETERS_TO_METERS = 1000; public final static int KILOMETERS_TO_METERS = 1000;
public final static double DEG_TO_RAD = Math.PI / 180.; public final static double DEG_TO_RAD = Math.PI / 180.;
// Cosine cache constants // Scale cache constants
private final static int SCALE_CACHE_LENGTH = 1800; private final static int SCALE_CACHE_LENGTH = 1800;
private final static int SCALE_CACHE_INCREMENT = 100000; private final static int SCALE_CACHE_INCREMENT = 100000;
// COS_CACHE_LENGTH cached values between 0 and COS_CACHE_MAX_DEGREES degrees. // SCALE_CACHE_LENGTH cached values between 0 and COS_CACHE_MAX_DEGREES degrees.
private final static double[][] SCALE_CACHE = new double[SCALE_CACHE_LENGTH][]; private final static double[][] SCALE_CACHE = new double[SCALE_CACHE_LENGTH][];
/** /**
@ -33,7 +33,7 @@ public final class CheapRulerSingleton {
} }
private static double[] calcKxKyFromILat(int ilat) { private static double[] calcKxKyFromILat(int ilat) {
double lat = DEG_TO_RAD*(ilat-90000000)/1000000.; double lat = DEG_TO_RAD*ilat*ILATLNG_TO_LATLNG - 90;
double cos = Math.cos(lat); double cos = Math.cos(lat);
double cos2 = 2 * cos * cos - 1; double cos2 = 2 * cos * cos - 1;
double cos3 = 2 * cos * cos2 - cos; double cos3 = 2 * cos * cos2 - cos;
@ -51,7 +51,7 @@ public final class CheapRulerSingleton {
/** /**
* Calculate the degree->meter scale for given latitude * Calculate the degree->meter scale for given latitude
* *
* @result [lon->meter,lat->meter] * @result [lon-&gt;meter,lat-&gt;meter]
*/ */
public static double[] getLonLatToMeterScales( int ilat ) { public static double[] getLonLatToMeterScales( int ilat ) {
return SCALE_CACHE[ ilat / SCALE_CACHE_INCREMENT ]; return SCALE_CACHE[ ilat / SCALE_CACHE_INCREMENT ];
@ -65,6 +65,7 @@ public final class CheapRulerSingleton {
* @param ilat1 Integer latitude for the start point, this is (latitude + 90) * 1e6. * @param ilat1 Integer latitude for the start point, this is (latitude + 90) * 1e6.
* @param ilon2 Integer longitude for the end point, this is (longitude + 180) * 1e6. * @param ilon2 Integer longitude for the end point, this is (longitude + 180) * 1e6.
* @param ilat2 Integer latitude for the end point, this is (latitude + 90) * 1e6. * @param ilat2 Integer latitude for the end point, this is (latitude + 90) * 1e6.
* @return The distance between the two points, in meters.
* *
* @note Integer longitude is ((longitude in degrees) + 180) * 1e6. * @note Integer longitude is ((longitude in degrees) + 180) * 1e6.
* Integer latitude is ((latitude in degrees) + 90) * 1e6. * Integer latitude is ((latitude in degrees) + 90) * 1e6.