mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
keep bent streets, enclosed landmarks and same-name outlines honest
A street ribbon that holds neither its ring mean nor the anchor is centred on the street's nearest point when the street runs within 100 m. Nominatim outline selection ranks an exact name, then one holding every asked word, then an overlap, and refuses an overlap whose name lacks the ask's last word unless that word is in the result's address or type, so "Central Park Zoo" is no longer Central Park. The server caches every accepted outline and answers each ask with the one holding its resolved anchor (sent as alat/alon), read across the antimeridian. A duplicate mark that fails to clean up no longer tears down the new outline it duplicates.
This commit is contained in:
1 parent
d9a460658d
commit
a38a065c5c
16 files changed
+516
-133
No files matched your search
@@ -6,6 +6,7 @@ import { readFileSync } from 'node:fs';
|
||||
import { FEATURE_SOURCE_METHODS } from '../sources/featureSource.js';
|
||||
import { createAnnotationResolver } from './resolver.js';
|
||||
import { polygonsContain } from '../data/adminBoundaries.js';
|
||||
import { streetFootprint } from './outlineRungs.js';
|
||||
|
||||
function viewerAt(lat, lon, height = 20_000) {
|
||||
return {
|
||||
@@ -338,6 +339,54 @@ test('a courtyard outline with no filled candidate anchor remains a point', asyn
|
||||
}
|
||||
});
|
||||
|
||||
test('a bent street keeps its outline when the anchor sits beside the centreline', async () => {
|
||||
// 500 m east then 500 m north: the ring mean lands off the 22 m ribbon.
|
||||
const lat0 = 30.27;
|
||||
const lon0 = -97.74;
|
||||
const dLon = 500 / (111320 * Math.cos((lat0 * Math.PI) / 180));
|
||||
const dLat = 500 / 111320;
|
||||
const line = [
|
||||
[lon0, lat0],
|
||||
[lon0 + dLon / 2, lat0],
|
||||
[lon0 + dLon, lat0],
|
||||
[lon0 + dLon, lat0 + dLat / 2],
|
||||
[lon0 + dLon, lat0 + dLat],
|
||||
];
|
||||
const footprint = streetFootprint({ lines: [line] });
|
||||
// A geocoded point 15 m north of the first leg, outside the ribbon.
|
||||
const lat = lat0 + 15 / 111320;
|
||||
const lon = lon0 + dLon / 2;
|
||||
assert.equal(polygonsContain(footprint.polygons, lat, lon), false);
|
||||
const { resolve } = harness(
|
||||
{ lat, lng: lon, name: 'Bent Street', label: 'Bent St', types: ['route'] },
|
||||
{ outlineRungs: rungsAnswering(footprint) },
|
||||
);
|
||||
const pending = await resolve('Bent Street', viewerAt(lat, lon, 3000), {
|
||||
entityKind: 'street',
|
||||
});
|
||||
const outline = await pending.resolveOutline();
|
||||
assert.equal(outline?.ring, footprint.ring, 'the street is still drawn');
|
||||
assert.ok(polygonsContain(outline.polygons, outline.lat, outline.lon));
|
||||
assert.ok(Math.abs(outline.lat - lat0) < 1e-7, 'centred on the street');
|
||||
assert.ok(Math.abs(outline.lon - lon) < 1e-7);
|
||||
// A same-name street that never comes near the anchor is not that street.
|
||||
const far = lat0 + 300 / 111320;
|
||||
const away = harness(
|
||||
{
|
||||
lat: far,
|
||||
lng: lon,
|
||||
name: 'Bent Street',
|
||||
label: 'Bent St',
|
||||
types: ['route'],
|
||||
},
|
||||
{ outlineRungs: rungsAnswering(footprint) },
|
||||
);
|
||||
const distant = await away.resolve('Bent Street', viewerAt(far, lon, 3000), {
|
||||
entityKind: 'street',
|
||||
});
|
||||
assert.equal((await distant.resolveOutline())?.ring ?? null, null);
|
||||
});
|
||||
|
||||
test('local dateline outlines share a frame for area, centering and filled anchors', async () => {
|
||||
const ring = [
|
||||
[179.9995, -0.0005],
|
||||
|
||||
Reference in new issue
Block a user