From 8217e858367cf2b7fb1617fd46582be2d7a9cf8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Mon, 23 Feb 2026 21:14:40 +0400 Subject: [PATCH] Improve display of boundaries like cities, states, etc. --- app/services/osm.js | 25 +++++++++++++++++++++- tests/unit/services/osm-test.js | 37 ++++++++++++++++++++++++++------- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/app/services/osm.js b/app/services/osm.js index 47d81f5..f097424 100644 --- a/app/services/osm.js +++ b/app/services/osm.js @@ -165,12 +165,35 @@ out center; normalizeOsmApiData(elements, targetId, targetType) { if (!elements || elements.length === 0) return null; - const mainElement = elements.find( + let mainElement = elements.find( (el) => String(el.id) === String(targetId) && el.type === targetType ); if (!mainElement) return null; + // If it's a boundary relation, try to find the label or admin_centre node + // and use that as the main element (better coordinates and tags). + if (targetType === 'relation' && mainElement.members) { + const labelMember = mainElement.members.find( + (m) => m.role === 'label' && m.type === 'node' + ); + const adminCentreMember = mainElement.members.find( + (m) => m.role === 'admin_centre' && m.type === 'node' + ); + + const targetMember = labelMember || adminCentreMember; + + if (targetMember) { + const targetNode = elements.find( + (el) => + String(el.id) === String(targetMember.ref) && el.type === 'node' + ); + if (targetNode) { + mainElement = targetNode; + } + } + } + let lat = mainElement.lat; let lon = mainElement.lon; diff --git a/tests/unit/services/osm-test.js b/tests/unit/services/osm-test.js index 1c28b1e..74a8e64 100644 --- a/tests/unit/services/osm-test.js +++ b/tests/unit/services/osm-test.js @@ -52,7 +52,7 @@ module('Unit | Service | osm', function (hooks) { assert.strictEqual(result.osmType, 'way'); }); - test('normalizeOsmApiData calculates centroid for relations with member nodes', function (assert) { + test('normalizeOsmApiData prioritizes label node for relations', function (assert) { let service = this.owner.lookup('service:osm'); const elements = [ { @@ -64,17 +64,38 @@ module('Unit | Service | osm', function (hooks) { ], tags: { name: 'Test Relation' }, }, - { id: 1, type: 'node', lat: 10, lon: 10 }, - { id: 2, type: 'node', lat: 30, lon: 30 }, + { id: 1, type: 'node', lat: 10, lon: 10, tags: { name: 'Admin Centre' } }, + { id: 2, type: 'node', lat: 30, lon: 30, tags: { name: 'Label Node' } }, ]; const result = service.normalizeOsmApiData(elements, 789, 'relation'); - assert.strictEqual(result.title, 'Test Relation'); - assert.strictEqual(result.lat, 20); // (10+30)/2 - assert.strictEqual(result.lon, 20); // (10+30)/2 - assert.strictEqual(result.osmId, '789'); - assert.strictEqual(result.osmType, 'relation'); + assert.strictEqual(result.title, 'Label Node'); + assert.strictEqual(result.lat, 30); + assert.strictEqual(result.lon, 30); + assert.strictEqual(result.osmId, '2'); + assert.strictEqual(result.osmType, 'node'); + }); + + test('normalizeOsmApiData falls back to admin_centre node for relations', function (assert) { + let service = this.owner.lookup('service:osm'); + const elements = [ + { + id: 789, + type: 'relation', + members: [{ type: 'node', ref: 1, role: 'admin_centre' }], + tags: { name: 'Test Relation' }, + }, + { id: 1, type: 'node', lat: 10, lon: 10, tags: { name: 'Admin Centre' } }, + ]; + + const result = service.normalizeOsmApiData(elements, 789, 'relation'); + + assert.strictEqual(result.title, 'Admin Centre'); + assert.strictEqual(result.lat, 10); + assert.strictEqual(result.lon, 10); + assert.strictEqual(result.osmId, '1'); + assert.strictEqual(result.osmType, 'node'); }); test('normalizeOsmApiData calculates centroid for relations with member ways', function (assert) {