mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-19 13:03:36 +00:00
[editor] Support complex POI types in the editor (#2855)
Signed-off-by: map-per <map-per@gmx.de>
This commit is contained in:
1
android/sdk/src/main/assets/mapcss-mapping.csv
Symbolic link
1
android/sdk/src/main/assets/mapcss-mapping.csv
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../../../../data/mapcss-mapping.csv
|
||||||
|
@@ -394,32 +394,25 @@
|
|||||||
<type id="amenity-pharmacy" group="shop">
|
<type id="amenity-pharmacy" group="shop">
|
||||||
<include group="poi_internet" />
|
<include group="poi_internet" />
|
||||||
</type>
|
</type>
|
||||||
<!-- Can not be added because it is a complex type -->
|
<type id="amenity-place_of_worship-buddhist">
|
||||||
<type id="amenity-place_of_worship-buddhist" can_add="no">
|
|
||||||
<include group="poi_internet" />
|
<include group="poi_internet" />
|
||||||
</type>
|
</type>
|
||||||
<!-- Can not be added because it is a complex type -->
|
<type id="amenity-place_of_worship-christian">
|
||||||
<type id="amenity-place_of_worship-christian" can_add="no">
|
|
||||||
<include group="poi_internet" />
|
<include group="poi_internet" />
|
||||||
</type>
|
</type>
|
||||||
<!-- Can not be added because it is a complex type -->
|
<type id="amenity-place_of_worship-hindu">
|
||||||
<type id="amenity-place_of_worship-hindu" can_add="no">
|
|
||||||
<include group="poi_internet" />
|
<include group="poi_internet" />
|
||||||
</type>
|
</type>
|
||||||
<!-- Can not be added because it is a complex type -->
|
<type id="amenity-place_of_worship-jewish">
|
||||||
<type id="amenity-place_of_worship-jewish" can_add="no">
|
|
||||||
<include group="poi_internet" />
|
<include group="poi_internet" />
|
||||||
</type>
|
</type>
|
||||||
<!-- Can not be added because it is a complex type -->
|
<type id="amenity-place_of_worship-muslim">
|
||||||
<type id="amenity-place_of_worship-muslim" can_add="no">
|
|
||||||
<include group="poi_internet" />
|
<include group="poi_internet" />
|
||||||
</type>
|
</type>
|
||||||
<!-- Can not be added because it is a complex type -->
|
<type id="amenity-place_of_worship-shinto">
|
||||||
<type id="amenity-place_of_worship-shinto" can_add="no">
|
|
||||||
<include group="poi_internet" />
|
<include group="poi_internet" />
|
||||||
</type>
|
</type>
|
||||||
<!-- Can not be added because it is a complex type -->
|
<type id="amenity-place_of_worship-taoist">
|
||||||
<type id="amenity-place_of_worship-taoist" can_add="no">
|
|
||||||
<include group="poi_internet" />
|
<include group="poi_internet" />
|
||||||
</type>
|
</type>
|
||||||
<type id="amenity-place_of_worship">
|
<type id="amenity-place_of_worship">
|
||||||
@@ -705,6 +698,9 @@
|
|||||||
<type id="leisure-resort">
|
<type id="leisure-resort">
|
||||||
<include group="poi_internet" />
|
<include group="poi_internet" />
|
||||||
</type>
|
</type>
|
||||||
|
<type id="leisure-sports_centre-sport-swimming">
|
||||||
|
<include group="poi_internet" />
|
||||||
|
</type>
|
||||||
<type id="leisure-sports_centre">
|
<type id="leisure-sports_centre">
|
||||||
<include group="poi_internet" />
|
<include group="poi_internet" />
|
||||||
</type>
|
</type>
|
||||||
@@ -1115,6 +1111,7 @@
|
|||||||
<type id="tourism-artwork">
|
<type id="tourism-artwork">
|
||||||
<include field="name" />
|
<include field="name" />
|
||||||
</type>
|
</type>
|
||||||
|
<!-- Not addable because OSM category is too broad and due to vandalism problems -->
|
||||||
<type id="tourism-attraction" can_add="no">
|
<type id="tourism-attraction" can_add="no">
|
||||||
<include group="poi_internet" />
|
<include group="poi_internet" />
|
||||||
<!-- <include field="wikipedia" />-->
|
<!-- <include field="wikipedia" />-->
|
||||||
@@ -1144,26 +1141,22 @@
|
|||||||
<include group="poi_internet" />
|
<include group="poi_internet" />
|
||||||
<include field="self_service" />
|
<include field="self_service" />
|
||||||
</type>
|
</type>
|
||||||
<!-- Can not be added because it is a complex type -->
|
<type id="tourism-information-office">
|
||||||
<type id="tourism-information-office" can_add="no">
|
|
||||||
<include group="poi_internet" />
|
<include group="poi_internet" />
|
||||||
</type>
|
</type>
|
||||||
<!-- Can not be added because it is a complex type -->
|
<type id="tourism-information-visitor_centre">
|
||||||
<type id="tourism-information-visitor_centre" can_add="no">
|
|
||||||
<include group="poi_internet" />
|
<include group="poi_internet" />
|
||||||
</type>
|
</type>
|
||||||
<!-- Can not be added because it is a complex type -->
|
<type id="tourism-information-board">
|
||||||
<type id="tourism-information-board" can_add="no">
|
|
||||||
<include field="name" />
|
<include field="name" />
|
||||||
</type>
|
</type>
|
||||||
<!-- Can not be added because it is a complex type -->
|
<type id="tourism-information-map">
|
||||||
<type id="tourism-information-map" can_add="no">
|
|
||||||
<include field="name" />
|
<include field="name" />
|
||||||
</type>
|
</type>
|
||||||
<!-- Can not be added because it is a complex type -->
|
<type id="tourism-information-guidepost">
|
||||||
<type id="tourism-information-guidepost" can_add="no">
|
|
||||||
</type>
|
</type>
|
||||||
<type id="tourism-information">
|
<!-- Too generic to add -->
|
||||||
|
<type id="tourism-information" can_add="no">
|
||||||
<include group="poi" />
|
<include group="poi" />
|
||||||
</type>
|
</type>
|
||||||
<type id="amenity-ranger_station">
|
<type id="amenity-ranger_station">
|
||||||
@@ -1509,67 +1502,50 @@
|
|||||||
<type id="leisure-escape_game">
|
<type id="leisure-escape_game">
|
||||||
<include group="poi_internet" />
|
<include group="poi_internet" />
|
||||||
</type>
|
</type>
|
||||||
<!-- Uncomment this after our editor core supports complex types
|
<type id="amenity-vending_machine-parking_tickets">
|
||||||
|
<include field="operator" />
|
||||||
|
<include field="level" />
|
||||||
|
</type>
|
||||||
|
<type id="amenity-vending_machine-public_transport">
|
||||||
|
<include field="operator" />
|
||||||
|
<include field="level" />
|
||||||
|
</type>
|
||||||
<type id="amenity-vending_machine-cigarettes">
|
<type id="amenity-vending_machine-cigarettes">
|
||||||
<tag k="amenity" v="vending_machine" />
|
|
||||||
<tag k="vending" v="cigarettes" />
|
|
||||||
<include field="operator" />
|
|
||||||
</type>
|
|
||||||
<type id="amenity-vending_machine-coffee">
|
|
||||||
<tag k="amenity" v="vending_machine" />
|
|
||||||
<tag k="vending" v="coffee" />
|
|
||||||
<include field="operator" />
|
|
||||||
</type>
|
|
||||||
<type id="amenity-vending_machine-condoms">
|
|
||||||
<tag k="amenity" v="vending_machine" />
|
|
||||||
<tag k="vending" v="condoms" />
|
|
||||||
<include field="operator" />
|
<include field="operator" />
|
||||||
|
<include field="level" />
|
||||||
</type>
|
</type>
|
||||||
<type id="amenity-vending_machine-drinks">
|
<type id="amenity-vending_machine-drinks">
|
||||||
<tag k="amenity" v="vending_machine" />
|
|
||||||
<tag k="vending" v="drinks" />
|
|
||||||
<include field="operator" />
|
<include field="operator" />
|
||||||
|
<include field="level" />
|
||||||
|
</type>
|
||||||
|
<type id="amenity-vending_machine-excrement_bags">
|
||||||
|
<include field="operator" />
|
||||||
|
<include field="level" />
|
||||||
|
</type>
|
||||||
|
<type id="amenity-vending_machine-coffee">
|
||||||
|
<include field="operator" />
|
||||||
|
<include field="level" />
|
||||||
|
</type>
|
||||||
|
<type id="amenity-vending_machine-condoms">
|
||||||
|
<include field="operator" />
|
||||||
|
<include field="level" />
|
||||||
</type>
|
</type>
|
||||||
<type id="amenity-vending_machine-food">
|
<type id="amenity-vending_machine-food">
|
||||||
<tag k="amenity" v="vending_machine" />
|
|
||||||
<tag k="vending" v="food" />
|
|
||||||
<include field="operator" />
|
<include field="operator" />
|
||||||
|
<include field="level" />
|
||||||
</type>
|
</type>
|
||||||
<type id="amenity-vending_machine-newspapers">
|
<type id="amenity-vending_machine-newspapers">
|
||||||
<tag k="amenity" v="vending_machine" />
|
|
||||||
<tag k="vending" v="newspapers" />
|
|
||||||
<include field="operator" />
|
<include field="operator" />
|
||||||
|
<include field="level" />
|
||||||
</type>
|
</type>
|
||||||
<type id="amenity-vending_machine-sweets">
|
<type id="amenity-vending_machine-sweets">
|
||||||
<tag k="amenity" v="vending_machine" />
|
|
||||||
<tag k="vending" v="sweets" />
|
|
||||||
<include field="operator" />
|
<include field="operator" />
|
||||||
|
<include field="level" />
|
||||||
</type>
|
</type>
|
||||||
<type id="shop-car_repair-tyres">
|
<type id="amenity-vending_machine">
|
||||||
<tag k="shop" v="car_repair" />
|
<include field="operator" />
|
||||||
<tag k="service" v="tyres" />
|
<include field="level" />
|
||||||
<include group="poi_internet" />
|
|
||||||
</type>
|
</type>
|
||||||
<type id="leisure-sports_centre-climbing">
|
|
||||||
<tag k="leisure" v="sports_centre" />
|
|
||||||
<tag k="sport" v="climbing" />
|
|
||||||
<include group="poi_internet" />
|
|
||||||
</type>
|
|
||||||
<type id="leisure-sports_centre-shooting">
|
|
||||||
<tag k="leisure" v="sports_centre" />
|
|
||||||
<tag k="sport" v="shooting" />
|
|
||||||
<include group="poi_internet" />
|
|
||||||
</type>
|
|
||||||
<type id="leisure-sports_centre-swimming">
|
|
||||||
<tag k="leisure" v="sports_centre" />
|
|
||||||
<tag k="sport" v="swimming" />
|
|
||||||
<include group="poi_internet" />
|
|
||||||
</type>
|
|
||||||
<type id="leisure-sports_centre-yoga">
|
|
||||||
<tag k="leisure" v="sports_centre" />
|
|
||||||
<tag k="sport" v="yoga" />
|
|
||||||
<include group="poi_internet" />
|
|
||||||
</type-->
|
|
||||||
<!-- Not addable as mapping as a node is uncommon -->
|
<!-- Not addable as mapping as a node is uncommon -->
|
||||||
<type id="natural-beach" can_add="no">
|
<type id="natural-beach" can_add="no">
|
||||||
<include field="name" />
|
<include field="name" />
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
# highway|bus_stop;[highway=bus_stop];;name;int_name;22;
|
# highway|bus_stop;[highway=bus_stop];;name;int_name;22;
|
||||||
# It contains:
|
# It contains:
|
||||||
# - type name: "highway|bus_stop" ("|" is converted to "-" internally)
|
# - type name: "highway|bus_stop" ("|" is converted to "-" internally)
|
||||||
# - mapcss selectors for tags: "[highway=bus_stop]", multiple selectors are separated with commas
|
# - mapcss selectors for tags: "[highway=bus_stop]", multiple selectors are separated with commas, best practice tagging for OSM editor is listed first
|
||||||
# - "x" for a deprecated type or an empty cell otherwise
|
# - "x" for a deprecated type or an empty cell otherwise
|
||||||
# - primary title tag (usually "name")
|
# - primary title tag (usually "name")
|
||||||
# - secondary title tag (usually "int_name")
|
# - secondary title tag (usually "int_name")
|
||||||
@@ -626,7 +626,7 @@ highway|trunk_link|tunnel;[highway=trunk_link][tunnel?];;name;int_name;503;
|
|||||||
drinking_water|yes;[drinking_water=yes],[drinking_water=treated],[drinking_water:refill=yes];;;;504;
|
drinking_water|yes;[drinking_water=yes],[drinking_water=treated],[drinking_water:refill=yes];;;;504;
|
||||||
drinking_water|no;505;
|
drinking_water|no;505;
|
||||||
amenity|sailing_school;[amenity=sailing_school],[education=sailing_school];;name;int_name;506;
|
amenity|sailing_school;[amenity=sailing_school],[education=sailing_school];;name;int_name;506;
|
||||||
amenity|flight_school;[amenity=sailing_school],[education=flight_school];;name;int_name;507;
|
amenity|flight_school;[amenity=flight_school],[education=flight_school];;name;int_name;507;
|
||||||
amenity|prep_school;[amenity=prep_school],[education=prep_school];;name;int_name;508;
|
amenity|prep_school;[amenity=prep_school],[education=prep_school];;name;int_name;508;
|
||||||
amenity|car_pooling;509;
|
amenity|car_pooling;509;
|
||||||
social_facility|soup_kitchen;510;
|
social_facility|soup_kitchen;510;
|
||||||
|
|||||||
|
Can't render this file because it contains an unexpected character in line 7 and column 16.
|
@@ -18,6 +18,8 @@ set(SRC
|
|||||||
edits_migration.hpp
|
edits_migration.hpp
|
||||||
feature_matcher.cpp
|
feature_matcher.cpp
|
||||||
feature_matcher.hpp
|
feature_matcher.hpp
|
||||||
|
feature_type_to_osm.cpp
|
||||||
|
feature_type_to_osm.hpp
|
||||||
new_feature_categories.cpp
|
new_feature_categories.cpp
|
||||||
new_feature_categories.hpp
|
new_feature_categories.hpp
|
||||||
opening_hours_ui.cpp
|
opening_hours_ui.cpp
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ set(SRC
|
|||||||
editor_config_test.cpp
|
editor_config_test.cpp
|
||||||
editor_notes_test.cpp
|
editor_notes_test.cpp
|
||||||
feature_matcher_test.cpp
|
feature_matcher_test.cpp
|
||||||
|
feature_type_to_osm_test.cpp
|
||||||
match_by_geometry_test.cpp
|
match_by_geometry_test.cpp
|
||||||
new_feature_categories_test.cpp
|
new_feature_categories_test.cpp
|
||||||
opening_hours_ui_test.cpp
|
opening_hours_ui_test.cpp
|
||||||
|
|||||||
224
libs/editor/editor_tests/feature_type_to_osm_test.cpp
Normal file
224
libs/editor/editor_tests/feature_type_to_osm_test.cpp
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
#include "testing/testing.hpp"
|
||||||
|
|
||||||
|
#include "editor/feature_type_to_osm.hpp"
|
||||||
|
|
||||||
|
#include "indexer/classificator.hpp"
|
||||||
|
#include "indexer/classificator_loader.hpp"
|
||||||
|
|
||||||
|
using namespace editor;
|
||||||
|
|
||||||
|
UNIT_TEST(simpleType)
|
||||||
|
{
|
||||||
|
std::string data =
|
||||||
|
"amenity|restaurant;61;\n"
|
||||||
|
"amenity|bicycle_parking;1071;\n";
|
||||||
|
|
||||||
|
classificator::Load();
|
||||||
|
|
||||||
|
TypeToOSMTranslator translator(false);
|
||||||
|
std::stringstream s(data);
|
||||||
|
translator.LoadFromStream(s);
|
||||||
|
|
||||||
|
uint32_t type = classif().GetTypeByReadableObjectName("amenity-restaurant");
|
||||||
|
std::vector<OSMTag> result = translator.OsmTagsFromType(type);
|
||||||
|
TEST_EQUAL(result.size(), 1, ());
|
||||||
|
TEST_EQUAL(result[0].key, "amenity", ());
|
||||||
|
TEST_EQUAL(result[0].value, "restaurant", ());
|
||||||
|
}
|
||||||
|
|
||||||
|
UNIT_TEST(simpleTypeWithTags)
|
||||||
|
{
|
||||||
|
std::string data =
|
||||||
|
"building;[building];;addr:housenumber;name;1;\n"
|
||||||
|
"amenity|school;[amenity=school],[education=school];;name;int_name;36;\n"
|
||||||
|
"amenity|doctors;[amenity=doctors][healthcare=doctor],[amenity=doctors],[healthcare=doctor];;name;int_name;207;\n";
|
||||||
|
|
||||||
|
classificator::Load();
|
||||||
|
|
||||||
|
TypeToOSMTranslator translator(false);
|
||||||
|
std::stringstream s(data);
|
||||||
|
translator.LoadFromStream(s);
|
||||||
|
|
||||||
|
uint32_t buildingType = classif().GetTypeByReadableObjectName("building");
|
||||||
|
std::vector<OSMTag> buildingResult = translator.OsmTagsFromType(buildingType);
|
||||||
|
TEST_EQUAL(buildingResult.size(), 1, ());
|
||||||
|
TEST_EQUAL(buildingResult[0].key, "building", ());
|
||||||
|
TEST_EQUAL(buildingResult[0].value, "yes", ());
|
||||||
|
|
||||||
|
uint32_t schoolType = classif().GetTypeByReadableObjectName("amenity-school");
|
||||||
|
std::vector<OSMTag> schoolResult = translator.OsmTagsFromType(schoolType);
|
||||||
|
TEST_EQUAL(schoolResult.size(), 1, ());
|
||||||
|
TEST_EQUAL(schoolResult[0].key, "amenity", ());
|
||||||
|
TEST_EQUAL(schoolResult[0].value, "school", ());
|
||||||
|
|
||||||
|
uint32_t doctorType = classif().GetTypeByReadableObjectName("amenity-doctors");
|
||||||
|
std::vector<OSMTag> doctorResult = translator.OsmTagsFromType(doctorType);
|
||||||
|
TEST_EQUAL(doctorResult.size(), 2, ());
|
||||||
|
TEST_EQUAL(doctorResult[0].key, "amenity", ());
|
||||||
|
TEST_EQUAL(doctorResult[0].value, "doctors", ());
|
||||||
|
TEST_EQUAL(doctorResult[1].key, "healthcare", ());
|
||||||
|
TEST_EQUAL(doctorResult[1].value, "doctor", ());
|
||||||
|
}
|
||||||
|
|
||||||
|
UNIT_TEST(complexType)
|
||||||
|
{
|
||||||
|
std::string data =
|
||||||
|
"building;[building];;addr:housenumber;name;1;\n"
|
||||||
|
" # comment that should be ignored\n"
|
||||||
|
"\n"
|
||||||
|
"amenity|restaurant;61;\n"
|
||||||
|
"tourism|information|office;[tourism=information][information=office];;name;int_name;313;\n"
|
||||||
|
"historic|castle|fortress;[historic=castle][castle_type=fortress],[historic=fortress];;name;int_name;1144;\n"
|
||||||
|
"#comment\n"
|
||||||
|
"amenity|place_of_worship|christian|mormon;[amenity=place_of_worship][religion=christian][denomination=mormon];;name;int_name;1572;\n";
|
||||||
|
|
||||||
|
classificator::Load();
|
||||||
|
|
||||||
|
TypeToOSMTranslator translator(false);
|
||||||
|
std::stringstream s(data);
|
||||||
|
translator.LoadFromStream(s);
|
||||||
|
|
||||||
|
uint32_t officeType = classif().GetTypeByReadableObjectName("tourism-information-office");
|
||||||
|
std::vector<OSMTag> officeResult = translator.OsmTagsFromType(officeType);
|
||||||
|
TEST_EQUAL(officeResult.size(), 2, ());
|
||||||
|
TEST_EQUAL(officeResult[0].key, "tourism", ());
|
||||||
|
TEST_EQUAL(officeResult[0].value, "information", ());
|
||||||
|
TEST_EQUAL(officeResult[1].key, "information", ());
|
||||||
|
TEST_EQUAL(officeResult[1].value, "office", ());
|
||||||
|
|
||||||
|
uint32_t fortressType = classif().GetTypeByReadableObjectName("historic-castle-fortress");
|
||||||
|
std::vector<OSMTag> fortressResult = translator.OsmTagsFromType(fortressType);
|
||||||
|
TEST_EQUAL(fortressResult.size(), 2, ());
|
||||||
|
TEST_EQUAL(fortressResult[0].key, "historic", ());
|
||||||
|
TEST_EQUAL(fortressResult[0].value, "castle", ());
|
||||||
|
TEST_EQUAL(fortressResult[1].key, "castle_type", ());
|
||||||
|
TEST_EQUAL(fortressResult[1].value, "fortress", ());
|
||||||
|
|
||||||
|
uint32_t mormonType = classif().GetTypeByReadableObjectName("amenity-place_of_worship-christian-mormon");
|
||||||
|
std::vector<OSMTag> mormonResult = translator.OsmTagsFromType(mormonType);
|
||||||
|
TEST_EQUAL(mormonResult.size(), 3, ());
|
||||||
|
TEST_EQUAL(mormonResult[0].key, "amenity", ());
|
||||||
|
TEST_EQUAL(mormonResult[0].value, "place_of_worship", ());
|
||||||
|
TEST_EQUAL(mormonResult[1].key, "religion", ());
|
||||||
|
TEST_EQUAL(mormonResult[1].value, "christian", ());
|
||||||
|
TEST_EQUAL(mormonResult[2].key, "denomination", ());
|
||||||
|
TEST_EQUAL(mormonResult[2].value, "mormon", ());
|
||||||
|
}
|
||||||
|
|
||||||
|
UNIT_TEST(mandatorySelector)
|
||||||
|
{
|
||||||
|
std::string data =
|
||||||
|
"amenity|parking|fee;[amenity=parking][fee];;name;int_name;125;\n"
|
||||||
|
"highway|track|bridge;[highway=track][bridge?];;name;int_name;193;\n"
|
||||||
|
"shop;[shop?];;name;int_name;943;\n"
|
||||||
|
"disusedbusiness;[disused:shop?],[disused:amenity=restaurant],[disused:amenity=fast_food],[disused:amenity=cafe],[disused:amenity=pub],[disused:amenity=bar];;;;1237;\n";
|
||||||
|
|
||||||
|
classificator::Load();
|
||||||
|
|
||||||
|
TypeToOSMTranslator translator(false);
|
||||||
|
std::stringstream s(data);
|
||||||
|
translator.LoadFromStream(s);
|
||||||
|
|
||||||
|
uint32_t parkingType = classif().GetTypeByReadableObjectName("amenity-parking-fee");
|
||||||
|
std::vector<OSMTag> parkingResult = translator.OsmTagsFromType(parkingType);
|
||||||
|
TEST_EQUAL(parkingResult.size(), 2, ());
|
||||||
|
TEST_EQUAL(parkingResult[0].key, "amenity", ());
|
||||||
|
TEST_EQUAL(parkingResult[0].value, "parking", ());
|
||||||
|
TEST_EQUAL(parkingResult[1].key, "fee", ());
|
||||||
|
TEST_EQUAL(parkingResult[1].value, "yes", ());
|
||||||
|
|
||||||
|
uint32_t trackType = classif().GetTypeByReadableObjectName("highway-track-bridge");
|
||||||
|
std::vector<OSMTag> trackResult = translator.OsmTagsFromType(trackType);
|
||||||
|
TEST_EQUAL(trackResult.size(), 2, ());
|
||||||
|
TEST_EQUAL(trackResult[0].key, "highway", ());
|
||||||
|
TEST_EQUAL(trackResult[0].value, "track", ());
|
||||||
|
TEST_EQUAL(trackResult[1].key, "bridge", ());
|
||||||
|
TEST_EQUAL(trackResult[1].value, "yes", ());
|
||||||
|
|
||||||
|
uint32_t shopType = classif().GetTypeByReadableObjectName("shop");
|
||||||
|
std::vector<OSMTag> shopResult = translator.OsmTagsFromType(shopType);
|
||||||
|
TEST_EQUAL(shopResult.size(), 1, ());
|
||||||
|
TEST_EQUAL(shopResult[0].key, "shop", ());
|
||||||
|
TEST_EQUAL(shopResult[0].value, "yes", ());
|
||||||
|
|
||||||
|
uint32_t disusedType = classif().GetTypeByReadableObjectName("disusedbusiness");
|
||||||
|
std::vector<OSMTag> disusedResult = translator.OsmTagsFromType(disusedType);
|
||||||
|
TEST_EQUAL(disusedResult.size(), 1, ());
|
||||||
|
TEST_EQUAL(disusedResult[0].key, "disused:shop", ());
|
||||||
|
TEST_EQUAL(disusedResult[0].value, "yes", ());
|
||||||
|
}
|
||||||
|
|
||||||
|
UNIT_TEST(forbiddenSelector)
|
||||||
|
{
|
||||||
|
std::string data =
|
||||||
|
"amenity|lounger;[amenity=lounger][!seasonal];;name;int_name;153;\n"
|
||||||
|
"amenity|charging_station|motorcar|small;[amenity=charging_station][motorcar?][!capacity],[amenity=charging_station][motorcar?][capacity=1],[amenity=charging_station][motorcar?][capacity=2];;name;int_name;201;\n";
|
||||||
|
|
||||||
|
classificator::Load();
|
||||||
|
|
||||||
|
TypeToOSMTranslator translator(false);
|
||||||
|
std::stringstream s(data);
|
||||||
|
translator.LoadFromStream(s);
|
||||||
|
|
||||||
|
uint32_t loungerType = classif().GetTypeByReadableObjectName("amenity-lounger");
|
||||||
|
std::vector<OSMTag> loungerResult = translator.OsmTagsFromType(loungerType);
|
||||||
|
TEST_EQUAL(loungerResult.size(), 1, ());
|
||||||
|
TEST_EQUAL(loungerResult[0].key, "amenity", ());
|
||||||
|
TEST_EQUAL(loungerResult[0].value, "lounger", ());
|
||||||
|
|
||||||
|
uint32_t chargingType = classif().GetTypeByReadableObjectName("amenity-charging_station-motorcar-small");
|
||||||
|
std::vector<OSMTag> chargingResult = translator.OsmTagsFromType(chargingType);
|
||||||
|
TEST_EQUAL(chargingResult.size(), 2, ());
|
||||||
|
TEST_EQUAL(chargingResult[0].key, "amenity", ());
|
||||||
|
TEST_EQUAL(chargingResult[0].value, "charging_station", ());
|
||||||
|
TEST_EQUAL(chargingResult[1].key, "motorcar", ());
|
||||||
|
TEST_EQUAL(chargingResult[1].value, "yes", ());
|
||||||
|
}
|
||||||
|
|
||||||
|
UNIT_TEST(ignoreComments)
|
||||||
|
{
|
||||||
|
std::string data =
|
||||||
|
"building;[building];;addr:housenumber;name;1;\n"
|
||||||
|
" # comment that should be ignored\n"
|
||||||
|
"\n"
|
||||||
|
"deprecated:waterway|riverbank:05.2024;52;x\n"
|
||||||
|
"amenity|restaurant;61;\n"
|
||||||
|
"moved:amenity|telephone:05.2024;122;amenity|telephone\n"
|
||||||
|
"natural|lake;564;natural|water|lake\n"; // moved type, should be ignored
|
||||||
|
|
||||||
|
classificator::Load();
|
||||||
|
|
||||||
|
TypeToOSMTranslator translator(false);
|
||||||
|
std::stringstream s(data);
|
||||||
|
translator.LoadFromStream(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
UNIT_TEST(loadConfigFile)
|
||||||
|
{
|
||||||
|
TypeToOSMTranslator translator(false);
|
||||||
|
translator.LoadConfigFile();
|
||||||
|
|
||||||
|
size_t size = translator.GetStorage().size();
|
||||||
|
LOG(LINFO, ("Size of feature type storage:", size));
|
||||||
|
ASSERT(size > 1300, ());
|
||||||
|
ASSERT(size < 1700, ());
|
||||||
|
}
|
||||||
|
|
||||||
|
UNIT_TEST(testWithRealFile)
|
||||||
|
{
|
||||||
|
classificator::Load();
|
||||||
|
|
||||||
|
uint32_t restaurantType = classif().GetTypeByReadableObjectName("amenity-restaurant");
|
||||||
|
std::vector<OSMTag> restaurantResult = GetOSMTranslator().OsmTagsFromType(restaurantType);
|
||||||
|
TEST_EQUAL(restaurantResult.size(), 1, ());
|
||||||
|
TEST_EQUAL(restaurantResult[0].key, "amenity", ());
|
||||||
|
TEST_EQUAL(restaurantResult[0].value, "restaurant", ());
|
||||||
|
|
||||||
|
uint32_t officeType = classif().GetTypeByReadableObjectName("tourism-information-office");
|
||||||
|
std::vector<OSMTag> officeResult = GetOSMTranslator().OsmTagsFromType(officeType);
|
||||||
|
TEST_EQUAL(officeResult.size(), 2, ());
|
||||||
|
TEST_EQUAL(officeResult[0].key, "tourism", ());
|
||||||
|
TEST_EQUAL(officeResult[0].value, "information", ());
|
||||||
|
TEST_EQUAL(officeResult[1].key, "information", ());
|
||||||
|
TEST_EQUAL(officeResult[1].value, "office", ());
|
||||||
|
}
|
||||||
166
libs/editor/feature_type_to_osm.cpp
Normal file
166
libs/editor/feature_type_to_osm.cpp
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
#include "editor/feature_type_to_osm.hpp"
|
||||||
|
|
||||||
|
#include "base/assert.hpp"
|
||||||
|
#include "coding/reader_streambuf.hpp"
|
||||||
|
#include "indexer/classificator.hpp"
|
||||||
|
#include "platform/platform.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace editor
|
||||||
|
{
|
||||||
|
TypeToOSMTranslator::TypeToOSMTranslator(bool initialize)
|
||||||
|
{
|
||||||
|
if (initialize)
|
||||||
|
LoadConfigFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TypeToOSMTranslator::LoadConfigFile()
|
||||||
|
{
|
||||||
|
Platform & p = GetPlatform();
|
||||||
|
std::unique_ptr<ModelReader> reader = p.GetReader("mapcss-mapping.csv");
|
||||||
|
ReaderStreamBuf buffer(std::move(reader));
|
||||||
|
std::istream s(&buffer);
|
||||||
|
|
||||||
|
LoadFromStream(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TypeToOSMTranslator::LoadFromStream(std::istream & s)
|
||||||
|
{
|
||||||
|
m_storage.clear();
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
while (s.good())
|
||||||
|
{
|
||||||
|
getline(s, line);
|
||||||
|
strings::Trim(line);
|
||||||
|
|
||||||
|
// skip empty lines, comments, deprecated and moved types
|
||||||
|
if (line.empty() || line.front() == '#' || line.starts_with("deprecated") || line.starts_with("moved") ||
|
||||||
|
line.back() != ';')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::vector<std::string_view> rowTokens = strings::Tokenize(line, ";");
|
||||||
|
if (rowTokens.size() < 2)
|
||||||
|
{
|
||||||
|
ASSERT(false, ("Invalid feature type definition:", line));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get internal feature type
|
||||||
|
std::vector<std::string_view> featureTypeTokens = strings::Tokenize(rowTokens[0], "|");
|
||||||
|
uint32_t type = classif().GetTypeByPathSafe(featureTypeTokens);
|
||||||
|
ASSERT(type != IndexAndTypeMapping::INVALID_TYPE, ("Feature with invalid type:", line));
|
||||||
|
|
||||||
|
if (rowTokens.size() == 2)
|
||||||
|
{
|
||||||
|
// Derive OSM tags from type name
|
||||||
|
ASSERT(featureTypeTokens.size() <= 2, ("OSM tags can not be inferred from name:", line));
|
||||||
|
|
||||||
|
OSMTag osmTag;
|
||||||
|
|
||||||
|
// e.g. "amenity-restaurant"
|
||||||
|
if (featureTypeTokens.size() >= 2)
|
||||||
|
{
|
||||||
|
osmTag.key = featureTypeTokens[0];
|
||||||
|
osmTag.value = featureTypeTokens[1];
|
||||||
|
}
|
||||||
|
// e.g. "building"
|
||||||
|
else if (featureTypeTokens.size() == 1)
|
||||||
|
{
|
||||||
|
osmTag.key = featureTypeTokens[0];
|
||||||
|
osmTag.value = "yes";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_storage.insert({type, {osmTag}});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// OSM tags are listed in the feature type entry
|
||||||
|
std::vector<std::string_view> osmTagTokens = strings::Tokenize(rowTokens[1], ",");
|
||||||
|
|
||||||
|
// First entry is the best practice way to tag a feature
|
||||||
|
std::string_view osmTagList = osmTagTokens[0];
|
||||||
|
|
||||||
|
// Process OSM tag list (e.g. "[tourism=information][information=office]")
|
||||||
|
std::vector<OSMTag> osmTags;
|
||||||
|
size_t pos = 0;
|
||||||
|
|
||||||
|
while ((pos = osmTagList.find('[', pos)) != std::string::npos)
|
||||||
|
{
|
||||||
|
size_t end = osmTagList.find(']', pos);
|
||||||
|
|
||||||
|
if (end == std::string::npos)
|
||||||
|
{
|
||||||
|
ASSERT(false, ("Bracket not closed in OSM tag:", line));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view keyValuePair = osmTagList.substr(pos + 1, end - pos - 1);
|
||||||
|
|
||||||
|
if (keyValuePair.empty())
|
||||||
|
{
|
||||||
|
ASSERT(false, ("Key value pair is empty:", line));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t equalSign = keyValuePair.find('=');
|
||||||
|
if (equalSign != std::string::npos)
|
||||||
|
{
|
||||||
|
// Tags in key=value format
|
||||||
|
OSMTag osmTag;
|
||||||
|
osmTag.key = keyValuePair.substr(0, equalSign);
|
||||||
|
osmTag.value = keyValuePair.substr(equalSign + 1);
|
||||||
|
|
||||||
|
// mapcss-mapping.csv uses 'not' instead of 'no' as a workaround for the rendering engine
|
||||||
|
if (osmTag.value == "not")
|
||||||
|
osmTag.value = "no";
|
||||||
|
|
||||||
|
osmTags.push_back(osmTag);
|
||||||
|
}
|
||||||
|
else if (keyValuePair.front() == '!')
|
||||||
|
{
|
||||||
|
// Tags with "forbidden" selector '!' are skipped
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Tags with optional "mandatory" selector '?'
|
||||||
|
if (keyValuePair.back() == '?')
|
||||||
|
keyValuePair.remove_suffix(1);
|
||||||
|
|
||||||
|
OSMTag osmTag;
|
||||||
|
osmTag.key = keyValuePair;
|
||||||
|
osmTag.value = "yes";
|
||||||
|
|
||||||
|
osmTags.push_back(osmTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = end + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(!osmTags.empty(), ("No OSM tags found for feature:", line));
|
||||||
|
|
||||||
|
m_storage.insert({type, osmTags});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<OSMTag> const & TypeToOSMTranslator::OsmTagsFromType(uint32_t type) const
|
||||||
|
{
|
||||||
|
auto it = m_storage.find(type);
|
||||||
|
|
||||||
|
if (it == m_storage.end())
|
||||||
|
{
|
||||||
|
ASSERT(false, ("OSM tags for type", type, "could not be found"));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeToOSMTranslator const & GetOSMTranslator()
|
||||||
|
{
|
||||||
|
static TypeToOSMTranslator translator;
|
||||||
|
return translator;
|
||||||
|
}
|
||||||
|
} // namespace editor
|
||||||
34
libs/editor/feature_type_to_osm.hpp
Normal file
34
libs/editor/feature_type_to_osm.hpp
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace editor
|
||||||
|
{
|
||||||
|
|
||||||
|
struct OSMTag
|
||||||
|
{
|
||||||
|
std::string key;
|
||||||
|
std::string value;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TypeToOSMTranslator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TypeToOSMTranslator() : TypeToOSMTranslator(true) {}
|
||||||
|
explicit TypeToOSMTranslator(bool initialize);
|
||||||
|
|
||||||
|
void LoadConfigFile();
|
||||||
|
void LoadFromStream(std::istream & s);
|
||||||
|
std::vector<OSMTag> const & OsmTagsFromType(uint32_t type) const;
|
||||||
|
|
||||||
|
std::unordered_map<uint32_t, std::vector<OSMTag>> const & GetStorage() const { return m_storage; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<uint32_t, std::vector<OSMTag>> m_storage;
|
||||||
|
};
|
||||||
|
|
||||||
|
TypeToOSMTranslator const & GetOSMTranslator();
|
||||||
|
|
||||||
|
} // namespace editor
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
#include "editor/xml_feature.hpp"
|
#include "editor/xml_feature.hpp"
|
||||||
|
|
||||||
|
#include "editor/feature_type_to_osm.hpp"
|
||||||
#include "editor/keys_to_remove.hpp"
|
#include "editor/keys_to_remove.hpp"
|
||||||
|
|
||||||
#include "indexer/classificator.hpp"
|
#include "indexer/classificator.hpp"
|
||||||
@@ -640,36 +642,16 @@ void XMLFeature::RemoveTag(string_view key)
|
|||||||
|
|
||||||
void XMLFeature::SetOSMTagsForType(uint32_t type)
|
void XMLFeature::SetOSMTagsForType(uint32_t type)
|
||||||
{
|
{
|
||||||
if (ftypes::IsRecyclingCentreChecker::Instance()(type))
|
if (ftypes::IsAddressChecker::Instance()(type))
|
||||||
{
|
|
||||||
SetTagValue("amenity", "recycling");
|
|
||||||
SetTagValue("recycling_type", "centre");
|
|
||||||
}
|
|
||||||
else if (ftypes::IsRecyclingContainerChecker::Instance()(type))
|
|
||||||
{
|
|
||||||
SetTagValue("amenity", "recycling");
|
|
||||||
SetTagValue("recycling_type", "container");
|
|
||||||
}
|
|
||||||
else if (ftypes::IsAddressChecker::Instance()(type))
|
|
||||||
{
|
{
|
||||||
// Addresses don't have a category tag
|
// Addresses don't have a category tag
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
string const strType = classif().GetReadableObjectName(type);
|
|
||||||
strings::SimpleTokenizer iter(strType, "-");
|
|
||||||
string_view const k = *iter;
|
|
||||||
|
|
||||||
if (++iter)
|
std::vector<OSMTag> const & osmTags = GetOSMTranslator().OsmTagsFromType(type);
|
||||||
{
|
|
||||||
// Main type is stored as "k=amenity v=restaurant"
|
for(auto const & osmTag : osmTags)
|
||||||
SetTagValue(k, *iter);
|
SetTagValue(osmTag.key, osmTag.value);
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Main type is stored as "k=building v=yes"
|
|
||||||
SetTagValue(k, kYes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void XMLFeature::UpdateOSMTag(std::string_view key, std::string_view value)
|
void XMLFeature::UpdateOSMTag(std::string_view key, std::string_view value)
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ copy_resources(
|
|||||||
patterns.txt
|
patterns.txt
|
||||||
transit_colors.txt
|
transit_colors.txt
|
||||||
types.txt
|
types.txt
|
||||||
|
mapcss-mapping.csv
|
||||||
World.mwm
|
World.mwm
|
||||||
WorldCoasts.mwm
|
WorldCoasts.mwm
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user