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:
authorvng <viktor.govako@gmail.com>2012-10-09 19:14:48 +0400
committerAlex Zolotarev <alex@maps.me>2015-09-23 01:45:03 +0300
commite36dbe4dd06573a8032e8228a789879f1234181f (patch)
tree779638c20784cbd5644b6cc24e4f56dd8b81d580 /indexer/feature_algo.cpp
parentadf9d0a6ccb9d202d7ffeed423a219ef3f2e155c (diff)
Get correct center for point or area feature in GetVisiblePOI.
Diffstat (limited to 'indexer/feature_algo.cpp')
-rw-r--r--indexer/feature_algo.cpp106
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();
+ }
+ }
+}
+
+}