Make nogo weight proportional to nogo distance
Compute the nogo cost as proportional to the length of the segment inside the nogo area.
This commit is contained in:
parent
3479fd7323
commit
2591f22348
7 changed files with 347 additions and 34 deletions
117
brouter-core/src/test/java/btools/router/OsmNodeNamedTest.java
Normal file
117
brouter-core/src/test/java/btools/router/OsmNodeNamedTest.java
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
package btools.router;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import btools.util.CheapRulerSingleton;
|
||||
|
||||
public class OsmNodeNamedTest {
|
||||
static int toOsmLon(double lon) {
|
||||
return (int)( ( lon + 180. ) / CheapRulerSingleton.ILATLNG_TO_LATLNG + 0.5);
|
||||
}
|
||||
|
||||
static int toOsmLat(double lat) {
|
||||
return (int)( ( lat + 90. ) / CheapRulerSingleton.ILATLNG_TO_LATLNG + 0.5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDistanceWithinRadius() {
|
||||
// Segment ends
|
||||
int lon1, lat1, lon2, lat2;
|
||||
// Circle definition
|
||||
OsmNodeNamed node = new OsmNodeNamed();
|
||||
// Center
|
||||
node.ilon = toOsmLon(2.334243);
|
||||
node.ilat = toOsmLat(48.824017);
|
||||
// Radius
|
||||
node.radius = 30 / 110984.;
|
||||
|
||||
// Check distance within radius is correctly computed if the segment passes through the center
|
||||
lon1 = toOsmLon(2.332559);
|
||||
lat1 = toOsmLat(48.823822);
|
||||
lon2 = toOsmLon(2.335018);
|
||||
lat2 = toOsmLat(48.824105);
|
||||
double totalSegmentLength = CheapRulerSingleton.distance(lon1, lat1, lon2, lat2);
|
||||
assertEquals(
|
||||
"Works for segment aligned with the nogo center",
|
||||
2 * node.radius * 110984.,
|
||||
node.distanceWithinRadius(lon1, lat1, lon2, lat2, totalSegmentLength),
|
||||
0.01 * (2 * node.radius * 110984.)
|
||||
);
|
||||
|
||||
// Check distance within radius is correctly computed for a given circle
|
||||
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
|
||||
);
|
||||
|
||||
// Check distance within radius is the same if we reverse start and end point
|
||||
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
|
||||
);
|
||||
|
||||
// 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);
|
||||
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 = CheapRulerSingleton.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 = CheapRulerSingleton.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
|
||||
);
|
||||
|
||||
// Check distance within radius is correctly computed if both points are on
|
||||
// the same side of the center.
|
||||
// Note: the only such case possible is with one point outside and one
|
||||
// point within the circle, as we expect the segment to have a non-empty
|
||||
// intersection with the circle.
|
||||
lon1 = toOsmLon(2.332559);
|
||||
lat1 = toOsmLat(48.823822);
|
||||
lon2 = toOsmLon(2.33431);
|
||||
lat2 = toOsmLat(48.824027);
|
||||
totalSegmentLength = CheapRulerSingleton.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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -30,8 +30,8 @@ import btools.util.CheapRulerSingleton;
|
|||
|
||||
public class OsmNogoPolygonTest {
|
||||
|
||||
static final int offset_x = 11000000;
|
||||
static final int offset_y = 50000000;
|
||||
static final int OFFSET_X = 11000000;
|
||||
static final int OFFSET_Y = 50000000;
|
||||
|
||||
static OsmNogoPolygon polygon;
|
||||
static OsmNogoPolygon polyline;
|
||||
|
|
@ -39,11 +39,11 @@ public class OsmNogoPolygonTest {
|
|||
static final double[] lons = { 1.0, 1.0, 0.5, 0.5, 1.0, 1.0, -1.1, -1.0 };
|
||||
static final double[] lats = { -1.0, -0.1, -0.1, 0.1, 0.1, 1.0, 1.1, -1.0 };
|
||||
|
||||
static int toOsmLon(double lon) {
|
||||
static int toOsmLon(double lon, int offset_x) {
|
||||
return (int)( ( lon + 180. ) *1000000. + 0.5)+offset_x; // see ServerHandler.readPosition()
|
||||
}
|
||||
|
||||
static int toOsmLat(double lat) {
|
||||
static int toOsmLat(double lat, int offset_y) {
|
||||
return (int)( ( lat + 90. ) *1000000. + 0.5)+offset_y;
|
||||
}
|
||||
|
||||
|
|
@ -51,11 +51,11 @@ public class OsmNogoPolygonTest {
|
|||
public static void setUp() throws Exception {
|
||||
polygon = new OsmNogoPolygon(true);
|
||||
for (int i = 0; i<lons.length; i++) {
|
||||
polygon.addVertex(toOsmLon(lons[i]),toOsmLat(lats[i]));
|
||||
polygon.addVertex(toOsmLon(lons[i], OFFSET_X),toOsmLat(lats[i], OFFSET_Y));
|
||||
}
|
||||
polyline = new OsmNogoPolygon(false);
|
||||
for (int i = 0; i<lons.length; i++) {
|
||||
polyline.addVertex(toOsmLon(lons[i]),toOsmLat(lats[i]));
|
||||
polyline.addVertex(toOsmLon(lons[i], OFFSET_X),toOsmLat(lats[i], OFFSET_Y));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -72,8 +72,8 @@ public class OsmNogoPolygonTest {
|
|||
polygon.calcBoundingCircle();
|
||||
double r = polygon.radius;
|
||||
for (int i=0; i<lons.length; i++) {
|
||||
double dpx = (toOsmLon(lons[i]) - polygon.ilon) * dlon2m;
|
||||
double dpy = (toOsmLon(lats[i]) - polygon.ilon) * dlat2m;
|
||||
double dpx = (toOsmLon(lons[i], OFFSET_X) - polygon.ilon) * dlon2m;
|
||||
double dpy = (toOsmLat(lats[i], OFFSET_Y) - polygon.ilat) * dlat2m;
|
||||
double r1 = Math.sqrt(dpx * dpx + dpy * dpy);
|
||||
double diff = r-r1;
|
||||
assertTrue("i: "+i+" r("+r+") >= r1("+r1+")", diff >= 0);
|
||||
|
|
@ -81,8 +81,8 @@ public class OsmNogoPolygonTest {
|
|||
polyline.calcBoundingCircle();
|
||||
r = polyline.radius;
|
||||
for (int i=0; i<lons.length; i++) {
|
||||
double dpx = (toOsmLon(lons[i]) - polyline.ilon) * dlon2m;
|
||||
double dpy = (toOsmLon(lats[i]) - polyline.ilon) * dlat2m;
|
||||
double dpx = (toOsmLon(lons[i], OFFSET_X) - polyline.ilon) * dlon2m;
|
||||
double dpy = (toOsmLat(lats[i], OFFSET_Y) - polyline.ilat) * dlat2m;
|
||||
double r1 = Math.sqrt(dpx * dpx + dpy * dpy);
|
||||
double diff = r-r1;
|
||||
assertTrue("i: "+i+" r("+r+") >= r1("+r1+")", diff >= 0);
|
||||
|
|
@ -96,7 +96,7 @@ public class OsmNogoPolygonTest {
|
|||
boolean[] within = { true, false, false, false, false, true, true, true, true, true, };
|
||||
|
||||
for (int i=0; i<plons.length; i++) {
|
||||
assertEquals("("+plons[i]+","+plats[i]+")",within[i],polygon.isWithin(toOsmLon(plons[i]), toOsmLat(plats[i])));
|
||||
assertEquals("("+plons[i]+","+plats[i]+")",within[i],polygon.isWithin(toOsmLon(plons[i], OFFSET_X), toOsmLat(plats[i], OFFSET_Y)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -109,7 +109,7 @@ public class OsmNogoPolygonTest {
|
|||
boolean[] within = { false, false, false, true, true, true, false, true, true, true };
|
||||
|
||||
for (int i=0; i<p0lons.length; i++) {
|
||||
assertEquals("("+p0lons[i]+","+p0lats[i]+")-("+p1lons[i]+","+p1lats[i]+")",within[i],polygon.intersects(toOsmLon(p0lons[i]), toOsmLat(p0lats[i]), toOsmLon(p1lons[i]), toOsmLat(p1lats[i])));
|
||||
assertEquals("("+p0lons[i]+","+p0lats[i]+")-("+p1lons[i]+","+p1lats[i]+")",within[i],polygon.intersects(toOsmLon(p0lons[i], OFFSET_X), toOsmLat(p0lats[i], OFFSET_Y), toOsmLon(p1lons[i], OFFSET_X), toOsmLat(p1lats[i], OFFSET_Y)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +122,7 @@ public class OsmNogoPolygonTest {
|
|||
boolean[] within = { false, false, false, true, true, true, false, true, true, false };
|
||||
|
||||
for (int i=0; i<p0lons.length; i++) {
|
||||
assertEquals("("+p0lons[i]+","+p0lats[i]+")-("+p1lons[i]+","+p1lats[i]+")",within[i],polyline.intersects(toOsmLon(p0lons[i]), toOsmLat(p0lats[i]), toOsmLon(p1lons[i]), toOsmLat(p1lats[i])));
|
||||
assertEquals("("+p0lons[i]+","+p0lats[i]+")-("+p1lons[i]+","+p1lats[i]+")",within[i],polyline.intersects(toOsmLon(p0lons[i], OFFSET_X), toOsmLat(p0lats[i], OFFSET_Y), toOsmLon(p1lons[i], OFFSET_X), toOsmLat(p1lats[i], OFFSET_Y)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -144,4 +144,57 @@ public class OsmNogoPolygonTest {
|
|||
assertFalse(OsmNogoPolygon.isOnLine(0,-10, 10,10, 20,30));
|
||||
assertFalse(OsmNogoPolygon.isOnLine(30,50, 10,10, 20,30));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDistanceWithinPolygon() {
|
||||
// Testing polygon
|
||||
final double[] lons = { 2.333523, 2.333432, 2.333833, 2.333983, 2.334815, 2.334766, 2.333523 };
|
||||
final double[] lats = { 48.823778, 48.824091, 48.82389, 48.824165, 48.824232, 48.82384, 48.823778 };
|
||||
OsmNogoPolygon polygon = new OsmNogoPolygon(true);
|
||||
for (int i = 0; i < lons.length; i++) {
|
||||
polygon.addVertex(toOsmLon(lons[i], 0), toOsmLat(lats[i], 0));
|
||||
}
|
||||
|
||||
// Check with a segment with a single intersection with the polygon
|
||||
int lon1 = toOsmLon(2.33308732509613, 0);
|
||||
int lat1 = toOsmLat(48.8238790443901, 0);
|
||||
int lon2 = toOsmLon(2.33378201723099, 0);
|
||||
int lat2 = toOsmLat(48.8239585098974, 0);
|
||||
assertEquals(
|
||||
"Should give the correct length for a segment with a single intersection",
|
||||
17.5,
|
||||
polygon.distanceWithinPolygon(lon1, lat1, lon2, lat2),
|
||||
0.05 * 17.5
|
||||
);
|
||||
|
||||
// Check with a segment crossing multiple times the polygon
|
||||
lon2 = toOsmLon(2.33488172292709, 0);
|
||||
lat2 = toOsmLat(48.8240891862353, 0);
|
||||
assertEquals(
|
||||
"Should give the correct length for a segment with multiple intersections",
|
||||
85,
|
||||
polygon.distanceWithinPolygon(lon1, lat1, lon2, lat2),
|
||||
0.05 * 85
|
||||
);
|
||||
|
||||
// Check that it works when a point is within the polygon
|
||||
lon2 = toOsmLon(2.33433187007904, 0);
|
||||
lat2 = toOsmLat(48.8240238480664, 0);
|
||||
assertEquals(
|
||||
"Should give the correct length when last point is within the polygon",
|
||||
50,
|
||||
polygon.distanceWithinPolygon(lon1, lat1, lon2, lat2),
|
||||
0.05 * 50
|
||||
);
|
||||
lon1 = toOsmLon(2.33433187007904, 0);
|
||||
lat1 = toOsmLat(48.8240238480664, 0);
|
||||
lon2 = toOsmLon(2.33488172292709, 0);
|
||||
lat2 = toOsmLat(48.8240891862353, 0);
|
||||
assertEquals(
|
||||
"Should give the correct length when first point is within the polygon",
|
||||
35,
|
||||
polygon.distanceWithinPolygon(lon1, lat1, lon2, lat2),
|
||||
0.05 * 35
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue