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

algorithm.cpp « geometry - github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: e2b57ae2c4d288eaa8c0a658f203c68ec0cc7858 (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
#include "geometry/algorithm.hpp"
#include "geometry/triangle2d.hpp"

#include "base/logging.hpp"

namespace m2
{
// CalculatePolyLineCenter -----------------------------------------------------------------------------

void CalculatePolyLineCenter::operator()(m2::PointD const & pt)
{
  m_length += (m_poly.empty() ? 0.0 : m_poly.back().m_p.Length(pt));
  m_poly.emplace_back(pt, m_length);
}

PointD CalculatePolyLineCenter::GetResult() const
{
  using TIter = vector<Value>::const_iterator;

  double const l = m_length / 2.0;

  TIter 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;
  }

  TIter 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);
}

// CalculatePointOnSurface -------------------------------------------------------------------------

CalculatePointOnSurface::CalculatePointOnSurface(m2::RectD const & rect)
  : m_rectCenter(rect.Center())
  , m_center(m_rectCenter)
  , m_squareDistanceToApproximate(numeric_limits<double>::max())
{
}

void CalculatePointOnSurface::operator()(PointD const & p1, PointD const & p2, PointD const & p3)
{
  if (m_squareDistanceToApproximate == 0.0)
    return;
  if (m2::IsPointInsideTriangle(m_rectCenter, p1, p2, p3))
  {
    m_center = m_rectCenter;
    m_squareDistanceToApproximate = 0.0;
    return;
  }
  PointD triangleCenter(p1);
  triangleCenter += p2;
  triangleCenter += p3;
  triangleCenter = triangleCenter / 3.0;

  double triangleDistance = m_rectCenter.SquareLength(triangleCenter);
  if (triangleDistance <= m_squareDistanceToApproximate)
  {
    m_center = triangleCenter;
    m_squareDistanceToApproximate = triangleDistance;
  }
}

// CalculateBoundingBox ----------------------------------------------------------------------------

void CalculateBoundingBox::operator()(PointD const & p)
{
  // Works just fine. If you don't belive me, see geometry/rect2d.hpp.
  // Pay attention to MakeEmpty and Add functions.
  m_boundingBox.Add(p);
}
}  // namespace m2