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

algorithm.hpp « geometry - github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 962f51ed202902bccbdc2e32f83f9a280779c48e (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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#pragma once

#include "geometry/point2d.hpp"
#include "geometry/rect2d.hpp"

#include "std/type_traits.hpp"
#include "std/array.hpp"
#include "std/vector.hpp"

namespace m2
{
// This class is used to calculate a point on a polyline
// such as that the paths (not the distance) from that point
// to both ends of a polyline have the same length.
class CalculatePolyLineCenter
{
public:
  CalculatePolyLineCenter() : m_length(0.0) {}
  void operator()(PointD const & pt);

  PointD GetResult() const;

private:
  struct Value
  {
    Value(PointD const & p, double l) : m_p(p), m_len(l) {}
    bool operator<(Value const & r) const { return (m_len < r.m_len); }
    PointD m_p;
    double m_len;
  };

  vector<Value> m_poly;
  double m_length;
};

// This class is used to calculate a point such as that
// it lays on the figure triangle that is the closest to
// figure bounding box center.
class CalculatePointOnSurface
{
public:
  CalculatePointOnSurface(RectD const & rect);

  void operator()(PointD const & p1, PointD const & p2, PointD const & p3);
  PointD GetResult() const { return m_center; }
private:
  PointD m_rectCenter;
  PointD m_center;
  double m_squareDistanceToApproximate;
};

// Calculates the smallest rect that includes given geometry.
class CalculateBoundingBox
{
public:
  void operator()(PointD const & p);
  RectD GetResult() const { return m_boundingBox; }
private:
  RectD m_boundingBox;
};

namespace impl
{
template <typename TCalculator, typename TIterator>
m2::PointD ApplyPointOnSurfaceCalculator(TIterator begin, TIterator end, TCalculator && calc)
{
  array<m2::PointD, 3> triangle;
  while (begin != end)
  {
    for (auto i = 0; i < 3; ++i)
    {
      // Cannot use ASSERT_NOT_EQUAL, due to absence of an approbriate DebugPrint.
      ASSERT(begin != end, ("Not enough points to calculate point on surface"));
      triangle[i] = *begin++;
    }
    calc(triangle[0], triangle[1], triangle[2]);
  }
  return calc.GetResult();
}

template <typename TCalculator, typename TIterator>
auto ApplyCalculator(TIterator begin, TIterator end, TCalculator && calc)
    -> decltype(calc.GetResult())
{
  for (; begin != end; ++begin)
    calc(*begin);
  return calc.GetResult();
}

template <typename TCalculator, typename TIterator>
auto SelectImplementation(TIterator begin, TIterator end, TCalculator && calc, true_type const &)
    -> decltype(calc.GetResult())
{
  return impl::ApplyPointOnSurfaceCalculator(begin, end, forward<TCalculator>(calc));
}

template <typename TCalculator, typename TIterator>
auto SelectImplementation(TIterator begin, TIterator end, TCalculator && calc, false_type const &)
    -> decltype(calc.GetResult())
{
  return impl::ApplyCalculator(begin, end, forward<TCalculator>(calc));
}
}  // namespace impl

template <typename TCalculator, typename TIterator>
auto ApplyCalculator(TIterator begin, TIterator end, TCalculator && calc)
    -> decltype(calc.GetResult())
{
  return impl::SelectImplementation(begin, end, forward<TCalculator>(calc),
                                    is_same<CalculatePointOnSurface,
                                            typename remove_reference<TCalculator>::type>());
}

template <typename TCalculator, typename TCollection>
auto ApplyCalculator(TCollection && collection, TCalculator && calc)
    -> decltype(calc.GetResult())
{
  return ApplyCalculator(begin(collection), end(collection), forward<TCalculator>(calc));
}
}  // namespace m2