diff --git a/editor/editor_tests/CMakeLists.txt b/editor/editor_tests/CMakeLists.txt
index aa63b7a3cf..fe43bb756c 100644
--- a/editor/editor_tests/CMakeLists.txt
+++ b/editor/editor_tests/CMakeLists.txt
@@ -5,6 +5,7 @@ set(
config_loader_test.cpp
editor_config_test.cpp
editor_notes_test.cpp
+ match_by_geometry_test.cpp
opening_hours_ui_test.cpp
osm_feature_matcher_test.cpp
ui2oh_test.cpp
diff --git a/editor/editor_tests/match_by_geometry_test.cpp b/editor/editor_tests/match_by_geometry_test.cpp
new file mode 100644
index 0000000000..ce936d200e
--- /dev/null
+++ b/editor/editor_tests/match_by_geometry_test.cpp
@@ -0,0 +1,256 @@
+#include "testing/testing.hpp"
+
+#include "editor/osm_feature_matcher.hpp"
+#include "editor/xml_feature.hpp"
+
+#include "3party/pugixml/src/pugixml.hpp"
+
+namespace
+{
+// This place on OSM map https://www.openstreetmap.org/relation/1359233.
+string const kSenatskiyDvorets = R"XXX(
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+)XXX";
+
+UNIT_TEST(MatchByGeometry)
+{
+ pugi::xml_document osmResponse;
+ TEST(osmResponse.load_buffer(kSenatskiyDvorets.c_str(), kSenatskiyDvorets.size()), ());
+
+ // It is a triangulated polygon. Every triangle is presented as three points.
+ // For simplification, you can visualize it as a single sequence of points
+ // by using, for ex. Gnuplot.
+ vector geometry = {
+ {37.621818614168603, 67.468231078000599},
+ {37.621858847304139, 67.468292768808396},
+ {37.621783745451154, 67.468236442418657},
+ {37.621783745451154, 67.468236442418657},
+ {37.621858847304139, 67.468292768808396},
+ {37.621840071840893, 67.468327637525846},
+ {37.621783745451154, 67.468236442418657},
+ {37.621840071840893, 67.468327637525846},
+ {37.620694768582979, 67.46837323507944},
+ {37.621783745451154, 67.468236442418657},
+ {37.620694768582979, 67.46837323507944},
+ {37.620887887633501, 67.46797626814228},
+ {37.620887887633501, 67.46797626814228},
+ {37.620694768582979, 67.46837323507944},
+ {37.620826196825703, 67.467957492679034},
+ {37.621783745451154, 67.468236442418657},
+ {37.620887887633501, 67.46797626814228},
+ {37.621625495118082, 67.467576618996077},
+ {37.621625495118082, 67.467576618996077},
+ {37.620887887633501, 67.46797626814228},
+ {37.621373367468806, 67.467496152725033},
+ {37.621373367468806, 67.467496152725033},
+ {37.620887887633501, 67.46797626814228},
+ {37.621365320841704, 67.467439826335323},
+ {37.621373367468806, 67.467496152725033},
+ {37.621365320841704, 67.467439826335323},
+ {37.621386778513994, 67.467447872962424},
+ {37.621783745451154, 67.468236442418657},
+ {37.621625495118082, 67.467576618996077},
+ {37.621869576140256, 67.467936035006772},
+ {37.621869576140256, 67.467936035006772},
+ {37.621625495118082, 67.467576618996077},
+ {37.621856165095096, 67.467691953984598},
+ {37.621856165095096, 67.467691953984598},
+ {37.621625495118082, 67.467576618996077},
+ {37.621966135665531, 67.467348631228134},
+ {37.621966135665531, 67.467348631228134},
+ {37.621625495118082, 67.467576618996077},
+ {37.621722054643357, 67.467270847166105},
+ {37.621966135665531, 67.467348631228134},
+ {37.621722054643357, 67.467270847166105},
+ {37.621880304976401, 67.46708309253367},
+ {37.621880304976401, 67.46708309253367},
+ {37.621722054643357, 67.467270847166105},
+ {37.621445787112748, 67.467185016477004},
+ {37.621880304976401, 67.46708309253367},
+ {37.621445787112748, 67.467185016477004},
+ {37.621236574808023, 67.466879244647032},
+ {37.621236574808023, 67.466879244647032},
+ {37.621445787112748, 67.467185016477004},
+ {37.621365320841704, 67.467439826335323},
+ {37.621236574808023, 67.466879244647032},
+ {37.621365320841704, 67.467439826335323},
+ {37.620887887633501, 67.46797626814228},
+ {37.621966135665531, 67.467348631228134},
+ {37.621880304976401, 67.46708309253367},
+ {37.622068059608836, 67.46738081773654},
+ {37.622068059608836, 67.46738081773654},
+ {37.621880304976401, 67.46708309253367},
+ {37.622121703789531, 67.466683443387467},
+ {37.622121703789531, 67.466683443387467},
+ {37.621880304976401, 67.46708309253367},
+ {37.622019779846227, 67.466648574670018},
+ {37.622068059608836, 67.46738081773654},
+ {37.622121703789531, 67.466683443387467},
+ {37.622078788444981, 67.467426415290134},
+ {37.621869576140256, 67.467936035006772},
+ {37.621856165095096, 67.467691953984598},
+ {37.622033190891386, 67.467748280374309},
+ {37.621869576140256, 67.467936035006772},
+ {37.622033190891386, 67.467748280374309},
+ {37.622041237518488, 67.467981632560367},
+ {37.622041237518488, 67.467981632560367},
+ {37.622033190891386, 67.467748280374309},
+ {37.62210024611727, 67.467734869329149},
+ {37.622041237518488, 67.467981632560367},
+ {37.62210024611727, 67.467734869329149},
+ {37.622344327139444, 67.468314226480686},
+ {37.622344327139444, 67.468314226480686},
+ {37.62210024611727, 67.467734869329149},
+ {37.622078788444981, 67.467426415290134},
+ {37.622078788444981, 67.467426415290134},
+ {37.62210024611727, 67.467734869329149},
+ {37.622060012981734, 67.46746664842567},
+ {37.622344327139444, 67.468314226480686},
+ {37.622078788444981, 67.467426415290134},
+ {37.622121703789531, 67.466683443387467},
+ {37.622041237518488, 67.467981632560367},
+ {37.622344327139444, 67.468314226480686},
+ {37.622092199490169, 67.468252535672889},
+ {37.622092199490169, 67.468252535672889},
+ {37.622344327139444, 67.468314226480686},
+ {37.622049284145589, 67.468392010542686},
+ {37.622049284145589, 67.468392010542686},
+ {37.622344327139444, 67.468314226480686},
+ {37.622188759015415, 67.468845303869585},
+ {37.622049284145589, 67.468392010542686},
+ {37.622188759015415, 67.468845303869585},
+ {37.621840071840893, 67.468327637525846},
+ {37.621840071840893, 67.468327637525846},
+ {37.622188759015415, 67.468845303869585},
+ {37.620694768582979, 67.46837323507944},
+ {37.622041237518488, 67.467981632560367},
+ {37.622092199490169, 67.468252535672889},
+ {37.622065377399821, 67.468244489045759}
+ };
+
+ auto const matched = osm::GetBestOsmWayOrRelation(osmResponse, geometry);
+ TEST_EQUAL(matched.attribute("id").value(), string("85761"), ());
+}
+} // namespace
+
diff --git a/editor/editor_tests/osm_feature_matcher_test.cpp b/editor/editor_tests/osm_feature_matcher_test.cpp
index 842c2122ca..2a87ae4799 100644
--- a/editor/editor_tests/osm_feature_matcher_test.cpp
+++ b/editor/editor_tests/osm_feature_matcher_test.cpp
@@ -525,843 +525,52 @@ UNIT_TEST(HouseWithSeveralEntrances)
TEST_EQUAL(bestWay.attribute("id").value(), string("30680719"), ());
}
-string const kSenatskiyDvorets = "XXX("
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- ""
- ")XXX";
+string const kRelationWithSingleWay = R"XXX(
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+)XXX";
-UNIT_TEST(MatchByGeometry)
+UNIT_TEST(RelationWithSingleWay)
{
pugi::xml_document osmResponse;
- TEST(osmResponse.load_buffer(kSenatskiyDvorets.c_str(), kSenatskiyDvorets.size()), ());
+ TEST(osmResponse.load_buffer(kRelationWithSingleWay.c_str(), kRelationWithSingleWay.size()), ());
vector geometry = {
- {37.618409526485265815, 67.4572930295563821},
- {37.618404162067207608, 67.45729839397444038},
- {37.618240547316077027, 67.45714819026849795},
- {37.618240547316077027, 67.45714819026849795},
- {37.618404162067207608, 67.45729839397444038},
- {37.61823518289801882, 67.45715355468655616},
- {37.61823518289801882, 67.45715355468655616},
- {37.618404162067207608, 67.45729839397444038},
- {37.618205678598627628, 67.45744591547136792},
- {37.618205678598627628, 67.45744591547136792},
- {37.618404162067207608, 67.45729839397444038},
- {37.618573141236396395, 67.45775705171939762},
- {37.618573141236396395, 67.45775705171939762},
- {37.618404162067207608, 67.45729839397444038},
- {37.618798446795324253, 67.45764439893994790},
- {37.618573141236396395, 67.45775705171939762},
- {37.618798446795324253, 67.45764439893994790},
- {37.618803811213410881, 67.45794212414281787},
- {37.618803811213410881, 67.45794212414281787},
- {37.618798446795324253, 67.45764439893994790},
- {37.618884277484454515, 67.4577195007929049},
- {37.618884277484454515, 67.4577195007929049},
- {37.618798446795324253, 67.45764439893994790},
- {37.618809175631469088, 67.45762830568574486},
- {37.618884277484454515, 67.4577195007929049},
- {37.618809175631469088, 67.45762830568574486},
- {37.618897688529614243, 67.45770340753870186},
- {37.618803811213410881, 67.45794212414281787},
- {37.618884277484454515, 67.4577195007929049},
- {37.618945968292251791, 67.45777046276458577},
- {37.618803811213410881, 67.457942124142817875},
- {37.618945968292251791, 67.457770462764585773},
- {37.618857455394106637, 67.457987721696412109},
- {37.618857455394106637, 67.457987721696412109},
- {37.618945968292251791, 67.457770462764585773},
- {37.619031798981353631, 67.457842882408527885},
- {37.619031798981353631, 67.457842882408527885},
- {37.618945968292251791, 67.457770462764585773},
- {37.618959379337411519, 67.457757051719397623},
- {37.619031798981353631, 67.457842882408527885},
- {37.618959379337411519, 67.457757051719397623},
- {37.619045210026541781, 67.457829471363339735},
- {37.618857455394106637, 67.457987721696412109},
- {37.619031798981353631, 67.457842882408527885},
- {37.619045210026541781, 67.45833640887093452},
- {37.619045210026541781, 67.45833640887093452},
- {37.619031798981353631, 67.457842882408527885},
- {37.619372439528802943, 67.458132560984296333},
- {37.619045210026541781, 67.45833640887093452},
- {37.619372439528802943, 67.458132560984296333},
- {37.619549465325093252, 67.45828008248119545},
- {37.619549465325093252, 67.45828008248119545},
- {37.619372439528802943, 67.458132560984296333},
- {37.619385850573962671, 67.458116467730064869},
- {37.619549465325093252, 67.45828008248119545},
- {37.619385850573962671, 67.458116467730064869},
- {37.619560194161238087, 67.458266671436035722},
- {37.619045210026541781, 67.45833640887093452},
- {37.619549465325093252, 67.45828008248119545},
- {37.619600427296774114, 67.458368595379369026},
- {37.619600427296774114, 67.458368595379369026},
- {37.619549465325093252, 67.45828008248119545},
- {37.619603109505789007, 67.458325680034789684},
- {37.619045210026541781, 67.45833640887093452},
- {37.619600427296774114, 67.458368595379369026},
- {37.619592380669644172, 67.458626087446702968},
- {37.619592380669644172, 67.458626087446702968},
- {37.619600427296774114, 67.458368595379369026},
- {37.61969698682202079, 67.458502705831108415},
- {37.61969698682202079, 67.458502705831108415},
- {37.619600427296774114, 67.458368595379369026},
- {37.619691622403934161, 67.45845710827751418},
- {37.619691622403934161, 67.45845710827751418},
- {37.619600427296774114, 67.458368595379369026},
- {37.619675529149731119, 67.458416875141978153},
- {37.619675529149731119, 67.458416875141978153},
- {37.619600427296774114, 67.458368595379369026},
- {37.619643342641325034, 67.458384688633572068},
- {37.619592380669644172, 67.458626087446702968},
- {37.61969698682202079, 67.458502705831108415},
- {37.619635296014223513, 67.458607311983456611},
- {37.619635296014223513, 67.458607311983456611},
- {37.61969698682202079, 67.458502705831108415},
- {37.619688940194919269, 67.458545621175659335},
- {37.619635296014223513, 67.458607311983456611},
- {37.619688940194919269, 67.458545621175659335},
- {37.619670164731672912, 67.458580489893108734},
- {37.619045210026541781, 67.45833640887093452},
- {37.619592380669644172, 67.458626087446702968},
- {37.619061303280744823, 67.458695824881601766},
- {37.619061303280744823, 67.458695824881601766},
- {37.619592380669644172, 67.458626087446702968},
- {37.619549465325093252, 67.458714600344848122},
- {37.619549465325093252, 67.458714600344848122},
- {37.619592380669644172, 67.458626087446702968},
- {37.619589698460629279, 67.458677049418355409},
- {37.619061303280744823, 67.458695824881601766},
- {37.619549465325093252, 67.458714600344848122},
- {37.619383168364947778, 67.458864804050818975},
- {37.619383168364947778, 67.458864804050818975},
- {37.619549465325093252, 67.458714600344848122},
- {37.619560194161238087, 67.458728011390036272},
- {37.619383168364947778, 67.458864804050818975},
- {37.619560194161238087, 67.458728011390036272},
- {37.619396579410107506, 67.458878215095978703},
- {37.619061303280744823, 67.458695824881601766},
- {37.619383168364947778, 67.458864804050818975},
- {37.619058621071729931, 67.459165211462703837},
- {37.619061303280744823, 67.458695824881601766},
- {37.619058621071729931, 67.459165211462703837},
- {37.618876230857352994, 67.459036465429051077},
- {37.618876230857352994, 67.459036465429051077},
- {37.619058621071729931, 67.459165211462703837},
- {37.618967425964541462, 67.459251042151834099},
- {37.618967425964541462, 67.459251042151834099},
- {37.619058621071729931, 67.459165211462703837},
- {37.619069349907846345, 67.459181304716935301},
- {37.618967425964541462, 67.459251042151834099},
- {37.619069349907846345, 67.459181304716935301},
- {37.618978154800657876, 67.459267135406037141},
- {37.618876230857352994, 67.459036465429051077},
- {37.618967425964541462, 67.459251042151834099},
- {37.618916463992860599, 67.459296639705428333},
- {37.618876230857352994, 67.459036465429051077},
- {37.618916463992860599, 67.459296639705428333},
- {37.61883867993086028, 67.459074016355515369},
- {37.61883867993086028, 67.459074016355515369},
- {37.618916463992860599, 67.459296639705428333},
- {37.618833315512773652, 67.45937174155841376},
- {37.618833315512773652, 67.45937174155841376},
- {37.618916463992860599, 67.459296639705428333},
- {37.618849408767005116, 67.459385152603573488},
- {37.618849408767005116, 67.459385152603573488},
- {37.618916463992860599, 67.459296639705428333},
- {37.618927192829005435, 67.459312732959631376},
- {37.61883867993086028, 67.459074016355515369},
- {37.618833315512773652, 67.45937174155841376},
- {37.618610692162889109, 67.45927249982412377},
- {37.618610692162889109, 67.45927249982412377},
- {37.618833315512773652, 67.45937174155841376},
- {37.61846317066596157, 67.459715064314877964},
- {37.618610692162889109, 67.45927249982412377},
- {37.61846317066596157, 67.459715064314877964},
- {37.618243229525120341, 67.459615822580587974},
- {37.618243229525120341, 67.459615822580587974},
- {37.61846317066596157, 67.459715064314877964},
- {37.618283462660627947, 67.459881361275023437},
- {37.618283462660627947, 67.459881361275023437},
- {37.61846317066596157, 67.459715064314877964},
- {37.61847658171114972, 67.459731157569081006},
- {37.618283462660627947, 67.459881361275023437},
- {37.61847658171114972, 67.459731157569081006},
- {37.618296873705816097, 67.459897454529226479},
- {37.618243229525120341, 67.459615822580587974},
- {37.618283462660627947, 67.459881361275023437},
- {37.618211043016685835, 67.459905501156328},
- {37.618211043016685835, 67.459905501156328},
- {37.618283462660627947, 67.459881361275023437},
- {37.618240547316077027, 67.45991891220151615},
- {37.618243229525120341, 67.459615822580587974},
- {37.618211043016685835, 67.459905501156328},
- {37.618181538717323065, 67.459916229992472836},
- {37.618243229525120341, 67.459615822580587974},
- {37.618181538717323065, 67.459916229992472836},
- {37.617977690830656456, 67.459825034885284367},
- {37.618243229525120341, 67.459615822580587974},
- {37.617977690830656456, 67.459825034885284367},
- {37.618152034417931873, 67.459575589445051946},
- {37.618152034417931873, 67.459575589445051946},
- {37.617977690830656456, 67.459825034885284367},
- {37.617932093277062222, 67.459495123174008313},
- {37.617932093277062222, 67.459495123174008313},
- {37.617977690830656456, 67.459825034885284367},
- {37.617969644203554935, 67.459795530585921597},
- {37.617932093277062222, 67.459495123174008313},
- {37.617969644203554935, 67.459795530585921597},
- {37.617940139904163743, 67.459739204196182527},
- {37.617940139904163743, 67.459739204196182527},
- {37.617969644203554935, 67.459795530585921597},
- {37.617940139904163743, 67.459784801749776761},
- {37.617932093277062222, 67.459495123174008313},
- {37.617940139904163743, 67.459739204196182527},
- {37.617918682231902494, 67.459733839778095899},
- {37.617932093277062222, 67.459495123174008313},
- {37.617918682231902494, 67.459733839778095899},
- {37.61791600002285918, 67.459497805383051627},
- {37.618152034417931873, 67.459575589445051946},
- {37.617932093277062222, 67.459495123174008313},
- {37.618143987790830352, 67.459170575880790466},
- {37.618143987790830352, 67.459170575880790466},
- {37.617932093277062222, 67.459495123174008313},
- {37.617913317813815866, 67.458652909537050846},
- {37.618143987790830352, 67.459170575880790466},
- {37.617913317813815866, 67.458652909537050846},
- {37.618106436864337638, 67.457987721696412109},
- {37.618143987790830352, 67.459170575880790466},
- {37.618106436864337638, 67.457987721696412109},
- {37.618176174299236436, 67.45875483348038415},
- {37.61883867993086028, 67.459074016355515369},
- {37.618610692162889109, 67.45927249982412377},
- {37.618583870072541231, 67.459208126807283179},
- {37.61883867993086028, 67.459074016355515369},
- {37.618583870072541231, 67.459208126807283179},
- {37.618299555914859411, 67.459071334146500476},
- {37.61883867993086028, 67.459074016355515369},
- {37.618299555914859411, 67.459071334146500476},
- {37.618176174299236436, 67.45875483348038415},
- {37.618176174299236436, 67.45875483348038415},
- {37.618299555914859411, 67.459071334146500476},
- {37.618143987790830352, 67.459170575880790466},
- {37.618143987790830352, 67.459170575880790466},
- {37.618299555914859411, 67.459071334146500476},
- {37.618213725225729149, 67.45920276238919655},
- {37.618213725225729149, 67.45920276238919655},
- {37.618299555914859411, 67.459071334146500476},
- {37.618302238123874304, 67.459157164835602316},
- {37.619061303280744823, 67.458695824881601766},
- {37.618876230857352994, 67.459036465429051077},
- {37.618790400168222732, 67.45893990590377598},
- {37.619045210026541781, 67.45833640887093452},
- {37.619061303280744823, 67.458695824881601766},
- {37.618999612472947547, 67.458639498491891118},
- {37.619045210026541781, 67.45833640887093452},
- {37.618999612472947547, 67.458639498491891118},
- {37.618988883636802711, 67.458398099678731796},
- {37.618988883636802711, 67.458398099678731796},
- {37.618999612472947547, 67.458639498491891118},
- {37.618964743755498148, 67.458561714429862377},
- {37.618988883636802711, 67.458398099678731796},
- {37.618964743755498148, 67.458561714429862377},
- {37.618959379337411519, 67.45847856594977543},
- {37.618857455394106637, 67.457987721696412109},
- {37.619045210026541781, 67.45833640887093452},
- {37.618763578077874854, 67.458097692266846934},
- {37.618573141236396395, 67.457757051719397623},
- {37.618803811213410881, 67.457942124142817875},
- {37.618535590309903682, 67.45785361124467272},
- {37.618535590309903682, 67.45785361124467272},
- {37.618803811213410881, 67.457942124142817875},
- {37.618168127672134915, 67.458301540153485121},
- {37.618535590309903682, 67.45785361124467272},
- {37.618168127672134915, 67.458301540153485121},
- {37.61822177185283067, 67.458030637040963029},
- {37.61822177185283067, 67.458030637040963029},
- {37.618168127672134915, 67.458301540153485121},
- {37.618106436864337638, 67.457987721696412109},
- {37.618106436864337638, 67.457987721696412109},
- {37.618168127672134915, 67.458301540153485121},
- {37.618176174299236436, 67.45875483348038415},
- {37.61823518289801882, 67.457153554686556163},
- {37.618205678598627628, 67.457445915471367925},
- {37.618160081045033394, 67.457148190268497956},
- {37.618160081045033394, 67.457148190268497956},
- {37.618205678598627628, 67.457445915471367925},
- {37.617934775486105536, 67.457258160838904359},
- {37.617934775486105536, 67.457258160838904359},
- {37.618205678598627628, 67.457445915471367925},
- {37.618093025819149489, 67.457499559652063681},
- {37.617934775486105536, 67.457258160838904359},
- {37.618093025819149489, 67.457499559652063681},
- {37.617883813514453095, 67.4573359449009331},
- {37.617883813514453095, 67.4573359449009331},
- {37.618093025819149489, 67.457499559652063681},
- {37.617889177932511302, 67.457571979296005793},
- {37.617889177932511302, 67.457571979296005793},
- {37.618093025819149489, 67.457499559652063681},
- {37.618106436864337638, 67.457987721696412109},
- {37.617889177932511302, 67.457571979296005793},
- {37.618106436864337638, 67.457987721696412109},
- {37.617910635604800973, 67.458441015023311138},
- {37.617910635604800973, 67.458441015023311138},
- {37.618106436864337638, 67.457987721696412109},
- {37.617913317813815866, 67.458652909537050846},
- {37.617910635604800973, 67.458441015023311138},
- {37.617913317813815866, 67.458652909537050846},
- {37.617897224559612823, 67.458652909537050846},
- {37.617910635604800973, 67.458441015023311138},
- {37.617897224559612823, 67.458652909537050846},
- {37.617891860141554616, 67.458441015023311138},
- {37.617883813514453095, 67.4573359449009331},
- {37.617889177932511302, 67.457571979296005793},
- {37.617875766887323152, 67.457569297086962479},
- {37.617883813514453095, 67.4573359449009331},
- {37.617875766887323152, 67.457569297086962479},
- {37.617870402469264945, 67.4573359449009331},
- {37.617934775486105536, 67.457258160838904359},
- {37.617883813514453095, 67.4573359449009331},
- {37.617883813514453095, 67.457284982929280659},
- {37.618160081045033394, 67.457148190268497956},
- {37.617934775486105536, 67.457258160838904359},
- {37.618152034417931873, 67.457134779223309806},
- {37.618152034417931873, 67.457134779223309806},
- {37.617934775486105536, 67.457258160838904359},
- {37.617926728859004015, 67.457242067584701317},
- {37.61823518289801882, 67.457153554686556163},
- {37.618160081045033394, 67.457148190268497956},
- {37.618194949762482793, 67.457132097014266492}
+ {37.539920043497688, 67.533792313440074},
+ {37.539477479006933, 67.533234413960827},
+ {37.541207503834414, 67.532770391797811},
+ {37.539477479006933, 67.533234413960827},
+ {37.541207503834414, 67.532770391797811},
+ {37.54076493934366, 67.532212492318536}
};
- auto const matched = osm::GetBestOsmWayOrRelation(osmResponse, geometry);
- TEST_EQUAL(matched.attribute("id").value(), string("1359233"), ());
+ auto const bestWay = osm::GetBestOsmWayOrRelation(osmResponse, geometry);
+ TEST_EQUAL(bestWay.attribute("id").value(), string("26232961"), ());
}
} // namespace
diff --git a/editor/osm_feature_matcher.cpp b/editor/osm_feature_matcher.cpp
index e74fede6a1..159c59ad88 100644
--- a/editor/osm_feature_matcher.cpp
+++ b/editor/osm_feature_matcher.cpp
@@ -20,59 +20,27 @@ namespace
namespace bg = boost::geometry;
// Use simple xy coordinates because spherical are not supported by boost::geometry algorithms.
-using SimplePoint = bg::model::d2::point_xy;
-using Polygon = bg::model::polygon;
+using PointXY = bg::model::d2::point_xy;
+using Polygon = bg::model::polygon;
using MultiPolygon = bg::model::multi_polygon;
-using Linestring = bg::model::linestring;
+using Linestring = bg::model::linestring;
using MultiLinestring = bg::model::multi_linestring;
using AreaType = bg::default_area_result::type;
using ForEachRefFn = function;
using ForEachWayFn = function;
-const double kPointDiffEps = 1e-5;
-const double kPenaltyScore = -1;
-
-AreaType Area(Polygon const & polygon)
-{
- AreaType innerArea = 0.0;
- for (auto const & inn : polygon.inners())
- {
- innerArea += bg::area(inn);
- }
-
- return bg::area(polygon.outer()) - innerArea;
-}
-
-AreaType Area(MultiPolygon const & multipolygon)
-{
- AreaType result = 0.0;
- for (auto const & polygon : multipolygon)
- {
- result += Area(polygon);
- }
-
- return result;
-}
+double const kPointDiffEps = 1e-5;
+double const kPenaltyScore = -1;
AreaType IntersectionArea(MultiPolygon const & our, Polygon const & their)
{
- AreaType intersectionArea = 0.0;
- MultiPolygon tmp;
- for (auto const & triangle : our)
- {
- bg::intersection(triangle, their.outer(), tmp);
- intersectionArea += bg::area(tmp);
- tmp.clear();
- for (auto const & inn : their.inners())
- {
- bg::intersection(triangle, inn, tmp);
- intersectionArea -= bg::area(tmp);
- tmp.clear();
- }
- }
+ ASSERT(bg::is_valid(our), ());
+ ASSERT(bg::is_valid(their), ());
- return intersectionArea;
+ MultiPolygon result;
+ bg::intersection(our, their, result);
+ return bg::area(result);
}
void AddInnerIfNeeded(pugi::xml_document const & osmResponse, pugi::xml_node const & way,
@@ -101,7 +69,7 @@ void AddInnerIfNeeded(pugi::xml_document const & osmResponse, pugi::xml_node con
void MakeOuterRing(MultiLinestring & outerLines, Polygon & dest)
{
- bool needReverse =
+ bool const needReverse =
outerLines.size() > 1 && bg::equals(outerLines[0].front(), outerLines[1].back());
for (size_t i = 0; i < outerLines.size(); ++i)
@@ -113,44 +81,21 @@ void MakeOuterRing(MultiLinestring & outerLines, Polygon & dest)
}
}
-void CorrectPolygon(Polygon & dest)
+double MatchByGeometry(MultiPolygon const & our, Polygon const & their)
{
- bg::correct(dest.outer());
-
- for (auto & inn : dest.inners())
- {
- bg::correct(inn);
- }
-}
-
-double
-MatchByGeometry(MultiPolygon const & our, Polygon const & their)
-{
- if (!bg::is_valid(their.outer()))
+ if (!bg::is_valid(our) || !bg::is_valid(their))
return kPenaltyScore;
- for (auto const & inn : their.inners())
- {
- if (!bg::is_valid(inn))
- return kPenaltyScore;
- }
-
- for (auto const & t : our)
- {
- if (!bg::is_valid(t))
- return kPenaltyScore;
- }
-
- auto const ourArea = Area(our);
- auto const theirArea = Area(their);
+ auto const ourArea = bg::area(our);
+ auto const theirArea = bg::area(their);
auto const intersectionArea = IntersectionArea(our, their);
- auto const overlayArea = ourArea + theirArea - intersectionArea;
+ auto const unionArea = ourArea + theirArea - intersectionArea;
// Avoid infinity.
- if(overlayArea == 0.0)
+ if (my::AlmostEqualAbs(unionArea, 0.0, 1e-18))
return kPenaltyScore;
- auto const score = intersectionArea / overlayArea;
+ auto const score = intersectionArea / unionArea;
// If area of the intersection is a half of the object area, penalty score will be returned.
if (score <= 0.5)
@@ -159,24 +104,33 @@ MatchByGeometry(MultiPolygon const & our, Polygon const & their)
return score;
}
-MultiPolygon TriangelsToPolygons(vector const & triangels)
+MultiPolygon TriangelsToPolygon(vector const & points)
{
size_t const kTriangleSize = 3;
- CHECK_GREATER_OR_EQUAL(triangels.size(), kTriangleSize, ());
-
- MultiPolygon result;
- Polygon triangle;
- for (size_t i = 0; i < triangels.size(); ++i)
+ CHECK_EQUAL(points.size() % kTriangleSize, 0, ());
+ CHECK(!points.empty(), ());
+ vector polygons;
+ for (size_t i = 0; i < points.size(); i += kTriangleSize)
{
- if (i % kTriangleSize == 0)
- result.emplace_back();
-
- bg::append(result.back(), boost::make_tuple(triangels[i].x, triangels[i].y));
-
- if ((i + 1) % kTriangleSize == 0)
- bg::correct(result.back());
+ MultiPolygon polygon;
+ polygon.resize(1);
+ auto & p = polygon[0];
+ auto & outer = p.outer();
+ for (size_t j = i; j < i + kTriangleSize; ++j)
+ outer.push_back(PointXY(points[j].x, points[j].y));
+ bg::correct(p);
+ ASSERT(bg::is_valid(polygon), ());
+ polygons.push_back(polygon);
}
+ CHECK(!polygons.empty(), ());
+ auto & result = polygons[0];
+ for (size_t i = 1; i < polygons.size(); ++i)
+ {
+ MultiPolygon u;
+ bg::union_(result, polygons[i], u);
+ u.swap(result);
+ }
return result;
}
@@ -213,25 +167,40 @@ void ForEachWayInRelation(pugi::xml_document const & osmResponse, pugi::xml_node
auto const way = osmResponse.select_node(xpath.c_str()).node();
auto const rolePath = "member[@ref='" + wayRef + "']/@role";
- pugi::xpath_node role = relation.select_node(rolePath.c_str());
+ pugi::xpath_node roleNode = relation.select_node(rolePath.c_str());
- // Some ways can be missed from relation and
- // we need to understand role of the way (inner/outer).
- if (!way || (!role && nodesSet.size() != 1))
+ // It is possible to have a wayRef that refers to a way not included in a given relation.
+ // We can skip such ways.
+ if (!way)
continue;
- fn(way, role.attribute().value());
+ // If more than one way is given and there is one with no role specified,
+ // it's an error. We skip this particular way but try to use others anyway.
+ if (!roleNode && nodesSet.size() != 1)
+ continue;
+
+ string role = "outer";
+ if (roleNode)
+ role = roleNode.attribute().value();
+
+ fn(way, role);
}
}
+template
+void AppendWay(pugi::xml_document const & osmResponse, pugi::xml_node const & way, Geometry & dest)
+{
+ ForEachRefInWay(osmResponse, way, [&dest](XMLFeature const & xmlFt)
+ {
+ auto const & p = xmlFt.GetMercatorCenter();
+ bg::append(dest, boost::make_tuple(p.x, p.y));
+ });
+}
+
Polygon GetWaysGeometry(pugi::xml_document const & osmResponse, pugi::xml_node const & way)
{
Polygon result;
- ForEachRefInWay(osmResponse, way, [&result](XMLFeature const & xmlFt)
- {
- auto const & p = xmlFt.GetMercatorCenter();
- bg::append(result, boost::make_tuple(p.x, p.y));
- });
+ AppendWay(osmResponse, way, result);
bg::correct(result);
@@ -250,11 +219,7 @@ Polygon GetRelationsGeometry(pugi::xml_document const & osmResponse,
if (role == "outer")
{
outerLines.emplace_back();
- ForEachRefInWay(osmResponse, way, [&outerLines](XMLFeature const & xmlFt)
- {
- auto const & p = xmlFt.GetMercatorCenter();
- bg::append(outerLines.back(), boost::make_tuple(p.x, p.y));
- });
+ AppendWay(osmResponse, way, outerLines.back());
}
else if (role == "inner")
{
@@ -263,19 +228,14 @@ Polygon GetRelationsGeometry(pugi::xml_document const & osmResponse,
// Support several inner rings.
AddInnerIfNeeded(osmResponse, way, result);
-
- ForEachRefInWay(osmResponse, way, [&result](XMLFeature const & xmlFt)
- {
- auto const & p = xmlFt.GetMercatorCenter();
- bg::append(result.inners().back(), boost::make_tuple(p.x, p.y));
- });
+ AppendWay(osmResponse, way, result.inners().back());
}
};
ForEachWayInRelation(osmResponse, relation, fn);
MakeOuterRing(outerLines, result);
- CorrectPolygon(result);
+ bg::correct(result);
return result;
}
@@ -302,7 +262,7 @@ double ScoreGeometry(pugi::xml_document const & osmResponse,
if (bg::is_empty(their))
return kPenaltyScore;
- auto const our = TriangelsToPolygons(ourGeometry);
+ auto const our = TriangelsToPolygon(ourGeometry);
if (bg::is_empty(our))
return kPenaltyScore;