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

feature_algo.cpp « indexer - github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 996b3fb426592eadf64048a7db0f13dd0eb8b877 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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();
    }
  }
}

}