From d656f81529908c84b270363d8126cd2569c16a2e Mon Sep 17 00:00:00 2001 From: Nickolay Polyarnyi Date: Sat, 8 Nov 2014 19:28:21 +0300 Subject: [PATCH 1/3] Rotation of 3 points in 3D implemented and covered by tests. Only interval and rational calculation implemented correctly. Double arithmetic calculation implemented WRONG! (test will fail, if you will uncomment double-arithmetic optimisation) It seems, that I was wrong in eps calcultaion. My calculations - https://www.dropbox.com/s/6ntftgxuld53clz/19_3.jpeg?dl=0 But orientation of 3D points is usable - but it can be a bit slow (interval and rational arithmetic driven). --- include/cg/operations/orientation.h | 77 ++++++++++ include/cg/primitives/point.h | 225 ++++++++++++++++------------ tests/CMakeLists.txt | 6 - tests/orientation.cpp | 34 +++++ tests/random_utils.h | 16 ++ 5 files changed, 260 insertions(+), 98 deletions(-) diff --git a/include/cg/operations/orientation.h b/include/cg/operations/orientation.h index dd76371..3f97588 100644 --- a/include/cg/operations/orientation.h +++ b/include/cg/operations/orientation.h @@ -118,4 +118,81 @@ namespace cg { return (a <= b && b <= c) || (c <= b && b <= a); } + + struct orientation_3d_vectors_d + { + boost::optional operator() (point_3 const & a, point_3 const & b, point_3 const & c) const + { + double x23 = a.x * (b.y*c.z-b.z*c.y); + double y13 = a.y * (b.x*c.z-b.z*c.x); + double z12 = a.z * (b.x*c.y-b.y*c.x); + double eps = (fabs(x23) + fabs(y13) + fabs(z12)) * 8 * std::numeric_limits::epsilon(); + + double res = x23 - y13 + z12; + + if (res > eps) + return CG_RIGHT; + + if (res < -eps) + return CG_LEFT; + + return boost::none; + } + }; + + struct orientation_3d_vectors_i + { + boost::optional operator() (point_3 const & a, point_3 const & b, point_3 const & c) const + { + typedef boost::numeric::interval_lib::unprotect >::type interval; + + boost::numeric::interval::traits_type::rounding _; + interval res = (interval(b.y) * c.z - interval(b.z) * c.y) * a.x + - (interval(b.x) * c.z - interval(b.z) * c.x) * a.y + + (interval(b.x) * c.y - interval(b.y) * c.x) * a.z; + + if (res.lower() > 0) + return CG_RIGHT; + + if (res.upper() < 0) + return CG_LEFT; + + if (res.upper() == res.lower()) + return CG_COLLINEAR; + + return boost::none; + } + }; + + struct orientation_3d_vectors_r + { + boost::optional operator() (point_3 const & a, point_3 const & b, point_3 const & c) const + { + mpq_class res = (mpq_class(b.y) * c.z - mpq_class(b.z) * c.y) * a.x + - (mpq_class(b.x) * c.z - mpq_class(b.z) * c.x) * a.y + + (mpq_class(b.x) * c.y - mpq_class(b.y) * c.x) * a.z; + + int cres = cmp(res, 0); + + if (cres > 0) + return CG_RIGHT; + + if (cres < 0) + return CG_LEFT; + + return CG_COLLINEAR; + } + }; + + inline orientation_t orientation_3d_vectors(point_3 const & a, point_3 const & b, point_3 const & c) + { +// if (boost::optional v = orientation_3d_vectors_d()(a, b, c)) +// return *v; + + if (boost::optional v = orientation_3d_vectors_i()(a, b, c)) + return *v; + + return *orientation_3d_vectors_r()(a, b, c); + } + } diff --git a/include/cg/primitives/point.h b/include/cg/primitives/point.h index efaa0ad..f389dd1 100644 --- a/include/cg/primitives/point.h +++ b/include/cg/primitives/point.h @@ -2,96 +2,137 @@ #include "vector.h" -namespace cg -{ - template struct point_2t; - - typedef point_2t point_2; - typedef point_2t point_2f; - typedef point_2t point_2i; - - template - struct point_2t - { - Scalar x, y; - - point_2t(Scalar x, Scalar y) - : x(x) - , y(y) - {} - - template - point_2t(point_2t const & o) - : x(o.x) - , y(o.y) - {} - - point_2t() - : x(0) - , y(0) - {} - - point_2t & operator += (vector_2t const & delta) - { - x += delta.x; - y += delta.y; - return *this; - } - }; - - template - inline bool operator < (point_2t const & a, point_2t const & b) - { - if (a.x == b.x) - return a.y < b.y; - else - return a.x < b.x; - } - - template - bool operator > (point_2t const & a, point_2t const & b) - { - return b < a; - } - - template - bool operator == (point_2t const & a, point_2t const & b) - { - return (a.x == b.x) && (a.y == b.y); - } - - template - bool operator <= (point_2t const & a, point_2t const & b) - { - return !(a > b); - } - - template - bool operator >= (point_2t const & a, point_2t const & b) - { - return !(a < b); - } - - - template - bool operator != (point_2t const & a, point_2t const & b) - { - return !(a == b); - } - - // в этом месте возможно переполнение! - template - vector_2t const operator - (point_2t const & a, point_2t const & b) - { - return vector_2t(a.x - b.x, a.y - b.y); - } - - // в этом месте возможно переполнение! - template - point_2t const operator + (point_2t const & pt, vector_2t const & delta) - { - point_2t res(pt); - res += delta; - return res; - } +namespace cg { + template struct point_2t; + + typedef point_2t point_2; + typedef point_2t point_2f; + typedef point_2t point_2i; + + template + struct point_2t { + Scalar x, y; + + point_2t(Scalar x, Scalar y) + : x(x), y(y) { + } + + template + point_2t(point_2t const &o) + : x(o.x), y(o.y) { + } + + point_2t() + : x(0), y(0) { + } + + point_2t &operator+=(vector_2t const &delta) { + x += delta.x; + y += delta.y; + return *this; + } + }; + + template + inline bool operator<(point_2t const &a, point_2t const &b) { + if (a.x == b.x) + return a.y < b.y; + else + return a.x < b.x; + } + + template + bool operator>(point_2t const &a, point_2t const &b) { + return b < a; + } + + template + bool operator==(point_2t const &a, point_2t const &b) { + return (a.x == b.x) && (a.y == b.y); + } + + template + bool operator<=(point_2t const &a, point_2t const &b) { + return !(a > b); + } + + template + bool operator>=(point_2t const &a, point_2t const &b) { + return !(a < b); + } + + + template + bool operator!=(point_2t const &a, point_2t const &b) { + return !(a == b); + } + + // в этом месте возможно переполнение! + template + vector_2t const operator-(point_2t const &a, point_2t const &b) { + return vector_2t(a.x - b.x, a.y - b.y); + } + + // в этом месте возможно переполнение! + template + point_2t const operator+(point_2t const &pt, vector_2t const &delta) { + point_2t res(pt); + res += delta; + return res; + } + + template struct point_3t; + + typedef point_3t point_3; + typedef point_3t point_3f; + typedef point_3t point_3i; + + template + struct point_3t { + Scalar x, y, z; + + point_3t(Scalar x, Scalar y, Scalar z) + : x(x), y(y), z(z) { + } + + template + point_3t(point_3t const &o) + : x(o.x), y(o.y), z(o.z) { + } + + point_3t() + : x(0), y(0), z(0) { + } + + point_3t & operator *= (Scalar s) + { + x *= s; + y *= s; + z *= s; + return *this; + } + }; + + template + bool operator==(point_3t const &a, point_3t const &b) { + return (a.x == b.x) && (a.y == b.y) && (a.z == b.z); + } + + template + bool operator!=(point_3t const &a, point_3t const &b) { + return !(a == b); + } + + template + point_3t operator * (point_3t v, Scalar s) + { + return v *= s; + } + + template + point_3t operator * (Scalar s, point_3t v) + { + return v *= s; + } + } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 12e84eb..647488e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -14,13 +14,7 @@ include_directories(${Boost_INCLUDE_DIRS}) link_directories(${Boost_LIBRARYDIR}) set(SOURCES - triangulation.cpp orientation.cpp - has_intersection.cpp - contains.cpp - convex_hull.cpp - dynamic_convex_hull.cpp - convex.cpp ) add_executable(cg-test ${SOURCES}) diff --git a/tests/orientation.cpp b/tests/orientation.cpp index 239e721..55a23b2 100644 --- a/tests/orientation.cpp +++ b/tests/orientation.cpp @@ -125,3 +125,37 @@ TEST(orientation, uniform1) } } + +TEST(orientation_3d_vectors, simple) +{ + cg::point_3 i(1, 0, 0); + cg::point_3 j(0, 1, 0); + cg::point_3 k(0, 0, 1); + EXPECT_EQ(cg::orientation_t::CG_RIGHT, cg::orientation_3d_vectors(i, j, k)); + EXPECT_EQ(cg::orientation_t::CG_LEFT, cg::orientation_3d_vectors(i, k, j)); + EXPECT_EQ(cg::orientation_t::CG_LEFT, cg::orientation_3d_vectors(k, j, i)); + EXPECT_EQ(cg::orientation_t::CG_LEFT, cg::orientation_3d_vectors(j, i, k)); + EXPECT_EQ(cg::orientation_t::CG_RIGHT, cg::orientation_3d_vectors(j, k, i)); + EXPECT_EQ(cg::orientation_t::CG_RIGHT, cg::orientation_3d_vectors(k, i, j)); + + EXPECT_EQ(cg::orientation_t::CG_RIGHT, *cg::orientation_3d_vectors_r()(i, j, k)); + EXPECT_EQ(cg::orientation_t::CG_LEFT, *cg::orientation_3d_vectors_r()(i, k, j)); + EXPECT_EQ(cg::orientation_t::CG_LEFT, *cg::orientation_3d_vectors_r()(k, j, i)); + EXPECT_EQ(cg::orientation_t::CG_LEFT, *cg::orientation_3d_vectors_r()(j, i, k)); + EXPECT_EQ(cg::orientation_t::CG_RIGHT, *cg::orientation_3d_vectors_r()(j, k, i)); + EXPECT_EQ(cg::orientation_t::CG_RIGHT, *cg::orientation_3d_vectors_r()(k, i, j)); +} + +TEST(orientation_3d_vectors, uniform_line) +{ + uniform_random_real distr(-(1LL << 53), (1LL << 53)); + + std::vector pts = uniform_points3d(1000); + for (size_t l = 0; l < pts.size(); l++) + { + cg::point_3 a = pts[l]; + cg::point_3 b = a * distr(); + cg::point_3 c = a * distr(); + EXPECT_EQ(*cg::orientation_3d_vectors_r()(a, b, c), cg::orientation_3d_vectors(a, b, c)); + } +} \ No newline at end of file diff --git a/tests/random_utils.h b/tests/random_utils.h index 39495e2..45a02b3 100644 --- a/tests/random_utils.h +++ b/tests/random_utils.h @@ -18,3 +18,19 @@ inline std::vector uniform_points(size_t count) return res; } + +inline std::vector uniform_points3d(size_t count) +{ + util::uniform_random_real rand(-100., 100.); + + std::vector res(count); + + for (size_t l = 0; l != count; ++l) + { + rand >> res[l].x; + rand >> res[l].y; + rand >> res[l].z; + } + + return res; +} From 3a2d8be8dea85512d930a0f5ca7b2225682bdc61 Mon Sep 17 00:00:00 2001 From: Nickolay Polyarnyi Date: Mon, 10 Nov 2014 00:53:56 +0300 Subject: [PATCH 2/3] Tests back. --- tests/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 647488e..12e84eb 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -14,7 +14,13 @@ include_directories(${Boost_INCLUDE_DIRS}) link_directories(${Boost_LIBRARYDIR}) set(SOURCES + triangulation.cpp orientation.cpp + has_intersection.cpp + contains.cpp + convex_hull.cpp + dynamic_convex_hull.cpp + convex.cpp ) add_executable(cg-test ${SOURCES}) From 5c2e98b9313fa3c1fe987098263929096364e976 Mon Sep 17 00:00:00 2001 From: Nickolay Polyarnyi Date: Mon, 10 Nov 2014 23:08:02 +0300 Subject: [PATCH 3/3] Formatting in accordance with local code-style. --- include/cg/operations/orientation.h | 132 ++++++------- include/cg/primitives/point.h | 286 +++++++++++++++------------- tests/orientation.cpp | 73 +++---- tests/random_utils.h | 34 ++-- 4 files changed, 274 insertions(+), 251 deletions(-) diff --git a/include/cg/operations/orientation.h b/include/cg/operations/orientation.h index 3f97588..2291c7d 100644 --- a/include/cg/operations/orientation.h +++ b/include/cg/operations/orientation.h @@ -26,7 +26,7 @@ namespace cg struct orientation_d { - boost::optional operator() (point_2 const & a, point_2 const & b, point_2 const & c) const + boost::optional operator()(point_2 const &a, point_2 const &b, point_2 const &c) const { double l = (b.x - a.x) * (c.y - a.y); double r = (b.y - a.y) * (c.x - a.x); @@ -45,13 +45,13 @@ namespace cg struct orientation_i { - boost::optional operator() (point_2 const & a, point_2 const & b, point_2 const & c) const + boost::optional operator()(point_2 const &a, point_2 const &b, point_2 const &c) const { typedef boost::numeric::interval_lib::unprotect >::type interval; boost::numeric::interval::traits_type::rounding _; - interval res = (interval(b.x) - a.x) * (interval(c.y) - a.y) - - (interval(b.y) - a.y) * (interval(c.x) - a.x); + interval res = (interval(b.x) - a.x) * (interval(c.y) - a.y) + - (interval(b.y) - a.y) * (interval(c.x) - a.x); if (res.lower() > 0) return CG_LEFT; @@ -68,10 +68,10 @@ namespace cg struct orientation_r { - boost::optional operator() (point_2 const & a, point_2 const & b, point_2 const & c) const + boost::optional operator()(point_2 const &a, point_2 const &b, point_2 const &c) const { - mpq_class res = (mpq_class(b.x) - a.x) * (mpq_class(c.y) - a.y) - - (mpq_class(b.y) - a.y) * (mpq_class(c.x) - a.x); + mpq_class res = (mpq_class(b.x) - a.x) * (mpq_class(c.y) - a.y) + - (mpq_class(b.y) - a.y) * (mpq_class(c.x) - a.x); int cres = cmp(res, 0); @@ -85,7 +85,7 @@ namespace cg } }; - inline orientation_t orientation(point_2 const & a, point_2 const & b, point_2 const & c) + inline orientation_t orientation(point_2 const &a, point_2 const &b, point_2 const &c) { if (boost::optional v = orientation_d()(a, b, c)) return *v; @@ -96,7 +96,7 @@ namespace cg return *orientation_r()(a, b, c); } - inline bool counterclockwise(contour_2 const & c) + inline bool counterclockwise(contour_2 const &c) { if (c.size() < 3) return true; @@ -113,86 +113,86 @@ namespace cg return orientation(prev, min_point, next) == CG_LEFT; } - template - bool collinear_are_ordered_along_line(point_2t const & a, point_2t const & b, point_2t const & c) + template + bool collinear_are_ordered_along_line(point_2t const &a, point_2t const &b, point_2t const &c) { return (a <= b && b <= c) || (c <= b && b <= a); } - struct orientation_3d_vectors_d - { - boost::optional operator() (point_3 const & a, point_3 const & b, point_3 const & c) const - { - double x23 = a.x * (b.y*c.z-b.z*c.y); - double y13 = a.y * (b.x*c.z-b.z*c.x); - double z12 = a.z * (b.x*c.y-b.y*c.x); - double eps = (fabs(x23) + fabs(y13) + fabs(z12)) * 8 * std::numeric_limits::epsilon(); + struct orientation_3d_vectors_d + { + boost::optional operator()(point_3 const &a, point_3 const &b, point_3 const &c) const + { + double x23 = a.x * (b.y * c.z - b.z * c.y); + double y13 = a.y * (b.x * c.z - b.z * c.x); + double z12 = a.z * (b.x * c.y - b.y * c.x); + double eps = (fabs(x23) + fabs(y13) + fabs(z12)) * 8 * std::numeric_limits::epsilon(); - double res = x23 - y13 + z12; + double res = x23 - y13 + z12; - if (res > eps) - return CG_RIGHT; + if (res > eps) + return CG_RIGHT; - if (res < -eps) - return CG_LEFT; + if (res < -eps) + return CG_LEFT; - return boost::none; - } - }; + return boost::none; + } + }; - struct orientation_3d_vectors_i - { - boost::optional operator() (point_3 const & a, point_3 const & b, point_3 const & c) const - { - typedef boost::numeric::interval_lib::unprotect >::type interval; + struct orientation_3d_vectors_i + { + boost::optional operator()(point_3 const &a, point_3 const &b, point_3 const &c) const + { + typedef boost::numeric::interval_lib::unprotect >::type interval; - boost::numeric::interval::traits_type::rounding _; - interval res = (interval(b.y) * c.z - interval(b.z) * c.y) * a.x - - (interval(b.x) * c.z - interval(b.z) * c.x) * a.y - + (interval(b.x) * c.y - interval(b.y) * c.x) * a.z; + boost::numeric::interval::traits_type::rounding _; + interval res = (interval(b.y) * c.z - interval(b.z) * c.y) * a.x + - (interval(b.x) * c.z - interval(b.z) * c.x) * a.y + + (interval(b.x) * c.y - interval(b.y) * c.x) * a.z; - if (res.lower() > 0) - return CG_RIGHT; + if (res.lower() > 0) + return CG_RIGHT; - if (res.upper() < 0) - return CG_LEFT; + if (res.upper() < 0) + return CG_LEFT; - if (res.upper() == res.lower()) - return CG_COLLINEAR; + if (res.upper() == res.lower()) + return CG_COLLINEAR; - return boost::none; - } - }; + return boost::none; + } + }; - struct orientation_3d_vectors_r - { - boost::optional operator() (point_3 const & a, point_3 const & b, point_3 const & c) const - { - mpq_class res = (mpq_class(b.y) * c.z - mpq_class(b.z) * c.y) * a.x - - (mpq_class(b.x) * c.z - mpq_class(b.z) * c.x) * a.y - + (mpq_class(b.x) * c.y - mpq_class(b.y) * c.x) * a.z; + struct orientation_3d_vectors_r + { + boost::optional operator()(point_3 const &a, point_3 const &b, point_3 const &c) const + { + mpq_class res = (mpq_class(b.y) * c.z - mpq_class(b.z) * c.y) * a.x + - (mpq_class(b.x) * c.z - mpq_class(b.z) * c.x) * a.y + + (mpq_class(b.x) * c.y - mpq_class(b.y) * c.x) * a.z; - int cres = cmp(res, 0); + int cres = cmp(res, 0); - if (cres > 0) - return CG_RIGHT; + if (cres > 0) + return CG_RIGHT; - if (cres < 0) - return CG_LEFT; + if (cres < 0) + return CG_LEFT; - return CG_COLLINEAR; - } - }; + return CG_COLLINEAR; + } + }; - inline orientation_t orientation_3d_vectors(point_3 const & a, point_3 const & b, point_3 const & c) - { + inline orientation_t orientation_3d_vectors(point_3 const &a, point_3 const &b, point_3 const &c) + { // if (boost::optional v = orientation_3d_vectors_d()(a, b, c)) // return *v; - if (boost::optional v = orientation_3d_vectors_i()(a, b, c)) - return *v; + if (boost::optional v = orientation_3d_vectors_i()(a, b, c)) + return *v; - return *orientation_3d_vectors_r()(a, b, c); - } + return *orientation_3d_vectors_r()(a, b, c); + } } diff --git a/include/cg/primitives/point.h b/include/cg/primitives/point.h index f389dd1..015aeaa 100644 --- a/include/cg/primitives/point.h +++ b/include/cg/primitives/point.h @@ -2,137 +2,159 @@ #include "vector.h" -namespace cg { - template struct point_2t; - - typedef point_2t point_2; - typedef point_2t point_2f; - typedef point_2t point_2i; - - template - struct point_2t { - Scalar x, y; - - point_2t(Scalar x, Scalar y) - : x(x), y(y) { - } - - template - point_2t(point_2t const &o) - : x(o.x), y(o.y) { - } - - point_2t() - : x(0), y(0) { - } - - point_2t &operator+=(vector_2t const &delta) { - x += delta.x; - y += delta.y; - return *this; - } - }; - - template - inline bool operator<(point_2t const &a, point_2t const &b) { - if (a.x == b.x) - return a.y < b.y; - else - return a.x < b.x; - } - - template - bool operator>(point_2t const &a, point_2t const &b) { - return b < a; - } - - template - bool operator==(point_2t const &a, point_2t const &b) { - return (a.x == b.x) && (a.y == b.y); - } - - template - bool operator<=(point_2t const &a, point_2t const &b) { - return !(a > b); - } - - template - bool operator>=(point_2t const &a, point_2t const &b) { - return !(a < b); - } - - - template - bool operator!=(point_2t const &a, point_2t const &b) { - return !(a == b); - } - - // в этом месте возможно переполнение! - template - vector_2t const operator-(point_2t const &a, point_2t const &b) { - return vector_2t(a.x - b.x, a.y - b.y); - } - - // в этом месте возможно переполнение! - template - point_2t const operator+(point_2t const &pt, vector_2t const &delta) { - point_2t res(pt); - res += delta; - return res; - } - - template struct point_3t; - - typedef point_3t point_3; - typedef point_3t point_3f; - typedef point_3t point_3i; - - template - struct point_3t { - Scalar x, y, z; - - point_3t(Scalar x, Scalar y, Scalar z) - : x(x), y(y), z(z) { - } - - template - point_3t(point_3t const &o) - : x(o.x), y(o.y), z(o.z) { - } - - point_3t() - : x(0), y(0), z(0) { - } - - point_3t & operator *= (Scalar s) - { - x *= s; - y *= s; - z *= s; - return *this; - } - }; - - template - bool operator==(point_3t const &a, point_3t const &b) { - return (a.x == b.x) && (a.y == b.y) && (a.z == b.z); - } - - template - bool operator!=(point_3t const &a, point_3t const &b) { - return !(a == b); - } - - template - point_3t operator * (point_3t v, Scalar s) - { - return v *= s; - } - - template - point_3t operator * (Scalar s, point_3t v) - { - return v *= s; - } +namespace cg +{ + template + struct point_2t; + + typedef point_2t point_2; + typedef point_2t point_2f; + typedef point_2t point_2i; + + template + struct point_2t + { + Scalar x, y; + + point_2t(Scalar x, Scalar y) + : x(x), y(y) + { + } + + template + point_2t(point_2t const &o) + : x(o.x), y(o.y) + { + } + + point_2t() + : x(0), y(0) + { + } + + point_2t &operator+=(vector_2t const &delta) + { + x += delta.x; + y += delta.y; + return *this; + } + }; + + template + inline bool operator<(point_2t const &a, point_2t const &b) + { + if (a.x == b.x) + return a.y < b.y; + else + return a.x < b.x; + } + + template + bool operator>(point_2t const &a, point_2t const &b) + { + return b < a; + } + + template + bool operator==(point_2t const &a, point_2t const &b) + { + return (a.x == b.x) && (a.y == b.y); + } + + template + bool operator<=(point_2t const &a, point_2t const &b) + { + return !(a > b); + } + + template + bool operator>=(point_2t const &a, point_2t const &b) + { + return !(a < b); + } + + + template + bool operator!=(point_2t const &a, point_2t const &b) + { + return !(a == b); + } + + // в этом месте возможно переполнение! + template + vector_2t const operator-(point_2t const &a, point_2t const &b) + { + return vector_2t(a.x - b.x, a.y - b.y); + } + + // в этом месте возможно переполнение! + template + point_2t const operator+(point_2t const &pt, vector_2t const &delta) + { + point_2t res(pt); + res += delta; + return res; + } + + template + struct point_3t; + + typedef point_3t point_3; + typedef point_3t point_3f; + typedef point_3t point_3i; + + template + struct point_3t + { + Scalar x, y, z; + + point_3t(Scalar x, Scalar y, Scalar z) + : x(x), y(y), z(z) + { + } + + template + point_3t(point_3t const &o) + : x(o.x), y(o.y), z(o.z) + { + } + + point_3t() + : x(0), y(0), z(0) + { + } + + point_3t &operator*=(Scalar s) + { + x *= s; + y *= s; + z *= s; + return *this; + } + }; + + template + bool operator==(point_3t const &a, point_3t const &b) + { + return (a.x == b.x) && (a.y == b.y) && (a.z == b.z); + } + + template + bool operator!=(point_3t const &a, point_3t const &b) + { + return !(a == b); + } + + template + point_3t operator*(point_3t v, Scalar s) + { + return v *= s; + } + + template + point_3t operator*(Scalar s, point_3t v) + { + return v *= s; + } } diff --git a/tests/orientation.cpp b/tests/orientation.cpp index 55a23b2..452327c 100644 --- a/tests/orientation.cpp +++ b/tests/orientation.cpp @@ -36,9 +36,9 @@ TEST(orientation, counterclockwise0) using cg::point_2; std::vector a = boost::assign::list_of(point_2(0, 0)) - (point_2(1, 0)) - (point_2(1, 1)) - (point_2(0, 1)); + (point_2(1, 0)) + (point_2(1, 1)) + (point_2(0, 1)); EXPECT_TRUE(cg::counterclockwise(cg::contour_2(a))); } @@ -49,8 +49,8 @@ TEST(orientation, counterclockwise1) using cg::point_2; std::vector a = boost::assign::list_of(point_2(0, 0)) - (point_2(2, 0)) - (point_2(1, 2)); + (point_2(2, 0)) + (point_2(1, 2)); EXPECT_TRUE(cg::counterclockwise(cg::contour_2(a))); } @@ -61,8 +61,8 @@ TEST(orientation, counterclockwise2) using cg::point_2; std::vector a = boost::assign::list_of(point_2(1, 0)) - (point_2(3, 0)) - (point_2(0, 2)); + (point_2(3, 0)) + (point_2(0, 2)); EXPECT_TRUE(cg::counterclockwise(cg::contour_2(a))); } @@ -73,15 +73,16 @@ TEST(orientation, counterclockwise3) using cg::point_2; std::vector a = boost::assign::list_of(point_2(0, 0)) - (point_2(0, 1)) - (point_2(1, 1)) - (point_2(1, 1)); + (point_2(0, 1)) + (point_2(1, 1)) + (point_2(1, 1)); EXPECT_FALSE(cg::counterclockwise(cg::contour_2(a))); } #include + using std::cerr; using std::endl; @@ -128,34 +129,34 @@ TEST(orientation, uniform1) TEST(orientation_3d_vectors, simple) { - cg::point_3 i(1, 0, 0); - cg::point_3 j(0, 1, 0); - cg::point_3 k(0, 0, 1); - EXPECT_EQ(cg::orientation_t::CG_RIGHT, cg::orientation_3d_vectors(i, j, k)); - EXPECT_EQ(cg::orientation_t::CG_LEFT, cg::orientation_3d_vectors(i, k, j)); - EXPECT_EQ(cg::orientation_t::CG_LEFT, cg::orientation_3d_vectors(k, j, i)); - EXPECT_EQ(cg::orientation_t::CG_LEFT, cg::orientation_3d_vectors(j, i, k)); - EXPECT_EQ(cg::orientation_t::CG_RIGHT, cg::orientation_3d_vectors(j, k, i)); - EXPECT_EQ(cg::orientation_t::CG_RIGHT, cg::orientation_3d_vectors(k, i, j)); - - EXPECT_EQ(cg::orientation_t::CG_RIGHT, *cg::orientation_3d_vectors_r()(i, j, k)); - EXPECT_EQ(cg::orientation_t::CG_LEFT, *cg::orientation_3d_vectors_r()(i, k, j)); - EXPECT_EQ(cg::orientation_t::CG_LEFT, *cg::orientation_3d_vectors_r()(k, j, i)); - EXPECT_EQ(cg::orientation_t::CG_LEFT, *cg::orientation_3d_vectors_r()(j, i, k)); - EXPECT_EQ(cg::orientation_t::CG_RIGHT, *cg::orientation_3d_vectors_r()(j, k, i)); - EXPECT_EQ(cg::orientation_t::CG_RIGHT, *cg::orientation_3d_vectors_r()(k, i, j)); + cg::point_3 i(1, 0, 0); + cg::point_3 j(0, 1, 0); + cg::point_3 k(0, 0, 1); + EXPECT_EQ(cg::orientation_t::CG_RIGHT, cg::orientation_3d_vectors(i, j, k)); + EXPECT_EQ(cg::orientation_t::CG_LEFT, cg::orientation_3d_vectors(i, k, j)); + EXPECT_EQ(cg::orientation_t::CG_LEFT, cg::orientation_3d_vectors(k, j, i)); + EXPECT_EQ(cg::orientation_t::CG_LEFT, cg::orientation_3d_vectors(j, i, k)); + EXPECT_EQ(cg::orientation_t::CG_RIGHT, cg::orientation_3d_vectors(j, k, i)); + EXPECT_EQ(cg::orientation_t::CG_RIGHT, cg::orientation_3d_vectors(k, i, j)); + + EXPECT_EQ(cg::orientation_t::CG_RIGHT, *cg::orientation_3d_vectors_r()(i, j, k)); + EXPECT_EQ(cg::orientation_t::CG_LEFT, *cg::orientation_3d_vectors_r()(i, k, j)); + EXPECT_EQ(cg::orientation_t::CG_LEFT, *cg::orientation_3d_vectors_r()(k, j, i)); + EXPECT_EQ(cg::orientation_t::CG_LEFT, *cg::orientation_3d_vectors_r()(j, i, k)); + EXPECT_EQ(cg::orientation_t::CG_RIGHT, *cg::orientation_3d_vectors_r()(j, k, i)); + EXPECT_EQ(cg::orientation_t::CG_RIGHT, *cg::orientation_3d_vectors_r()(k, i, j)); } TEST(orientation_3d_vectors, uniform_line) { - uniform_random_real distr(-(1LL << 53), (1LL << 53)); - - std::vector pts = uniform_points3d(1000); - for (size_t l = 0; l < pts.size(); l++) - { - cg::point_3 a = pts[l]; - cg::point_3 b = a * distr(); - cg::point_3 c = a * distr(); - EXPECT_EQ(*cg::orientation_3d_vectors_r()(a, b, c), cg::orientation_3d_vectors(a, b, c)); - } + uniform_random_real distr(-(1LL << 53), (1LL << 53)); + + std::vector pts = uniform_points3d(1000); + for (size_t l = 0; l < pts.size(); l++) + { + cg::point_3 a = pts[l]; + cg::point_3 b = a * distr(); + cg::point_3 c = a * distr(); + EXPECT_EQ(*cg::orientation_3d_vectors_r()(a, b, c), cg::orientation_3d_vectors(a, b, c)); + } } \ No newline at end of file diff --git a/tests/random_utils.h b/tests/random_utils.h index 45a02b3..a21eef7 100644 --- a/tests/random_utils.h +++ b/tests/random_utils.h @@ -6,31 +6,31 @@ inline std::vector uniform_points(size_t count) { - util::uniform_random_real rand(-100., 100.); + util::uniform_random_real rand(-100., 100.); - std::vector res(count); + std::vector res(count); - for (size_t l = 0; l != count; ++l) - { - rand >> res[l].x; - rand >> res[l].y; - } + for (size_t l = 0; l != count; ++l) + { + rand >> res[l].x; + rand >> res[l].y; + } - return res; + return res; } inline std::vector uniform_points3d(size_t count) { - util::uniform_random_real rand(-100., 100.); + util::uniform_random_real rand(-100., 100.); - std::vector res(count); + std::vector res(count); - for (size_t l = 0; l != count; ++l) - { - rand >> res[l].x; - rand >> res[l].y; - rand >> res[l].z; - } + for (size_t l = 0; l != count; ++l) + { + rand >> res[l].x; + rand >> res[l].y; + rand >> res[l].z; + } - return res; + return res; }