Make coastline features generation more optimal - don't intersect with regions that fully inside feature's rect.

This commit is contained in:
vng 2011-09-07 19:27:56 +03:00 committed by Alex Zolotarev
parent bf694656b5
commit 71bbdf2278
2 changed files with 50 additions and 19 deletions

View file

@ -6,11 +6,14 @@
#include "../geometry/region2d/binary_operators.hpp"
#include "../base/string_utils.hpp"
#include "../base/logging.hpp"
#include "../std/bind.hpp"
typedef m2::RegionI RegionT;
typedef m2::PointI PointT;
typedef m2::RectI RectT;
CoastlineFeaturesGenerator::CoastlineFeaturesGenerator(uint32_t coastType, int level)
@ -22,15 +25,14 @@ namespace
{
m2::RectD GetLimitRect(RegionT const & rgn)
{
m2::RectI r = rgn.GetRect();
RectT r = rgn.GetRect();
return m2::RectD(r.minX(), r.minY(), r.maxX(), r.maxY());
}
inline m2::PointI D2I(m2::PointD const & p)
inline PointT D2I(m2::PointD const & p)
{
m2::PointU const pu = PointD2PointU(p, POINT_COORD_BITS);
return m2::PointI(static_cast<int32_t>(pu.x),
static_cast<int32_t>(pu.y));
return PointT(static_cast<int32_t>(pu.x), static_cast<int32_t>(pu.y));
}
class DoCreateRegion
@ -109,26 +111,37 @@ namespace
{
class DoDifference
{
vector<RegionT> m_res;
RectT m_src;
vector<RegionT> m_res, m_readyRes;
vector<m2::PointD> m_points;
public:
DoDifference(RegionT const & rgn)
{
m_res.push_back(rgn);
m_src = rgn.GetRect();
}
void operator() (RegionT const & r)
{
vector<RegionT> local;
if (m_src.IsRectInside(r.GetRect()))
{
// if r is fully inside source rect region,
// put it to the result vector without any intersection
m_readyRes.push_back(r);
}
else
{
vector<RegionT> local;
for (size_t i = 0; i < m_res.size(); ++i)
m2::DiffRegions(m_res[i], r, local);
for (size_t i = 0; i < m_res.size(); ++i)
m2::DiffRegions(m_res[i], r, local);
local.swap(m_res);
local.swap(m_res);
}
}
void operator() (m2::PointI const & p)
void operator() (PointT const & p)
{
CoordPointT const c = PointU2PointD(m2::PointU(
static_cast<uint32_t>(p.x),
@ -136,23 +149,38 @@ namespace
m_points.push_back(m2::PointD(c.first, c.second));
}
void AssignGeometry(FeatureBuilder1 & fb)
void AssignGeometry(vector<RegionT> const & v, FeatureBuilder1 & fb)
{
for (size_t i = 0; i < m_res.size(); ++i)
for (size_t i = 0; i < v.size(); ++i)
{
m_points.clear();
m_points.reserve(m_res[i].Size() + 1);
m_points.reserve(v[i].Size() + 1);
m_res[i].ForEachPoint(bind<void>(ref(*this), _1));
v[i].ForEachPoint(bind<void>(ref(*this), _1));
fb.AddPolygon(m_points);
}
}
void AssignGeometry(FeatureBuilder1 & fb)
{
AssignGeometry(m_res, fb);
AssignGeometry(m_readyRes, fb);
}
};
class DoLogRegions
{
public:
void operator() (RegionT const & r)
{
LOG_SHORT(LINFO, ("Boundary", r));
}
};
}
bool CoastlineFeaturesGenerator::GetFeature(size_t i, FeatureBuilder1 & fb)
{
{
// get rect cell
CellIdT cell = CellIdT::FromBitsAndLevel(i, m_Level);
double minX, minY, maxX, maxY;
@ -160,8 +188,8 @@ bool CoastlineFeaturesGenerator::GetFeature(size_t i, FeatureBuilder1 & fb)
// create rect region
typedef m2::PointD P;
m2::PointI arr[] = { D2I(P(minX, minY)), D2I(P(minX, maxY)),
D2I(P(maxX, maxY)), D2I(P(maxX, minY)) };
PointT arr[] = { D2I(P(minX, minY)), D2I(P(minX, maxY)),
D2I(P(maxX, maxY)), D2I(P(maxX, minY)) };
RegionT rectR(arr, arr + ARRAY_SIZE(arr));
// substract all 'land' from this region

View file

@ -345,17 +345,18 @@ namespace feature
public:
BoundsDistance(uint32_t cellID, int level)
{
RectId cell = RectId::FromBitsAndLevel(cellID, level);
RectId const cell = RectId::FromBitsAndLevel(cellID, level);
CellIdConverter<MercatorBounds, RectId>::GetCellBounds(cell, m_minX, m_minY, m_maxX, m_maxY);
}
void SetEpsilon(double eps) { m_eps = 2.0*eps; }
void SetEpsilon(double eps) { m_eps = eps; }
double operator() (m2::PointD const & p) const
{
if (fabs(p.x - m_minX) <= m_eps || fabs(p.x - m_maxX) <= m_eps ||
fabs(p.y - m_minY) <= m_eps || fabs(p.y - m_maxY) <= m_eps)
{
// points near rect should be in a result simplified vector
return std::numeric_limits<double>::max();
}
@ -371,6 +372,8 @@ namespace feature
{
BoundsDistance dist(cellID, g_coastsCellLevel);
feature::SimplifyPoints(dist, in, out, level);
//LOG(LINFO, ("Special simplification", in.size(), out.size()));
}
else
{