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:
authorSergey Magidovich <mgsergio@mapswithme.com>2016-02-13 19:04:32 +0300
committerSergey Yershov <yershov@corp.mail.ru>2016-03-23 16:20:48 +0300
commitfdaa9d6cf6496e0cf6b42ee864b90e7df778ce9c (patch)
treeb1ba1e94089da588a6eaa13d6a123484ae5c430b /geometry
parent138798419bd017ea5236b5e24f43149b1881a35c (diff)
Code review and refactoring of geometry/algorithm.
Diffstat (limited to 'geometry')
-rw-r--r--geometry/algorithm.cpp2
-rw-r--r--geometry/algorithm.hpp67
-rw-r--r--geometry/geometry_tests/algorithm_test.cpp35
3 files changed, 82 insertions, 22 deletions
diff --git a/geometry/algorithm.cpp b/geometry/algorithm.cpp
index 76ebe95f09..e2b57ae2c4 100644
--- a/geometry/algorithm.cpp
+++ b/geometry/algorithm.cpp
@@ -13,7 +13,7 @@ void CalculatePolyLineCenter::operator()(m2::PointD const & pt)
m_poly.emplace_back(pt, m_length);
}
-PointD CalculatePolyLineCenter::GetCenter() const
+PointD CalculatePolyLineCenter::GetResult() const
{
using TIter = vector<Value>::const_iterator;
diff --git a/geometry/algorithm.hpp b/geometry/algorithm.hpp
index 6513bd6885..962f51ed20 100644
--- a/geometry/algorithm.hpp
+++ b/geometry/algorithm.hpp
@@ -3,6 +3,8 @@
#include "geometry/point2d.hpp"
#include "geometry/rect2d.hpp"
+#include "std/type_traits.hpp"
+#include "std/array.hpp"
#include "std/vector.hpp"
namespace m2
@@ -16,7 +18,7 @@ public:
CalculatePolyLineCenter() : m_length(0.0) {}
void operator()(PointD const & pt);
- PointD GetCenter() const;
+ PointD GetResult() const;
private:
struct Value
@@ -40,7 +42,7 @@ public:
CalculatePointOnSurface(RectD const & rect);
void operator()(PointD const & p1, PointD const & p2, PointD const & p3);
- PointD GetCenter() const { return m_center; }
+ PointD GetResult() const { return m_center; }
private:
PointD m_rectCenter;
PointD m_center;
@@ -52,8 +54,67 @@ class CalculateBoundingBox
{
public:
void operator()(PointD const & p);
- RectD GetBoundingBox() const { return m_boundingBox; }
+ 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
diff --git a/geometry/geometry_tests/algorithm_test.cpp b/geometry/geometry_tests/algorithm_test.cpp
index 3f349f9791..efde4580c5 100644
--- a/geometry/geometry_tests/algorithm_test.cpp
+++ b/geometry/geometry_tests/algorithm_test.cpp
@@ -14,28 +14,24 @@ namespace
{
PointD GetPolyLineCenter(vector<PointD> const & points)
{
- CalculatePolyLineCenter doCalc;
- for (auto const & p : points)
- doCalc(p);
- return doCalc.GetCenter();
+ return m2::ApplyCalculator(points, m2::CalculatePolyLineCenter());
}
RectD GetBoundingBox(vector<PointD> const & points)
{
- CalculateBoundingBox doCalc;
- for (auto const p : points)
- doCalc(p);
- return doCalc.GetBoundingBox();
+ return m2::ApplyCalculator(points, m2::CalculateBoundingBox());
}
PointD GetPointOnSurface(vector<PointD> const & points)
{
- ASSERT(!points.empty() && points.size() % 3 == 0, ());
- CalculatePointOnSurface doCalc(GetBoundingBox(points));
- for (auto i = 0; i < points.size() - 3; i += 3)
- doCalc(points[i], points[i + 1], points[i + 2]);
- return doCalc.GetCenter();
+ ASSERT(!points.empty() && points.size() % 3 == 0, ("points.size() =", points.size()));
+ auto const boundingBox = GetBoundingBox(points);
+ return m2::ApplyCalculator(points, m2::CalculatePointOnSurface(boundingBox));
+}
+bool PointsAlmostEqual(PointD const & p1, PointD const & p2)
+{
+ return p1.EqualDxDy(p2, 1e-7);
}
} // namespace
@@ -146,21 +142,24 @@ UNIT_TEST(CalculatePointOnSurface)
{
vector<PointD> const points {
{0, 0}, {1, 1}, {2, 0},
- {1, 1}, {2, 0}, {3, 1},
+ {1, 1}, {2, 0}, {3, 1}, // Center of this triangle is used as a result.
{2, 0}, {3, 1}, {4, 0},
{4, 0}, {3, 1}, {4, 2},
- {3, 1}, {4, 2}, {3, 3},
+ {3, 1}, {4, 2}, {3, 3}, // Or this.
{4, 2}, {3, 3}, {4, 4},
{3, 3}, {4, 4}, {2, 4},
- {3, 3}, {2, 4}, {1, 3},
+ {3, 3}, {2, 4}, {1, 3}, // Or this.
{1, 3}, {2, 4}, {0, 4},
{0, 4}, {1, 3}, {0, 2},
- {1, 3}, {0, 2}, {1, 1}, // Center of this triangle is used as a result.
+ {1, 3}, {0, 2}, {1, 1}, // Or this
{0, 2}, {1, 1}, {0, 0},
};
- TEST_EQUAL(GetPointOnSurface(points), PointD(2.0 / 3.0, 2), ());
+ auto const result = GetPointOnSurface(points);
+ TEST(PointsAlmostEqual(result, {10.0 / 3.0, 2}) || PointsAlmostEqual(result, {2, 2.0 / 3.0}) ||
+ PointsAlmostEqual(result, {2, 10.0 / 3.0}) || PointsAlmostEqual(result, {2.0 / 3.0, 2}),
+ ("result = ", result));
}
}