forked from MapComplete/MapComplete
Themes(GRB): fix detection of overlapping buildings
This commit is contained in:
parent
915b732204
commit
6bdda9fb12
9 changed files with 34 additions and 184 deletions
|
@ -1,38 +0,0 @@
|
||||||
{
|
|
||||||
"id": "crab_address",
|
|
||||||
"name": "CRAB-addressen",
|
|
||||||
"description": "Address data for Flanders by the governement, suited for import into OpenStreetMap. Datadump from 2021-10-26. This layer contains only visualisation logic. Import buttons should be added via an override. Note that HNRLABEL contains the original value, whereas _HNRLABEL contains a slightly cleaned version",
|
|
||||||
"source": {
|
|
||||||
"osmTags": "HUISNR~*",
|
|
||||||
"geoJson": "https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/CRAB_2021_10_26/tile_{z}_{x}_{y}.geojson",
|
|
||||||
"geoJsonZoomLevel": 18
|
|
||||||
},
|
|
||||||
"calculatedTags": [
|
|
||||||
"_HNRLABEL=(() => {const lbl = feat.properties.HNRLABEL?.split('-')?.map(l => Number(l))?.filter(i => !isNaN (i)) ;if(lbl?.length != 2) {return feat.properties.HNRLABEL}; const addresses = []; for(let i = lbl[0]; i <= lbl[1]; i += 1){addresses.push(''+i);}; return addresses.join(';') })()"
|
|
||||||
],
|
|
||||||
"title": "CRAB-adres",
|
|
||||||
"pointRendering": [
|
|
||||||
{
|
|
||||||
"location": [
|
|
||||||
"point",
|
|
||||||
"centroid"
|
|
||||||
],
|
|
||||||
"iconSize": "50,50",
|
|
||||||
"label": "<div style='margin-top: -42px; color: white' class='rounded-full p-1 font-bold relative'>{_HNRLABEL}</div>",
|
|
||||||
"anchor": "center",
|
|
||||||
"marker": [
|
|
||||||
{
|
|
||||||
"icon": "./assets/layers/crab_address/housenumber_blank.svg"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"lineRendering": [],
|
|
||||||
"tagRenderings": [
|
|
||||||
{
|
|
||||||
"id": "render_crab",
|
|
||||||
"render": "Volgens het CRAB ligt hier <b>{STRAATNM}</b> {HUISNR} (label: {HNRLABEL})"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"allowMove": false
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="371px" height="190px" viewBox="0 0 371 190" version="1.1">
|
|
||||||
<g id="surface1">
|
|
||||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,35.294119%,67.843139%);fill-opacity:1;" d="M 30.542969 0 L 340.457031 0 C 357.261719 0 370.792969 13.542969 370.792969 30.363281 L 370.792969 159.636719 C 370.792969 176.457031 357.261719 190 340.457031 190 L 30.542969 190 C 13.738281 190 0.210938 176.457031 0.210938 159.636719 L 0.210938 30.363281 C 0.210938 13.542969 13.738281 0 30.542969 0 Z M 30.542969 0 "/>
|
|
||||||
<path style="fill:none;stroke-width:5.0152;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:4;" d="M 8.747177 22.772972 L 8.747177 65.005236 C 15.786155 65.005236 22.825134 72.044549 22.825134 79.083862 L 148.642348 79.083862 C 148.642348 72.044549 155.681326 65.005236 162.720304 65.005236 L 162.720304 22.772972 C 155.681326 22.772972 148.642348 15.733659 148.642348 8.694346 L 22.825134 8.694346 C 22.825134 15.733659 15.786155 22.772972 8.747177 22.772972 Z M 8.747177 22.772972 " transform="matrix(2.159848,0,0,2.161965,0.208987,0.000000000000015341)"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1.2 KiB |
|
@ -1,2 +0,0 @@
|
||||||
SPDX-FileCopyrightText: Pieter Vander Vennet
|
|
||||||
SPDX-License-Identifier: CC0-1.0
|
|
|
@ -1,10 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"path": "housenumber_blank.svg",
|
|
||||||
"license": "CC0-1.0",
|
|
||||||
"authors": [
|
|
||||||
"Pieter Vander Vennet"
|
|
||||||
],
|
|
||||||
"sources": []
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -622,128 +622,6 @@
|
||||||
"isCounted": false
|
"isCounted": false
|
||||||
},
|
},
|
||||||
"address",
|
"address",
|
||||||
{
|
|
||||||
"builtin": "crab_address",
|
|
||||||
"override": {
|
|
||||||
"calculatedTags+": [
|
|
||||||
"_embedded_in=overlapWith(feat)('osm_buildings_no_points').filter(b => /* Do not match newly created objects */ b.feat.properties.id.indexOf('-') < 0)[0]?.feat?.properties ?? {}",
|
|
||||||
"_embedding_nr=get(feat)('_embedded_in')['addr:housenumber']+(get(feat)('_embedded_in')['addr:unit'] ?? '')",
|
|
||||||
"_embedding_street=get(feat)('_embedded_in')['addr:street']",
|
|
||||||
"_embedding_id=get(feat)('_embedded_in').id",
|
|
||||||
"_closeby_addresses=closestn(feat)('address',10,undefined,50).map(f => f.feat).filter(addr => addr.properties['addr:street'] == feat.properties['STRAATNM'] && feat.properties['HNRLABEL'] == addr.properties['addr:housenumber'] + (addr.properties['addr:unit']??'') ).length",
|
|
||||||
"_has_identical_closeby_address=get(feat)('_closeby_addresses') >= 1 ? 'yes' : 'no'",
|
|
||||||
"_embedded_in_grb=overlapWith(feat)('grb')[0]?.feat?.properties ?? {}",
|
|
||||||
"_embedding_nr_grb=get(feat)('_embedded_in_grb')['addr:housenumber']",
|
|
||||||
"_embedding_street_grb=get(feat)('_embedded_in_grb')['addr:street']"
|
|
||||||
],
|
|
||||||
"filter": [
|
|
||||||
{
|
|
||||||
"id": "show_matched_addresses",
|
|
||||||
"options": [
|
|
||||||
{
|
|
||||||
"question": "Show all CRAB-addresses (including already matched ones)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"question": "Only show unmatched addresses",
|
|
||||||
"osmTags": {
|
|
||||||
"and": [
|
|
||||||
"_has_identical_closeby_address!=yes",
|
|
||||||
{
|
|
||||||
"#": "Matches the embedding OSM object",
|
|
||||||
"or": [
|
|
||||||
"_embedding_nr!:={HUISNR}",
|
|
||||||
"_embedding_street!:={STRAATNM}"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"#": "Matches the embedding GRB object",
|
|
||||||
"or": [
|
|
||||||
"_embedding_nr_grb!:={HUISNR}",
|
|
||||||
"_embedding_street_grb!:={STRAATNM}"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"default": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tagRenderings+": [
|
|
||||||
{
|
|
||||||
"id": "render_embedded",
|
|
||||||
"render": "Dit CRAB-adres ligt in <a href='https://osm.org/{_embedding_id}' target='_blank'>OSM-gebouw {_embedding_id}</a>",
|
|
||||||
"mappings": [
|
|
||||||
{
|
|
||||||
"if": "_embedding_id=",
|
|
||||||
"then": {
|
|
||||||
"nl": "Geen omliggend OSM-gebouw gevonden"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "embedded_address",
|
|
||||||
"render": "Het omliggende OSM-gebouw heeft geen volledig address",
|
|
||||||
"mappings": [
|
|
||||||
{
|
|
||||||
"if": {
|
|
||||||
"and": [
|
|
||||||
"_embedding_street~*",
|
|
||||||
"_embedding_nr~*"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"then": "Het omliggende object met addres heeft <b>{_embedding_street}</b> {_embedding_nr}"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"condition": "_embedding_id~*"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "apply-button",
|
|
||||||
"render": "{tag_apply(addr:street=$STRAATNM; addr:housenumber=$_HNRLABEL,Apply this address on the OSM-building,,_embedding_id)}",
|
|
||||||
"condition": {
|
|
||||||
"and": [
|
|
||||||
"_embedding_id!=",
|
|
||||||
{
|
|
||||||
"or": [
|
|
||||||
"_embedding_street!:={STRAATNM}",
|
|
||||||
"_embedding_nr!:={_HNRLABEL}"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "import-button",
|
|
||||||
"render": {
|
|
||||||
"special": {
|
|
||||||
"type": "import_button",
|
|
||||||
"targetLayer": "address",
|
|
||||||
"tags": "addr:street=$STRAATNM; addr:housenumber=$_HNRLABEL",
|
|
||||||
"text": {
|
|
||||||
"nl": "Voeg dit adres als een nieuw adrespunt toe"
|
|
||||||
},
|
|
||||||
"snap_onto_layers": "osm_buildings_no_points"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mappings": [
|
|
||||||
{
|
|
||||||
"if": "_embedding_id=",
|
|
||||||
"then": {
|
|
||||||
"nl": "Geen omliggend OSM-gebouw gevonden. Een omliggend gebouw is nodig om dit punt als adres punt toe te voegen. <div class=subtle>Importeer eerst de gebouwen. Vernieuw dan de pagina om losse adressen toe te voegen</div>"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"condition": {
|
|
||||||
"or": [
|
|
||||||
"_embedding_street!:={STRAATNM}",
|
|
||||||
"_embedding_nr!:={_HNRLABEL}"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"builtin": "current_view",
|
"builtin": "current_view",
|
||||||
"override": {
|
"override": {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { GeoOperations } from "./GeoOperations"
|
import { GeoOperations } from "./GeoOperations"
|
||||||
import Combine from "../UI/Base/Combine"
|
import Combine from "../UI/Base/Combine"
|
||||||
import BaseUIElement from "../UI/BaseUIElement"
|
|
||||||
import List from "../UI/Base/List"
|
import List from "../UI/Base/List"
|
||||||
import Title from "../UI/Base/Title"
|
import Title from "../UI/Base/Title"
|
||||||
import { BBox } from "./BBox"
|
import { BBox } from "./BBox"
|
||||||
|
@ -17,6 +16,10 @@ export interface ExtraFuncParams {
|
||||||
layerId: string,
|
layerId: string,
|
||||||
bbox: BBox
|
bbox: BBox
|
||||||
) => Feature<Geometry, Record<string, string>>[][]
|
) => Feature<Geometry, Record<string, string>>[][]
|
||||||
|
getProbablyOverlapsWith: (
|
||||||
|
layerId: string,
|
||||||
|
bbox: BBox
|
||||||
|
) => Feature<Geometry, Record<string, string>>[][]
|
||||||
getFeatureById: (id: string) => Feature<Geometry, Record<string, string>>
|
getFeatureById: (id: string) => Feature<Geometry, Record<string, string>>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,13 +105,13 @@ class OverlapFunc implements ExtraFunction {
|
||||||
"...layerIds - one or more layer ids of the layer from which every feature is checked for overlap)",
|
"...layerIds - one or more layer ids of the layer from which every feature is checked for overlap)",
|
||||||
]
|
]
|
||||||
|
|
||||||
_f(params, feat) {
|
_f(params: ExtraFuncParams, feat: Feature) {
|
||||||
return (...layerIds: string[]) => {
|
return (...layerIds: string[]) => {
|
||||||
const result: { feat: any; overlap: number }[] = []
|
const result: { feat: any; overlap: number }[] = []
|
||||||
const seenIds = new Set<string>()
|
const seenIds = new Set<string>()
|
||||||
const bbox = BBox.get(feat)
|
const bbox = BBox.get(feat)
|
||||||
for (const layerId of layerIds) {
|
for (const layerId of layerIds) {
|
||||||
const otherFeaturess = params.getFeaturesWithin(layerId, bbox)
|
const otherFeaturess = params.getProbablyOverlapsWith(layerId, bbox)
|
||||||
if (otherFeaturess === undefined) {
|
if (otherFeaturess === undefined) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,19 @@ export default class GeoIndexedStore implements FeatureSource {
|
||||||
const bboxFeature = bbox.asGeojsonCached()
|
const bboxFeature = bbox.asGeojsonCached()
|
||||||
return this.features.data.filter((f) => GeoOperations.completelyWithin(f, bboxFeature))
|
return this.features.data.filter((f) => GeoOperations.completelyWithin(f, bboxFeature))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current features within the given bbox.
|
||||||
|
*
|
||||||
|
* @param bbox
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
public GetFeaturesProbablyOverlappingWith(bbox: BBox): Feature[] {
|
||||||
|
return this.features.data.filter((f) => {
|
||||||
|
const fBbox = BBox.get(f)
|
||||||
|
return fBbox.overlapsWith(bbox)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GeoIndexedStoreForLayer extends GeoIndexedStore implements FeatureSourceForLayer {
|
export class GeoIndexedStoreForLayer extends GeoIndexedStore implements FeatureSourceForLayer {
|
||||||
|
|
|
@ -290,8 +290,22 @@ export default class MetaTagging {
|
||||||
indexedFeatures: IndexedFeatureSource
|
indexedFeatures: IndexedFeatureSource
|
||||||
perLayer: ReadonlyMap<string, GeoIndexedStoreForLayer>
|
perLayer: ReadonlyMap<string, GeoIndexedStoreForLayer>
|
||||||
}) {
|
}) {
|
||||||
return {
|
return <ExtraFuncParams>{
|
||||||
getFeatureById: (id) => state.indexedFeatures.featuresById.data.get(id),
|
getFeatureById: (id) => state.indexedFeatures.featuresById.data.get(id),
|
||||||
|
getProbablyOverlapsWith: (layerId, bbox) => {
|
||||||
|
if (layerId === "*" || layerId === null || layerId === undefined) {
|
||||||
|
const feats: Feature[][] = []
|
||||||
|
state.perLayer.forEach((layer) => {
|
||||||
|
feats.push(layer.GetFeaturesWithin(bbox))
|
||||||
|
})
|
||||||
|
return feats
|
||||||
|
}
|
||||||
|
if (!state.perLayer.get(layerId)) {
|
||||||
|
// This layer is not loaded
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return [state.perLayer.get(layerId).GetFeaturesProbablyOverlappingWith(bbox)]
|
||||||
|
},
|
||||||
getFeaturesWithin: (layerId, bbox) => {
|
getFeaturesWithin: (layerId, bbox) => {
|
||||||
if (layerId === "*" || layerId === null || layerId === undefined) {
|
if (layerId === "*" || layerId === null || layerId === undefined) {
|
||||||
const feats: Feature[][] = []
|
const feats: Feature[][] = []
|
||||||
|
|
|
@ -278,7 +278,6 @@ class LineRenderingLayer {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
features.features.addCallbackAndRunD(async (feats) => {
|
features.features.addCallbackAndRunD(async (feats) => {
|
||||||
console.log("New features!", this._layername, feats)
|
|
||||||
updateNeededSrc.set(true)
|
updateNeededSrc.set(true)
|
||||||
this.update(feats)
|
this.update(feats)
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue