Improve display of boundaries like cities, states, etc.

This commit is contained in:
2026-02-23 21:14:40 +04:00
parent d9645d1a8c
commit 8217e85836
2 changed files with 53 additions and 9 deletions

View File

@@ -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;

View File

@@ -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) {