Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
159
generator/water_boundary_checker.hpp
Normal file
159
generator/water_boundary_checker.hpp
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
#pragma once
|
||||
#include "generator/feature_builder.hpp"
|
||||
|
||||
#include "indexer/classificator.hpp"
|
||||
|
||||
#include "geometry/region2d.hpp"
|
||||
#include "geometry/tree4d.hpp"
|
||||
|
||||
class WaterBoundaryChecker
|
||||
{
|
||||
struct RegionTraits
|
||||
{
|
||||
m2::RectD const & LimitRect(m2::RegionD const & r) const { return r.GetRect(); }
|
||||
};
|
||||
m4::Tree<m2::RegionD, RegionTraits> m_tree;
|
||||
|
||||
size_t m_totalFeatures = 0;
|
||||
size_t m_totalBorders = 0;
|
||||
size_t m_skippedBorders = 0;
|
||||
size_t m_selectedPolygons = 0;
|
||||
|
||||
public:
|
||||
~WaterBoundaryChecker()
|
||||
{
|
||||
LOG(LINFO, ("Features checked:", m_totalFeatures, "borders checked:", m_totalBorders,
|
||||
"borders skipped:", m_skippedBorders, "selected polygons:", m_selectedPolygons));
|
||||
}
|
||||
|
||||
void LoadWaterGeometry(std::string const & rawGeometryFileName)
|
||||
{
|
||||
LOG(LINFO, ("Loading water geometry:", rawGeometryFileName));
|
||||
FileReader reader(rawGeometryFileName);
|
||||
ReaderSource<FileReader> file(reader);
|
||||
|
||||
size_t total = 0;
|
||||
while (true)
|
||||
{
|
||||
uint64_t numGeometries = 0;
|
||||
file.Read(&numGeometries, sizeof(numGeometries));
|
||||
|
||||
if (numGeometries == 0)
|
||||
break;
|
||||
|
||||
++total;
|
||||
|
||||
for (size_t i = 0; i < numGeometries; ++i)
|
||||
{
|
||||
uint64_t numPoints = 0;
|
||||
file.Read(&numPoints, sizeof(numPoints));
|
||||
|
||||
std::vector<m2::PointD> points(numPoints);
|
||||
file.Read(points.data(), sizeof(m2::PointD) * numPoints);
|
||||
m_tree.Add(m2::RegionD(std::move(points)));
|
||||
}
|
||||
}
|
||||
LOG(LINFO, ("Load", total, "water geometries"));
|
||||
}
|
||||
|
||||
bool IsBoundaries(feature::FeatureBuilder const & fb)
|
||||
{
|
||||
++m_totalFeatures;
|
||||
|
||||
static uint32_t const kBoundaryType = classif().GetTypeByPath({"boundary", "administrative"});
|
||||
if (!fb.IsLine() || !fb.HasType(kBoundaryType, 2))
|
||||
return false;
|
||||
|
||||
++m_totalBorders;
|
||||
return true;
|
||||
}
|
||||
|
||||
enum class ProcessState
|
||||
{
|
||||
Initial,
|
||||
Water,
|
||||
Earth
|
||||
};
|
||||
|
||||
// TODO(pastk): boundaries along the coast are being "torn" into small pieces instead of being discarded completely.
|
||||
// Likely it happens because an already simplified coastline is used, while boundary lines are not simplified yet.
|
||||
// It causes these lines to intersect each other often.
|
||||
// https://github.com/organicmaps/organicmaps/issues/6445
|
||||
void ProcessBoundary(feature::FeatureBuilder const & boundary, std::vector<feature::FeatureBuilder> & parts)
|
||||
{
|
||||
double constexpr kExtension = 0.01;
|
||||
ProcessState state = ProcessState::Initial;
|
||||
|
||||
feature::FeatureBuilder::PointSeq points;
|
||||
|
||||
for (auto const & p : boundary.GetOuterGeometry())
|
||||
{
|
||||
m2::RectD r(p.x - kExtension, p.y - kExtension, p.x + kExtension, p.y + kExtension);
|
||||
size_t hits = 0;
|
||||
m_tree.ForEachInRect(r, [&](m2::RegionD const & rgn)
|
||||
{
|
||||
++m_selectedPolygons;
|
||||
hits += rgn.Contains(p) ? 1 : 0;
|
||||
});
|
||||
|
||||
bool inWater = (hits & 0x01) == 1;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case ProcessState::Initial:
|
||||
{
|
||||
if (inWater)
|
||||
{
|
||||
state = ProcessState::Water;
|
||||
}
|
||||
else
|
||||
{
|
||||
points.push_back(p);
|
||||
state = ProcessState::Earth;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ProcessState::Water:
|
||||
{
|
||||
if (inWater)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
points.push_back(p);
|
||||
state = ProcessState::Earth;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ProcessState::Earth:
|
||||
{
|
||||
if (inWater)
|
||||
{
|
||||
if (points.size() > 1)
|
||||
{
|
||||
parts.push_back(boundary);
|
||||
parts.back().AssignPoints(std::move(points));
|
||||
}
|
||||
points.clear();
|
||||
state = ProcessState::Water;
|
||||
}
|
||||
else
|
||||
{
|
||||
points.push_back(p);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (points.size() > 1)
|
||||
{
|
||||
parts.push_back(boundary);
|
||||
parts.back().AssignPoints(std::move(points));
|
||||
}
|
||||
|
||||
if (parts.empty())
|
||||
m_skippedBorders++;
|
||||
}
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue