]> git.openstreetmap.org Git - nominatim.git/blob - lib-php/ClassTypes.php
add framework for analysing housenumbers
[nominatim.git] / lib-php / ClassTypes.php
1 <?php
2 /**
3  * SPDX-License-Identifier: GPL-2.0-only
4  *
5  * This file is part of Nominatim. (https://nominatim.org)
6  *
7  * Copyright (C) 2022 by the Nominatim developer community.
8  * For a full list of authors see the git log.
9  */
10
11 namespace Nominatim\ClassTypes;
12
13 /**
14  * Create a label tag for the given place that can be used as an XML name.
15  *
16  * @param array[] $aPlace  Information about the place to label.
17  *
18  * A label tag groups various object types together under a common
19  * label. The returned value is lower case and has no spaces
20  */
21 function getLabelTag($aPlace, $sCountry = null)
22 {
23     $iRank = (int) ($aPlace['rank_address'] ?? 30);
24     $sLabel;
25     if (isset($aPlace['place_type'])) {
26         $sLabel = $aPlace['place_type'];
27     } elseif ($aPlace['class'] == 'boundary' && $aPlace['type'] == 'administrative') {
28         $sLabel = getBoundaryLabel($iRank/2, $sCountry);
29     } elseif ($aPlace['type'] == 'postal_code') {
30         $sLabel = 'postcode';
31     } elseif ($iRank < 26) {
32         $sLabel = $aPlace['type'];
33     } elseif ($iRank < 28) {
34         $sLabel = 'road';
35     } elseif ($aPlace['class'] == 'place'
36             && ($aPlace['type'] == 'house_number' ||
37                 $aPlace['type'] == 'house_name' ||
38                 $aPlace['type'] == 'country_code')
39     ) {
40         $sLabel = $aPlace['type'];
41     } else {
42         $sLabel = $aPlace['class'];
43     }
44
45     return strtolower(str_replace(' ', '_', $sLabel));
46 }
47
48 /**
49  * Create a label for the given place.
50  *
51  * @param array[] $aPlace  Information about the place to label.
52  */
53 function getLabel($aPlace, $sCountry = null)
54 {
55     if (isset($aPlace['place_type'])) {
56         return ucwords(str_replace('_', ' ', $aPlace['place_type']));
57     }
58
59     if ($aPlace['class'] == 'boundary' && $aPlace['type'] == 'administrative') {
60         return getBoundaryLabel(($aPlace['rank_address'] ?? 30)/2, $sCountry ?? null);
61     }
62
63     // Return a label only for 'important' class/type combinations
64     if (getImportance($aPlace) !== null) {
65         return ucwords(str_replace('_', ' ', $aPlace['type']));
66     }
67
68     return null;
69 }
70
71
72 /**
73  * Return a simple label for an administrative boundary for the given country.
74  *
75  * @param int $iAdminLevel   Content of admin_level tag.
76  * @param string $sCountry   Country code of the country where the object is
77  *                           in. May be null, in which case a world-wide
78  *                           fallback is used.
79  * @param string $sFallback  String to return if no explicit string is listed.
80  *
81  * @return string
82  */
83 function getBoundaryLabel($iAdminLevel, $sCountry, $sFallback = 'Administrative')
84 {
85     static $aBoundaryList = array (
86                              'default' => array (
87                                            1 => 'Continent',
88                                            2 => 'Country',
89                                            3 => 'Region',
90                                            4 => 'State',
91                                            5 => 'State District',
92                                            6 => 'County',
93                                            7 => 'Municipality',
94                                            8 => 'City',
95                                            9 => 'City District',
96                                            10 => 'Suburb',
97                                            11 => 'Neighbourhood',
98                                            12 => 'City Block'
99                                           ),
100                              'no' => array (
101                                       3 => 'State',
102                                       4 => 'County'
103                                      ),
104                              'se' => array (
105                                       3 => 'State',
106                                       4 => 'County'
107                                      )
108             );
109
110     if (isset($aBoundaryList[$sCountry])
111         && isset($aBoundaryList[$sCountry][$iAdminLevel])
112     ) {
113         return $aBoundaryList[$sCountry][$iAdminLevel];
114     }
115
116     return $aBoundaryList['default'][$iAdminLevel] ?? $sFallback;
117 }
118
119 /**
120  * Return an estimated radius of how far the object node extends.
121  *
122  * @param array[] $aPlace  Information about the place. This must be a node
123  *                         feature.
124  *
125  * @return float  The radius around the feature in degrees.
126  */
127 function getDefRadius($aPlace)
128 {
129     $aSpecialRadius = array(
130                        'place:continent' => 25,
131                        'place:country' => 7,
132                        'place:state' => 2.6,
133                        'place:province' => 2.6,
134                        'place:region' => 1.0,
135                        'place:county' => 0.7,
136                        'place:city' => 0.16,
137                        'place:municipality' => 0.16,
138                        'place:island' => 0.32,
139                        'place:postcode' => 0.16,
140                        'place:town' => 0.04,
141                        'place:village' => 0.02,
142                        'place:hamlet' => 0.02,
143                        'place:district' => 0.02,
144                        'place:borough' => 0.02,
145                        'place:suburb' => 0.02,
146                        'place:locality' => 0.01,
147                        'place:neighbourhood'=> 0.01,
148                        'place:quarter' => 0.01,
149                        'place:city_block' => 0.01,
150                        'landuse:farm' => 0.01,
151                        'place:farm' => 0.01,
152                        'place:airport' => 0.015,
153                        'aeroway:aerodrome' => 0.015,
154                        'railway:station' => 0.005
155            );
156
157     $sClassPlace = $aPlace['class'].':'.$aPlace['type'];
158
159     return $aSpecialRadius[$sClassPlace] ?? 0.00005;
160 }
161
162 /**
163  * Get the icon to use with the given object.
164  */
165 function getIcon($aPlace)
166 {
167     $aIcons = array(
168                'boundary:administrative' => 'poi_boundary_administrative',
169                'place:city' => 'poi_place_city',
170                'place:town' => 'poi_place_town',
171                'place:village' => 'poi_place_village',
172                'place:hamlet' => 'poi_place_village',
173                'place:suburb' => 'poi_place_village',
174                'place:locality' => 'poi_place_village',
175                'place:airport' => 'transport_airport2',
176                'aeroway:aerodrome' => 'transport_airport2',
177                'railway:station' => 'transport_train_station2',
178                'amenity:place_of_worship' => 'place_of_worship_unknown3',
179                'amenity:pub' => 'food_pub',
180                'amenity:bar' => 'food_bar',
181                'amenity:university' => 'education_university',
182                'tourism:museum' => 'tourist_museum',
183                'amenity:arts_centre' => 'tourist_art_gallery2',
184                'tourism:zoo' => 'tourist_zoo',
185                'tourism:theme_park' => 'poi_point_of_interest',
186                'tourism:attraction' => 'poi_point_of_interest',
187                'leisure:golf_course' => 'sport_golf',
188                'historic:castle' => 'tourist_castle',
189                'amenity:hospital' => 'health_hospital',
190                'amenity:school' => 'education_school',
191                'amenity:theatre' => 'tourist_theatre',
192                'amenity:library' => 'amenity_library',
193                'amenity:fire_station' => 'amenity_firestation3',
194                'amenity:police' => 'amenity_police2',
195                'amenity:bank' => 'money_bank2',
196                'amenity:post_office' => 'amenity_post_office',
197                'tourism:hotel' => 'accommodation_hotel2',
198                'amenity:cinema' => 'tourist_cinema',
199                'tourism:artwork' => 'tourist_art_gallery2',
200                'historic:archaeological_site' => 'tourist_archaeological2',
201                'amenity:doctors' => 'health_doctors',
202                'leisure:sports_centre' => 'sport_leisure_centre',
203                'leisure:swimming_pool' => 'sport_swimming_outdoor',
204                'shop:supermarket' => 'shopping_supermarket',
205                'shop:convenience' => 'shopping_convenience',
206                'amenity:restaurant' => 'food_restaurant',
207                'amenity:fast_food' => 'food_fastfood',
208                'amenity:cafe' => 'food_cafe',
209                'tourism:guest_house' => 'accommodation_bed_and_breakfast',
210                'amenity:pharmacy' => 'health_pharmacy_dispensing',
211                'amenity:fuel' => 'transport_fuel',
212                'natural:peak' => 'poi_peak',
213                'natural:wood' => 'landuse_coniferous_and_deciduous',
214                'shop:bicycle' => 'shopping_bicycle',
215                'shop:clothes' => 'shopping_clothes',
216                'shop:hairdresser' => 'shopping_hairdresser',
217                'shop:doityourself' => 'shopping_diy',
218                'shop:estate_agent' => 'shopping_estateagent2',
219                'shop:car' => 'shopping_car',
220                'shop:garden_centre' => 'shopping_garden_centre',
221                'shop:car_repair' => 'shopping_car_repair',
222                'shop:bakery' => 'shopping_bakery',
223                'shop:butcher' => 'shopping_butcher',
224                'shop:apparel' => 'shopping_clothes',
225                'shop:laundry' => 'shopping_laundrette',
226                'shop:beverages' => 'shopping_alcohol',
227                'shop:alcohol' => 'shopping_alcohol',
228                'shop:optician' => 'health_opticians',
229                'shop:chemist' => 'health_pharmacy',
230                'shop:gallery' => 'tourist_art_gallery2',
231                'shop:jewelry' => 'shopping_jewelry',
232                'tourism:information' => 'amenity_information',
233                'historic:ruins' => 'tourist_ruin',
234                'amenity:college' => 'education_school',
235                'historic:monument' => 'tourist_monument',
236                'historic:memorial' => 'tourist_monument',
237                'historic:mine' => 'poi_mine',
238                'tourism:caravan_site' => 'accommodation_caravan_park',
239                'amenity:bus_station' => 'transport_bus_station',
240                'amenity:atm' => 'money_atm2',
241                'tourism:viewpoint' => 'tourist_view_point',
242                'tourism:guesthouse' => 'accommodation_bed_and_breakfast',
243                'railway:tram' => 'transport_tram_stop',
244                'amenity:courthouse' => 'amenity_court',
245                'amenity:recycling' => 'amenity_recycling',
246                'amenity:dentist' => 'health_dentist',
247                'natural:beach' => 'tourist_beach',
248                'railway:tram_stop' => 'transport_tram_stop',
249                'amenity:prison' => 'amenity_prison',
250                'highway:bus_stop' => 'transport_bus_stop2'
251     );
252
253     $sClassPlace = $aPlace['class'].':'.$aPlace['type'];
254
255     return $aIcons[$sClassPlace] ?? null;
256 }
257
258 /**
259  * Get an icon for the given object with its full URL.
260  */
261 function getIconFile($aPlace)
262 {
263     if (CONST_MapIcon_URL === false) {
264         return null;
265     }
266
267     $sIcon = getIcon($aPlace);
268
269     if (!isset($sIcon)) {
270         return null;
271     }
272
273     return CONST_MapIcon_URL.'/'.$sIcon.'.p.20.png';
274 }
275
276 /**
277  * Return a class importance value for the given place.
278  *
279  * @param array[] $aPlace  Information about the place.
280  *
281  * @return int  An importance value. The lower the value, the more
282  *              important the class.
283  */
284 function getImportance($aPlace)
285 {
286     static $aWithImportance = null;
287
288     if ($aWithImportance === null) {
289         $aWithImportance = array_flip(array(
290                                            'boundary:administrative',
291                                            'place:country',
292                                            'place:state',
293                                            'place:province',
294                                            'place:county',
295                                            'place:city',
296                                            'place:region',
297                                            'place:island',
298                                            'place:town',
299                                            'place:village',
300                                            'place:hamlet',
301                                            'place:suburb',
302                                            'place:locality',
303                                            'landuse:farm',
304                                            'place:farm',
305                                            'highway:motorway_junction',
306                                            'highway:motorway',
307                                            'highway:trunk',
308                                            'highway:primary',
309                                            'highway:secondary',
310                                            'highway:tertiary',
311                                            'highway:residential',
312                                            'highway:unclassified',
313                                            'highway:living_street',
314                                            'highway:service',
315                                            'highway:track',
316                                            'highway:road',
317                                            'highway:byway',
318                                            'highway:bridleway',
319                                            'highway:cycleway',
320                                            'highway:pedestrian',
321                                            'highway:footway',
322                                            'highway:steps',
323                                            'highway:motorway_link',
324                                            'highway:trunk_link',
325                                            'highway:primary_link',
326                                            'landuse:industrial',
327                                            'landuse:residential',
328                                            'landuse:retail',
329                                            'landuse:commercial',
330                                            'place:airport',
331                                            'aeroway:aerodrome',
332                                            'railway:station',
333                                            'amenity:place_of_worship',
334                                            'amenity:pub',
335                                            'amenity:bar',
336                                            'amenity:university',
337                                            'tourism:museum',
338                                            'amenity:arts_centre',
339                                            'tourism:zoo',
340                                            'tourism:theme_park',
341                                            'tourism:attraction',
342                                            'leisure:golf_course',
343                                            'historic:castle',
344                                            'amenity:hospital',
345                                            'amenity:school',
346                                            'amenity:theatre',
347                                            'amenity:public_building',
348                                            'amenity:library',
349                                            'amenity:townhall',
350                                            'amenity:community_centre',
351                                            'amenity:fire_station',
352                                            'amenity:police',
353                                            'amenity:bank',
354                                            'amenity:post_office',
355                                            'leisure:park',
356                                            'amenity:park',
357                                            'landuse:park',
358                                            'landuse:recreation_ground',
359                                            'tourism:hotel',
360                                            'tourism:motel',
361                                            'amenity:cinema',
362                                            'tourism:artwork',
363                                            'historic:archaeological_site',
364                                            'amenity:doctors',
365                                            'leisure:sports_centre',
366                                            'leisure:swimming_pool',
367                                            'shop:supermarket',
368                                            'shop:convenience',
369                                            'amenity:restaurant',
370                                            'amenity:fast_food',
371                                            'amenity:cafe',
372                                            'tourism:guest_house',
373                                            'amenity:pharmacy',
374                                            'amenity:fuel',
375                                            'natural:peak',
376                                            'waterway:waterfall',
377                                            'natural:wood',
378                                            'natural:water',
379                                            'landuse:forest',
380                                            'landuse:cemetery',
381                                            'landuse:allotments',
382                                            'landuse:farmyard',
383                                            'railway:rail',
384                                            'waterway:canal',
385                                            'waterway:river',
386                                            'waterway:stream',
387                                            'shop:bicycle',
388                                            'shop:clothes',
389                                            'shop:hairdresser',
390                                            'shop:doityourself',
391                                            'shop:estate_agent',
392                                            'shop:car',
393                                            'shop:garden_centre',
394                                            'shop:car_repair',
395                                            'shop:newsagent',
396                                            'shop:bakery',
397                                            'shop:furniture',
398                                            'shop:butcher',
399                                            'shop:apparel',
400                                            'shop:electronics',
401                                            'shop:department_store',
402                                            'shop:books',
403                                            'shop:yes',
404                                            'shop:outdoor',
405                                            'shop:mall',
406                                            'shop:florist',
407                                            'shop:charity',
408                                            'shop:hardware',
409                                            'shop:laundry',
410                                            'shop:shoes',
411                                            'shop:beverages',
412                                            'shop:dry_cleaning',
413                                            'shop:carpet',
414                                            'shop:computer',
415                                            'shop:alcohol',
416                                            'shop:optician',
417                                            'shop:chemist',
418                                            'shop:gallery',
419                                            'shop:mobile_phone',
420                                            'shop:sports',
421                                            'shop:jewelry',
422                                            'shop:pet',
423                                            'shop:beauty',
424                                            'shop:stationery',
425                                            'shop:shopping_centre',
426                                            'shop:general',
427                                            'shop:electrical',
428                                            'shop:toys',
429                                            'shop:jeweller',
430                                            'shop:betting',
431                                            'shop:household',
432                                            'shop:travel_agency',
433                                            'shop:hifi',
434                                            'amenity:shop',
435                                            'tourism:information',
436                                            'place:house',
437                                            'place:house_name',
438                                            'place:house_number',
439                                            'place:country_code',
440                                            'leisure:pitch',
441                                            'highway:unsurfaced',
442                                            'historic:ruins',
443                                            'amenity:college',
444                                            'historic:monument',
445                                            'railway:subway',
446                                            'historic:memorial',
447                                            'leisure:nature_reserve',
448                                            'leisure:common',
449                                            'waterway:lock_gate',
450                                            'natural:fell',
451                                            'amenity:nightclub',
452                                            'highway:path',
453                                            'leisure:garden',
454                                            'landuse:reservoir',
455                                            'leisure:playground',
456                                            'leisure:stadium',
457                                            'historic:mine',
458                                            'natural:cliff',
459                                            'tourism:caravan_site',
460                                            'amenity:bus_station',
461                                            'amenity:kindergarten',
462                                            'highway:construction',
463                                            'amenity:atm',
464                                            'amenity:emergency_phone',
465                                            'waterway:lock',
466                                            'waterway:riverbank',
467                                            'natural:coastline',
468                                            'tourism:viewpoint',
469                                            'tourism:hostel',
470                                            'tourism:bed_and_breakfast',
471                                            'railway:halt',
472                                            'railway:platform',
473                                            'railway:tram',
474                                            'amenity:courthouse',
475                                            'amenity:recycling',
476                                            'amenity:dentist',
477                                            'natural:beach',
478                                            'place:moor',
479                                            'amenity:grave_yard',
480                                            'waterway:drain',
481                                            'landuse:grass',
482                                            'landuse:village_green',
483                                            'natural:bay',
484                                            'railway:tram_stop',
485                                            'leisure:marina',
486                                            'highway:stile',
487                                            'natural:moor',
488                                            'railway:light_rail',
489                                            'railway:narrow_gauge',
490                                            'natural:land',
491                                            'amenity:village_hall',
492                                            'waterway:dock',
493                                            'amenity:veterinary',
494                                            'landuse:brownfield',
495                                            'leisure:track',
496                                            'railway:historic_station',
497                                            'landuse:construction',
498                                            'amenity:prison',
499                                            'landuse:quarry',
500                                            'amenity:telephone',
501                                            'highway:traffic_signals',
502                                            'natural:heath',
503                                            'historic:house',
504                                            'amenity:social_club',
505                                            'landuse:military',
506                                            'amenity:health_centre',
507                                            'historic:building',
508                                            'amenity:clinic',
509                                            'highway:services',
510                                            'amenity:ferry_terminal',
511                                            'natural:marsh',
512                                            'natural:hill',
513                                            'highway:raceway',
514                                            'amenity:taxi',
515                                            'amenity:take_away',
516                                            'amenity:car_rental',
517                                            'place:islet',
518                                            'amenity:nursery',
519                                            'amenity:nursing_home',
520                                            'amenity:toilets',
521                                            'amenity:hall',
522                                            'waterway:boatyard',
523                                            'highway:mini_roundabout',
524                                            'historic:manor',
525                                            'tourism:chalet',
526                                            'amenity:bicycle_parking',
527                                            'amenity:hotel',
528                                            'waterway:weir',
529                                            'natural:wetland',
530                                            'natural:cave_entrance',
531                                            'amenity:crematorium',
532                                            'tourism:picnic_site',
533                                            'landuse:wood',
534                                            'landuse:basin',
535                                            'natural:tree',
536                                            'leisure:slipway',
537                                            'landuse:meadow',
538                                            'landuse:piste',
539                                            'amenity:care_home',
540                                            'amenity:club',
541                                            'amenity:medical_centre',
542                                            'historic:roman_road',
543                                            'historic:fort',
544                                            'railway:subway_entrance',
545                                            'historic:yes',
546                                            'highway:gate',
547                                            'leisure:fishing',
548                                            'historic:museum',
549                                            'amenity:car_wash',
550                                            'railway:level_crossing',
551                                            'leisure:bird_hide',
552                                            'natural:headland',
553                                            'tourism:apartments',
554                                            'amenity:shopping',
555                                            'natural:scrub',
556                                            'natural:fen',
557                                            'building:yes',
558                                            'mountain_pass:yes',
559                                            'amenity:parking',
560                                            'highway:bus_stop',
561                                            'place:postcode',
562                                            'amenity:post_box',
563                                            'place:houses',
564                                            'railway:preserved',
565                                            'waterway:derelict_canal',
566                                            'amenity:dead_pub',
567                                            'railway:disused_station',
568                                            'railway:abandoned',
569                                            'railway:disused'
570                 ));
571     }
572
573     $sClassPlace = $aPlace['class'].':'.$aPlace['type'];
574
575     return $aWithImportance[$sClassPlace] ?? null;
576 }