mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
fix(search): normalize geocoder bias across the antimeridian (#1272)
Keep geocoder viewport bias near the antimeridian and omit misleading wrapped viewboxes. Contribution by @asturksever.
This commit is contained in:
1 parent
ba292ce475
commit
a43ff8619e
6 files changed
+50
-7
No files matched your search
+20
-5
@@ -206,12 +206,27 @@ export function photonSearchUrl(
|
||||
url.searchParams.set('limit', String(limit));
|
||||
|
||||
const corners = String(bias ?? '').split('|');
|
||||
if (corners.length === 2) {
|
||||
const [swLat, swLng] = corners[0].split(',').map(Number);
|
||||
const [neLat, neLng] = corners[1].split(',').map(Number);
|
||||
if ([swLat, swLng, neLat, neLng].every(Number.isFinite)) {
|
||||
const tokens = corners.flatMap((corner) => corner.split(','));
|
||||
if (
|
||||
corners.length === 2 &&
|
||||
corners.every((corner) => corner.split(',').length === 2) &&
|
||||
tokens.every((token) => token.trim() !== '')
|
||||
) {
|
||||
const [swLat, swLng, neLat, neLng] = tokens.map(Number);
|
||||
if (
|
||||
[swLat, swLng, neLat, neLng].every(Number.isFinite) &&
|
||||
Math.abs(swLat) <= 90 &&
|
||||
Math.abs(neLat) <= 90 &&
|
||||
swLat <= neLat &&
|
||||
Math.abs(swLng) <= 180 &&
|
||||
Math.abs(neLng) <= 180
|
||||
) {
|
||||
const midpoint = (swLng + neLng + (swLng > neLng ? 360 : 0)) / 2;
|
||||
url.searchParams.set('lat', String((swLat + neLat) / 2));
|
||||
url.searchParams.set('lon', String((swLng + neLng) / 2));
|
||||
url.searchParams.set(
|
||||
'lon',
|
||||
String(midpoint > 180 ? midpoint - 360 : midpoint),
|
||||
);
|
||||
}
|
||||
}
|
||||
return url.toString();
|
||||
|
||||
@@ -452,3 +452,14 @@ function readGeocodingConsumer(file) {
|
||||
? [file, 'annotations/resolver.js'] : [file];
|
||||
return files.map((name) => fs.readFileSync(path.join(ROOT, 'src', name), 'utf8')).join('\n');
|
||||
}
|
||||
|
||||
|
||||
test('wrapped view bias stays near the antimeridian and malformed coordinates are omitted', () => {
|
||||
for (const [bias, expected] of [['-20,170|-10,-171', 179.5], ['50,175|60,-165', -175], ['0,180|10,-180', 180], ['0,-180|10,180', 0]]) {
|
||||
const params = new URL(photonSearchUrl('island', { bias })).searchParams;
|
||||
assert.equal(Number(params.get('lon')), expected);
|
||||
}
|
||||
for (const bias of ['-91,0|0,1', '0,181|1,0', '10,0|0,1', ',|,', '0,1,2|3,4', '0,1|Infinity,2']) {
|
||||
assert.equal(new URL(photonSearchUrl('island', { bias })).searchParams.has('lon'), false);
|
||||
}
|
||||
});
|
||||
@@ -166,6 +166,8 @@ export function nominatimViewboxFromBounds(bounds) {
|
||||
const neLat = nominatimLatitude(match[3]);
|
||||
const neLng = nominatimLongitude(match[4]);
|
||||
if ([swLat, swLng, neLat, neLng].some((value) => value === null)) return null;
|
||||
if (swLat >= neLat) return null;
|
||||
// One Nominatim viewbox cannot express a wrapped interval. Omit this soft
|
||||
// preference rather than biasing the search toward the opposite hemisphere.
|
||||
if (swLat >= neLat || swLng > neLng) return null;
|
||||
return `${swLng},${neLat},${neLng},${swLat}`;
|
||||
}
|
||||
@@ -173,3 +173,12 @@ test('a viewport hint is sent only when every edge is a real coordinate', () =>
|
||||
`${JSON.stringify(bounds)} must not become a viewbox`,
|
||||
);
|
||||
});
|
||||
|
||||
test('wrapped viewports omit the Nominatim bias without rejecting the search', () => {
|
||||
assert.equal(nominatimViewboxFromBounds('-20,170|-10,-171'), null);
|
||||
assert.equal(nominatimViewboxFromBounds('50,175|60,-165'), null);
|
||||
assert.equal(
|
||||
nominatimViewboxFromBounds('-20,170|-10,180'),
|
||||
'170,-10,180,-20',
|
||||
);
|
||||
});
|
||||
Reference in new issue
Block a user