#include "gtest/gtest.h" #include #include <2geom/coord.h> #include <2geom/interval.h> #include <2geom/intersection.h> // streams out a vector template std::ostream& operator<< (std::ostream &out, const std::vector > &v) { typedef std::ostream_iterator > Iter; std::copy (v.begin (), v.end (), Iter (out, " ")); return out; } template std::vector vector_from_array(const T (&x)[xn]) { std::vector v; for(unsigned i = 0; i < xn; i++) { v.push_back(x[i]); } return v; } template void expect_array(const T (&x)[xn], std::vector y) { EXPECT_EQ(xn, y.size()); for(unsigned i = 0; i < y.size(); i++) { EXPECT_EQ(x[i], y[i]); } } Geom::Interval bound_vector(std::vector const &v) { double low = v[0]; double high = v[0]; for(double i : v) { low = std::min(i, low); high = std::max(i, high); } return Geom::Interval(low-1, high-1); } // Custom assertion formatting predicates template ::testing::AssertionResult ObjectNear(char const *l_expr, char const *r_expr, char const */*eps_expr*/, T const &l, T const &r, Geom::Coord eps) { if (!Geom::are_near(l, r, eps)) { return ::testing::AssertionFailure() << "Objects are not near\n" << "First object: " << l_expr << "\n" << "Value: " << l << "\n" << "Second object: " << r_expr << "\n" << "Value: " << r << "\n" << "Threshold: " << Geom::format_coord_nice(eps) << std::endl; } return ::testing::AssertionSuccess(); } template ::testing::AssertionResult ObjectNotNear(char const *l_expr, char const *r_expr, char const */*eps_expr*/, T const &l, T const &r, Geom::Coord eps) { if (Geom::are_near(l, r, eps)) { return ::testing::AssertionFailure() << "Objects are near\n" << "First object: " << l_expr << "\n" << "Value: " << l << "\n" << "Second object: " << r_expr << "\n" << "Value: " << r << "\n" << "Threshold: " << Geom::format_coord_nice(eps) << std::endl; } return ::testing::AssertionSuccess(); } #define EXPECT_near(a, b, eps) EXPECT_PRED_FORMAT3(ObjectNear, a, b, eps) #define EXPECT_not_near(a, b, eps) EXPECT_PRED_FORMAT3(ObjectNotNear, a, b, eps) template ::testing::AssertionResult VectorEqual(char const *l_expr, char const *r_expr, std::vector const &l, std::vector const &r) { if (l.size() != r.size()) { return ::testing::AssertionFailure() << "Vectors differ in size\n" << l_expr << " has size " << l.size() << "\n" << r_expr << " has size " << r.size() << std::endl; } for (unsigned i = 0; i < l.size(); ++i) { if (!(l[i] == r[i])) { return ::testing::AssertionFailure() << "Vectors differ" << "\nVector: " << l_expr << "\nindex " << i << " contains: " << l[i] << "\nVector:" << r_expr << "\nindex " << i << " contains: " << r[i] << std::endl; } } return ::testing::AssertionSuccess(); } template ::testing::AssertionResult VectorNear(char const *l_expr, char const *r_expr, char const */*eps_expr*/, std::vector const &l, std::vector const &r, Geom::Coord eps) { if (l.size() != r.size()) { return ::testing::AssertionFailure() << "Vectors differ in size\n" << l_expr << "has size " << l.size() << "\n" << r_expr << "has size " << r.size() << std::endl; } for (unsigned i = 0; i < l.size(); ++i) { if (!Geom::are_near(l[i], r[i], eps)) { return ::testing::AssertionFailure() << "Vectors differ by more than " << Geom::format_coord_nice(eps) << "\nVector: " << l_expr << "\nindex " << i << " contains: " << l[i] << "\nVector:" << r_expr << "\nindex " << i << " contains: " << r[i] << std::endl; } } return ::testing::AssertionSuccess(); } #define EXPECT_vector_equal(a, b) EXPECT_PRED_FORMAT2(VectorEqual, a, b) #define EXPECT_vector_near(a, b, eps) EXPECT_PRED_FORMAT3(VectorNear, a, b, eps) template ::testing::AssertionResult IntersectionsValid( char const *l_expr, char const *r_expr, const char */*xs_expr*/, const char */*eps_expr*/, TA const &shape_a, TB const &shape_b, std::vector::TimeType, typename Geom::ShapeTraits::TimeType> > const &xs, Geom::Coord eps) { std::ostringstream os; bool failed = false; for (unsigned i = 0; i < xs.size(); ++i) { Geom::Point pa = shape_a.pointAt(xs[i].first); Geom::Point pb = shape_b.pointAt(xs[i].second); if (!Geom::are_near(pa, xs[i].point(), eps) || !Geom::are_near(pb, xs[i].point(), eps) || !Geom::are_near(pb, pa, eps)) { os << "Intersection " << i << " does not match\n" << Geom::format_coord_nice(xs[i].first) << " evaluates to " << pa << "\n" << Geom::format_coord_nice(xs[i].second) << " evaluates to " << pb << "\n" << "Reported intersection point is " << xs[i].point() << std::endl; failed = true; } } if (failed) { return ::testing::AssertionFailure() << "Intersections do not match\n" << "Shape A: " << l_expr << "\n" << "Shape B: " << r_expr << "\n" << os.str() << "Threshold: " << Geom::format_coord_nice(eps) << std::endl; } return ::testing::AssertionSuccess(); } #define EXPECT_intersections_valid(a, b, xs, eps) EXPECT_PRED_FORMAT4(IntersectionsValid, a, b, xs, eps)