Pass no-go area polygons natively to BRouter
BRouter supports a `polygons` parameter with full vertex coordinates. We were approximating polygons as circles (centroid + max radius), which poorly represented elongated or concave shapes. Now passes polygon vertices directly — no approximation, exact no-go boundaries. Also removes unused haversineMeters helper and updates the spec. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d2ff488f37
commit
3abea9d5a8
2 changed files with 7 additions and 27 deletions
|
|
@ -52,7 +52,7 @@ export async function computeRoute(request: RouteRequest): Promise<EnrichedRoute
|
||||||
format,
|
format,
|
||||||
tiledesc: "true",
|
tiledesc: "true",
|
||||||
});
|
});
|
||||||
if (nogoParam) params.set("nogos", nogoParam);
|
if (nogoParam) params.set("polygons", nogoParam);
|
||||||
return fetchSegment(`${BROUTER_URL}/brouter?${params}`);
|
return fetchSegment(`${BROUTER_URL}/brouter?${params}`);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
@ -180,40 +180,19 @@ function extractSurfacesFromMessages(properties: Record<string, unknown>): Map<n
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert no-go area polygons to BRouter's `nogos` parameter format.
|
* Convert no-go area polygons to BRouter's `polygons` parameter format.
|
||||||
* BRouter accepts `lon,lat,radius` per no-go circle, separated by `|`.
|
* Format: lon1,lat1,lon2,lat2,...,lonN,latN separated by `|` per polygon.
|
||||||
* We approximate each polygon as a circle: centroid + max distance to any vertex.
|
|
||||||
*/
|
*/
|
||||||
function noGoAreasToParam(areas: NoGoArea[]): string {
|
function noGoAreasToParam(areas: NoGoArea[]): string {
|
||||||
return areas
|
return areas
|
||||||
.map((area) => {
|
.map((area) => {
|
||||||
const pts = area.points;
|
if (area.points.length < 3) return null;
|
||||||
if (pts.length === 0) return null;
|
return area.points.map((p) => `${p.lon},${p.lat}`).join(",");
|
||||||
// Centroid
|
|
||||||
const cLat = pts.reduce((s, p) => s + p.lat, 0) / pts.length;
|
|
||||||
const cLon = pts.reduce((s, p) => s + p.lon, 0) / pts.length;
|
|
||||||
// Max distance from centroid in meters (approximate)
|
|
||||||
const maxDist = Math.max(
|
|
||||||
...pts.map((p) => haversineMeters(cLat, cLon, p.lat, p.lon)),
|
|
||||||
);
|
|
||||||
return `${cLon},${cLat},${Math.ceil(maxDist)}`;
|
|
||||||
})
|
})
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join("|");
|
.join("|");
|
||||||
}
|
}
|
||||||
|
|
||||||
function haversineMeters(lat1: number, lon1: number, lat2: number, lon2: number): number {
|
|
||||||
const R = 6371000;
|
|
||||||
const dLat = ((lat2 - lat1) * Math.PI) / 180;
|
|
||||||
const dLon = ((lon2 - lon1) * Math.PI) / 180;
|
|
||||||
const a =
|
|
||||||
Math.sin(dLat / 2) ** 2 +
|
|
||||||
Math.cos((lat1 * Math.PI) / 180) *
|
|
||||||
Math.cos((lat2 * Math.PI) / 180) *
|
|
||||||
Math.sin(dLon / 2) ** 2;
|
|
||||||
return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getBRouterUrl(): string {
|
export function getBRouterUrl(): string {
|
||||||
return BROUTER_URL;
|
return BROUTER_URL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ Users SHALL be able to draw polygons on the map that BRouter avoids when computi
|
||||||
|
|
||||||
#### Scenario: Route avoids no-go area
|
#### Scenario: Route avoids no-go area
|
||||||
- **WHEN** a route is computed and a no-go area intersects the direct path
|
- **WHEN** a route is computed and a no-go area intersects the direct path
|
||||||
- **THEN** BRouter routes around the no-go area
|
- **THEN** BRouter request includes the polygon vertices via the `polygons` parameter
|
||||||
|
- **AND** BRouter routes around the no-go area
|
||||||
|
|
||||||
#### Scenario: Delete no-go area
|
#### Scenario: Delete no-go area
|
||||||
- **WHEN** a user deletes a no-go area polygon
|
- **WHEN** a user deletes a no-go area polygon
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue