mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-24 09:04:02 +02:00
suggest housenumber/housename values from surrounding features (#10949)
housenumber/housename are taken from surrounding areas, as well as address points that are inside (or on the perimeter of) the same building as the selected feature
This commit is contained in:
@@ -49,10 +49,13 @@ _Breaking developer changes, which may affect downstream projects or sites that
|
||||
#### :earth_asia: Localization
|
||||
#### :hourglass: Performance
|
||||
#### :mortar_board: Walkthrough / Help
|
||||
#### :rocket: Presets
|
||||
* Suggest housenumber/housename values from surrounding areas ([#10946])
|
||||
#### :hammer: Development
|
||||
|
||||
[#9873]: https://github.com/openstreetmap/iD/issues/9873
|
||||
[#10104]: https://github.com/openstreetmap/iD/issues/10104
|
||||
[#10946]: https://github.com/openstreetmap/iD/issues/10946
|
||||
[#10959]: https://github.com/openstreetmap/iD/issues/10959
|
||||
[#10966]: https://github.com/openstreetmap/iD/issues/10966
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import * as countryCoder from '@rapideditor/country-coder';
|
||||
|
||||
import { presetManager } from '../../presets';
|
||||
import { fileFetcher } from '../../core/file_fetcher';
|
||||
import { geoExtent, geoChooseEdge, geoSphericalDistance } from '../../geo';
|
||||
import { geoChooseEdge, geoSphericalDistance, geoPolygonContainsPolygon, geoPointInPolygon } from '../../geo';
|
||||
import { uiCombobox } from '../combobox';
|
||||
import { utilArrayUniqBy, utilGetSetValue, utilNoAuto, utilRebind, utilTotalExtent, utilTriggerEvent } from '../../util';
|
||||
import { t } from '../../core/localizer';
|
||||
@@ -39,7 +39,7 @@ export function uiFieldAddress(field, context) {
|
||||
function getNear(isAddressable, type, searchRadius, resultProp) {
|
||||
var extent = combinedEntityExtent();
|
||||
var l = extent.center();
|
||||
var box = geoExtent(l).padByMeters(searchRadius);
|
||||
var box = extent.padByMeters(searchRadius);
|
||||
|
||||
var features = context.history().intersects(box)
|
||||
.filter(isAddressable)
|
||||
@@ -77,6 +77,35 @@ export function uiFieldAddress(field, context) {
|
||||
return utilArrayUniqBy(features, 'value');
|
||||
}
|
||||
|
||||
function getEnclosing(isAddressable, type, resultProp) {
|
||||
var extent = combinedEntityExtent();
|
||||
|
||||
var features = context.history().intersects(extent)
|
||||
.filter(isAddressable)
|
||||
.map(d => {
|
||||
if (d.geometry(context.graph()) !== 'area') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const geom = d.asGeoJSON(context.graph()).coordinates[0];
|
||||
if (!geoPolygonContainsPolygon(geom, extent.polygon())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const value = resultProp && d.tags[resultProp] ? d.tags[resultProp] : d.tags.name;
|
||||
return {
|
||||
title: value,
|
||||
value,
|
||||
dist: 0,
|
||||
geom,
|
||||
type,
|
||||
klass: `address-${type}`
|
||||
};
|
||||
}).filter(Boolean);
|
||||
|
||||
return utilArrayUniqBy(features, 'value');
|
||||
}
|
||||
|
||||
function getNearStreets() {
|
||||
function isAddressable(d) {
|
||||
return d.tags.highway && d.tags.name && d.type === 'way';
|
||||
@@ -130,6 +159,37 @@ export function uiFieldAddress(field, context) {
|
||||
return getNear(hasTag, key, 200, tagKey);
|
||||
}
|
||||
|
||||
function getEnclosingValues(key) {
|
||||
const tagKey = `${field.key}:${key}`;
|
||||
|
||||
// 1. areas encompassing the feature that have the address tag
|
||||
function hasTag(d) {
|
||||
return _entityIDs.indexOf(d.id) === -1 && d.tags[tagKey];
|
||||
}
|
||||
const enclosingAddresses = getEnclosing(hasTag, key, tagKey);
|
||||
|
||||
// 2. also include addresses from points which are encompassed by
|
||||
// the same building area as the current feature
|
||||
function isBuilding(d) {
|
||||
return _entityIDs.indexOf(d.id) === -1 && d.tags.building && d.tags.building !== 'no';
|
||||
}
|
||||
const enclosingBuildings = getEnclosing(isBuilding, 'building', 'building').map(d => d.geom);
|
||||
function isInNearbyBuilding(d) {
|
||||
return hasTag(d) &&
|
||||
d.type === 'node' &&
|
||||
enclosingBuildings.some(geom =>
|
||||
geoPointInPolygon(d.loc, geom) ||
|
||||
geom.indexOf(d.loc) !== -1
|
||||
);
|
||||
}
|
||||
const nearPointAddresses = getNear(isInNearbyBuilding, key, 100, tagKey);
|
||||
|
||||
return utilArrayUniqBy([
|
||||
...enclosingAddresses,
|
||||
...nearPointAddresses
|
||||
], 'value').sort((a, b) => a.value > b.value ? 1 : -1);
|
||||
}
|
||||
|
||||
|
||||
function updateForCountryCode() {
|
||||
|
||||
@@ -146,6 +206,10 @@ export function uiFieldAddress(field, context) {
|
||||
}
|
||||
}
|
||||
|
||||
const maybeDropdowns = new Set([
|
||||
'housenumber',
|
||||
'housename'
|
||||
]);
|
||||
const dropdowns = new Set([
|
||||
'block_number',
|
||||
'city',
|
||||
@@ -164,7 +228,8 @@ export function uiFieldAddress(field, context) {
|
||||
'street+place',
|
||||
'subdistrict',
|
||||
'suburb',
|
||||
'town'
|
||||
'town',
|
||||
...maybeDropdowns
|
||||
]);
|
||||
|
||||
var widths = addressFormat.widths || {
|
||||
@@ -211,7 +276,9 @@ export function uiFieldAddress(field, context) {
|
||||
|
||||
|
||||
function addDropdown(d) {
|
||||
if (!dropdowns.has(d.id)) return; // not a dropdown
|
||||
if (!dropdowns.has(d.id)) {
|
||||
return false; // not a dropdown
|
||||
}
|
||||
|
||||
var nearValues;
|
||||
switch (d.id) {
|
||||
@@ -234,10 +301,23 @@ export function uiFieldAddress(field, context) {
|
||||
case 'postcode':
|
||||
nearValues = getNearPostcodes;
|
||||
break;
|
||||
case 'housenumber':
|
||||
case 'housename':
|
||||
nearValues = getEnclosingValues;
|
||||
break;
|
||||
default:
|
||||
nearValues = getNearValues;
|
||||
}
|
||||
|
||||
if (maybeDropdowns.has(d.id)) {
|
||||
const candidates = nearValues(d.id);
|
||||
// only add dropdown if there are possible values for the
|
||||
// corresponding tag: e.g. only show ▼ caret for
|
||||
// housenumber/housename if the feature is actually
|
||||
// encompassed by another feature with such an address
|
||||
if (candidates.length === 0) return false;
|
||||
}
|
||||
|
||||
d3_select(this)
|
||||
.call(uiCombobox(context, `address-${d.isAutoStreetPlace ? 'street-place' : d.id}`)
|
||||
.minItems(1)
|
||||
|
||||
Reference in New Issue
Block a user