OsmNodeNamed extends OsmNode { public double distanceWithinRadius(int lon1, int lat1, int lon2, int lat2, double totalSegmentLength) { double[] lonlat2m = CheapRuler.getLonLatToMeterScales( (lat1 + lat2) >> 1 ); boolean isFirstPointWithinCircle = CheapRuler.distance(lon1, lat1, ilon, ilat) < radius; boolean isLastPointWithinCircle = CheapRuler.distance(lon2, lat2, ilon, ilat) < radius; if (isFirstPointWithinCircle) { if (isLastPointWithinCircle) { return totalSegmentLength; } int tmp = lon2; lon2 = lon1; lon1 = tmp; tmp = lat2; lat2 = lat1; lat1 = tmp; isLastPointWithinCircle = isFirstPointWithinCircle; isFirstPointWithinCircle = false; } double initialToProject = ( (lon2 - lon1) * (ilon - lon1) * lonlat2m[0] * lonlat2m[0] + (lat2 - lat1) * (ilat - lat1) * lonlat2m[1] * lonlat2m[1] ) / totalSegmentLength; double initialToCenter = CheapRuler.distance(ilon, ilat, lon1, lat1); double halfDistanceWithin = Math.sqrt( radius*radius - ( initialToCenter*initialToCenter - initialToProject*initialToProject ) ); if (isLastPointWithinCircle) { return halfDistanceWithin + (totalSegmentLength - initialToProject); } return 2 * halfDistanceWithin; } OsmNodeNamed();  OsmNodeNamed( OsmNode n); @Override String toString(); double distanceWithinRadius(int lon1, int lat1, int lon2, int lat2, double totalSegmentLength); static OsmNodeNamed decodeNogo( String s ); public String name; public double radius; public double nogoWeight; public boolean isNogo; }
@Test public void testDistanceWithinRadius() { int lon1, lat1, lon2, lat2; OsmNodeNamed node = new OsmNodeNamed(); node.ilon = toOsmLon(2.334243); node.ilat = toOsmLat(48.824017); node.radius = 30; lon1 = toOsmLon(2.332559); lat1 = toOsmLat(48.823822); lon2 = toOsmLon(2.335018); lat2 = toOsmLat(48.824105); double totalSegmentLength = CheapRuler.distance(lon1, lat1, lon2, lat2); assertEquals( "Works for segment aligned with the nogo center", 2 * node.radius, node.distanceWithinRadius(lon1, lat1, lon2, lat2, totalSegmentLength), 0.01 * (2 * node.radius) ); node.ilon = toOsmLon(2.33438); node.ilat = toOsmLat(48.824275); assertEquals( "Works for a segment with no particular properties", 27.5, node.distanceWithinRadius(lon1, lat1, lon2, lat2, totalSegmentLength), 0.1 * 27.5 ); assertEquals( "Works if we switch firs and last point", node.distanceWithinRadius(lon2, lat2, lon1, lat1, totalSegmentLength), node.distanceWithinRadius(lon1, lat1, lon2, lat2, totalSegmentLength), 0.01 ); lon2 = toOsmLon(2.334495); lat2 = toOsmLat(48.824045); totalSegmentLength = CheapRuler.distance(lon1, lat1, lon2, lat2); assertEquals( "Works if last point is within the circle", 17, node.distanceWithinRadius(lon1, lat1, lon2, lat2, totalSegmentLength), 0.1 * 17 ); lon1 = toOsmLon(2.334495); lat1 = toOsmLat(48.824045); lon2 = toOsmLon(2.335018); lat2 = toOsmLat(48.824105); totalSegmentLength = CheapRuler.distance(lon1, lat1, lon2, lat2); assertEquals( "Works if first point is within the circle", 9, node.distanceWithinRadius(lon1, lat1, lon2, lat2, totalSegmentLength), 0.1 * 9 ); lon1 = toOsmLon(2.33427); lat1 = toOsmLat(48.82402); lon2 = toOsmLon(2.334587); lat2 = toOsmLat(48.824061); totalSegmentLength = CheapRuler.distance(lon1, lat1, lon2, lat2); assertEquals( "Works if both points are within the circle", 25, node.distanceWithinRadius(lon1, lat1, lon2, lat2, totalSegmentLength), 0.1 * 25 ); lon1 = toOsmLon(2.332559); lat1 = toOsmLat(48.823822); lon2 = toOsmLon(2.33431); lat2 = toOsmLat(48.824027); totalSegmentLength = CheapRuler.distance(lon1, lat1, lon2, lat2); assertEquals( "Works if both points are on the same side of the circle center", 5, node.distanceWithinRadius(lon1, lat1, lon2, lat2, totalSegmentLength), 0.1 * 5 ); }