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