diff options
author | vng <viktor.govako@gmail.com> | 2012-10-09 19:14:48 +0400 |
---|---|---|
committer | Alex Zolotarev <alex@maps.me> | 2015-09-23 01:45:03 +0300 |
commit | e36dbe4dd06573a8032e8228a789879f1234181f (patch) | |
tree | 779638c20784cbd5644b6cc24e4f56dd8b81d580 /indexer/feature_algo.cpp | |
parent | adf9d0a6ccb9d202d7ffeed423a219ef3f2e155c (diff) |
Get correct center for point or area feature in GetVisiblePOI.
Diffstat (limited to 'indexer/feature_algo.cpp')
-rw-r--r-- | indexer/feature_algo.cpp | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/indexer/feature_algo.cpp b/indexer/feature_algo.cpp new file mode 100644 index 0000000000..996b3fb426 --- /dev/null +++ b/indexer/feature_algo.cpp @@ -0,0 +1,106 @@ +#include "feature_algo.hpp" +#include "feature.hpp" + + +namespace feature +{ + +class CalcPolyCenter +{ + typedef m2::PointD P; + + struct Value + { + Value(P const & p, double l) : m_p(p), m_len(l) {} + + bool operator< (Value const & r) const { return (m_len < r.m_len); } + + P m_p; + double m_len; + }; + + vector<Value> m_poly; + double m_length; + +public: + CalcPolyCenter() : m_length(0.0) {} + + void operator() (CoordPointT const & pt) + { + m2::PointD p(pt.first, pt.second); + + m_length += (m_poly.empty() ? 0.0 : m_poly.back().m_p.Length(p)); + m_poly.push_back(Value(p, m_length)); + } + + P GetCenter() const + { + typedef vector<Value>::const_iterator IterT; + + double const l = m_length / 2.0; + + IterT e = lower_bound(m_poly.begin(), m_poly.end(), Value(m2::PointD(0, 0), l)); + if (e == m_poly.begin()) + { + /// @todo It's very strange, but we have linear objects with zero length. + LOG(LWARNING, ("Zero length linear object")); + return e->m_p; + } + + IterT b = e-1; + + double const f = (l - b->m_len) / (e->m_len - b->m_len); + + // For safety reasons (floating point calculations) do comparison instead of ASSERT. + if (0.0 <= f && f <= 1.0) + return (b->m_p * (1-f) + e->m_p * f); + else + return ((b->m_p + e->m_p) / 2.0); + } +}; + +class CalcMassCenter +{ + typedef m2::PointD P; + P m_center; + size_t m_count; + +public: + CalcMassCenter() : m_center(0.0, 0.0), m_count(0) {} + + void operator() (P const & p1, P const & p2, P const & p3) + { + ++m_count; + m_center += p1; + m_center += p2; + m_center += p3; + } + P GetCenter() const { return m_center / (3*m_count); } +}; + +m2::PointD GetCenter(FeatureType const & f) +{ + feature::EGeomType const type = f.GetFeatureType(); + switch (type) + { + case feature::GEOM_POINT: + return f.GetCenter(); + + case feature::GEOM_LINE: + { + CalcPolyCenter doCalc; + f.ForEachPointRef(doCalc, FeatureType::BEST_GEOMETRY); + return doCalc.GetCenter(); + } + + default: + { + ASSERT_EQUAL ( type, feature::GEOM_AREA, () ); + CalcMassCenter doCalc; + f.ForEachTriangleRef(doCalc, FeatureType::BEST_GEOMETRY); + return doCalc.GetCenter(); + } + } +} + +} |