Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rotation of 3 points in 3D implemented and covered by tests. #35

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions include/cg/operations/orientation.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,81 @@ namespace cg
{
return (a <= b && b <= c) || (c <= b && b <= a);
}

struct orientation_3d_vectors_d
{
boost::optional<orientation_t> 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<double>::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<orientation_t> operator() (point_3 const & a, point_3 const & b, point_3 const & c) const
{
typedef boost::numeric::interval_lib::unprotect<boost::numeric::interval<double> >::type interval;

boost::numeric::interval<double>::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<orientation_t> 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<orientation_t> v = orientation_3d_vectors_d()(a, b, c))
// return *v;

if (boost::optional<orientation_t> v = orientation_3d_vectors_i()(a, b, c))
return *v;

return *orientation_3d_vectors_r()(a, b, c);
}

}
225 changes: 133 additions & 92 deletions include/cg/primitives/point.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,96 +2,137 @@

#include "vector.h"

namespace cg
{
template <class Scalar> struct point_2t;

typedef point_2t<double> point_2;
typedef point_2t<float> point_2f;
typedef point_2t<int> point_2i;

template <class Scalar>
struct point_2t
{
Scalar x, y;

point_2t(Scalar x, Scalar y)
: x(x)
, y(y)
{}

template <class UScalar>
point_2t(point_2t<UScalar> const & o)
: x(o.x)
, y(o.y)
{}

point_2t()
: x(0)
, y(0)
{}

point_2t<Scalar> & operator += (vector_2t<Scalar> const & delta)
{
x += delta.x;
y += delta.y;
return *this;
}
};

template <class Scalar>
inline bool operator < (point_2t<Scalar> const & a, point_2t<Scalar> const & b)
{
if (a.x == b.x)
return a.y < b.y;
else
return a.x < b.x;
}

template <class Scalar>
bool operator > (point_2t<Scalar> const & a, point_2t<Scalar> const & b)
{
return b < a;
}

template <class Scalar>
bool operator == (point_2t<Scalar> const & a, point_2t<Scalar> const & b)
{
return (a.x == b.x) && (a.y == b.y);
}

template <class Scalar>
bool operator <= (point_2t<Scalar> const & a, point_2t<Scalar> const & b)
{
return !(a > b);
}

template <class Scalar>
bool operator >= (point_2t<Scalar> const & a, point_2t<Scalar> const & b)
{
return !(a < b);
}


template <class Scalar>
bool operator != (point_2t<Scalar> const & a, point_2t<Scalar> const & b)
{
return !(a == b);
}

// в этом месте возможно переполнение!
template <class Scalar>
vector_2t<Scalar> const operator - (point_2t<Scalar> const & a, point_2t<Scalar> const & b)
{
return vector_2t<Scalar>(a.x - b.x, a.y - b.y);
}

// в этом месте возможно переполнение!
template <class Scalar>
point_2t<Scalar> const operator + (point_2t<Scalar> const & pt, vector_2t<Scalar> const & delta)
{
point_2t<Scalar> res(pt);
res += delta;
return res;
}
namespace cg {
template<class Scalar> struct point_2t;

typedef point_2t<double> point_2;
typedef point_2t<float> point_2f;
typedef point_2t<int> point_2i;

template<class Scalar>
struct point_2t {
Scalar x, y;

point_2t(Scalar x, Scalar y)
: x(x), y(y) {
}

template<class UScalar>
point_2t(point_2t<UScalar> const &o)
: x(o.x), y(o.y) {
}

point_2t()
: x(0), y(0) {
}

point_2t<Scalar> &operator+=(vector_2t<Scalar> const &delta) {
x += delta.x;
y += delta.y;
return *this;
}
};

template<class Scalar>
inline bool operator<(point_2t<Scalar> const &a, point_2t<Scalar> const &b) {
if (a.x == b.x)
return a.y < b.y;
else
return a.x < b.x;
}

template<class Scalar>
bool operator>(point_2t<Scalar> const &a, point_2t<Scalar> const &b) {
return b < a;
}

template<class Scalar>
bool operator==(point_2t<Scalar> const &a, point_2t<Scalar> const &b) {
return (a.x == b.x) && (a.y == b.y);
}

template<class Scalar>
bool operator<=(point_2t<Scalar> const &a, point_2t<Scalar> const &b) {
return !(a > b);
}

template<class Scalar>
bool operator>=(point_2t<Scalar> const &a, point_2t<Scalar> const &b) {
return !(a < b);
}


template<class Scalar>
bool operator!=(point_2t<Scalar> const &a, point_2t<Scalar> const &b) {
return !(a == b);
}

// в этом месте возможно переполнение!
template<class Scalar>
vector_2t<Scalar> const operator-(point_2t<Scalar> const &a, point_2t<Scalar> const &b) {
return vector_2t<Scalar>(a.x - b.x, a.y - b.y);
}

// в этом месте возможно переполнение!
template<class Scalar>
point_2t<Scalar> const operator+(point_2t<Scalar> const &pt, vector_2t<Scalar> const &delta) {
point_2t<Scalar> res(pt);
res += delta;
return res;
}

template<class Scalar> struct point_3t;

typedef point_3t<double> point_3;
typedef point_3t<float> point_3f;
typedef point_3t<int> point_3i;

template<class Scalar>
struct point_3t {
Scalar x, y, z;

point_3t(Scalar x, Scalar y, Scalar z)
: x(x), y(y), z(z) {
}

template<class UScalar>
point_3t(point_3t<UScalar> const &o)
: x(o.x), y(o.y), z(o.z) {
}

point_3t()
: x(0), y(0), z(0) {
}

point_3t<Scalar> & operator *= (Scalar s)
{
x *= s;
y *= s;
z *= s;
return *this;
}
};

template<class Scalar>
bool operator==(point_3t<Scalar> const &a, point_3t<Scalar> const &b) {
return (a.x == b.x) && (a.y == b.y) && (a.z == b.z);
}

template<class Scalar>
bool operator!=(point_3t<Scalar> const &a, point_3t<Scalar> const &b) {
return !(a == b);
}

template <class Scalar>
point_3t<Scalar> operator * (point_3t<Scalar> v, Scalar s)
{
return v *= s;
}

template <class Scalar>
point_3t<Scalar> operator * (Scalar s, point_3t<Scalar> v)
{
return v *= s;
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Антон вам еще не рассказал, почему 3 пробела хорошо, а 4 плохо?)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нет :)
Предположение - чтобы не было споров?
Или у четырех есть фатальный недостаток?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Есть. Четыре пробела слишком большой отступ, а два слишком маленький :) Надо поправить на три.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ну елки-палки. Это какой-то мрак. Стандарты ведь есть, IDE ведь должны бы быть (а с этого года и для плюсов). Сейчас испорчу на три.

}
6 changes: 0 additions & 6 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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})
Expand Down
34 changes: 34 additions & 0 deletions tests/orientation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<double, std::mt19937> distr(-(1LL << 53), (1LL << 53));

std::vector<cg::point_3> 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));
}
}
16 changes: 16 additions & 0 deletions tests/random_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,19 @@ inline std::vector<cg::point_2> uniform_points(size_t count)

return res;
}

inline std::vector<cg::point_3> uniform_points3d(size_t count)
{
util::uniform_random_real<double> rand(-100., 100.);

std::vector<cg::point_3> res(count);

for (size_t l = 0; l != count; ++l)
{
rand >> res[l].x;
rand >> res[l].y;
rand >> res[l].z;
}

return res;
}