diff --git a/generator/CMakeLists.txt b/generator/CMakeLists.txt index 1a48ee444c..4e65f3edab 100644 --- a/generator/CMakeLists.txt +++ b/generator/CMakeLists.txt @@ -127,8 +127,6 @@ set( osm_o5m_source.hpp osm_source.cpp osm_xml_source.hpp - place.cpp - place.hpp place_node.hpp place_processor.cpp place_processor.hpp diff --git a/generator/final_processor_intermediate_mwm.cpp b/generator/final_processor_intermediate_mwm.cpp index 2c2705acee..6a8858a160 100644 --- a/generator/final_processor_intermediate_mwm.cpp +++ b/generator/final_processor_intermediate_mwm.cpp @@ -139,21 +139,18 @@ public: static bool IsPlace(FeatureBuilder const & fb) { auto const type = GetPlaceType(fb); - return type != ftype::GetEmptyValue() && !fb.GetName().empty(); + return type != ftype::GetEmptyValue() && !fb.GetName().empty() && NeedProcessPlace(fb); } bool Process(FeatureBuilder const & fb) { - if (!IsPlace(fb)) - return false; - - m_processor.TryUpdate(fb); + m_processor.Add(fb); return true; } - std::vector GetFeatures() const + std::vector GetFeatures() { - return m_processor.GetFeatures(); + return m_processor.ProcessPlaces(); } std::shared_ptr GetTable() const diff --git a/generator/generator_integration_tests/features_tests.cpp b/generator/generator_integration_tests/features_tests.cpp index 016d336cf4..a2561a2f0c 100644 --- a/generator/generator_integration_tests/features_tests.cpp +++ b/generator/generator_integration_tests/features_tests.cpp @@ -127,17 +127,17 @@ public: rawGenerator.GenerateCountries(); TEST(rawGenerator.Execute(), ()); - TestCountry(northAuckland, 1811971 /* fbsCnt */, 12195948 /* pointsCnt */, 1007372 /* pointCnt */, - 205469 /* lineCnt */, 599130 /* areaCnt */, 212087 /* poiCnt */, + TestCountry(northAuckland, 1811963 /* fbsCnt */, 12195155 /* pointsCnt */, 1007377 /* pointCnt */, + 205469 /* lineCnt */, 599117 /* areaCnt */, 212086 /* poiCnt */, 521 /* cityTownOrVillageCnt */, 3557 /* bookingHotelsCnt */); - TestCountry(northWellington, 797778 /* fbsCnt */, 7772270 /* pointsCnt */, 460446 /* pointCnt */, - 87058 /* lineCnt */, 250274 /* areaCnt */, 95651 /* poiCnt */, + TestCountry(northWellington, 797790 /* fbsCnt */, 7772135 /* pointsCnt */, 460460 /* pointCnt */, + 87058 /* lineCnt */, 250272 /* areaCnt */, 95650 /* poiCnt */, 297 /* cityTownOrVillageCnt */, 1062 /* bookingHotelsCnt */); - TestCountry(southCanterbury, 636934 /* fbsCnt */, 6984360 /* pointsCnt */, 397634 /* pointCnt */, - 81712 /* lineCnt */, 157588 /* areaCnt */, 89249 /* poiCnt */, + TestCountry(southCanterbury, 636992 /* fbsCnt */, 6984268 /* pointsCnt */, 397694 /* pointCnt */, + 81712 /* lineCnt */, 157586 /* areaCnt */, 89249 /* poiCnt */, 331 /* cityTownOrVillageCnt */, 2085 /* bookingHotelsCnt */); - TestCountry(southSouthland, 340491 /* fbsCnt */, 5342804 /* pointsCnt */, 185845 /* pointCnt */, - 40124 /* lineCnt */, 114522 /* areaCnt */, 40497 /* poiCnt */, + TestCountry(southSouthland, 340492 /* fbsCnt */, 5342793 /* pointsCnt */, 185847 /* pointCnt */, + 40124 /* lineCnt */, 114521 /* areaCnt */, 40497 /* poiCnt */, 297 /* cityTownOrVillageCnt */, 1621 /* bookingHotelsCnt */); } @@ -169,7 +169,7 @@ public: TestGeneratedFile(metalines, 288032 /* fileSize */); TestGeneratedFile(restrictions, 273283 /* fileSize */); TestGeneratedFile(roadAccess, 1918315 /* fileSize */); - TestGeneratedFile(m_genInfo.m_citiesBoundariesFilename, 2435 /* fileSize */); + TestGeneratedFile(m_genInfo.m_citiesBoundariesFilename, 87 /* fileSize */); } void BuildWorldOneThread() diff --git a/generator/generator_tests/CMakeLists.txt b/generator/generator_tests/CMakeLists.txt index 57175aed14..accfd146fb 100644 --- a/generator/generator_tests/CMakeLists.txt +++ b/generator/generator_tests/CMakeLists.txt @@ -28,6 +28,7 @@ set( osm2meta_test.cpp osm_o5m_source_test.cpp osm_type_test.cpp + place_processor_tests.cpp popularity_builder_tests.cpp region_info_collector_tests.cpp regions_tests.cpp diff --git a/generator/generator_tests/place_processor_tests.cpp b/generator/generator_tests/place_processor_tests.cpp new file mode 100644 index 0000000000..1526367be0 --- /dev/null +++ b/generator/generator_tests/place_processor_tests.cpp @@ -0,0 +1,1385 @@ +#include "testing/testing.hpp" + +#include "generator/cities_boundaries_builder.hpp" +#include "generator/feature_builder.hpp" +#include "generator/feature_maker_base.hpp" +#include "generator/generator_tests/common.hpp" +#include "generator/osm2type.hpp" +#include "generator/osm_element.hpp" +#include "generator/place_processor.hpp" + +#include "indexer/classificator_loader.hpp" + +#include "geometry/point2d.hpp" + +#include +#include +#include +#include +#include +#include +#include + +namespace +{ +using namespace generator_tests; + +class IdGenerator +{ +public: + friend IdGenerator & GetIdGen(); + + void StopInc() { m_isInc = false; } + void StartInc() { m_isInc = true; } + uint64_t GetId() { return m_isInc ? m_id++ : m_id; } + +private: + IdGenerator() = default; + + uint64_t m_id = 0; + bool m_isInc = true; +}; + +IdGenerator & GetIdGen() +{ + static IdGenerator idGenerator; + return idGenerator; +} + +struct DisablerIdInc +{ + DisablerIdInc() { GetIdGen().StopInc(); } + ~DisablerIdInc() { GetIdGen().StartInc(); } +}; + +feature::FeatureBuilder MakeFbForTest(Tags const & tags, OsmElement::EntityType t, + std::vector const & points) +{ + auto element = MakeOsmElement(GetIdGen().GetId(), tags, t); + feature::FeatureBuilder result; + ftype::GetNameAndType(&element, result.GetParams()); + if (element.IsNode()) + { + CHECK_EQUAL(points.size(), 1, ()); + result.SetOsmId(base::MakeOsmNode(element.m_id)); + result.SetCenter(points.front()); + } + else if (element.IsRelation() || element.IsWay()) + { + for (auto const & p : points) + result.AddPoint(p); + + CHECK(result.IsGeometryClosed(), ()); + + result.SetArea(); + + result.SetOsmId(element.IsRelation() ? base::MakeOsmRelation(element.m_id) + : base::MakeOsmWay(element.m_id)); + } + return result; +} + +bool TestTable(generator::OsmIdToBoundariesTable & table, + std::set, size_t>> const & answer) +{ + bool result = true; + table.ForEachCluster([&](auto & ids, auto const & boundaries) { + if (!result) + return; + + std::sort(std::begin(ids), std::end(ids)); + if (!answer.count(std::make_pair(ids, boundaries.size()))) + result = false; + }); + return result; +} + +struct Loader +{ + Loader() { classificator::Load(); } +}; + +feature::FeatureBuilder MakeArea() +{ + return MakeFbForTest({{"name", "City"}, {"place", "city"}}, OsmElement::EntityType::Relation, + {{172.54302978515625, -43.48331750944707}, + {172.59796142578125, -43.572929222492384}, + {172.67898559570312, -43.55302701392868}, + {172.67967224121094, -43.48680489735276}, + {172.62542724609375, -43.4509250075837}, + {172.54302978515625, -43.48331750944707}}); +} +} // namespace + +namespace generator_tests +{ +class TestPlaceProcessor +{ +public: + TestPlaceProcessor() : kArea(MakeArea()) {} + +protected: + Loader m_loader; + feature::FeatureBuilder const kArea; +}; +} // namespace generator_tests + +namespace +{ +using namespace generator_tests; + +UNIT_CLASS_TEST(TestPlaceProcessor, EmptyTest) +{ + generator::PlaceProcessor pp; + TEST_EQUAL(pp.ProcessPlaces(), std::vector(), ()); +} + +UNIT_CLASS_TEST(TestPlaceProcessor, OnePlacePointTest) +{ + auto const point = + MakeFbForTest({{"name", "City"}, {"place", "city"}}, OsmElement::EntityType::Node, + {{172.6314353942871, -43.493592271503786}}); + + auto table = std::make_shared(); + generator::PlaceProcessor pp(table); + pp.Add(point); + + std::vector r{point}; + TEST_EQUAL(pp.ProcessPlaces(), r, ()); + TEST(TestTable(*table, {}), ()); +} + +UNIT_CLASS_TEST(TestPlaceProcessor, OnePlaceAreaTest) +{ + auto table = std::make_shared(); + generator::PlaceProcessor pp(table); + pp.Add(kArea); + + std::vector r{generator::MakePointFromArea(kArea)}; + TEST_EQUAL(pp.ProcessPlaces(), r, ()); + TEST(TestTable(*table, {{{kArea.GetMostGenericOsmId()}, 1 /* cluster size */}}), ()); +} + +UNIT_CLASS_TEST(TestPlaceProcessor, PointInAreaTest) +{ + auto const point = + MakeFbForTest({{"name", "City"}, {"place", "city"}}, OsmElement::EntityType::Node, + {{172.6314353942871, -43.493592271503786}}); + + auto table = std::make_shared(); + generator::PlaceProcessor pp(table); + pp.Add(kArea); + pp.Add(point); + + std::vector r{point}; + TEST_EQUAL(pp.ProcessPlaces(), r, ()); + TEST(TestTable(*table, {{{point.GetMostGenericOsmId(), kArea.GetMostGenericOsmId()}, + 1 /* cluster size */}}), + ()); +} + +UNIT_CLASS_TEST(TestPlaceProcessor, SameNamesButDifferentPlacesTest) +{ + auto const point = + MakeFbForTest({{"name", "City"}, {"place", "city"}}, OsmElement::EntityType::Node, + {{162.6314353942871, -33.493592271503786}}); + + auto table = std::make_shared(); + generator::PlaceProcessor pp(table); + pp.Add(kArea); + pp.Add(point); + + std::vector r{point, generator::MakePointFromArea(kArea)}; + TEST_EQUAL(pp.ProcessPlaces(), r, ()); + TEST(TestTable(*table, {{{kArea.GetMostGenericOsmId()}, 1 /* cluster size */}}), ()); +} + +UNIT_CLASS_TEST(TestPlaceProcessor, SelectBestPlaceTest) +{ + auto const point1 = + MakeFbForTest({{"name", "City"}, {"place", "city"}}, OsmElement::EntityType::Node, + {{162.6314353942871, -33.493592271503786}}); + auto const point2 = MakeFbForTest({{"name", "City"}, {"place", "city"}, {"capital", "yes"}}, + OsmElement::EntityType::Node, {{162.63145, -33.4935}}); + + auto table = std::make_shared(); + generator::PlaceProcessor pp(table); + pp.Add(point1); + pp.Add(point2); + + std::vector r{point2}; + TEST_EQUAL(pp.ProcessPlaces(), r, ()); + TEST(TestTable(*table, {}), ()); +} + +UNIT_CLASS_TEST(TestPlaceProcessor, MinskDuplicatingCityFeatureTest) +{ + DisablerIdInc _; + auto const point = MakeFbForTest({{"name", "Minsk"}, {"place", "city"}}, + OsmElement::EntityType::Node, {{27.5618791, 64.2446451}}); + auto const areaPart1 = + MakeFbForTest({{"name", "Minsk"}, {"place", "city"}}, OsmElement::EntityType::Relation, + {{27.5790063, 64.1120914}, {27.5784754, 64.1117773}, {27.5778736, 64.1115736}, + {27.5743208, 64.1120444}, {27.573191, 64.1122333}, {27.5719433, 64.1119701}, + {27.571246, 64.112019}, {27.569903, 64.1120173}, {27.5707767, 64.1099835}, + {27.5718565, 64.1087414}, {27.5726993, 64.107156}, {27.5736119, 64.1043859}, + {27.5745665, 64.1017513}, {27.5724517, 64.1011675}, {27.5710354, 64.1005165}, + {27.5707194, 64.0996702}, {27.5710228, 64.0988618}, {27.5711957, 64.0989266}, + {27.5715637, 64.0990645}, {27.5729855, 64.0993918}, {27.5745135, 64.0999526}, + {27.5761693, 64.0949134}, {27.5796809, 64.085857}, {27.5796809, 64.085857}, + {27.580791, 64.0829941}, {27.5817534, 64.082657}, {27.5849589, 64.0739962}, + {27.585002, 64.0739308}, {27.5851241, 64.0737943}, {27.5854864, 64.0729675}, + {27.5861187, 64.0722764}, {27.5862672, 64.0719171}, {27.5864032, 64.0719726}, + {27.5865382, 64.072362}, {27.5868224, 64.0733319}, {27.5869297, 64.0746477}, + {27.586944, 64.0751056}, {27.5872443, 64.0751953}, {27.587316, 64.0761062}, + {27.5900156, 64.0771223}, {27.5908338, 64.0774303}, {27.5931024, 64.0711907}, + {27.5896623, 64.0698257}, {27.588003, 64.0691672}, {27.5885434, 64.0679732}, + {27.5879939, 64.0658802}, {27.5898642, 64.0607462}, {27.5966143, 64.0631399}, + {27.594319, 64.0690363}, {27.5935288, 64.0710662}, {27.5993956, 64.073371}, + {27.5988336, 64.075121}, {27.5972786, 64.0794044}, {27.5987962, 64.0799919}, + {27.5990869, 64.0807793}, {27.5982678, 64.0816265}, {27.5982678, 64.0816265}, + {27.5989973, 64.0837186}, {27.5974631, 64.0850973}, {27.596692, 64.0862706}, + {27.596401, 64.0860951}, {27.5962937, 64.0863847}, {27.5964385, 64.0864626}, + {27.596004, 64.0877258}, {27.5957036, 64.0876454}, {27.5951779, 64.0890509}, + {27.5947756, 64.0891152}, {27.5942981, 64.0895229}, {27.5939655, 64.0903169}, + {27.5938195, 64.0907493}, {27.5934291, 64.0919047}, {27.5934291, 64.0919047}, + {27.5949049, 64.0941558}, {27.5930908, 64.0976205}, {27.5916048, 64.0993006}, + {27.5927009, 64.111637}, {27.5918564, 64.1136603}, {27.5886491, 64.1151372}, + {27.5830131, 64.1139277}, {27.5811056, 64.1133437}, {27.5805439, 64.1122604}, + {27.5799263, 64.1137374}, {27.5800188, 64.114277}, {27.5796146, 64.1153059}, + {27.5796146, 64.1153059}, {27.5777248, 64.1201135}, {27.5766019, 64.1232713}, + {27.5760196, 64.1259331}, {27.5783105, 64.1266668}, {27.5796115, 64.1268269}, + {27.5867366, 64.1269269}, {27.5915801, 64.1269669}, {27.5976646, 64.127107}, + {27.6006975, 64.1271347}, {27.6006975, 64.1271347}, {27.6016112, 64.127113}, + {27.6099881, 64.1271614}, {27.6197065, 64.1273292}, {27.6255501, 64.1274388}, + {27.6343077, 64.1276112}, {27.6387285, 64.1277442}, {27.6435823, 64.1280655}, + {27.6459949, 64.1285825}, {27.6488306, 64.1293659}, {27.6504286, 64.1300239}, + {27.6518542, 64.1306975}, {27.6550345, 64.1323268}, {27.6566638, 64.1333765}, + {27.6584028, 64.1346611}, {27.6609878, 64.1368074}, {27.6642151, 64.1409748}, + {27.6657034, 64.14345}, {27.6667961, 64.1453666}, {27.6678356, 64.146443}, + {27.6694454, 64.1446188}, {27.6709858, 64.1423145}, {27.6724826, 64.1392118}, + {27.674061, 64.1359523}, {27.6763772, 64.1348056}, {27.6773471, 64.132405}, + {27.6786234, 64.1303933}, {27.6790945, 64.128829}, {27.6789687, 64.1272843}, + {27.6776575, 64.1254244}, {27.6756971, 64.123183}, {27.6742241, 64.122398}, + {27.6728371, 64.1222226}, {27.6718316, 64.1217441}, {27.6688664, 64.1206873}, + {27.6653931, 64.1181658}, {27.6636934, 64.1168333}, {27.662918, 64.1162601}, + {27.6623113, 64.1158405}, {27.6612946, 64.1152265}, {27.6622247, 64.1140256}, + {27.6617275, 64.1136171}, {27.6604219, 64.1122188}, {27.6594334, 64.1101831}, + {27.6588195, 64.1083232}, {27.6583566, 64.105911}, {27.657752, 64.1034964}, + {27.6566508, 64.1012166}, {27.6563544, 64.1000893}, {27.6561391, 64.0995637}, + {27.6556586, 64.0985094}, {27.6551308, 64.0976763}, {27.6557134, 64.097588}, + {27.6566301, 64.0973165}, {27.657125, 64.0990466}, {27.6585211, 64.1024677}, + {27.6585845, 64.102674}, {27.6586793, 64.1027967}, {27.6588575, 64.1031756}, + {27.6587014, 64.103325}, {27.6592317, 64.1042446}, {27.6593918, 64.1044859}, + {27.6598459, 64.1056002}, {27.6602861, 64.1069493}, {27.6604254, 64.1076179}, + {27.6606504, 64.1084346}, {27.660871, 64.1089666}, {27.6610906, 64.1093371}, + {27.6612555, 64.1098993}, {27.6613085, 64.110345}, {27.6614282, 64.1105485}, + {27.661757, 64.1106793}, {27.6619723, 64.1109583}, {27.6616974, 64.1111211}, + {27.6619658, 64.1114161}, {27.6625648, 64.1122267}, {27.6630691, 64.1130747}, + {27.6637793, 64.1137616}, {27.6643437, 64.1140417}, {27.6649706, 64.1142555}, + {27.6659355, 64.1144625}, {27.6668255, 64.1152963}, {27.6672048, 64.1157274}, + {27.6672584, 64.1158557}, {27.6691796, 64.1138943}, {27.6656665, 64.1103955}, + {27.6666333, 64.1091951}, {27.6732495, 64.1023586}, {27.6737303, 64.1028324}, + {27.6754628, 64.1045834}, {27.6761743, 64.1054277}, {27.6767259, 64.1051479}, + {27.6775265, 64.1047293}, {27.6786778, 64.104164}, {27.6797698, 64.1036125}, + {27.6803258, 64.1032171}, {27.679862, 64.1026444}, {27.6791095, 64.1015216}, + {27.6782862, 64.1002807}, {27.6775339, 64.0991396}, {27.6772204, 64.0986868}, + {27.6765594, 64.097609}, {27.6758024, 64.0964815}, {27.6750387, 64.0953893}, + {27.6741807, 64.0940801}, {27.6739912, 64.0938627}, {27.6721369, 64.0908087}, + {27.6716126, 64.0898062}, {27.6714232, 64.0893327}, {27.6702468, 64.0861471}, + {27.6723409, 64.085184}, {27.6723822, 64.0859798}, {27.6728544, 64.0853669}, + {27.6735731, 64.0848934}, {27.6749882, 64.0842832}, {27.6785159, 64.0826356}, + {27.6805385, 64.0817193}, {27.681896, 64.081076}, {27.683364, 64.0806416}, + {27.6848898, 64.0802626}, {27.6857003, 64.0800064}, {27.6859753, 64.0799207}, + {27.6865126, 64.0797956}, {27.6868481, 64.0796474}, {27.6880818, 64.0793552}, + {27.6885919, 64.0793003}, {27.6894154, 64.0793694}, {27.6900974, 64.0795716}, + {27.6909374, 64.0799065}, {27.6937173, 64.0812177}, {27.6949423, 64.0821012}, + {27.6953086, 64.0825274}, {27.706443, 64.0957401}, {27.706924, 64.0964808}, + {27.7075435, 64.0978724}, {27.7078581, 64.0981338}, {27.7083924, 64.0974842}, + {27.7084259, 64.0974435}, {27.7129791, 64.1013387}, {27.7103062, 64.104691}, + {27.7090168, 64.106118}, {27.7081571, 64.1067142}, {27.7081571, 64.1067142}, + {27.7069504, 64.1086176}, {27.7070104, 64.1093596}, {27.7070222, 64.1095819}, + {27.7070217, 64.1097321}, {27.7070188, 64.110517}, {27.7068945, 64.1114195}, + {27.7066743, 64.1121424}, {27.7061421, 64.1136766}, {27.7019533, 64.1187426}, + {27.7001302, 64.120939}, {27.6977221, 64.1237644}, {27.7025345, 64.1216807}, + {27.7025322, 64.121668}, {27.7025962, 64.1217141}, {27.7028937, 64.1217533}, + {27.703265, 64.121699}, {27.7036732, 64.1215271}, {27.7049022, 64.1211726}, + {27.7053015, 64.1209561}, {27.7054986, 64.1208912}, {27.7058531, 64.1208891}, + {27.7060397, 64.1209435}, {27.7062228, 64.1210574}, {27.7063754, 64.1211887}, + {27.7065689, 64.1212838}, {27.7067047, 64.1213144}, {27.7068141, 64.1212936}, + {27.7068774, 64.1213131}, {27.7068802, 64.1213917}, {27.7069397, 64.1214235}, + {27.7071279, 64.1212031}, {27.7072539, 64.1211834}, {27.7076341, 64.1213744}, + {27.7077078, 64.1213693}, {27.7079182, 64.1211328}, {27.7081101, 64.1210882}, + {27.7088953, 64.1211218}, {27.7089484, 64.1212822}, {27.7094217, 64.1212304}, + {27.7094966, 64.121113}, {27.7098409, 64.1202648}, {27.710022, 64.1198669}, + {27.7103526, 64.1192848}, {27.7105106, 64.1193322}, {27.7114549, 64.1192417}, + {27.7127171, 64.1190411}, {27.7128822, 64.1189905}, {27.7137238, 64.1185681}, + {27.7140023, 64.1183768}, {27.7139264, 64.1186995}, {27.7137132, 64.1195552}, + {27.7127652, 64.121357}, {27.7149871, 64.1235437}, {27.7147154, 64.1252968}, + {27.7146113, 64.125885}, {27.7143333, 64.1262235}, {27.7140374, 64.1265706}, + {27.7139966, 64.1267949}, {27.7139451, 64.1273675}, {27.7140752, 64.1279309}, + {27.7141226, 64.1288453}, {27.7139633, 64.1304768}, {27.7141876, 64.1306953}, + {27.7143811, 64.1308322}, {27.7147454, 64.1310886}, {27.7151672, 64.1312931}, + {27.7157985, 64.1316925}, {27.7166563, 64.1322055}, {27.7167499, 64.1322592}, + {27.7168659, 64.1322911}, {27.7173297, 64.1323482}, {27.7175162, 64.1340771}, + {27.7175739, 64.1346587}, {27.7171692, 64.1349771}, {27.717173, 64.1359607}, + {27.7173009, 64.1364475}, {27.7176735, 64.1363512}, {27.7178825, 64.1361836}, + {27.7182456, 64.1357958}, {27.7187241, 64.1352554}, {27.7200957, 64.1354254}, + {27.7210731, 64.1355582}, {27.7223668, 64.1371366}, {27.7228698, 64.1376951}, + {27.7231108, 64.1379302}, {27.7232668, 64.1378017}, {27.7252083, 64.1362114}, + {27.7276317, 64.134114}, {27.7283747, 64.1335883}, {27.7289487, 64.1330464}, + {27.7337664, 64.1290722}, {27.734058, 64.1287967}, {27.7346197, 64.1283549}, + {27.7348437, 64.1282048}, {27.73621, 64.1270826}, {27.7390808, 64.1247029}, + {27.7416204, 64.1225895}, {27.7416204, 64.1225895}, {27.7428846, 64.1215374}, + {27.7438204, 64.1208049}, {27.7450154, 64.119771}, {27.7485272, 64.1168429}, + {27.7489219, 64.1165698}, {27.7538279, 64.112508}, {27.7556647, 64.1109448}, + {27.7568443, 64.1108565}, {27.7571339, 64.1107438}, {27.7575162, 64.1108541}, + {27.7611827, 64.1120454}, {27.7613512, 64.1118106}, {27.7654699, 64.1130357}, + {27.7658698, 64.1131526}, {27.769757, 64.1142965}, {27.7700829, 64.113812}, + {27.7704476, 64.1135544}, {27.7706515, 64.1134365}, {27.7708554, 64.1134579}, + {27.7716684, 64.1138977}, {27.7725002, 64.1126176}, {27.7728719, 64.1121869}, + {27.773273, 64.112069}, {27.7735503, 64.1122047}, {27.7736034, 64.1123934}, + {27.7737686, 64.1127887}, {27.7740399, 64.1128359}, {27.7743998, 64.1128359}, + {27.7753732, 64.1128005}, {27.7755207, 64.1128417}, {27.7775538, 64.1127929}, + {27.7820163, 64.1127819}, {27.7820828, 64.1161002}, {27.7821979, 64.1187024}, + {27.7821714, 64.1205701}, {27.7822783, 64.1226943}, {27.7824116, 64.1263974}, + {27.7825305, 64.1315365}, {27.7813495, 64.1343725}, {27.7824924, 64.137205}, + {27.7839429, 64.1381873}, {27.7900868, 64.1376704}, {27.797059, 64.1372931}, + {27.7954991, 64.1396299}, {27.7992867, 64.1406438}, {27.8055127, 64.1442693}, + {27.808292, 64.1446239}, {27.8096215, 64.1421139}, {27.8159196, 64.1468434}, + {27.8184363, 64.1640835}, {27.8114698, 64.1641767}, {27.8100663, 64.1666346}, + {27.8040602, 64.1683304}, {27.8038842, 64.1685194}, {27.8039515, 64.1686271}, + {27.8038846, 64.1687558}, {27.8029206, 64.1691507}, {27.8025217, 64.1692892}, + {27.8023778, 64.1689915}, {27.8000099, 64.1701163}, {27.799892, 64.1701694}, + {27.7988716, 64.1706629}, {27.7978753, 64.1711668}, {27.798187, 64.1716297}, + {27.7966091, 64.1722832}, {27.7962344, 64.1722071}, {27.7957522, 64.1726688}, + {27.7953646, 64.1728199}, {27.7960406, 64.1744721}, {27.7962229, 64.1754803}, + {27.7962447, 64.1761888}, {27.7957942, 64.179225}, {27.7938838, 64.1824656}, + {27.7853018, 64.1860278}, {27.7830162, 64.182466}, {27.7712706, 64.1825197}, + {27.7666045, 64.1817804}, {27.7606678, 64.1806654}, {27.7514843, 64.1778497}, + {27.7514843, 64.1778497}, {27.7542732, 64.1848931}, {27.7542958, 64.1887668}, + {27.7636481, 64.1938069}, {27.7661414, 64.1951506}, {27.7744556, 64.1992469}, + {27.8037779, 64.1962129}, {27.822109, 64.1943212}, {27.8223786, 64.1942934}, + {27.8229396, 64.1942549}, {27.8288841, 64.1936209}, {27.834522, 64.1962926}, + {27.8363869, 64.1967484}, {27.8380465, 64.1972467}, {27.8418781, 64.1978909}, + {27.8440867, 64.1983516}, {27.8448898, 64.1984269}, {27.845492, 64.1985421}, + {27.8490651, 64.19951}, {27.8490764, 64.2020847}, {27.849076, 64.2133097}, + {27.849076, 64.2133097}, {27.8490752, 64.2394614}, {27.8411286, 64.2394652}, + {27.8407892, 64.2437051}, {27.8407658, 64.244966}, {27.8401421, 64.2448082}, + {27.8342188, 64.2434143}, {27.8310969, 64.2444325}, {27.8295539, 64.2465681}, + {27.8257452, 64.2428466}, {27.8257452, 64.2428466}, {27.8225811, 64.2397581}, + {27.8211733, 64.2412038}, {27.8205506, 64.2415263}, {27.8178268, 64.2416005}, + {27.8160074, 64.2416093}, {27.8152722, 64.2416256}, {27.814393, 64.2416218}, + {27.8138525, 64.2416583}, {27.8133895, 64.2416862}, {27.8129275, 64.2417157}, + {27.8107502, 64.2417126}, {27.8078156, 64.2417227}, {27.8065559, 64.2417476}, + {27.8056565, 64.2417654}, {27.8042309, 64.2417673}, {27.7997037, 64.2417734}, + {27.7963986, 64.2417848}, {27.7927631, 64.2418143}, {27.7881526, 64.2405436}, + {27.7855233, 64.2406383}, {27.7855233, 64.2406383}, {27.7855239, 64.2387759}, + {27.7777893, 64.238686}, {27.7763832, 64.2386962}, {27.7756309, 64.2387228}, + {27.775657, 64.2403477}, {27.7755978, 64.2434296}, {27.7698104, 64.2466486}, + {27.7466028, 64.2626021}, {27.7465331, 64.2626476}, {27.7466813, 64.2628498}, + {27.7467357, 64.2629357}, {27.7468325, 64.2630963}, {27.7469803, 64.2633411}, + {27.7471429, 64.2636163}, {27.7460927, 64.2642666}, {27.7457064, 64.2636337}, + {27.7452988, 64.2638803}, {27.7452554, 64.2638274}, {27.7451378, 64.2638912}, + {27.745449, 64.2643955}, {27.7455904, 64.2646247}, {27.7482879, 64.2689987}, + {27.7486112, 64.269523}, {27.7520168, 64.2730108}, {27.7523283, 64.273376}, + {27.7521673, 64.2734607}, {27.7466382, 64.2756087}, {27.7451582, 64.2761443}, + {27.7449685, 64.2761939}, {27.7443515, 64.2764267}, {27.7430144, 64.2769044}, + {27.7427883, 64.2769888}, {27.7428608, 64.2771861}, {27.7490647, 64.2912875}, + {27.74914, 64.2914426}, {27.74914, 64.2914426}, {27.7266159, 64.2832695}, + {27.7260293, 64.2834597}, {27.7188974, 64.2860202}, {27.7192095, 64.2867528}, + {27.7191281, 64.2886115}, {27.7178257, 64.2909178}, {27.717066, 64.2914197}, + {27.7161977, 64.2923151}, {27.7157861, 64.293067}, {27.7157861, 64.293067}, + {27.7171356, 64.2933615}, {27.718199, 64.2935935}, {27.7184682, 64.2931993}, + {27.7200353, 64.293084}, {27.721343, 64.2932387}, {27.7248507, 64.2940129}, + {27.7252354, 64.2935596}, {27.7300102, 64.2956275}, {27.7296685, 64.296438}, + {27.7328781, 64.2972588}, {27.7317424, 64.3007683}, {27.7343281, 64.3011808}, + {27.7352797, 64.3008944}, {27.732789, 64.3094956}, {27.7348028, 64.3108377}, + {27.740326, 64.3099655}, {27.7424557, 64.3097756}, {27.743932, 64.3109682}, + {27.7447023, 64.3102681}, {27.7451738, 64.3103652}, {27.742925, 64.3217075}, + {27.742925, 64.3217075}, {27.7428779, 64.3219448}, {27.7414496, 64.3213423}, + {27.7398585, 64.3289334}, {27.7438485, 64.3285823}, {27.746351, 64.3322382}, + {27.746351, 64.3322382}, {27.7463197, 64.3348596}, {27.7443493, 64.3444394}, + {27.7435602, 64.3450193}, {27.7413923, 64.3454825}, {27.7387398, 64.3488098}, + {27.7387398, 64.3488098}, {27.7352518, 64.3459431}, {27.734151, 64.3473283}, + {27.7332464, 64.346638}, {27.7243513, 64.3398496}, {27.721461, 64.3418598}, + {27.7190346, 64.3428022}, {27.7061644, 64.3447548}, {27.6926371, 64.3446664}, + {27.6921613, 64.3399363}, {27.6909206, 64.3405439}, {27.6907246, 64.3404011}, + {27.6881222, 64.3398469}, {27.6862366, 64.3410704}, {27.6851743, 64.3392515}, + {27.6860439, 64.3385338}, {27.6852789, 64.3377748}, {27.6859596, 64.336847}, + {27.6864897, 64.3366602}, {27.6871162, 64.3374192}, {27.6879401, 64.3386789}, + {27.6897691, 64.3382816}, {27.6905179, 64.3346572}, {27.6864812, 64.333223}, + {27.6854689, 64.3330406}, {27.6833998, 64.3322689}, {27.6831325, 64.3321933}, + {27.6819822, 64.3315875}, {27.6819822, 64.3315875}, {27.6819384, 64.3314877}, + {27.6808903, 64.3309128}, {27.6804267, 64.3311713}, {27.6802575, 64.3308815}, + {27.6809418, 64.3301214}, {27.6803756, 64.3298339}, {27.6801149, 64.3303231}, + {27.6797427, 64.3310177}, {27.6789333, 64.3306028}, {27.6792999, 64.3299102}, + {27.6795621, 64.3293885}, {27.6749959, 64.3269301}, {27.674755, 64.3270364}, + {27.6746072, 64.3269765}, {27.673556, 64.3264114}, {27.6726572, 64.3259057}, + {27.6725242, 64.3258527}, {27.672389, 64.3260942}, {27.6721151, 64.3265244}, + {27.6720903, 64.3265605}, {27.6718322, 64.3270833}, {27.6720619, 64.3272475}, + {27.6718461, 64.3275945}, {27.6720679, 64.3278232}, {27.6720336, 64.3278822}, + {27.6720469, 64.3278942}, {27.6722227, 64.3280283}, {27.672413, 64.328122}, + {27.6725501, 64.3281792}, {27.6724814, 64.3283221}, {27.6724171, 64.3283012}, + {27.6722512, 64.3286855}, {27.672158, 64.3286433}, {27.6719329, 64.3285442}, + {27.6718526, 64.3288411}, {27.6702343, 64.3298891}, {27.6641829, 64.3270074}, + {27.6641829, 64.3270074}, {27.6641742, 64.3266227}, {27.664201, 64.3264339}, + {27.6639771, 64.3262962}, {27.6640714, 64.3260614}, {27.6647372, 64.3257241}, + {27.66478, 64.3256237}, {27.6631366, 64.3246904}, {27.6631366, 64.3246904}, + {27.6626545, 64.3244235}, {27.6625587, 64.3243694}, {27.6625587, 64.3243694}, + {27.6632614, 64.3231479}, {27.6622282, 64.3225989}, {27.6622071, 64.3224857}, + {27.662732, 64.3215411}, {27.6631664, 64.32128}, {27.6641466, 64.3206841}, + {27.6645375, 64.320447}, {27.6642877, 64.3199579}, {27.664076, 64.3200822}, + {27.6629126, 64.3207565}, {27.6614741, 64.3218055}, {27.6590529, 64.3231601}, + {27.6589503, 64.3235567}, {27.658746, 64.3236712}, {27.6583308, 64.3235725}, + {27.6399171, 64.3347926}, {27.6398651, 64.3351383}, {27.6396823, 64.3352455}, + {27.6394227, 64.3351262}, {27.6330096, 64.3389213}, {27.6332817, 64.3393032}, + {27.6332997, 64.3392915}, {27.6350133, 64.3412399}, {27.634923, 64.3412786}, + {27.634888, 64.3413092}, {27.6333416, 64.3426474}, {27.6314699, 64.3404299}, + {27.6314154, 64.3403716}, {27.6313799, 64.3403335}, {27.6312156, 64.3401574}, + {27.6302219, 64.3408469}, {27.6302219, 64.3408469}, {27.6303714, 64.3409061}, + {27.6301666, 64.3417304}, {27.6304621, 64.3420817}, {27.6307356, 64.3425841}, + {27.6312637, 64.3433669}, {27.6318901, 64.3440008}, {27.6324568, 64.3444077}, + {27.6321289, 64.3454123}, {27.6364489, 64.3462701}, {27.6374156, 64.3465071}, + {27.6384619, 64.3469823}, {27.6392146, 64.347442}, {27.6399034, 64.3478679}, + {27.6404623, 64.3482995}, {27.6412079, 64.3490383}, {27.6414177, 64.3493191}, + {27.6415913, 64.3496597}, {27.6416961, 64.3500945}, {27.6417353, 64.3504959}, + {27.6418268, 64.3537048}, {27.6417814, 64.3538933}, {27.6417025, 64.3540255}, + {27.6415776, 64.3541282}, {27.6413096, 64.3541981}, {27.6389461, 64.3545246}, + {27.6389462, 64.3546445}, {27.6386149, 64.3546861}, {27.6386008, 64.3545722}, + {27.6373141, 64.3547501}, {27.632815, 64.3554428}, {27.632469, 64.3556276}, + {27.6323004, 64.3556128}, {27.6322325, 64.3555358}, {27.6322097, 64.3554042}, + {27.6322461, 64.3552483}, {27.6330205, 64.3540677}, {27.6329714, 64.3536832}, + {27.6331151, 64.3533032}, {27.6311475, 64.3519499}, {27.6332743, 64.3485688}, + {27.635411, 64.349915}, {27.6357333, 64.3494005}, {27.6312858, 64.3471352}, + {27.6314067, 64.3467546}, {27.6320887, 64.3457487}, {27.6309228, 64.3456154}, + {27.630183, 64.3455058}, {27.6284234, 64.3451888}, {27.6280833, 64.3451053}, + {27.6281914, 64.3450049}, {27.6280416, 64.3447953}, {27.6269314, 64.3445896}, + {27.6261757, 64.3443338}, {27.6259473, 64.3447895}, {27.6255839, 64.3451891}, + {27.625113, 64.3452047}, {27.6247515, 64.3447592}, {27.624594, 64.3445798}, + {27.6245559, 64.3445378}, {27.6244918, 64.3444523}, {27.6244351, 64.3443974}, + {27.6242802, 64.3442228}, {27.6241666, 64.3444535}, {27.622381, 64.3455291}, + {27.6192145, 64.3474115}, {27.6192137, 64.347112}, {27.6186219, 64.3474666}, + {27.6188564, 64.3475552}, {27.6146784, 64.3500223}, {27.6144037, 64.3503762}, + {27.6144037, 64.3503762}, {27.6127634, 64.3513883}, {27.6118549, 64.3517196}, + {27.6017381, 64.3578991}, {27.5984241, 64.359549}, {27.5987068, 64.3611203}, + {27.597921, 64.3613537}, {27.597921, 64.3613537}, {27.5977016, 64.3614188}, + {27.5973247, 64.3598476}, {27.5954242, 64.3605232}, {27.5956127, 64.3622046}, + {27.5950002, 64.3622517}, {27.5946232, 64.3608846}, {27.5928327, 64.3613717}, + {27.5903005, 64.3618491}, {27.5895279, 64.3619623}, {27.587184, 64.3625066}, + {27.5842606, 64.3625951}, {27.583042, 64.3626319}, {27.5818687, 64.3625985}, + {27.5791084, 64.362417}, {27.5791361, 64.3621128}, {27.5776413, 64.3620298}, + {27.5776564, 64.3622172}, {27.5775443, 64.3622082}, {27.5775219, 64.3622061}, + {27.5773137, 64.3621895}, {27.5756736, 64.3620569}, {27.5756782, 64.3620336}, + {27.5756902, 64.3619712}, {27.5756798, 64.361971}, {27.5725331, 64.3618554}, + {27.5713122, 64.3617087}, {27.568818, 64.3614091}, {27.5635364, 64.3609892}, + {27.5631262, 64.3611504}, {27.5631271, 64.3611228}, {27.5605005, 64.3608433}, + {27.5594797, 64.3607224}, {27.559423, 64.360989}, {27.559423, 64.360989}, + {27.5593797, 64.3609855}, {27.5593014, 64.3609698}, {27.5583635, 64.3608933}, + {27.5565602, 64.3607461}, {27.5551317, 64.3606456}, {27.5540485, 64.3605694}, + {27.5540478, 64.3605596}, {27.5534488, 64.360523}, {27.5530037, 64.360496}, + {27.550684, 64.3603544}, {27.5506981, 64.3601565}, {27.5486489, 64.3599951}, + {27.5486356, 64.3600784}, {27.5478722, 64.3600982}, {27.5450862, 64.3598879}, + {27.5442478, 64.3597403}, {27.5442478, 64.3597403}, {27.5437087, 64.3597189}, + {27.5428118, 64.3596179}, {27.5428118, 64.3596179}, {27.5425206, 64.3596153}, + {27.5419634, 64.3596082}, {27.5417969, 64.3594338}, {27.5388604, 64.3593563}, + {27.5386903, 64.3591885}, {27.5385544, 64.3591997}, {27.5383748, 64.3604123}, + {27.5379378, 64.3603731}, {27.5377349, 64.3601856}, {27.5374867, 64.3601677}, + {27.5374867, 64.3601677}, {27.5374009, 64.3601616}, {27.5372488, 64.3601507}, + {27.5363294, 64.3600849}, {27.5360268, 64.3600575}, {27.534528, 64.3599997}, + {27.533015, 64.3597201}, {27.5316497, 64.3594748}, {27.5314076, 64.3593721}, + {27.5310035, 64.3592988}, {27.5306032, 64.3590593}, {27.5305665, 64.3589819}, + {27.5306023, 64.3589539}, {27.5305672, 64.3588216}, {27.5304582, 64.3587361}, + {27.5303622, 64.3586373}, {27.5302365, 64.3585802}, {27.5298383, 64.358544}, + {27.528873, 64.3584345}, {27.5284579, 64.3584246}, {27.5284579, 64.3584246}, + {27.5282111, 64.3584187}, {27.5264337, 64.3582837}, {27.5263427, 64.3585559}, + {27.5242505, 64.3584144}, {27.524239, 64.3584294}, {27.5206622, 64.3581305}, + {27.5206244, 64.3580952}, {27.5195695, 64.357885}, {27.5188069, 64.3580153}, + {27.5173006, 64.3579037}, {27.5159809, 64.3577834}, {27.514206, 64.3575709}, + {27.5129958, 64.3576254}, {27.5119421, 64.3580071}, {27.5108841, 64.3583046}, + {27.5100525, 64.358377}, {27.5091555, 64.3584389}, {27.5078403, 64.3583073}, + {27.5076346, 64.3584817}, {27.5073926, 64.358452}, {27.507347, 64.3582585}, + {27.5048946, 64.357397}, {27.5033728, 64.3569765}, {27.5009464, 64.3567705}, + {27.4988628, 64.3566263}, {27.495092, 64.3563392}, {27.4947422, 64.3563361}, + {27.491687, 64.3562267}, {27.4903429, 64.3560886}, {27.4893192, 64.3560012}, + {27.4884512, 64.355936}, {27.487221, 64.3558302}, {27.4861289, 64.3557291}, + {27.4852322, 64.3555936}, {27.484357, 64.3554265}, {27.4818517, 64.3552616}, + {27.4799827, 64.3551225}, {27.4779655, 64.3548951}, {27.4742033, 64.354031}, + {27.4702634, 64.3527465}, {27.4697618, 64.352968}, {27.4693114, 64.352746}, + {27.4691771, 64.3522943}, {27.4654626, 64.3503408}, {27.4657157, 64.3502744}, + {27.4648259, 64.3497692}, {27.4648543, 64.3498797}, {27.4648543, 64.3498797}, + {27.4632376, 64.3487457}, {27.4613613, 64.3471703}, {27.4596336, 64.345543}, + {27.4583591, 64.3441921}, {27.4571371, 64.3426882}, {27.4563089, 64.3416028}, + {27.4554036, 64.340601}, {27.4550269, 64.3399458}, {27.4550329, 64.3398309}, + {27.4550996, 64.3397456}, {27.4551077, 64.3397354}, {27.454687, 64.3391966}, + {27.4546499, 64.3391446}, {27.4545047, 64.339184}, {27.4543666, 64.339137}, + {27.454107, 64.338848}, {27.4523391, 64.3365531}, {27.4494443, 64.3327956}, + {27.4491943, 64.3323797}, {27.4480956, 64.3309281}, {27.4473506, 64.329917}, + {27.4467718, 64.3292075}, {27.4460868, 64.3282827}, {27.4460131, 64.3283517}, + {27.44535, 64.3280234}, {27.4445066, 64.3279046}, {27.4435498, 64.3278835}, + {27.4421631, 64.3279442}, {27.4405734, 64.3278764}, {27.4405325, 64.3278185}, + {27.4405325, 64.3278185}, {27.4403006, 64.3274565}, {27.440274, 64.3274157}, + {27.4408174, 64.3272009}, {27.4412279, 64.3268866}, {27.4415538, 64.3265504}, + {27.4416195, 64.3263756}, {27.4418335, 64.3260532}, {27.4419387, 64.3255358}, + {27.4419825, 64.3253224}, {27.4421056, 64.3242828}, {27.4421358, 64.3240118}, + {27.4421535, 64.32379}, {27.4421515, 64.3237042}, {27.4419291, 64.3230464}, + {27.4411687, 64.3220143}, {27.4410368, 64.3219333}, {27.4410031, 64.3217975}, + {27.4394284, 64.3198542}, {27.4388353, 64.3191229}, {27.437531, 64.318405}, + {27.4363519, 64.3178544}, {27.4355839, 64.3175502}, {27.4353912, 64.317509}, + {27.4352675, 64.3174631}, {27.4352398, 64.3174576}, {27.4346566, 64.3173433}, + {27.4335943, 64.3175767}, {27.4335472, 64.3176038}, {27.4335451, 64.3176027}, + {27.4330806, 64.3178472}, {27.4329516, 64.3179152}, {27.432149, 64.3183379}, + {27.4325531, 64.3180613}, {27.4327429, 64.3177089}, {27.4329988, 64.3172361}, + {27.4336394, 64.3166523}, {27.4332372, 64.3164618}, {27.4334835, 64.3162223}, + {27.4339535, 64.3157046}, {27.4342081, 64.3154366}, {27.4343768, 64.3152922}, + {27.4344884, 64.3152271}, {27.4345526, 64.3151549}, {27.4345725, 64.3150921}, + {27.4345911, 64.3150158}, {27.4347084, 64.314904}, {27.4351928, 64.3143841}, + {27.4350881, 64.3142516}, {27.4348717, 64.3140892}, {27.4347594, 64.3139164}, + {27.4347594, 64.3139164}, {27.4345747, 64.3136333}, {27.4344012, 64.3133611}, + {27.4343456, 64.3132935}, {27.4341066, 64.3130027}, {27.4339046, 64.3127371}, + {27.4338534, 64.3126698}, {27.4326387, 64.3110725}, {27.4322464, 64.3105567}, + {27.4315187, 64.3096622}, {27.4311163, 64.3091444}, {27.4310148, 64.3090102}, + {27.4310068, 64.3087284}, {27.4285473, 64.3053163}, {27.4285473, 64.3053163}, + {27.4282623, 64.3049069}, {27.4278645, 64.3044161}, {27.4277042, 64.3042412}, + {27.4271981, 64.3035442}, {27.4271162, 64.3034215}, {27.4265927, 64.3025158}, + {27.4263514, 64.302211}, {27.4261924, 64.3020104}, {27.4239507, 64.2986311}, + {27.4239449, 64.2986223}, {27.4235376, 64.2980082}, {27.423562, 64.2976743}, + {27.4235097, 64.2975666}, {27.4235068, 64.2975605}, {27.4226418, 64.2957768}, + {27.422489, 64.2958561}, {27.4199584, 64.2911216}, {27.4192356, 64.2898109}, + {27.4192356, 64.2898109}, {27.4193112, 64.2894114}, {27.4190687, 64.2889425}, + {27.4189961, 64.2888021}, {27.4189682, 64.2887496}, {27.4188834, 64.2885843}, + {27.4185321, 64.2875741}, {27.418301, 64.2876599}, {27.4182791, 64.2876057}, + {27.4177079, 64.2861914}, {27.4174761, 64.2856172}, {27.417168, 64.2848545}, + {27.4172307, 64.2846909}, {27.4172586, 64.2846181}, {27.4166584, 64.2832015}, + {27.4166584, 64.2832015}, {27.4166001, 64.283064}, {27.4154969, 64.2803195}, + {27.4153436, 64.2797148}, {27.4151906, 64.279375}, {27.4145751, 64.2779915}, + {27.4138138, 64.2758234}, {27.4135404, 64.2750465}, {27.4133905, 64.2750825}, + {27.4126162, 64.2729374}, {27.412911, 64.2727403}, {27.4116225, 64.2680428}, + {27.4113659, 64.2680796}, {27.4099823, 64.2629982}, {27.4090388, 64.2622855}, + {27.4071533, 64.261649}, {27.4046655, 64.2607638}, {27.4044116, 64.2606619}, + {27.4038322, 64.2605227}, {27.4025071, 64.2603723}, {27.4026051, 64.2598577}, + {27.4032951, 64.2599397}, {27.4039502, 64.2598287}, {27.4044116, 64.259655}, + {27.4045202, 64.2596472}, {27.404959, 64.2594045}, {27.4055391, 64.2590833}, + {27.4080496, 64.2572714}, {27.4083371, 64.2564937}, {27.4083148, 64.2560282}, + {27.4079205, 64.2549579}, {27.4075643, 64.253463}, {27.4074277, 64.2528898}, + {27.4072249, 64.2528448}, {27.4067789, 64.2502682}, {27.406549, 64.2473737}, + {27.4066978, 64.2472394}, {27.4068932, 64.2441248}, {27.406659, 64.2440347}, + {27.4057007, 64.2441654}, {27.4056997, 64.2438665}, {27.4066367, 64.2436937}, + {27.4068331, 64.2436058}, {27.4068412, 64.243075}, {27.4070232, 64.2414024}, + {27.4072946, 64.2403231}, {27.4075168, 64.2403659}, {27.4077472, 64.2392707}, + {27.4076351, 64.2391948}, {27.4083976, 64.2362879}, {27.4085447, 64.2362144}, + {27.4094018, 64.2331756}, {27.4096854, 64.2323326}, {27.4098872, 64.231528}, + {27.4101206, 64.2311194}, {27.4107364, 64.228833}, {27.4107392, 64.2288284}, + {27.4105781, 64.2287675}, {27.4105763, 64.2287668}, {27.4108389, 64.227885}, + {27.4109917, 64.2278768}, {27.4114052, 64.2264411}, {27.4113543, 64.2262432}, + {27.410303, 64.2257219}, {27.4052454, 64.2245317}, {27.4044435, 64.2244717}, + {27.4020323, 64.2242635}, {27.4026535, 64.2252315}, {27.4016102, 64.2271894}, + {27.4023937, 64.2290423}, {27.4025147, 64.2297977}, {27.4027413, 64.2305677}, + {27.4027486, 64.2309301}, {27.4027079, 64.2313315}, {27.4026528, 64.2320315}, + {27.4022241, 64.2328237}, {27.4018685, 64.2335244}, {27.4016604, 64.2338597}, + {27.401567, 64.2342192}, {27.4014448, 64.2345883}, {27.4014305, 64.235001}, + {27.4013023, 64.2352131}, {27.4011283, 64.2355181}, {27.4007043, 64.2355456}, + {27.4003311, 64.236133}, {27.400251, 64.2375665}, {27.401075, 64.2378914}, + {27.4008276, 64.2389492}, {27.4012924, 64.2404725}, {27.4013187, 64.2435248}, + {27.401567, 64.2441508}, {27.4021215, 64.2444967}, {27.4021212, 64.2446019}, + {27.4012077, 64.2447783}, {27.3995984, 64.2447756}, {27.3993163, 64.2450449}, + {27.3990939, 64.245807}, {27.3993118, 64.2463}, {27.398796, 64.2462988}, + {27.3986588, 64.245806}, {27.3988265, 64.2450437}, {27.3987638, 64.2445283}, + {27.3972352, 64.2437789}, {27.3972247, 64.2436979}, {27.3978747, 64.2435394}, + {27.3983857, 64.2436139}, {27.3987741, 64.2434274}, {27.3995171, 64.242537}, + {27.3991248, 64.2380426}, {27.3999114, 64.2376801}, {27.399725, 64.23644}, + {27.3999578, 64.235762}, {27.3997557, 64.2337779}, {27.4014531, 64.2318993}, + {27.4014531, 64.2318993}, {27.4015133, 64.2314995}, {27.4015275, 64.2306148}, + {27.4014284, 64.2297229}, {27.4013359, 64.2293404}, {27.4009872, 64.2285303}, + {27.4007512, 64.2278973}, {27.4006439, 64.2272374}, {27.4006868, 64.2266958}, + {27.4008424, 64.2262719}, {27.4012286, 64.2254565}, {27.4012447, 64.2250595}, + {27.4010999, 64.2247216}, {27.40088, 64.224389}, {27.4007995, 64.2240188}, + {27.3998983, 64.2240456}, {27.3995218, 64.2240755}, {27.3995218, 64.2240755}, + {27.3991784, 64.2227845}, {27.3990905, 64.2220069}, {27.399475, 64.2214789}, + {27.402108, 64.2193647}, {27.4022253, 64.2186684}, {27.4022334, 64.2177951}, + {27.4031002, 64.2177987}, {27.4031046, 64.2166035}, {27.407588, 64.2166142}, + {27.4109196, 64.2166247}, {27.4124704, 64.2181587}, {27.4102764, 64.2253566}, + {27.4114616, 64.2258623}, {27.4115706, 64.2258718}, {27.4118372, 64.2250652}, + {27.4117536, 64.2250489}, {27.4120425, 64.2241364}, {27.4121428, 64.2241601}, + {27.412595, 64.2227301}, {27.4124832, 64.2226018}, {27.4130639, 64.2204331}, + {27.4140194, 64.2176804}, {27.4142258, 64.2164905}, {27.4154884, 64.212339}, + {27.4160615, 64.2099562}, {27.4163289, 64.2092479}, {27.4167351, 64.208465}, + {27.4170353, 64.2070078}, {27.4171494, 64.2062086}, {27.4155412, 64.2058406}, + {27.4127115, 64.2049071}, {27.4126188, 64.205026}, {27.4114557, 64.207375}, + {27.4114557, 64.207375}, {27.4114494, 64.2102317}, {27.4085299, 64.2102251}, + {27.4085359, 64.2075791}, {27.4082908, 64.2075718}, {27.4080648, 64.2076215}, + {27.4046333, 64.2076577}, {27.4044882, 64.2095682}, {27.3996806, 64.2094932}, + {27.3997754, 64.2081337}, {27.3997779, 64.2075786}, {27.3997975, 64.2030846}, + {27.3998128, 64.2003805}, {27.3987322, 64.2003779}, {27.3987384, 64.1977873}, + {27.3947856, 64.1977776}, {27.3947792, 64.2003683}, {27.3861105, 64.2003574}, + {27.3861168, 64.1967569}, {27.3854993, 64.1966904}, {27.3845638, 64.1962701}, + {27.3837344, 64.1954808}, {27.383161, 64.1950135}, {27.3805384, 64.1936746}, + {27.3795219, 64.1930508}, {27.3790799, 64.1928603}, {27.3780102, 64.1926064}, + {27.3768728, 64.1925004}, {27.3756527, 64.1926003}, {27.3747217, 64.1928313}, + {27.3740176, 64.1932442}, {27.3764876, 64.1904782}, {27.3774406, 64.1893572}, + {27.3806587, 64.186127}, {27.3801038, 64.186147}, {27.3825632, 64.1835495}, + {27.382739, 64.1833826}, {27.3840905, 64.1822216}, {27.3855899, 64.180991}, + {27.3855899, 64.180991}, {27.3873077, 64.1795811}, {27.3910827, 64.1769362}, + {27.3946601, 64.1737915}, {27.3947987, 64.173842}, {27.3966685, 64.1734947}, + {27.396682, 64.1737423}, {27.399822, 64.173733}, {27.3994851, 64.1750345}, + {27.3996717, 64.1780229}, {27.399736, 64.180362}, {27.3989099, 64.1803594}, + {27.3986072, 64.180157}, {27.3966479, 64.1801692}, {27.396637, 64.1806591}, + {27.3966351, 64.1808185}, {27.3965841, 64.185088}, {27.3966196, 64.1858882}, + {27.3971527, 64.185886}, {27.3996852, 64.1859966}, {27.399881, 64.1860015}, + {27.399872, 64.1862268}, {27.4009168, 64.1862337}, {27.4030697, 64.186232}, + {27.4051725, 64.1861986}, {27.4069699, 64.186205}, {27.4088595, 64.186223}, + {27.4105774, 64.1862647}, {27.4105717, 64.1891745}, {27.4113122, 64.1891636}, + {27.4139431, 64.18905}, {27.4222341, 64.1891155}, {27.4222341, 64.1891155}, + {27.4226166, 64.1875135}, {27.4227364, 64.186841}, {27.4228736, 64.1860704}, + {27.4238482, 64.1828726}, {27.4243269, 64.1811654}, {27.4248119, 64.1797349}, + {27.4249598, 64.1792987}, {27.4252452, 64.1784573}, {27.4262653, 64.1750269}, + {27.4277978, 64.1698484}, {27.4282711, 64.1683553}, {27.4283229, 64.1681095}, + {27.4289073, 64.1666422}, {27.4300546, 64.1642979}, {27.4301033, 64.1640962}, + {27.4301541, 64.1640392}, {27.4302385, 64.1638873}, {27.4306978, 64.1630701}, + {27.4305186, 64.1629979}, {27.4325911, 64.1599458}, {27.4350018, 64.156842}, + {27.4349083, 64.1568109}, {27.4355846, 64.1560928}, {27.4359099, 64.1557616}, + {27.4359195, 64.1557658}, {27.4359409, 64.1557458}, {27.437165, 64.1543682}, + {27.437238, 64.154415}, {27.4380828, 64.1537828}, {27.4382526, 64.1536213}, + {27.4383517, 64.1535606}, {27.4386395, 64.1532972}, {27.4415516, 64.1508974}, + {27.4431241, 64.1497349}, {27.4430674, 64.1496398}, {27.4439797, 64.1490954}, + {27.4452681, 64.1483801}, {27.4477536, 64.1471404}, {27.4504545, 64.1461391}, + {27.4530015, 64.1453652}, {27.4541182, 64.1452932}, {27.4573737, 64.1449223}, + {27.4575895, 64.1448803}, {27.4602345, 64.1443664}, {27.4602615, 64.1440554}, + {27.4613954, 64.1438735}, {27.4619606, 64.1438045}, {27.4619867, 64.1439116}, + {27.4625171, 64.1438491}, {27.463053, 64.1437601}, {27.463056, 64.1438816}, + {27.4635878, 64.1438003}, {27.4640203, 64.1437311}, {27.4644009, 64.1436705}, + {27.4647928, 64.1436079}, {27.4648507, 64.1435967}, {27.4650886, 64.1435511}, + {27.4652601, 64.1435181}, {27.4652703, 64.1435378}, {27.465278, 64.1435525}, + {27.4653376, 64.1435513}, {27.4660457, 64.1434259}, {27.4664142, 64.1433608}, + {27.4664908, 64.1433457}, {27.4667221, 64.1433}, {27.4667144, 64.1431388}, + {27.4666914, 64.1425525}, {27.4666801, 64.1422676}, {27.4666243, 64.1408465}, + {27.4666062, 64.1403853}, {27.4664135, 64.1403894}, {27.466295, 64.1403921}, + {27.466027, 64.1394853}, {27.4660097, 64.1394265}, {27.465951, 64.1393448}, + {27.4648712, 64.1376048}, {27.4641063, 64.1364248}, {27.4653375, 64.1359077}, + {27.4654827, 64.136145}, {27.4668691, 64.1350234}, {27.4670437, 64.135179}, + {27.4683103, 64.1338722}, {27.4683822, 64.1337358}, {27.4683198, 64.1334009}, + {27.4676692, 64.1327641}, {27.4684511, 64.1318496}, {27.4688227, 64.1315399}, + {27.469524, 64.1321231}, {27.4722172, 64.1344867}, {27.4724834, 64.1347131}, + {27.4727736, 64.1349536}, {27.4735669, 64.1346645}, {27.4734941, 64.1340496}, + {27.4733914, 64.1319798}, {27.4733781, 64.1317905}, {27.4741486, 64.1315712}, + {27.4749756, 64.1313994}, {27.4755848, 64.1335821}, {27.4763139, 64.1333724}, + {27.4778274, 64.1325538}, {27.4780181, 64.1325987}, {27.4781223, 64.1329749}, + {27.4782209, 64.1334887}, {27.4781271, 64.1336126}, {27.4782825, 64.1339598}, + {27.4785466, 64.1345502}, {27.4787826, 64.135078}, {27.478784, 64.1351395}, + {27.4791028, 64.1357864}, {27.4796983, 64.1373472}, {27.480201, 64.1383909}, + {27.4802862, 64.1393001}, {27.4803695, 64.1398336}, {27.4807553, 64.1397745}, + {27.4807553, 64.1397745}, {27.481594, 64.1396397}, {27.4818406, 64.1400806}, + {27.481904, 64.1402816}, {27.481904, 64.1402816}, {27.4823866, 64.1401829}, + {27.4825063, 64.1399216}, {27.4830589, 64.1397447}, {27.4924101, 64.1383875}, + {27.4928399, 64.1380805}, {27.4991264, 64.137122}, {27.5015387, 64.135504}, + {27.5031634, 64.1352095}, {27.5064028, 64.1357406}, {27.5069496, 64.1357364}, + {27.5267015, 64.1320164}, {27.5267015, 64.1320164}, {27.5296113, 64.1314683}, + {27.5330529, 64.1274268}, {27.5331065, 64.1271028}, {27.5336526, 64.127075}, + {27.5336958, 64.1272657}, {27.5336958, 64.1272657}, {27.5337352, 64.1274397}, + {27.5342309, 64.1280319}, {27.5362243, 64.1297088}, {27.5390449, 64.1297014}, + {27.5519079, 64.1271713}, {27.5538414, 64.1267583}, {27.5562361, 64.1264923}, + {27.5630167, 64.1266726}, {27.5642221, 64.1266285}, {27.5642221, 64.1266285}, + {27.5659498, 64.1266089}, {27.5703475, 64.1265817}, {27.5745009, 64.1260117}, + {27.5751796, 64.1259573}, {27.5751796, 64.1259573}, {27.5787007, 64.1149122}, + {27.5787007, 64.1149122}, {27.578024, 64.1147216}, {27.578889, 64.1123573}, + {27.5790063, 64.1120914}}); + + auto const areaPart2 = + MakeFbForTest({{"name", "Minsk"}, {"place", "city"}}, OsmElement::EntityType::Relation, + {{27.890273, 64.2114357}, {27.8889342, 64.2102497}, {27.8888851, 64.2069757}, + {27.8894455, 64.2031605}, {27.8906741, 64.2015762}, {27.8882492, 64.2005632}, + {27.8869774, 64.2000134}, {27.8857561, 64.1998499}, {27.8837025, 64.1996045}, + {27.8828566, 64.1991853}, {27.8821479, 64.1984536}, {27.8807838, 64.1960302}, + {27.8806487, 64.1953166}, {27.8863013, 64.1891715}, {27.8899898, 64.1900936}, + {27.889978, 64.1897944}, {27.8907918, 64.1897605}, {27.8958883, 64.1889885}, + {27.8958959, 64.1892705}, {27.8967571, 64.1891257}, {27.897032, 64.1893037}, + {27.8969171, 64.1910842}, {27.8967104, 64.1922742}, {27.8983434, 64.1928074}, + {27.8998435, 64.1926161}, {27.9006875, 64.1902277}, {27.9057408, 64.1904594}, + {27.9062775, 64.1949309}, {27.9083805, 64.1945619}, {27.9081326, 64.1926707}, + {27.9137731, 64.1953034}, {27.9181042, 64.1977157}, {27.9175388, 64.1980176}, + {27.917171, 64.1988802}, {27.9171727, 64.200133}, {27.9175348, 64.2006868}, + {27.9165042, 64.2016047}, {27.9131796, 64.2032769}, {27.9101579, 64.2034959}, + {27.9098172, 64.2040313}, {27.9101659, 64.2066987}, {27.9090988, 64.2068228}, + {27.9099774, 64.2124039}, {27.9102135, 64.2126494}, {27.9089198, 64.2126664}, + {27.9093494, 64.2162688}, {27.9065087, 64.2170935}, {27.9040064, 64.2173845}, + {27.9031429, 64.2201099}, {27.9008921, 64.219558}, {27.8962115, 64.2184621}, + {27.8958457, 64.2195595}, {27.894433, 64.2182941}, {27.890571, 64.2142697}, + {27.890273, 64.2114357}}); + + auto const areaPart3 = + MakeFbForTest({{"name", "Minsk"}, {"place", "city"}}, OsmElement::EntityType::Relation, + {{28.0607636, 64.1802131}, {28.05719, 64.1768369}, {28.0509593, 64.181908}, + {28.0506121, 64.1822574}, {28.0501472, 64.1828219}, {28.0497794, 64.1832291}, + {28.0492723, 64.1838266}, {28.04831, 64.1850076}, {28.0433069, 64.1907399}, + {28.0421224, 64.1913575}, {28.0410563, 64.1926122}, {28.0410496, 64.1926738}, + {28.0412432, 64.1929882}, {28.0330091, 64.2023494}, {28.0294086, 64.2063965}, + {28.0291182, 64.2064893}, {28.0285597, 64.2067321}, {28.0275941, 64.2071016}, + {28.0275466, 64.2071428}, {28.0270224, 64.2078147}, {28.0264053, 64.2090698}, + {28.0263051, 64.2096111}, {28.0262759, 64.2096661}, {28.025941, 64.2100989}, + {28.0254359, 64.2107079}, {28.0241097, 64.2095263}, {28.0233256, 64.2104881}, + {28.0219681, 64.2091865}, {28.0190494, 64.2118602}, {28.0171215, 64.2136353}, + {28.0203998, 64.2165537}, {28.0203854, 64.2166115}, {28.0143949, 64.2236133}, + {28.0143351, 64.223625}, {28.0138428, 64.2231704}, {28.0137839, 64.2231828}, + {28.013052, 64.2240838}, {28.0130575, 64.2241427}, {28.0135477, 64.2246059}, + {28.009333, 64.2293481}, {28.0080684, 64.2307582}, {28.0042998, 64.2351554}, + {28.0011268, 64.2387052}, {28.0007584, 64.2395436}, {27.9999031, 64.2419618}, + {27.9998506, 64.2425054}, {27.9999589, 64.24298}, {28.0029865, 64.2457057}, + {28.0086928, 64.2421224}, {28.0114627, 64.2393284}, {28.0145343, 64.2358036}, + {28.0148053, 64.236051}, {28.0149551, 64.2361971}, {28.0165106, 64.2354808}, + {28.0168355, 64.2351115}, {28.019794, 64.2371044}, {28.0208144, 64.2357966}, + {28.0222289, 64.2366486}, {28.0286682, 64.2296564}, {28.0355604, 64.2308665}, + {28.0323964, 64.2338889}, {28.0329469, 64.2346714}, {28.03482, 64.237562}, + {28.0336259, 64.2389323}, {28.0364279, 64.2413902}, {28.027377, 64.2516311}, + {28.0265302, 64.2525891}, {28.0258332, 64.2534686}, {28.0239635, 64.256326}, + {28.0219361, 64.260255}, {28.018266, 64.2644449}, {28.0153179, 64.2678361}, + {28.0132097, 64.2702612}, {28.0061748, 64.2780129}, {28.0061748, 64.2780129}, + {28.0103165, 64.2818246}, {28.0151346, 64.2762284}, {28.0254683, 64.2657034}, + {28.028928, 64.2621797}, {28.0292731, 64.2618249}, {28.0292731, 64.2618249}, + {28.03253, 64.2584765}, {28.0570805, 64.2332367}, {28.0584137, 64.2319769}, + {28.0513357, 64.2255514}, {28.0554729, 64.2208197}, {28.0597072, 64.2159642}, + {28.0567942, 64.2134041}, {28.0608997, 64.2086172}, {28.0595051, 64.2077352}, + {28.058389, 64.2066678}, {28.0584887, 64.206567}, {28.0547843, 64.2028898}, + {28.0545302, 64.2027093}, {28.0536219, 64.1945812}, {28.0535337, 64.194039}, + {28.0536517, 64.1939336}, {28.0577188, 64.1873279}, {28.0588309, 64.1847522}, + {28.0607636, 64.1802131}}); + + auto table = std::make_shared(); + generator::PlaceProcessor pp(table); + pp.Add(areaPart1); + pp.Add(areaPart2); + pp.Add(areaPart3); + pp.Add(point); + + std::vector r{point}; + TEST_EQUAL(pp.ProcessPlaces(), r, ()); + TEST(TestTable(*table, {{{point.GetMostGenericOsmId(), areaPart1.GetMostGenericOsmId()}, + 3 /* cluster size */}}), + ()); +} + +UNIT_CLASS_TEST(TestPlaceProcessor, VoronezhDuplicatingCityFeatureTest) +{ + DisablerIdInc _; + auto const point = MakeFbForTest({{"name", "Voronezh"}, {"place", "city"}}, + OsmElement::EntityType::Node, {{39.2005858, 60.53736258}}); + + auto const areaPart1 = + MakeFbForTest({{"name", "Voronezh"}, {"place", "city"}}, OsmElement::EntityType::Relation, + {{39.074534, 60.4989445}, {39.0679785, 60.4905635}, {39.0675323, 60.4899397}, + {39.0636533, 60.4853405}, {39.0590853, 60.4812033}, {39.0551326, 60.4775753}, + {39.0504648, 60.4742041}, {39.0467881, 60.4719245}, {39.0429923, 60.4697919}, + {39.0398945, 60.4691261}, {39.0384817, 60.468709}, {39.0384817, 60.468709}, + {39.0364008, 60.4680945}, {39.0337705, 60.4669019}, {39.0315385, 60.4659714}, + {39.0284701, 60.4644107}, {39.0259522, 60.462626}, {39.0232518, 60.4597917}, + {39.0208024, 60.4564464}, {39.0199627, 60.4552918}, {39.0176608, 60.4518437}, + {39.0132338, 60.4469233}, {39.0132338, 60.4469233}, {39.0292226, 60.4432002}, + {39.0309324, 60.4425288}, {39.0309324, 60.4425288}, {39.0307145, 60.4421027}, + {39.0300749, 60.4406326}, {39.0296959, 60.4397554}, {39.0290986, 60.4378256}, + {39.0285766, 60.4348871}, {39.0284563, 60.434014}, {39.0285916, 60.4322739}, + {39.0285328, 60.4311426}, {39.0278766, 60.4288425}, {39.0268417, 60.4246525}, + {39.0275896, 60.4212829}, {39.0276968, 60.4203925}, {39.0276303, 60.418198}, + {39.028197, 60.4159742}, {39.028849, 60.4141625}, {39.0310687, 60.4118203}, + {39.031518, 60.4112606}, {39.0319937, 60.4107157}, {39.0337694, 60.4076787}, + {39.0346303, 60.4057034}, {39.0355074, 60.4050395}, {39.0361619, 60.4042455}, + {39.0368269, 60.4016191}, {39.0385044, 60.3959187}, {39.0418776, 60.3905149}, + {39.0463729, 60.3842885}, {39.0532441, 60.3777555}, {39.0592906, 60.3701493}, + {39.0615436, 60.3664157}, {39.0626165, 60.3652248}, {39.0641614, 60.3638701}, + {39.0668932, 60.3624217}, {39.0680353, 60.3618357}, {39.0680353, 60.3618357}, + {39.0721372, 60.359349}, {39.0721372, 60.359349}, {39.0740941, 60.3581627}, + {39.0749359, 60.359281}, {39.079018, 60.3562537}, {39.0794019, 60.354685}, + {39.0794019, 60.354685}, {39.0805906, 60.3498271}, {39.0821251, 60.3500496}, + {39.0839445, 60.3532185}, {39.0843611, 60.3530262}, {39.0843611, 60.3530262}, + {39.0845581, 60.3529379}, {39.0869124, 60.3489466}, {39.0885632, 60.3467085}, + {39.0933362, 60.3492831}, {39.0947304, 60.3503509}, {39.0997245, 60.3567334}, + {39.0997245, 60.3567334}, {39.1032912, 60.357082}, {39.1059382, 60.3573342}, + {39.1101709, 60.3583243}, {39.1144932, 60.3594472}, {39.1157532, 60.3596367}, + {39.117361, 60.359902}, {39.1184208, 60.3600138}, {39.1203173, 60.3580744}, + {39.1219902, 60.3583593}, {39.1262941, 60.3575794}, {39.1262941, 60.3575794}, + {39.1237412, 60.3549011}, {39.1227098, 60.3542045}, {39.1203452, 60.3525582}, + {39.1197664, 60.3521273}, {39.1188233, 60.3508459}, {39.1183308, 60.3498493}, + {39.1182006, 60.3490173}, {39.11826, 60.346713}, {39.117875, 60.3461498}, + {39.1164904, 60.3460998}, {39.115364, 60.3458699}, {39.114078, 60.3446772}, + {39.1139158, 60.3441032}, {39.1139158, 60.3441032}, {39.113871, 60.3435707}, + {39.1142252, 60.3427219}, {39.1148919, 60.3418121}, {39.115958, 60.3400625}, + {39.1160004, 60.3384066}, {39.1154308, 60.3368106}, {39.1128315, 60.3362528}, + {39.1110461, 60.3364721}, {39.1096837, 60.3373646}, {39.109073, 60.3384296}, + {39.108243, 60.3394476}, {39.10663, 60.3402305}, {39.1040836, 60.3406151}, + {39.1030062, 60.3405022}, {39.1023422, 60.3398382}, {39.1020666, 60.3384852}, + {39.10139, 60.3368441}, {39.1005757, 60.3357541}, {39.0982204, 60.3338497}, + {39.0965666, 60.3327347}, {39.0953389, 60.33172}, {39.0938856, 60.3300913}, + {39.093397, 60.329089}, {39.0934471, 60.3276858}, {39.093635, 60.3258943}, + {39.0936225, 60.3243159}, {39.0930337, 60.3228499}, {39.0918936, 60.3218728}, + {39.0902148, 60.3212088}, {39.0878606, 60.3212463}, {39.085471, 60.3214255}, + {39.0849333, 60.3169451}, {39.0863073, 60.311688}, {39.0863073, 60.311688}, + {39.0888537, 60.3101306}, {39.0908582, 60.3083866}, {39.0912266, 60.3081377}, + {39.0927424, 60.3071137}, {39.0940354, 60.3068731}, {39.0961983, 60.3084753}, + {39.0982247, 60.3107693}, {39.0986835, 60.3144396}, {39.099438, 60.317613}, + {39.1006758, 60.318989}, {39.1011563, 60.3170258}, {39.1030494, 60.3175751}, + {39.1068643, 60.3174692}, {39.1132543, 60.3134163}, {39.11396, 60.306935}, + {39.1153125, 60.3049514}, {39.1202718, 60.302697}, {39.1254115, 60.3023364}, + {39.1287478, 60.3016151}, {39.1339579, 60.3020129}, {39.1351185, 60.3001271}, + {39.137206, 60.2984176}, {39.1378011, 60.2973997}, {39.1392295, 60.2963042}, + {39.1429381, 60.2945454}, {39.146035, 60.2933219}, {39.167594, 60.2845201}, + {39.1673725, 60.2838703}, {39.2077052, 60.268394}, {39.2077052, 60.268394}, + {39.2087758, 60.268088}, {39.209828, 60.2686863}, {39.2236482, 60.2571172}, + {39.2246857, 60.2559231}, {39.2273088, 60.2556491}, {39.230379, 60.2546161}, + {39.2350893, 60.260244}, {39.2376637, 60.2656999}, {39.2376637, 60.2656999}, + {39.2392797, 60.2708269}, {39.240442, 60.2755679}, {39.2420937, 60.2758737}, + {39.2417878, 60.2846827}, {39.2408914, 60.3009887}, {39.2406621, 60.3093235}, + {39.2408531, 60.3135674}, {39.2415031, 60.3198759}, {39.2424281, 60.3197796}, + {39.2539484, 60.3180343}, {39.2541584, 60.3180025}, {39.2675782, 60.3160143}, + {39.2740397, 60.3150203}, {39.2740397, 60.3150203}, {39.2749734, 60.3419983}, + {39.275752, 60.3424899}, {39.2708812, 60.3557508}, {39.2812542, 60.3593117}, + {39.283223, 60.3540214}, {39.2945803, 60.3554009}, {39.2962277, 60.3554009}, + {39.2972188, 60.3543964}, {39.2975938, 60.3535259}, {39.2976512, 60.3522484}, + {39.3000274, 60.3459835}, {39.305464, 60.3469016}, {39.2985469, 60.3647129}, + {39.293506, 60.3632006}, {39.2960938, 60.3559099}, {39.2946503, 60.3558435}, + {39.283886, 60.3545988}, {39.2765715, 60.3755792}, {39.2779886, 60.3762161}, + {39.2773621, 60.3779231}, {39.2785723, 60.3784636}, {39.2800477, 60.3776858}, + {39.2813772, 60.3772282}, {39.283943, 60.3769314}, {39.2902157, 60.3762002}, + {39.2906903, 60.3828151}, {39.291023, 60.3891575}, {39.2929219, 60.3919373}, + {39.293979, 60.3912521}, {39.2956429, 60.3895686}, {39.2978941, 60.3881787}, + {39.2993035, 60.3875524}, {39.300987, 60.3875915}, {39.3010653, 60.3890793}, + {39.3005368, 60.3940123}, {39.2997538, 60.4000024}, {39.3040682, 60.4014775}, + {39.3127663, 60.3925882}, {39.3282948, 60.3777679}, {39.331231, 60.3806455}, + {39.3283731, 60.3861266}, {39.3268071, 60.3881232}, {39.328345, 60.3921937}, + {39.327458, 60.3966287}, {39.3267239, 60.398831}, {39.3258674, 60.3998709}, + {39.3256428, 60.4019989}, {39.3260735, 60.4033692}, {39.3262497, 60.4039956}, + {39.3270131, 60.4051114}, {39.3285987, 60.4065991}, {39.3286378, 60.4071474}, + {39.3281187, 60.4088279}, {39.3254568, 60.4120033}, {39.3247624, 60.4156997}, + {39.3259345, 60.4175611}, {39.3287975, 60.4199101}, {39.3288143, 60.4212285}, + {39.3271259, 60.4209349}, {39.3267177, 60.4221369}, {39.3268946, 60.4354818}, + {39.3268946, 60.4354818}, {39.3234455, 60.4356568}, {39.3227292, 60.4283031}, + {39.3170582, 60.428253}, {39.3152786, 60.4282374}, {39.3152786, 60.4282374}, + {39.3130893, 60.4282181}, {39.3078204, 60.4522924}, {39.3003639, 60.4633539}, + {39.3015697, 60.4839487}, {39.3017753, 60.4867081}, {39.3024147, 60.4954957}, + {39.3036255, 60.4954311}, {39.3042343, 60.5008715}, {39.3116875, 60.4983026}, + {39.3133615, 60.4980633}, {39.3157246, 60.500738}, {39.3154218, 60.5017763}, + {39.3143403, 60.5016609}, {39.3126721, 60.5019185}, {39.3121571, 60.5022511}, + {39.311577, 60.5124536}, {39.311573, 60.5127076}, {39.3115653, 60.5129593}, + {39.3115349, 60.5133153}, {39.3090408, 60.5151322}, {39.3089062, 60.5166257}, + {39.3085829, 60.51721}, {39.307968, 60.5174115}, {39.3064283, 60.5172574}, + {39.3049834, 60.518412}, {39.3041794, 60.5195063}, {39.3037477, 60.5209847}, + {39.3035394, 60.5235956}, {39.3032838, 60.530016}, {39.3027223, 60.5335122}, + {39.3034859, 60.5341401}, {39.3035297, 60.5341239}, {39.3034808, 60.5349069}, + {39.3024286, 60.5353963}, {39.3006445, 60.548993}, {39.3006445, 60.548993}, + {39.3008994, 60.5556406}, {39.3009988, 60.5585426}, {39.3013448, 60.5614449}, + {39.3021529, 60.562164}, {39.3021529, 60.562164}, {39.3026498, 60.562606}, + {39.3044529, 60.5638511}, {39.3059691, 60.5646017}, {39.3066746, 60.5647744}, + {39.306911, 60.5648044}, {39.3069222, 60.5651797}, {39.3066746, 60.5652247}, + {39.3059991, 60.5655024}, {39.3026216, 60.5676791}, {39.3019761, 60.5687298}, + {39.3021003, 60.5700593}, {39.3163074, 60.5709238}, {39.3194146, 60.5646444}, + {39.3211107, 60.5614395}, {39.3212964, 60.5610886}, {39.3266931, 60.5640397}, + {39.330835, 60.5638531}, {39.3328094, 60.5641037}, {39.3345579, 60.5646188}, + {39.3345579, 60.5646188}, {39.3317416, 60.5677395}, {39.3326645, 60.5685767}, + {39.3330356, 60.5727345}, {39.3309367, 60.5751748}, {39.3305788, 60.5760347}, + {39.3297437, 60.5768636}, {39.3297437, 60.5818681}, {39.3298578, 60.5832858}, + {39.3306755, 60.585368}, {39.3316085, 60.5858757}, {39.3340388, 60.588322}, + {39.3396931, 60.5912002}, {39.3385995, 60.5940304}, {39.3467417, 60.5983273}, + {39.3473938, 60.6031924}, {39.3514231, 60.6031424}, {39.3545997, 60.6097464}, + {39.3603577, 60.60808}, {39.3648582, 60.6060818}, {39.3663164, 60.6030754}, + {39.3668564, 60.599907}, {39.3661723, 60.5945965}, {39.3661723, 60.5945965}, + {39.3674145, 60.5950105}, {39.3700248, 60.5958386}, {39.3709249, 60.5978728}, + {39.3718395, 60.5984406}, {39.372059, 60.6005552}, {39.3726891, 60.6009332}, + {39.3730851, 60.6016893}, {39.372311, 60.6019773}, {39.372149, 60.6028053}, + {39.372383, 60.6036336}, {39.371843, 60.6046596}, {39.3729591, 60.6054336}, + {39.3727611, 60.6060818}, {39.371519, 60.6061357}, {39.3709609, 60.6059017}, + {39.3703308, 60.6063518}, {39.3697548, 60.607936}, {39.3709789, 60.6084221}, + {39.3718468, 60.6088894}, {39.3678424, 60.6174459}, {39.367375, 60.6191103}, + {39.3688136, 60.6195598}, {39.3688136, 60.6195598}, {39.3753141, 60.6213985}, + {39.3858234, 60.6248484}, {39.391502, 60.6266435}, {39.391502, 60.6266435}, + {39.3963226, 60.6281673}, {39.4001924, 60.6293928}, {39.4017524, 60.6294092}, + {39.4027043, 60.6300776}, {39.4044894, 60.6307354}, {39.417116, 60.6349006}, + {39.4192352, 60.6292126}, {39.426212, 60.6316035}, {39.4250706, 60.6344354}, + {39.4318821, 60.6372139}, {39.4345433, 60.639202}, {39.439223, 60.6413125}, + {39.4464108, 60.6408231}, {39.4481543, 60.6402113}, {39.4575138, 60.6439735}, + {39.4582785, 60.6446159}, {39.4582785, 60.6446159}, {39.4493885, 60.6579124}, + {39.4493885, 60.6579124}, {39.4474814, 60.6607045}, {39.4478484, 60.6621725}, + {39.4369826, 60.6771237}, {39.4366352, 60.6810984}, {39.4366352, 60.6810984}, + {39.4364313, 60.6822654}, {39.4355144, 60.682907}, {39.4348296, 60.6834951}, + {39.4342526, 60.6840774}, {39.4287535, 60.6857176}, {39.4253747, 60.685791}, + {39.4243165, 60.687029}, {39.4211957, 60.6880738}, {39.4206681, 60.689036}, + {39.4168665, 60.688372}, {39.4156096, 60.6888689}, {39.4158277, 60.691229}, + {39.4163751, 60.6918299}, {39.416087, 60.6926411}, {39.4182005, 60.6929819}, + {39.4195288, 60.693217}, {39.4239747, 60.6933205}, {39.4263458, 60.6931226}, + {39.4263458, 60.6931226}, {39.4263196, 60.6963038}, {39.4297432, 60.6960238}, + {39.4310689, 60.6961463}, {39.4310689, 60.6961463}, {39.4423719, 60.6985356}, + {39.4452471, 60.7137373}, {39.4465565, 60.7244651}, {39.4465565, 60.7244651}, + {39.4078092, 60.7304534}, {39.4061858, 60.725761}, {39.4036409, 60.7265253}, + {39.404611, 60.7305046}, {39.402436, 60.7308777}, {39.4008629, 60.7311816}, + {39.3984821, 60.7315881}, {39.3589332, 60.7383393}, {39.3589332, 60.7383393}, + {39.3590823, 60.7383665}, {39.3591736, 60.7384484}, {39.3592001, 60.738564}, + {39.3589103, 60.7387503}, {39.3586863, 60.7390682}, {39.3585727, 60.7391061}, + {39.3583926, 60.7389965}, {39.3584265, 60.7386313}, {39.3582743, 60.738479}, + {39.3581999, 60.7384795}, {39.3576931, 60.7388254}, {39.3575104, 60.7390063}, + {39.357512, 60.7390416}, {39.357683, 60.7392339}, {39.3577664, 60.7397321}, + {39.3579152, 60.7399305}, {39.3581865, 60.7400766}, {39.35851, 60.7400844}, + {39.3591083, 60.7403941}, {39.3594898, 60.7403544}, {39.3595581, 60.7401607}, + {39.3595017, 60.7399075}, {39.3595467, 60.7395231}, {39.3600493, 60.739189}, + {39.3612026, 60.739237}, {39.3618422, 60.7399147}, {39.3618688, 60.7404685}, + {39.3617072, 60.7411736}, {39.3614372, 60.7418048}, {39.3614873, 60.7426897}, + {39.360987, 60.7430191}, {39.3608161, 60.7430313}, {39.3605729, 60.7427684}, + {39.3602726, 60.7427943}, {39.3601035, 60.7428678}, {39.3602499, 60.7436732}, + {39.3603207, 60.744376}, {39.3605352, 60.7450636}, {39.360415, 60.7454904}, + {39.3602973, 60.7464665}, {39.3601252, 60.746677}, {39.3597129, 60.7469782}, + {39.3597078, 60.747788}, {39.3594709, 60.7479558}, {39.359187, 60.7478522}, + {39.3590487, 60.7479558}, {39.3590167, 60.7484643}, {39.3590462, 60.7489904}, + {39.3591515, 60.7491202}, {39.3595968, 60.7493162}, {39.3596017, 60.7495212}, + {39.3595771, 60.7497335}, {39.359103, 60.7501013}, {39.3588142, 60.750595}, + {39.3585327, 60.7508395}, {39.3584857, 60.7510075}, {39.3585154, 60.751158}, + {39.3588339, 60.751395}, {39.3594056, 60.7515127}, {39.3594675, 60.7516912}, + {39.3594918, 60.7521092}, {39.3596232, 60.7522943}, {39.3598663, 60.7524568}, + {39.3600515, 60.7527409}, {39.3600939, 60.7529642}, {39.360255, 60.7530363}, + {39.3604599, 60.752861}, {39.3606222, 60.7526967}, {39.3607666, 60.7525063}, + {39.3608769, 60.7524583}, {39.3611002, 60.7524836}, {39.361298, 60.752618}, + {39.3613644, 60.7527664}, {39.3613644, 60.7529939}, {39.3612753, 60.7530971}, + {39.361209, 60.7532807}, {39.3611484, 60.7536571}, {39.3609291, 60.7539648}, + {39.3609334, 60.7541034}, {39.3611199, 60.7544877}, {39.361527, 60.7548156}, + {39.3616443, 60.7549966}, {39.3615708, 60.7552467}, {39.3616824, 60.7553457}, + {39.3620837, 60.7555035}, {39.3622471, 60.7556099}, {39.3625617, 60.7557487}, + {39.3626892, 60.7559754}, {39.3627189, 60.75611}, {39.3627917, 60.7562078}, + {39.3629583, 60.7562843}, {39.3631912, 60.7562073}, {39.3634253, 60.756148}, + {39.3635475, 60.7560834}, {39.3636306, 60.7557562}, {39.3638442, 60.7556985}, + {39.3641411, 60.7556747}, {39.3641971, 60.7555662}, {39.3641123, 60.7552829}, + {39.3642309, 60.7551659}, {39.3644312, 60.7551862}, {39.3646584, 60.7551405}, + {39.364955, 60.7551269}, {39.3651087, 60.7550215}, {39.3652804, 60.7546539}, + {39.3654883, 60.7545576}, {39.3656148, 60.7546931}, {39.3655636, 60.7552082}, + {39.3654009, 60.7554462}, {39.3653316, 60.7555578}, {39.3653768, 60.7556572}, + {39.3658468, 60.7557596}, {39.3661661, 60.7557627}, {39.3665246, 60.7559344}, + {39.3666843, 60.7560999}, {39.3666791, 60.7562304}, {39.3666451, 60.7563279}, + {39.3665047, 60.7563868}, {39.3664231, 60.7566337}, {39.3659089, 60.7573018}, + {39.3659089, 60.7574899}, {39.3662228, 60.7579352}, {39.3666061, 60.75793}, + {39.3669604, 60.7582042}, {39.3671051, 60.7584563}, {39.3670592, 60.75871}, + {39.3669314, 60.7588599}, {39.3669757, 60.759037}, {39.3671545, 60.7594066}, + {39.367301, 60.7594304}, {39.3675156, 60.7593623}, {39.3677659, 60.7594525}, + {39.3677608, 60.7596483}, {39.3676127, 60.7598629}, {39.367502, 60.7600384}, + {39.3675377, 60.7601797}, {39.3676144, 60.7601984}, {39.3678517, 60.7600971}, + {39.3681022, 60.7601267}, {39.3682646, 60.7602982}, {39.3682977, 60.7605425}, + {39.3681734, 60.7606392}, {39.3679493, 60.7605953}, {39.3678458, 60.760604}, + {39.367731, 60.7606726}, {39.3676901, 60.7607977}, {39.367761, 60.760958}, + {39.3679113, 60.7612194}, {39.3679292, 60.7612697}, {39.3680043, 60.7615166}, + {39.3679056, 60.7616138}, {39.3677666, 60.7617723}, {39.3675767, 60.7618591}, + {39.3672453, 60.7617847}, {39.3668742, 60.7615829}, {39.3666776, 60.7614305}, + {39.3665367, 60.7611932}, {39.3663385, 60.7610658}, {39.366217, 60.7611011}, + {39.3659725, 60.7612523}, {39.3657724, 60.7614251}, {39.3656002, 60.7619025}, + {39.3654932, 60.762266}, {39.3652139, 60.7627849}, {39.3645991, 60.7632498}, + {39.3643306, 60.7635255}, {39.3640787, 60.763905}, {39.3640609, 60.7641188}, + {39.3638915, 60.7643176}, {39.3638436, 60.7646903}, {39.3638499, 60.7649199}, + {39.3639038, 60.7650786}, {39.3638699, 60.7654253}, {39.3637104, 60.7658171}, + {39.3637554, 60.7662578}, {39.3636542, 60.7665613}, {39.3637314, 60.7667334}, + {39.3639266, 60.7667919}, {39.3640171, 60.7666021}, {39.3640845, 60.766582}, + {39.3642229, 60.7665204}, {39.3644855, 60.7666027}, {39.3645991, 60.7669586}, + {39.3645635, 60.7670795}, {39.3643932, 60.7671681}, {39.3641005, 60.7674325}, + {39.36412, 60.7676045}, {39.3643063, 60.7676791}, {39.3645245, 60.7676603}, + {39.3648643, 60.767808}, {39.3653001, 60.7681175}, {39.3652983, 60.7684198}, + {39.3651453, 60.7686955}, {39.3652247, 60.7689479}, {39.3652962, 60.7690314}, + {39.3653566, 60.7691803}, {39.3657062, 60.7697114}, {39.366399, 60.7706363}, + {39.3669171, 60.771202}, {39.3671205, 60.7714723}, {39.3674637, 60.7717233}, + {39.3681361, 60.7727795}, {39.3686628, 60.7732749}, {39.3693674, 60.773468}, + {39.3698564, 60.7741393}, {39.3703943, 60.7744495}, {39.3712066, 60.7755462}, + {39.3714814, 60.7757724}, {39.3718486, 60.7770151}, {39.3725285, 60.7774151}, + {39.3734269, 60.7775193}, {39.3739814, 60.7775128}, {39.3745876, 60.7773266}, + {39.3751649, 60.7774156}, {39.3757615, 60.7780349}, {39.3761322, 60.7781706}, + {39.3763628, 60.7779288}, {39.3763387, 60.7776069}, {39.3759939, 60.7771002}, + {39.3761766, 60.7766989}, {39.376543, 60.7765466}, {39.3769483, 60.7765628}, + {39.3775482, 60.776887}, {39.378228, 60.7770232}, {39.3788462, 60.7774124}, + {39.3808857, 60.7794285}, {39.3826802, 60.7807095}, {39.3835367, 60.7809909}, + {39.3841283, 60.7816774}, {39.3841409, 60.7820834}, {39.3840182, 60.7827732}, + {39.3833732, 60.7832923}, {39.3833767, 60.7848715}, {39.3823762, 60.7862636}, + {39.3818685, 60.7868076}, {39.3809478, 60.787058}, {39.3804323, 60.7871167}, + {39.3804106, 60.7874567}, {39.3806046, 60.7876639}, {39.3808454, 60.7881196}, + {39.3811547, 60.7885106}, {39.3827282, 60.7894831}, {39.3840971, 60.7906266}, + {39.3843981, 60.7918802}, {39.3840601, 60.7930658}, {39.3833189, 60.7938637}, + {39.3832662, 60.7947394}, {39.3834263, 60.7956248}, {39.3836624, 60.7967835}, + {39.384434, 60.7993788}, {39.385291, 60.8005561}, {39.3860103, 60.8009802}, + {39.3862, 60.8034728}, {39.3865338, 60.8048686}, {39.3864933, 60.8057589}, + {39.3868585, 60.8065811}, {39.387502, 60.8079652}, {39.387502, 60.8079652}, + {39.3870434, 60.8086982}, {39.3867144, 60.8090594}, {39.3866034, 60.8093016}, + {39.3865985, 60.8097296}, {39.3867394, 60.8101215}, {39.3869957, 60.8104504}, + {39.3870384, 60.8108097}, {39.3869754, 60.8111514}, {39.3867394, 60.8115229}, + {39.3861729, 60.8121043}, {39.3851303, 60.8127861}, {39.3846981, 60.8130065}, + {39.3844476, 60.8130804}, {39.3841317, 60.8130065}, {39.3837575, 60.8124401}, + {39.3835588, 60.8122484}, {39.3832963, 60.8121637}, {39.3829126, 60.8123124}, + {39.3825762, 60.8127466}, {39.3824223, 60.8132898}, {39.3824692, 60.8136355}, + {39.3821593, 60.8143721}, {39.3818447, 60.8150883}, {39.3816172, 60.815376}, + {39.3812498, 60.8156576}, {39.3809629, 60.8159639}, {39.3806181, 60.8164071}, + {39.3806739, 60.8169629}, {39.3808944, 60.8177307}, {39.3814753, 60.8193524}, + {39.38083, 60.8205586}, {39.3807012, 60.8210522}, {39.3807783, 60.8213758}, + {39.3824248, 60.82136}, {39.3830183, 60.8222001}, {39.3830747, 60.8244322}, + {39.3824789, 60.8253168}, {39.3815131, 60.8258504}, {39.3798251, 60.8262194}, + {39.3797678, 60.8268425}, {39.3801445, 60.8276581}, {39.3799871, 60.8280527}, + {39.379748, 60.8284423}, {39.3800511, 60.8290437}, {39.380368, 60.8291926}, + {39.3813391, 60.8294595}, {39.3816013, 60.8295727}, {39.3816809, 60.8298718}, + {39.3814362, 60.8302966}, {39.3812645, 60.8306791}, {39.3812541, 60.8310957}, + {39.3812949, 60.8313723}, {39.3814327, 60.8316467}, {39.3816684, 60.831792}, + {39.3822807, 60.8320161}, {39.3827056, 60.8322488}, {39.3828635, 60.8322914}, + {39.3831305, 60.8321476}, {39.3833097, 60.8320007}, {39.3838486, 60.8321324}, + {39.3842229, 60.8320212}, {39.3843725, 60.8319997}, {39.3845821, 60.8321574}, + {39.384562, 60.8324584}, {39.3845906, 60.8325979}, {39.3847337, 60.8326635}, + {39.385011, 60.8325855}, {39.3853766, 60.8326382}, {39.385551, 60.8328485}, + {39.3856408, 60.8331878}, {39.3855226, 60.833594}, {39.3855011, 60.8338457}, + {39.3855795, 60.8341481}, {39.385578, 60.8349811}, {39.3853598, 60.8356313}, + {39.3849157, 60.8361986}, {39.3845801, 60.8364215}, {39.3844606, 60.8366083}, + {39.3843759, 60.8371015}, {39.3844225, 60.8375956}, {39.3846578, 60.8380749}, + {39.384792, 60.8381866}, {39.38477, 60.8383973}, {39.3845393, 60.8385249}, + {39.3843197, 60.8385492}, {39.3839706, 60.8384339}, {39.3838097, 60.8384004}, + {39.3834946, 60.8385605}, {39.383468, 60.8388494}, {39.3834711, 60.8393577}, + {39.3833329, 60.8395251}, {39.3830942, 60.8395518}, {39.3826302, 60.8395384}, + {39.3819684, 60.8394877}, {39.3818684, 60.8391899}, {39.3817406, 60.8389632}, + {39.381458, 60.8388598}, {39.3812456, 60.8389812}, {39.3813186, 60.8397127}, + {39.3814742, 60.8403711}, {39.3816794, 60.8409309}, {39.3823271, 60.8415473}, + {39.3830653, 60.8420778}, {39.3833168, 60.8425103}, {39.3835612, 60.8432301}, + {39.3842663, 60.8435189}, {39.3846739, 60.8435511}, {39.3849843, 60.8437981}, + {39.3850938, 60.8449307}, {39.3853713, 60.845611}, {39.385822, 60.8461475}, + {39.386629, 60.8472838}, {39.387088, 60.8480411}, {39.3875296, 60.8486492}, + {39.3877639, 60.8488458}, {39.3881147, 60.8486562}, {39.3881169, 60.8481316}, + {39.3882105, 60.847843}, {39.3884451, 60.8477513}, {39.3886332, 60.8479778}, + {39.3889334, 60.8486955}, {39.3890308, 60.8495479}, {39.3891372, 60.850439}, + {39.389048, 60.8513337}, {39.3882467, 60.8526276}, {39.3873171, 60.8538228}, + {39.3873981, 60.8540237}, {39.3878632, 60.8542075}, {39.3881126, 60.854304}, + {39.3882951, 60.8544832}, {39.3883755, 60.8549049}, {39.388322, 60.8553333}, + {39.3878685, 60.8562486}, {39.3876164, 60.85671}, {39.3873583, 60.8572544}, + {39.3870869, 60.8582247}, {39.3868064, 60.8589522}, {39.3863113, 60.8595507}, + {39.3861009, 60.8596524}, {39.3858507, 60.8596066}, {39.3857465, 60.8593609}, + {39.3857549, 60.858888}, {39.3856396, 60.8585902}, {39.385232, 60.8585463}, + {39.3850596, 60.8585983}, {39.3851027, 60.8588635}, {39.3847504, 60.8590424}, + {39.3841551, 60.8592563}, {39.3839161, 60.8591185}, {39.3834614, 60.8590347}, + {39.3829781, 60.8590745}, {39.3826127, 60.8591919}, {39.3824131, 60.8594582}, + {39.3821259, 60.8598699}, {39.3817799, 60.8604711}, {39.3817166, 60.8609792}, + {39.3815385, 60.8614334}, {39.3812343, 60.8618045}, {39.3805543, 60.8625275}, + {39.3802341, 60.8627124}, {39.3798766, 60.8625683}, {39.3797786, 60.862334}, + {39.3797526, 60.8621373}, {39.3794166, 60.8626059}, {39.3794138, 60.8630614}, + {39.3794765, 60.8634835}, {39.3787556, 60.86397}, {39.3781866, 60.8645389}, + {39.3781866, 60.8645389}, {39.3780521, 60.8648428}, {39.3780551, 60.8654606}, + {39.3782602, 60.8659295}, {39.3792151, 60.8675964}, {39.3796791, 60.8687858}, + {39.379858, 60.8689957}, {39.3799276, 60.869532}, {39.3804858, 60.8697163}, + {39.3803013, 60.8702216}, {39.3803013, 60.8702216}, {39.3794977, 60.8701099}, + {39.3790968, 60.8701244}, {39.3786931, 60.8701306}, {39.3784357, 60.8697873}, + {39.3779207, 60.8696156}, {39.3776632, 60.8697748}, {39.3776632, 60.8697748}, + {39.3775627, 60.8707246}, {39.3760324, 60.8721779}, {39.3747449, 60.8728646}, + {39.3736018, 60.8734027}, {39.3721808, 60.8729211}, {39.3713117, 60.8734654}, + {39.3706666, 60.8739563}, {39.3698903, 60.8744567}, {39.3697467, 60.8746338}, + {39.3697467, 60.8746338}, {39.3651032, 60.8741594}, {39.3623772, 60.8743899}, + {39.3619106, 60.8750592}, {39.35963, 60.8784419}, {39.3577467, 60.8771992}, + {39.3577467, 60.8771992}, {39.3584476, 60.876563}, {39.3596633, 60.8750168}, + {39.3607623, 60.8722916}, {39.3612547, 60.8698211}, {39.3610701, 60.8678383}, + {39.3604116, 60.8663375}, {39.3591175, 60.8640173}, {39.3576198, 60.862279}, + {39.3559492, 60.8612081}, {39.3533183, 60.8606785}, {39.3516485, 60.8608173}, + {39.3495838, 60.861753}, {39.3481542, 60.8629834}, {39.3468653, 60.8634882}, + {39.3448637, 60.8635396}, {39.3432535, 60.863444}, {39.3416705, 60.8634735}, + {39.340865, 60.8640445}, {39.3400605, 60.8651296}, {39.3397396, 60.8666589}, + {39.340082, 60.868477}, {39.338931, 60.869521}, {39.3380439, 60.8696681}, + {39.3372596, 60.8694313}, {39.3367697, 60.868585}, {39.3362405, 60.8661394}, + {39.3360555, 60.8650941}, {39.335879, 60.8637611}, {39.3355401, 60.8625104}, + {39.335138, 60.8618518}, {39.3344714, 60.8611916}, {39.3337305, 60.860707}, + {39.3326791, 60.8606663}, {39.3317135, 60.8609024}, {39.331335, 60.8614871}, + {39.3314095, 60.8622361}, {39.3312192, 60.8629754}, {39.3309226, 60.8635815}, + {39.3301472, 60.8642496}, {39.3293692, 60.8648009}, {39.3285991, 60.8650711}, + {39.3275926, 60.8650093}, {39.325406, 60.8642403}, {39.3229466, 60.8634342}, + {39.3210379, 60.8625649}, {39.3191178, 60.8615676}, {39.3176468, 60.8601464}, + {39.3166931, 60.8582631}, {39.3166287, 60.8558169}, {39.3142039, 60.8504311}, + {39.3137749, 60.8472768}, {39.3073805, 60.8409467}, {39.3023594, 60.835754}, + {39.3013723, 60.8325568}, {39.301298, 60.8314029}, {39.3006441, 60.8269189}, + {39.3006656, 60.8196877}, {39.3002794, 60.8166191}, {39.299464, 60.8152888}, + {39.2985627, 60.8146237}, {39.2969105, 60.814452}, {39.294872, 60.8153747}, + {39.2934557, 60.8160184}, {39.2919109, 60.815482}, {39.2904517, 60.8125851}, + {39.2887137, 60.8110187}, {39.2868898, 60.8105038}, {39.2835638, 60.8105252}, + {39.2819545, 60.8092378}, {39.2814395, 60.8082293}, {39.2814854, 60.8069483}, + {39.2814854, 60.8069483}, {39.2816326, 60.8028434}, {39.281182, 60.7990669}, + {39.280946, 60.7973288}, {39.28071, 60.7942388}, {39.2805383, 60.7924364}, + {39.2792079, 60.7888315}, {39.2745731, 60.7830594}, {39.2721054, 60.779991}, + {39.2721054, 60.779991}, {39.2715261, 60.7779377}, {39.2699544, 60.7788766}, + {39.2691013, 60.7788979}, {39.2686684, 60.7786448}, {39.2677625, 60.7783024}, + {39.2677979, 60.779531}, {39.2680071, 60.7797348}, {39.2674814, 60.7800407}, + {39.2660168, 60.7815211}, {39.2649118, 60.781135}, {39.2651917, 60.780231}, + {39.2644066, 60.7784397}, {39.2636814, 60.7778193}, {39.2627148, 60.7771125}, + {39.2625354, 60.7773101}, {39.2622081, 60.7772995}, {39.2618863, 60.7771224}, + {39.2606954, 60.7789033}, {39.2597564, 60.7774719}, {39.25958, 60.7771295}, + {39.2590646, 60.7750195}, {39.2574105, 60.7747104}, {39.2567201, 60.7747829}, + {39.2568648, 60.7756567}, {39.2567008, 60.7758306}, {39.2570049, 60.7765162}, + {39.2566863, 60.7767093}, {39.2568505, 60.7770569}, {39.2568505, 60.7770569}, + {39.2556808, 60.7783458}, {39.2554196, 60.7783658}, {39.2543546, 60.7778033}, + {39.2541939, 60.7766781}, {39.2538322, 60.776477}, {39.2527472, 60.7745081}, + {39.2498072, 60.7754807}, {39.2470979, 60.7797799}, {39.2466792, 60.7809377}, + {39.2392047, 60.7828666}, {39.239044, 60.7826657}, {39.2496529, 60.7740659}, + {39.2519499, 60.7731652}, {39.2527455, 60.7714035}, {39.2521772, 60.7687893}, + {39.2510406, 60.7675958}, {39.2489947, 60.7669706}, {39.24621, 60.7684482}, + {39.244849, 60.7702758}, {39.2453053, 60.7725699}, {39.2397881, 60.7750974}, + {39.2327979, 60.7728243}, {39.2302974, 60.7724265}, {39.2256372, 60.774586}, + {39.2210339, 60.7690734}, {39.2229377, 60.7688548}, {39.2250412, 60.7680861}, + {39.2294021, 60.7652243}, {39.2268569, 60.7611643}, {39.2223259, 60.7553317}, + {39.2186797, 60.7547686}, {39.2186797, 60.7547686}, {39.2166289, 60.7546763}, + {39.21481, 60.7541095}, {39.2114927, 60.7501929}, {39.2010451, 60.7310453}, + {39.1947324, 60.7186209}, {39.1940148, 60.7186303}, {39.1940148, 60.7186303}, + {39.1929596, 60.7135347}, {39.1929596, 60.7135347}, {39.1929381, 60.7135384}, + {39.1926754, 60.7135833}, {39.1922298, 60.7136597}, {39.1922298, 60.7136597}, + {39.1919116, 60.713705}, {39.1888979, 60.7141327}, {39.1888979, 60.7141327}, + {39.1880892, 60.7106502}, {39.1879727, 60.709759}, {39.187914, 60.7091062}, + {39.1878863, 60.7087296}, {39.1883355, 60.708664}, {39.1882423, 60.7081112}, + {39.1879348, 60.7082149}, {39.1878899, 60.7081112}, {39.1876061, 60.7080739}, + {39.1874603, 60.7080249}, {39.1871713, 60.7079178}, {39.1866739, 60.7078659}, + {39.1863975, 60.7080249}, {39.1859173, 60.7080835}, {39.1853897, 60.7080567}, + {39.1849811, 60.7082149}, {39.1848118, 60.7084602}, {39.1847427, 60.7084326}, + {39.1846667, 60.7082666}, {39.1842382, 60.7083495}, {39.1833747, 60.7085568}, + {39.1832641, 60.7089335}, {39.1830843, 60.7089366}, {39.1829112, 60.7091836}, + {39.1834477, 60.7117371}, {39.1807226, 60.7118014}, {39.1807226, 60.7118014}, + {39.1804479, 60.7116133}, {39.1804479, 60.7116133}, {39.1711657, 60.6934705}, + {39.1711657, 60.6934705}, {39.1693903, 60.6900539}, {39.1693903, 60.6900539}, + {39.1670095, 60.6905592}, {39.1666335, 60.6892093}, {39.1653307, 60.6894434}, + {39.1653307, 60.6894434}, {39.1621514, 60.6895132}, {39.162135, 60.6902023}, + {39.1617133, 60.6902371}, {39.1616998, 60.6918047}, {39.1602775, 60.6918381}, + {39.1602495, 60.6913286}, {39.1591231, 60.6912582}, {39.1590514, 60.6902413}, + {39.1590027, 60.6895466}, {39.1581001, 60.6895481}, {39.1579375, 60.6887479}, + {39.1578532, 60.6877115}, {39.1583431, 60.6876104}, {39.1582188, 60.6869091}, + {39.1602567, 60.6866911}, {39.1604119, 60.6860273}, {39.1613131, 60.6860048}, + {39.1615707, 60.6856018}, {39.1626644, 60.6855198}, {39.1636792, 60.686174}, + {39.1636792, 60.686174}, {39.1645831, 60.6865985}, {39.1649631, 60.6877367}, + {39.1655263, 60.6876563}, {39.1658424, 60.6889681}, {39.1686459, 60.6884462}, + {39.166694, 60.684668}, {39.1652889, 60.6819339}, {39.1649497, 60.6810895}, + {39.1647075, 60.6804319}, {39.1644514, 60.6795253}, {39.1641537, 60.6783486}, + {39.164043, 60.6776702}, {39.163953, 60.6766874}, {39.1639288, 60.675964}, + {39.1639426, 60.6752095}, {39.1638645, 60.6751932}, {39.1638645, 60.6751932}, + {39.1636553, 60.6748951}, {39.1636553, 60.6748951}, {39.1633664, 60.6755132}, + {39.1620407, 60.6747767}, {39.1616145, 60.6754307}, {39.1613494, 60.6757161}, + {39.1613458, 60.6757199}, {39.1610141, 60.6761691}, {39.1610141, 60.6761691}, + {39.1607881, 60.6764753}, {39.1607881, 60.6764753}, {39.1607335, 60.6765493}, + {39.1603395, 60.6772572}, {39.1597249, 60.6783615}, {39.1592714, 60.6779979}, + {39.1592714, 60.6779979}, {39.1585192, 60.6778193}, {39.1587072, 60.6771141}, + {39.1584954, 60.6769636}, {39.153677, 60.677415}, {39.1526708, 60.6774055}, + {39.1507262, 60.6777029}, {39.1506764, 60.6777104}, {39.1498955, 60.6777726}, + {39.1489879, 60.677845}, {39.1459251, 60.6780892}, {39.1448019, 60.6781787}, + {39.1447123, 60.6778187}, {39.1441157, 60.6747943}, {39.1436984, 60.6734998}, + {39.1430578, 60.6734985}, {39.1423721, 60.6736492}, {39.141898, 60.6738049}, + {39.1419971, 60.6740951}, {39.1419152, 60.6741379}, {39.1417029, 60.6742298}, + {39.1415443, 60.674116}, {39.1413853, 60.6782394}, {39.1383174, 60.6771543}, + {39.140506, 60.6743414}, {39.1403559, 60.6743203}, {39.1403188, 60.6743119}, + {39.1399996, 60.6742392}, {39.1399055, 60.6740685}, {39.1398745, 60.6740123}, + {39.1398244, 60.6739084}, {39.139655, 60.6735578}, {39.1391778, 60.673296}, + {39.1391651, 60.673289}, {39.1387829, 60.6734893}, {39.1382804, 60.6733415}, + {39.1382804, 60.6733415}, {39.1364566, 60.6730238}, {39.1364566, 60.6730238}, + {39.1373136, 60.6676373}, {39.1367211, 60.6666879}, {39.1367863, 60.6657977}, + {39.1367137, 60.6645684}, {39.1363525, 60.6624237}, {39.1359295, 60.6604454}, + {39.1354017, 60.6598115}, {39.1349164, 60.6591683}, {39.1347061, 60.6589603}, + {39.1344061, 60.658079}, {39.1343154, 60.6544093}, {39.1337902, 60.6528918}, + {39.1332648, 60.6514345}, {39.1333174, 60.6507274}, {39.1322643, 60.6495766}, + {39.1311812, 60.6489146}, {39.1305346, 60.6478046}, {39.1306199, 60.6476437}, + {39.1296723, 60.6458906}, {39.1286388, 60.6442886}, {39.1275695, 60.6431144}, + {39.1260609, 60.6413089}, {39.1237516, 60.6380907}, {39.122466, 60.6371541}, + {39.1202441, 60.6361074}, {39.116608, 60.6347668}, {39.11479, 60.6346566}, + {39.11479, 60.6346566}, {39.1131669, 60.6350372}, {39.1121312, 60.6307225}, + {39.1115117, 60.6271944}, {39.110867, 60.6268382}, {39.1102702, 60.6205945}, + {39.1096733, 60.618804}, {39.1080206, 60.6149476}, {39.1059726, 60.6114809}, + {39.1042772, 60.6090386}, {39.1034517, 60.6078495}, {39.1020356, 60.6054971}, + {39.0987634, 60.6035601}, {39.0974232, 60.603347}, {39.0961428, 60.6023463}, + {39.094699, 60.6018808}, {39.093164, 60.6019453}, {39.0927901, 60.6020344}, + {39.0927901, 60.6020344}, {39.0908621, 60.6024938}, {39.0898627, 60.6025409}, + {39.0884213, 60.6031724}, {39.0869069, 60.6024131}, {39.0874503, 60.6036316}, + {39.0870531, 60.603939}, {39.0839177, 60.6059448}, {39.0842168, 60.606579}, + {39.082394, 60.6089421}, {39.0816136, 60.6089045}, {39.0816042, 60.6103149}, + {39.0806546, 60.6121577}, {39.0808425, 60.613521}, {39.0804947, 60.6159562}, + {39.0790932, 60.6201271}, {39.0775616, 60.622367}, {39.0746668, 60.6243017}, + {39.0728914, 60.6250398}, {39.0702083, 60.6250341}, {39.0689044, 60.624171}, + {39.0679128, 60.6219857}, {39.0673435, 60.6208472}, {39.0675639, 60.6144565}, + {39.0653602, 60.6134833}, {39.0644053, 60.6125098}, {39.0634503, 60.6102143}, + {39.0630087, 60.6073537}, {39.0630266, 60.6063403}, {39.06134, 60.6035438}, + {39.0592917, 60.601363}, {39.0577895, 60.598861}, {39.0612667, 60.5957567}, + {39.0649022, 60.5943114}, {39.0595021, 60.5902343}, {39.056567, 60.591372}, + {39.0554101, 60.5864061}, {39.0546168, 60.583958}, {39.0521549, 60.5821625}, + {39.0440392, 60.5818647}, {39.0430364, 60.5813185}, {39.0430364, 60.5813185}, + {39.0442178, 60.5785956}, {39.0460675, 60.5728621}, {39.0493924, 60.573944}, + {39.0516316, 60.5730794}, {39.0576664, 60.5756923}, {39.0650254, 60.5692313}, + {39.07058, 60.56373}, {39.0713164, 60.5630871}, {39.0702443, 60.5616339}, + {39.0737686, 60.5553721}, {39.0731672, 60.5549277}, {39.0761617, 60.5522271}, + {39.0799856, 60.5435022}, {39.0845975, 60.5422713}, {39.0849514, 60.5405316}, + {39.0849514, 60.5405316}, {39.0831578, 60.539268}, {39.0817256, 60.5375887}, + {39.0817416, 60.5349443}, {39.0819822, 60.5322787}, {39.082949, 60.5265732}, + {39.0855607, 60.5203736}, {39.0857793, 60.5197705}, {39.0858319, 60.5194978}, + {39.0858319, 60.5194978}, {39.0839032, 60.5197573}, {39.0656917, 60.5221284}, + {39.0634815, 60.5224153}, {39.0634138, 60.5219218}, {39.0635885, 60.5218609}, + {39.0639711, 60.5211452}, {39.0639756, 60.5208753}, {39.0635833, 60.5198633}, + {39.0617735, 60.5163554}, {39.0598699, 60.5127537}, {39.0594012, 60.511903}, + {39.058947, 60.5114991}, {39.0583233, 60.5112972}, {39.0580817, 60.5111567}, + {39.0578654, 60.5109332}, {39.0574796, 60.5102913}, {39.0573895, 60.5099669}, + {39.0574111, 60.5093541}, {39.0573895, 60.508871}, {39.0572705, 60.5083661}, + {39.0565315, 60.5065671}, {39.0558717, 60.5052836}, {39.0549416, 60.504029}, + {39.0534959, 60.5024211}, {39.0514804, 60.5001536}, {39.0511669, 60.4997965}, + {39.0496022, 60.4980337}, {39.0489208, 60.497071}, {39.0482539, 60.4972836}, + {39.0478373, 60.4969471}, {39.0473653, 60.496974}, {39.0464962, 60.4956651}, + {39.048701, 60.495083}, {39.0490182, 60.4951783}, {39.049436, 60.4954571}, + {39.0499384, 60.494985}, {39.0532603, 60.4986839}, {39.0566832, 60.5031153}, + {39.05748, 60.5039807}, {39.0584321, 60.505753}, {39.0594408, 60.5078646}, + {39.0605908, 60.5108811}, {39.061255, 60.5122011}, {39.0623819, 60.5141428}, + {39.063243, 60.5154205}, {39.0640309, 60.516751}, {39.0646518, 60.5176693}, + {39.0650901, 60.5191406}, {39.0656723, 60.5212038}, {39.0658838, 60.5215053}, + {39.0662078, 60.5216313}, {39.0829915, 60.5194067}, {39.0873385, 60.5189737}, + {39.0832019, 60.5141536}, {39.0831376, 60.5138536}, {39.0831376, 60.5138536}, + {39.0826737, 60.5122797}, {39.0821455, 60.5121339}, {39.0814726, 60.5113937}, + {39.0799613, 60.5079542}, {39.0785289, 60.5025001}, {39.0785289, 60.5025001}, + {39.074534, 60.4989445}}); + + auto const areaPart2 = + MakeFbForTest({{"name", "Voronezh"}, {"place", "city"}}, OsmElement::EntityType::Relation, + {{39.5946606, 60.8875289}, {39.5968517, 60.8869367}, {39.5972678, 60.8879075}, + {39.5986103, 60.8876559}, {39.5982294, 60.8865667}, {39.6055335, 60.8844839}, + {39.6191364, 60.8802595}, {39.6286584, 60.877039}, {39.6301079, 60.8766673}, + {39.6313778, 60.8764702}, {39.6317262, 60.876505}, {39.6325422, 60.8765938}, + {39.634078, 60.8770359}, {39.6347191, 60.8773924}, {39.635447, 60.8781113}, + {39.6368783, 60.880108}, {39.6377176, 60.8808965}, {39.6390401, 60.8816509}, + {39.6423185, 60.8824302}, {39.6456165, 60.8833201}, {39.6470101, 60.8836975}, + {39.6476579, 60.8837482}, {39.6485349, 60.8836432}, {39.6513069, 60.8828246}, + {39.6513069, 60.8828246}, {39.6521335, 60.8832661}, {39.6524211, 60.8836576}, + {39.6527818, 60.8842148}, {39.6539063, 60.8844241}, {39.6551225, 60.8846202}, + {39.6543976, 60.8849724}, {39.6493714, 60.8884477}, {39.6426274, 60.8919149}, + {39.6414069, 60.8920628}, {39.6430342, 60.8942449}, {39.6453643, 60.8938381}, + {39.6473183, 60.8928851}, {39.6472667, 60.8923942}, {39.6472517, 60.8916301}, + {39.6477421, 60.8907508}, {39.6488097, 60.8908887}, {39.6493376, 60.8912966}, + {39.6495535, 60.8919444}, {39.65005, 60.8931992}, {39.6548359, 60.8920746}, + {39.6567973, 60.8927024}, {39.6583664, 60.8925716}, {39.6596479, 60.8914732}, + {39.658968, 60.8908717}, {39.6589023, 60.8870805}, {39.6589523, 60.8856009}, + {39.6587403, 60.8855838}, {39.658523, 60.886978}, {39.6581896, 60.8878542}, + {39.6572372, 60.8880021}, {39.6563773, 60.8860512}, {39.6554342, 60.884433}, + {39.6541187, 60.88422}, {39.6530963, 60.884057}, {39.6525504, 60.8831694}, + {39.6518007, 60.8826616}, {39.651681, 60.8824671}, {39.651681, 60.8824671}, + {39.6509013, 60.8826646}, {39.6491612, 60.8831207}, {39.6481088, 60.8834785}, + {39.6474002, 60.8835556}, {39.6468108, 60.8834012}, {39.6453725, 60.8829943}, + {39.6437508, 60.882597}, {39.6419565, 60.8821976}, {39.6401832, 60.8816778}, + {39.6388317, 60.8811563}, {39.6376584, 60.880528}, {39.6370055, 60.8798228}, + {39.6359197, 60.8783514}, {39.6352398, 60.8775649}, {39.6345547, 60.877022}, + {39.6333095, 60.8765653}, {39.6322361, 60.8763473}, {39.6319032, 60.8763006}, + {39.6319032, 60.8763006}, {39.6319195, 60.8760831}, {39.6320477, 60.8758773}, + {39.6368601, 60.8743827}, {39.637021, 60.8744846}, {39.6379222, 60.8761046}, + {39.6384694, 60.8766357}, {39.6380831, 60.8768772}, {39.6385445, 60.8774512}, + {39.6390112, 60.8771132}, {39.6396979, 60.8779178}, {39.6404489, 60.8782772}, + {39.6418972, 60.8775853}, {39.6443005, 60.8784059}, {39.6446278, 60.8776925}, + {39.6475353, 60.8755574}, {39.6462264, 60.8736316}, {39.6450676, 60.8754233}, + {39.6425195, 60.8745544}, {39.6398856, 60.8729022}, {39.6411302, 60.8718775}, + {39.6405614, 60.8709118}, {39.6391775, 60.8719042}, {39.6392258, 60.8723549}, + {39.6386357, 60.8729022}, {39.6382119, 60.8726231}, {39.6377667, 60.8730737}, + {39.6378471, 60.8733527}, {39.6377452, 60.8735082}, {39.6367384, 60.8740927}, + {39.6318283, 60.8755843}, {39.6314688, 60.8759545}, {39.6313685, 60.8762914}, + {39.6313685, 60.8762914}, {39.630195, 60.8764159}, {39.5945785, 60.8871764}, + {39.5919657, 60.8781552}, {39.5928287, 60.8769627}, {39.6005411, 60.8735968}, + {39.6005411, 60.8735968}, {39.5976054, 60.8676474}, {39.5939809, 60.8687199}, + {39.5943137, 60.8704582}, {39.5845174, 60.8784659}, {39.5837184, 60.8780203}, + {39.5830939, 60.8782535}, {39.5835092, 60.8799295}, {39.5839792, 60.8802805}, + {39.5835354, 60.8831493}, {39.5842152, 60.8842446}, {39.5833523, 60.88414}, + {39.5821493, 60.8843753}, {39.5816001, 60.8860492}, {39.5811293, 60.8876967}, + {39.5813124, 60.8858399}, {39.5812601, 60.88482}, {39.5800308, 60.8848462}, + {39.5799262, 60.8872783}, {39.5796125, 60.8888735}, {39.5803448, 60.8898673}, + {39.5797956, 60.8905213}, {39.5782003, 60.8908351}, {39.5781146, 60.8905414}, + {39.5779781, 60.8905736}, {39.5740415, 60.8774795}, {39.5753507, 60.8771213}, + {39.5744063, 60.8734868}, {39.576217, 60.8732588}, {39.5756113, 60.8723404}, + {39.5754029, 60.8714806}, {39.574771, 60.870901}, {39.5729864, 60.8714415}, + {39.5728675, 60.871084}, {39.5728557, 60.8710875}, {39.5719833, 60.8713504}, + {39.5778618, 60.8906084}, {39.575843, 60.8911816}, {39.5753602, 60.8896041}, + {39.5765571, 60.8892074}, {39.5762171, 60.8880236}, {39.5743435, 60.8887027}, + {39.5702105, 60.8899383}, {39.5715808, 60.894876}, {39.5756376, 60.8934816}, + {39.575804, 60.8963848}, {39.5781623, 60.8954654}, {39.5771915, 60.8972755}, + {39.5764625, 60.8995225}, {39.5753972, 60.899806}, {39.5757272, 60.9020424}, + {39.5756667, 60.9085222}, {39.573761, 60.9090449}, {39.5739187, 60.9098494}, + {39.5730671, 60.9101433}, {39.5734202, 60.911451}, {39.5754811, 60.9111958}, + {39.5749125, 60.911625}, {39.5742956, 60.9120541}, {39.5735431, 60.9123752}, + {39.5714563, 60.9134857}, {39.5693639, 60.9155454}, {39.5686132, 60.9165059}, + {39.5681947, 60.9168706}, {39.566623, 60.9191666}, {39.565593, 60.9203736}, + {39.5648849, 60.9209153}, {39.5635974, 60.9213983}, {39.5624923, 60.9220313}, + {39.5616555, 60.9226857}, {39.5585468, 60.9220115}, {39.5584681, 60.9214718}, + {39.557726, 60.9215394}, {39.557773, 60.9236148}, {39.5559214, 60.9238989}, + {39.5558128, 60.9234483}, {39.5548729, 60.9236425}, {39.5550671, 60.9241629}, + {39.5556807, 60.9241862}, {39.5553234, 60.9255455}, {39.5520851, 60.926314}, + {39.5523514, 60.9275486}, {39.5551958, 60.9271128}, {39.5554258, 60.9285653}, + {39.5578103, 60.9285412}, {39.5581855, 60.9253456}, {39.5581065, 60.9247773}, + {39.5581492, 60.9242442}, {39.5582759, 60.9239838}, {39.5585549, 60.9236781}, + {39.5592254, 60.9234099}, {39.5601642, 60.9232007}, {39.5612425, 60.9231255}, + {39.5618486, 60.9228252}, {39.5627015, 60.9221813}, {39.563694, 60.9215806}, + {39.5649922, 60.9211138}, {39.565786, 60.9204969}, {39.5668375, 60.9192899}, + {39.5683503, 60.9170369}, {39.5688492, 60.9166025}, {39.5695037, 60.9156851}, + {39.5699787, 60.915234}, {39.5716011, 60.9136466}, {39.5736557, 60.9125361}, + {39.5744404, 60.9121829}, {39.575111, 60.9116786}, {39.5756098, 60.9112709}, + {39.5763403, 60.9116227}, {39.5775238, 60.9108459}, {39.5785224, 60.9087748}, + {39.5798354, 60.9086454}, {39.5798539, 60.9028942}, {39.5837002, 60.9017662}, + {39.5841002, 60.9034228}, {39.5880699, 60.9034358}, {39.59398, 60.9018506}, + {39.59533, 60.9044951}, {39.5967909, 60.9043656}, {39.5960327, 60.9024609}, + {39.5987153, 60.9017024}, {39.5946606, 60.8875289}}); + + auto table = std::make_shared(); + generator::PlaceProcessor pp(table); + pp.Add(areaPart1); + pp.Add(areaPart2); + pp.Add(point); + + std::vector r{point}; + TEST_EQUAL(pp.ProcessPlaces(), r, ()); + TEST(TestTable(*table, {{{point.GetMostGenericOsmId(), areaPart1.GetMostGenericOsmId()}, + 2 /* cluster size */}}), + ()); +} + +UNIT_CLASS_TEST(TestPlaceProcessor, KuznetsovoNearbyHamletsTest) +{ + auto const point1 = MakeFbForTest({{"name", "Кузнецово"}, {"place", "hamlet"}}, + OsmElement::EntityType::Node, {{39.5338039, 71.44840478}}); + + auto const way1 = + MakeFbForTest({{"name", "Кузнецово"}, {"place", "hamlet"}}, OsmElement::EntityType::Way, + {{39.5300791, 71.4499322}, + {39.5360952, 71.449952}, + {39.5358614, 71.4481361}, + {39.533932, 71.4479877}, + {39.5334559, 71.4466931}, + {39.5328246, 71.4468055}, + {39.531898, 71.447587}, + {39.5305723, 71.4482665}, + {39.5300791, 71.4499322}}); + + auto const point2 = MakeFbForTest({{"name", "Кузнецово"}, {"place", "hamlet"}}, + OsmElement::EntityType::Node, {{39.6701222, 71.52284624}}); + + auto const way2 = + MakeFbForTest({{"name", "Кузнецово"}, {"place", "hamlet"}}, OsmElement::EntityType::Way, + {{39.6670159, 71.5224511}, + {39.6719028, 71.525375}, + {39.6732332, 71.5231513}, + {39.6683465, 71.5202275}, + {39.6670159, 71.5224511}}); + + auto const point3 = MakeFbForTest({{"name", "Кузнецово"}, {"place", "hamlet"}}, + OsmElement::EntityType::Node, {{39.9688407, 71.45936188}}); + + auto const way3 = + MakeFbForTest({{"name", "Кузнецово"}, {"place", "hamlet"}}, OsmElement::EntityType::Way, + {{39.9694614, 71.4609508}, + {39.9695483, 71.460343}, + {39.9698434, 71.4598916}, + {39.970373, 71.4583027}, + {39.9703469, 71.458025}, + {39.9701473, 71.4578426}, + {39.969036, 71.458485}, + {39.9685064, 71.4579208}, + {39.968246, 71.4578946}, + {39.967647, 71.4588411}, + {39.9676383, 71.4589973}, + {39.9680029, 71.4591536}, + {39.9681505, 71.459414}, + {39.9670826, 71.4609508}, + {39.9690534, 71.461055}, + {39.9694614, 71.4609508}}); + + auto table = std::make_shared(); + generator::PlaceProcessor pp(table); + pp.Add(point1); + pp.Add(point2); + pp.Add(point3); + pp.Add(way1); + pp.Add(way2); + pp.Add(way3); + std::vector r{point1, point2, point3}; + TEST_EQUAL(pp.ProcessPlaces(), r, ()); + TEST( + TestTable( + *table, + {{{point1.GetMostGenericOsmId(), way1.GetMostGenericOsmId()}, 1 /* cluster size */}, + {{point2.GetMostGenericOsmId(), way2.GetMostGenericOsmId()}, 1 /* cluster size */}, + {{point3.GetMostGenericOsmId(), way3.GetMostGenericOsmId()}, 1 /* cluster size */}}), + ()); +} +} // namespace diff --git a/generator/place.cpp b/generator/place.cpp deleted file mode 100644 index c9d776ab22..0000000000 --- a/generator/place.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "generator/place.hpp" - -#include "indexer/classificator.hpp" -#include "indexer/ftypes_matcher.hpp" - -#include "geometry/mercator.hpp" - -using namespace feature; - -namespace generator -{ -Place::Place(FeatureBuilder const & ft, uint32_t type, bool saveParams) : - m_ft(ft), - m_pt(ft.GetKeyPoint()), - m_type(type) -{ - using namespace ftypes; - - if (!saveParams) - m_ft.SetParams({}/* params */); - - switch (IsLocalityChecker::Instance().GetType(m_type)) - { - case COUNTRY: m_thresholdM = 300000.0; break; - case STATE: m_thresholdM = 100000.0; break; - case CITY: m_thresholdM = 30000.0; break; - case TOWN: m_thresholdM = 20000.0; break; - case VILLAGE: m_thresholdM = 10000.0; break; - default: m_thresholdM = 10000.0; break; - } -} - -m2::RectD Place::GetLimitRect() const -{ - return MercatorBounds::RectByCenterXYAndSizeInMeters(m_pt, m_thresholdM); -} - -bool Place::IsEqual(Place const & r) const -{ - return (AreTypesEqual(m_type, r.m_type) && - m_ft.GetName() == r.m_ft.GetName() && - (IsPoint() || r.IsPoint()) && - MercatorBounds::DistanceOnEarth(m_pt, r.m_pt) < m_thresholdM); -} - -bool Place::IsBetterThan(Place const & r) const -{ - // Check ranks. - uint8_t const r1 = m_ft.GetRank(); - uint8_t const r2 = r.m_ft.GetRank(); - if (r1 != r2) - return r1 > r2; - - // Check types length. - // ("place-city-capital-2" is better than "place-city"). - uint8_t const l1 = ftype::GetLevel(m_type); - uint8_t const l2 = ftype::GetLevel(r.m_type); - if (l1 != l2) - return l1 > l2; - - // Assume that area places has better priority than point places at the very end ... - /// @todo It was usefull when place=XXX type has any area fill style. - /// Need to review priority logic here (leave the native osm label). - return !IsPoint() && r.IsPoint(); -} - -bool Place::AreTypesEqual(uint32_t t1, uint32_t t2) -{ - // Use 2-arity places comparison for filtering. - // ("place-city-capital-2" is equal to "place-city") - ftype::TruncValue(t1, 2); - ftype::TruncValue(t2, 2); - return (t1 == t2); -} -} // namespace generator diff --git a/generator/place.hpp b/generator/place.hpp deleted file mode 100644 index b96ec87a68..0000000000 --- a/generator/place.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include "generator/feature_builder.hpp" - -#include "geometry/point2d.hpp" -#include "geometry/rect2d.hpp" - -#include - -namespace generator -{ -/// Used to make a "good" node for a highway graph with OSRM for low zooms. -class Place -{ -public: - Place(feature::FeatureBuilder const & ft, uint32_t type, bool saveParams = true); - - feature::FeatureBuilder const & GetFeature() const { return m_ft; } - m2::RectD GetLimitRect() const; - bool IsEqual(Place const & r) const; - /// Check whether we need to replace place @r with place @this. - bool IsBetterThan(Place const & r) const; - -private: - bool IsPoint() const { return (m_ft.GetGeomType() == feature::GeomType::Point); } - static bool AreTypesEqual(uint32_t t1, uint32_t t2); - - feature::FeatureBuilder m_ft; - m2::PointD m_pt; - uint32_t m_type; - double m_thresholdM; -}; -} // namespace generator diff --git a/generator/place_processor.cpp b/generator/place_processor.cpp index 6d56b32f9f..7a7cd45d79 100644 --- a/generator/place_processor.cpp +++ b/generator/place_processor.cpp @@ -1,69 +1,245 @@ #include "generator/place_processor.hpp" +#include "generator/feature_maker_base.hpp" #include "generator/type_helper.hpp" #include "indexer/classificator.hpp" +#include "indexer/ftypes_matcher.hpp" + +#include "geometry/mercator.hpp" #include "base/assert.hpp" +#include +#include +#include +#include + using namespace feature; namespace generator { +uint32_t GetPlaceType(generator::FeaturePlace const & place) +{ + return GetPlaceType(place.GetFb()); +} +} // namespace generator + namespace { -std::shared_ptr -GetOrCreateBoundariesTable(std::shared_ptr boundariesTable) +using namespace generator; + +double GetThresholdM(ftypes::Type const & type) { - return boundariesTable ? boundariesTable : std::make_shared(); + switch (type) + { + case ftypes::COUNTRY: return 1000000.0; + case ftypes::STATE: return 100000.0; + case ftypes::CITY: return 30000.0; + case ftypes::TOWN: return 20000.0; + case ftypes::VILLAGE: return 5000.0; + default: return 10000.0; + } +} + +// Returns true if left place is worse than right place. +template +bool IsWorsePlace(T const & left, T const & right) +{ + auto const rankL = left.GetRank(); + auto const rankR = right.GetRank(); + auto const levelL = ftype::GetLevel(GetPlaceType(left)); + auto const levelR = ftype::GetLevel(GetPlaceType(right)); + auto const langCntL = left.GetMultilangName().CountLangs(); + auto const langCntR = right.GetMultilangName().CountLangs(); + auto const isPointL = left.IsPoint(); + auto const isPointR = right.IsPoint(); + auto const boxAreaL = left.GetLimitRect().Area(); + auto const boxAreaR = right.GetLimitRect().Area(); + return std::tie(rankL, levelL, langCntL, isPointL, boxAreaL) < + std::tie(rankR, levelR, langCntR, isPointR, boxAreaR); +} + +template +bool IsTheSamePlace(T const & left, T const & right) +{ + if (left.GetName() != right.GetName()) + return false; + + auto const & localityChecker = ftypes::IsLocalityChecker::Instance(); + auto const localityL = localityChecker.GetType(GetPlaceType(left)); + auto const localityR = localityChecker.GetType(GetPlaceType(right)); + if (localityL != localityR) + return false; + + auto const & rectL = left.GetLimitRect(); + auto const & rectR = right.GetLimitRect(); + if (rectL.IsIntersect(rectR)) + return true; + + auto const dist = MercatorBounds::DistanceOnEarth(left.GetKeyPoint(), right.GetKeyPoint()); + return dist <= GetThresholdM(localityL); +} + +template +Iterator FindGroupOfTheSamePlaces(Iterator start, Iterator end) +{ + CHECK(start != end, ()); + auto next = start; + while (++next != end) + { + if (!IsTheSamePlace(*next, *start)) + return next; + + start = next; + } + return end; } } // namespace +namespace generator +{ +bool NeedProcessPlace(feature::FeatureBuilder const & fb) +{ + auto const & islandChecker = ftypes::IsIslandChecker::Instance(); + auto const & localityChecker = ftypes::IsLocalityChecker::Instance(); + return islandChecker(fb.GetTypes()) || localityChecker.GetType(GetPlaceType(fb)) != ftypes::NONE; +} + +void FeaturePlace::Append(FeatureBuilder const & fb) +{ + if (m_fbs.empty() || IsWorsePlace(m_fbs[m_bestIndex], fb)) + m_bestIndex = m_fbs.size(); + + m_fbs.emplace_back(fb); + m_limitRect.Add(fb.GetLimitRect()); +} + +FeatureBuilder const & FeaturePlace::GetFb() const +{ + CHECK_LESS(m_bestIndex, m_fbs.size(), ()); + return m_fbs[m_bestIndex]; +} + +FeaturePlace::FeaturesBuilders const & FeaturePlace::GetFbs() const +{ + return m_fbs; +} + +m2::RectD const & FeaturePlace::GetLimitRect() const +{ + return m_limitRect; +} + +uint8_t FeaturePlace::GetRank() const +{ + return GetFb().GetRank(); +} + +std::string FeaturePlace::GetName() const +{ + return GetFb().GetName(); +} + +m2::PointD FeaturePlace::GetKeyPoint() const +{ + return GetFb().GetKeyPoint(); +} + +StringUtf8Multilang const & FeaturePlace::GetMultilangName() const +{ + return GetFb().GetMultilangName(); +} + +bool FeaturePlace::IsPoint() const +{ + return GetFb().IsPoint(); +} + PlaceProcessor::PlaceProcessor(std::shared_ptr boundariesTable) - : m_boundariesTable(GetOrCreateBoundariesTable(boundariesTable)) + : m_boundariesTable(boundariesTable) {} + +void PlaceProcessor::FillTable(FeaturePlaces::const_iterator start, FeaturePlaces::const_iterator end, + FeaturePlaces::const_iterator best) const { - ASSERT(m_boundariesTable.get(), ()); + CHECK(m_boundariesTable, ()); + base::GeoObjectId lastId; + for (auto outerIt = start; outerIt != end; ++outerIt) + { + auto const & fbs = outerIt->GetFbs(); + for (auto const & fb : fbs) + { + if (!(fb.IsArea() && ftypes::IsCityTownOrVillage(fb.GetTypes()))) + continue; + + auto const id = fb.GetLastOsmId(); + m_boundariesTable->Append(id, indexer::CityBoundary(fb.GetOuterGeometry())); + if (lastId != base::GeoObjectId()) + m_boundariesTable->Union(id, lastId); + + lastId = id; + } + } + + if (lastId != base::GeoObjectId()) + m_boundariesTable->Union(lastId, best->GetFb().GetMostGenericOsmId()); } -void PlaceProcessor::UnionEqualPlacesIds(Place const & place) +std::vector PlaceProcessor::ProcessPlaces() { - auto const id = place.GetFeature().GetLastOsmId(); - m_places.ForEachInRect(place.GetLimitRect(), [&](Place const & p) { - if (p.IsEqual(place)) - m_boundariesTable->Union(p.GetFeature().GetLastOsmId(), id); - }); + std::vector finalPlaces; + for (auto & nameToGeoObjectIdToFeaturePlaces : m_nameToPlaces) + { + std::vector places; + places.reserve(nameToGeoObjectIdToFeaturePlaces.second.size()); + for (auto const & geoObjectIdToFeaturePlaces : nameToGeoObjectIdToFeaturePlaces.second) + places.emplace_back(geoObjectIdToFeaturePlaces.second); + // Firstly, objects are geometrically sorted. + std::sort(std::begin(places), std::end(places), [](auto const & l, auto const & r) { + auto const & rectL = l.GetLimitRect(); + auto const & rectR = r.GetLimitRect(); + return rectL.Center() < rectR.Center(); + }); + // Secondly, a group of similar places is searched for, then a better place is searched in + // this group. + auto start = std::begin(places); + while (start != std::cend(places)) + { + auto end = FindGroupOfTheSamePlaces(start, std::end(places)); + auto best = std::max_element(start, end, IsWorsePlace); + auto bestFb = best->GetFb(); + auto const & localityChecker = ftypes::IsLocalityChecker::Instance(); + if (bestFb.IsArea() && localityChecker.GetType(GetPlaceType(bestFb)) != ftypes::NONE) + { + LOG(LWARNING, (bestFb, "is transforming to point.")); + TransformAreaToPoint(bestFb); + } + finalPlaces.emplace_back(std::move(bestFb)); + if (m_boundariesTable) + FillTable(start, end, best); + + start = end; + } + } + return finalPlaces; } -std::vector PlaceProcessor::GetFeatures() const +// static +std::string PlaceProcessor::GetKey(FeatureBuilder const & fb) { - std::vector result; - m_places.ForEach([&result](Place const & p) { - result.emplace_back(p.GetFeature()); - }); - - return result; + auto type = GetPlaceType(fb); + ftype::TruncValue(type, 2); + return fb.GetName() + "/" + std::to_string(type); } void PlaceProcessor::Add(FeatureBuilder const & fb) { auto const type = GetPlaceType(fb); - if (type == ftype::GetEmptyValue()) + if (type == ftype::GetEmptyValue() || !NeedProcessPlace(fb)) return; - - auto const id = fb.GetLastOsmId(); - m_boundariesTable->Append(id, indexer::CityBoundary(fb.GetOuterGeometry())); - UnionEqualPlacesIds(Place(fb, type, false /* saveParams */)); -} - -void PlaceProcessor::TryUpdate(FeatureBuilder const & fb) -{ - auto const type = GetPlaceType(fb); - Place const place(fb, type); - UnionEqualPlacesIds(place); - m_places.ReplaceEqualInRect(place, [](Place const & p1, Place const & p2) { - return p1.IsEqual(p2); - }, [](Place const & p1, Place const & p2) { - return p1.IsBetterThan(p2); - }); + // Objects are grouped with the same name and type. This does not guarantee that all objects describe + // the same place. The logic for the separation of different places of the same name is + // implemented in the function GetPlaces(). + m_nameToPlaces[GetKey(fb)][fb.GetMostGenericOsmId()].Append(fb); } } // namespace generator diff --git a/generator/place_processor.hpp b/generator/place_processor.hpp index ace01aa399..4bdece0f1b 100644 --- a/generator/place_processor.hpp +++ b/generator/place_processor.hpp @@ -2,29 +2,56 @@ #include "generator/cities_boundaries_builder.hpp" #include "generator/feature_builder.hpp" -#include "generator/place.hpp" - -#include "geometry/tree4d.hpp" #include +#include +#include #include namespace generator { +bool NeedProcessPlace(feature::FeatureBuilder const & fb); + +// This structure encapsulates work with elements of different types. +// This means that we can consider a set of polygons of one relation as a single entity. +class FeaturePlace +{ +public: + using FeaturesBuilders = std::vector; + + void Append(feature::FeatureBuilder const & fb); + feature::FeatureBuilder const & GetFb() const; + FeaturesBuilders const & GetFbs() const; + m2::RectD const & GetLimitRect() const; + uint8_t GetRank() const; + std::string GetName() const; + m2::PointD GetKeyPoint() const; + StringUtf8Multilang const & GetMultilangName() const; + bool IsPoint() const; + +private: + m2::RectD m_limitRect; + FeaturesBuilders m_fbs; + size_t m_bestIndex; +}; + // The class PlaceProcessor is responsible for the union of boundaries of the places. class PlaceProcessor { public: - PlaceProcessor(std::shared_ptr boundariesTable); + PlaceProcessor(std::shared_ptr boundariesTable = {}); void Add(feature::FeatureBuilder const & fb); - void TryUpdate(feature::FeatureBuilder const & fb); - std::vector GetFeatures() const; + std::vector ProcessPlaces(); private: - void UnionEqualPlacesIds(Place const & place); + using FeaturePlaces = std::vector; + static std::string GetKey(feature::FeatureBuilder const & fb); + void FillTable(FeaturePlaces::const_iterator start, FeaturePlaces::const_iterator end, + FeaturePlaces::const_iterator best) const; + + std::unordered_map> m_nameToPlaces; std::shared_ptr m_boundariesTable; - m4::Tree m_places; }; } // namespace generator