Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Zakharenkov <a-zakh@yandex.ru>2020-12-15 11:24:23 +0300
committerOlga Khlopkova <mesozoic.drones@gmail.com>2020-12-18 15:44:11 +0300
commit1006b18ce2e9cfa443a341d049c3f5fc2e8ca13b (patch)
tree396657d510eae5b4fb699626ab584ab1c0adde86 /generator
parent44eb20bd6fc5d76aea1fc07fdf561cc926d126a1 (diff)
[generator] Mark building with 'has_parts' property based on real buiding and building:part-s geometry
Diffstat (limited to 'generator')
-rw-r--r--generator/boost_helpers.hpp22
-rw-r--r--generator/final_processor_country.cpp80
-rw-r--r--generator/final_processor_country.hpp1
-rw-r--r--generator/hierarchy.cpp1
-rw-r--r--generator/osm2type.cpp2
-rw-r--r--generator/relation_tags.cpp5
6 files changed, 93 insertions, 18 deletions
diff --git a/generator/boost_helpers.hpp b/generator/boost_helpers.hpp
index 373e449d52..4fea844a62 100644
--- a/generator/boost_helpers.hpp
+++ b/generator/boost_helpers.hpp
@@ -10,12 +10,13 @@ namespace generator
{
namespace boost_helpers
{
-using BoostPoint = boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>;
-using BoostPolygon = boost::geometry::model::polygon<BoostPoint>;
-template <typename BoostPoint, typename BoostGeometry, typename FbGeometry>
+template <typename BoostGeometry, typename FbGeometry>
void FillBoostGeometry(BoostGeometry & geometry, FbGeometry const & fbGeometry)
{
+ using BoostPoint = typename boost::geometry::point_type<BoostGeometry>::type;
+
+ geometry.clear();
geometry.reserve(fbGeometry.size());
for (auto const & p : fbGeometry)
boost::geometry::append(geometry, BoostPoint{p.x, p.y});
@@ -24,16 +25,17 @@ void FillBoostGeometry(BoostGeometry & geometry, FbGeometry const & fbGeometry)
template <typename BoostPolygon>
void FillPolygon(BoostPolygon & polygon, feature::FeatureBuilder const & fb)
{
- using BoostPoint = typename BoostPolygon::point_type;
auto const & fbGeometry = fb.GetGeometry();
CHECK(!fbGeometry.empty(), ());
- auto it = std::begin(fbGeometry);
- FillBoostGeometry<BoostPoint>(polygon.outer(), *it);
+
+ polygon.clear();
+ FillBoostGeometry(polygon.outer(), *fbGeometry.begin());
polygon.inners().resize(fbGeometry.size() - 1);
- int i = 0;
- ++it;
- for (; it != std::end(fbGeometry); ++it)
- FillBoostGeometry<BoostPoint>(polygon.inners()[i++], *it);
+
+ size_t i = 0;
+
+ for (auto it = std::next(fbGeometry.begin()); it != fbGeometry.end(); ++it)
+ FillBoostGeometry(polygon.inners()[i++], *it);
boost::geometry::correct(polygon);
}
diff --git a/generator/final_processor_country.cpp b/generator/final_processor_country.cpp
index 543c7653dc..645077de21 100644
--- a/generator/final_processor_country.cpp
+++ b/generator/final_processor_country.cpp
@@ -2,6 +2,7 @@
#include "generator/affiliation.hpp"
#include "generator/booking_dataset.hpp"
+#include "generator/boost_helpers.hpp"
#include "generator/feature_builder.hpp"
#include "generator/final_processor_utils.hpp"
#include "generator/isolines_generator.hpp"
@@ -23,6 +24,13 @@
#include <utility>
#include <vector>
+#include "3party/boost/boost/geometry.hpp"
+#include "3party/boost/boost/geometry/geometries/register/point.hpp"
+#include "3party/boost/boost/geometry/geometries/register/ring.hpp"
+
+BOOST_GEOMETRY_REGISTER_POINT_2D(m2::PointD, double, boost::geometry::cs::cartesian, x, y)
+BOOST_GEOMETRY_REGISTER_RING(std::vector<m2::PointD>)
+
using namespace base::thread_pool::computational;
using namespace feature;
@@ -111,6 +119,7 @@ void CountryFinalProcessor::Process()
AddIsolines();
DropProhibitedSpeedCameras();
+ ProcessBuildingParts();
Finish();
}
@@ -195,6 +204,77 @@ void CountryFinalProcessor::ProcessRoundabouts()
}, m_threadsCount);
}
+bool DoesBuildingConsistOfParts(FeatureBuilder const & fbBuilding,
+ m4::Tree<FeatureBuilder> const & buildingPartsKDTree)
+{
+ namespace bg = boost::geometry;
+ using BoostPoint = bg::model::point<double, 2, bg::cs::cartesian>;
+ using BoostPolygon = bg::model::polygon<BoostPoint>;
+ using BoostMultiPolygon = bg::model::multi_polygon<BoostPolygon>;
+
+ BoostPolygon building;
+ BoostMultiPolygon partsUnion;
+
+ buildingPartsKDTree.ForEachInRect(fbBuilding.GetLimitRect(), [&](auto const & fbPart) {
+ // Lazy initialization that will not occur with high probability
+ if (bg::is_empty(building))
+ generator::boost_helpers::FillPolygon(building, fbBuilding);
+
+ BoostPolygon part;
+ generator::boost_helpers::FillPolygon(part, fbPart);
+
+ BoostMultiPolygon newPartsUnion;
+ bg::union_(partsUnion, part, newPartsUnion);
+ partsUnion = std::move(newPartsUnion);
+ });
+
+ if (bg::is_empty(building))
+ return false;
+
+ BoostMultiPolygon partsWithinBuilding;
+ bg::intersection(building, partsUnion, partsWithinBuilding);
+
+ // Consider a building as consisting of parts if the building footprint
+ // is covered with parts at least by 90%.
+ return bg::area(partsWithinBuilding) >= 0.9 * bg::area(building);
+}
+
+void CountryFinalProcessor::ProcessBuildingParts()
+{
+ static auto const & classificator = classif();
+ static auto const buildingClassifType = classificator.GetTypeByPath({"building"});
+ static auto const buildingPartClassifType = classificator.GetTypeByPath({"building:part"});
+ static auto const buildingWithPartsClassifType = classificator.GetTypeByPath({"building", "has_parts"});
+
+ ForEachMwmTmp(m_temporaryMwmPath, [&](auto const & name, auto const & path) {
+ if (!IsCountry(name))
+ return;
+
+ // All "building:part" features in MWM
+ m4::Tree<FeatureBuilder> buildingPartsKDTree;
+
+ ForEachFeatureRawFormat<serialization_policy::MaxAccuracy>(path, [&](auto && fb, auto /* pos */) {
+ if (!(fb.IsArea() && fb.IsValid()))
+ return;
+
+ if (fb.HasType(buildingPartClassifType))
+ buildingPartsKDTree.Add(fb);
+ });
+
+ FeatureBuilderWriter<serialization_policy::MaxAccuracy> writer(path, true /* mangleName */);
+ ForEachFeatureRawFormat<serialization_policy::MaxAccuracy>(path, [&](auto && fb, auto /* pos */) {
+ if (fb.IsArea() && fb.IsValid() &&
+ fb.HasType(buildingClassifType) &&
+ DoesBuildingConsistOfParts(fb, buildingPartsKDTree))
+ {
+ fb.AddType(buildingWithPartsClassifType);
+ }
+
+ writer.Write(fb);
+ });
+ }, m_threadsCount);
+}
+
void CountryFinalProcessor::AddIsolines()
{
// For generated isolines must be built isolines_info section based on the same
diff --git a/generator/final_processor_country.hpp b/generator/final_processor_country.hpp
index 7f1230f953..64d66ca69d 100644
--- a/generator/final_processor_country.hpp
+++ b/generator/final_processor_country.hpp
@@ -48,6 +48,7 @@ private:
void AddIsolines();
void DropProhibitedSpeedCameras();
void Finish();
+ void ProcessBuildingParts();
bool IsCountry(std::string const & filename);
diff --git a/generator/hierarchy.cpp b/generator/hierarchy.cpp
index e7546a5480..afd7a3b2fb 100644
--- a/generator/hierarchy.cpp
+++ b/generator/hierarchy.cpp
@@ -20,7 +20,6 @@
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <boost/geometry/geometries/register/ring.hpp>
-#include <boost/geometry/multi/geometries/register/multi_point.hpp>
BOOST_GEOMETRY_REGISTER_POINT_2D(m2::PointD, double, boost::geometry::cs::cartesian, x, y);
BOOST_GEOMETRY_REGISTER_RING(std::vector<m2::PointD>);
diff --git a/generator/osm2type.cpp b/generator/osm2type.cpp
index ac11f64acd..4edb30188e 100644
--- a/generator/osm2type.cpp
+++ b/generator/osm2type.cpp
@@ -720,8 +720,6 @@ void PostprocessElement(OsmElement * p, FeatureBuilderParams & params)
{"wheelchair", "designated",
[&params] { params.AddType(types.Get(CachedTypes::Type::WheelchairYes)); }},
{"wifi", "~", [&params] { params.AddType(types.Get(CachedTypes::Type::Wlan)); }},
- {"building:part", "no", [&params] { params.AddType(types.Get(CachedTypes::Type::HasParts)); }},
- {"building:parts", "~", [&params] { params.AddType(types.Get(CachedTypes::Type::HasParts)); }},
});
bool highwayDone = false;
diff --git a/generator/relation_tags.cpp b/generator/relation_tags.cpp
index 2099e06b0c..5488a8fc2e 100644
--- a/generator/relation_tags.cpp
+++ b/generator/relation_tags.cpp
@@ -98,12 +98,7 @@ void RelationTagsWay::Process(RelationElement const & e)
}
if (type == "building")
- {
- // If this way has "outline" role, add [building=has_parts] type.
- if (e.GetWayRole(m_current->m_id) == "outline")
- Base::AddCustomTag({"building", "has_parts"});
return;
- }
bool const isBoundary = (type == "boundary") && IsAcceptBoundary(e);
bool const processAssociatedStreet = type == "associatedStreet" &&