diff options
Diffstat (limited to 'tests/line-test.cpp')
-rw-r--r-- | tests/line-test.cpp | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/tests/line-test.cpp b/tests/line-test.cpp new file mode 100644 index 0000000..0625566 --- /dev/null +++ b/tests/line-test.cpp @@ -0,0 +1,185 @@ +/** @file + * @brief Unit tests for Line and related functions + * Uses the Google Testing Framework + *//* + * Authors: + * Krzysztof KosiĆski <tweenk.pl@gmail.com> + * + * Copyright 2015 Authors + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + */ + +#include "testing.h" +#include <iostream> +#include <glib.h> + +#include <2geom/line.h> +#include <2geom/affine.h> + +using namespace Geom; + +TEST(LineTest, VectorAndVersor) { + Line a(Point(10, 10), Point(-10, 20)); + Line b(Point(10, 10), Point(15, 15)); + EXPECT_EQ(a.vector(), Point(-20, 10)); + EXPECT_EQ(b.vector(), Point(5, 5)); + EXPECT_EQ(a.versor(), a.vector().normalized()); + EXPECT_EQ(b.versor(), b.vector().normalized()); +} + +TEST(LineTest, AngleBisector) { + Point o(0,0), a(1,1), b(3,0), c(-4, 0); + Point d(0.5231, 0.75223); + + // normal + Line ab1 = make_angle_bisector_line(a + d, o + d, b + d); + Line ab2 = make_angle_bisector_line(a - d, o - d, b - d); + EXPECT_FLOAT_EQ(ab1.angle(), Angle::from_degrees(22.5)); + EXPECT_FLOAT_EQ(ab2.angle(), Angle::from_degrees(22.5)); + + // half angle + Line bc1 = make_angle_bisector_line(b + d, o + d, c + d); + Line bc2 = make_angle_bisector_line(b - d, o - d, c - d); + EXPECT_FLOAT_EQ(bc1.angle(), Angle::from_degrees(90)); + EXPECT_FLOAT_EQ(bc2.angle(), Angle::from_degrees(90)); + + // zero angle + Line aa1 = make_angle_bisector_line(a + d, o + d, a + d); + Line aa2 = make_angle_bisector_line(a - d, o - d, a - d); + EXPECT_FLOAT_EQ(aa1.angle(), Angle::from_degrees(45)); + EXPECT_FLOAT_EQ(aa2.angle(), Angle::from_degrees(45)); +} + +TEST(LineTest, Equality) { + Line a(Point(0,0), Point(2,2)); + Line b(Point(2,2), Point(5,5)); + + EXPECT_EQ(a, a); + EXPECT_EQ(b, b); + EXPECT_EQ(a, b); +} + +TEST(LineTest, Reflection) { + Line a(Point(10, 0), Point(15,5)); + Point pa(10,5), ra(15,0); + + Line b(Point(1,-2), Point(2,0)); + Point pb(5,1), rb(1,3); + Affine reflecta = a.reflection(), reflectb = b.reflection(); + + Point testra = pa * reflecta; + Point testrb = pb * reflectb; + + constexpr Coord eps{1e-12}; + EXPECT_near(testra[X], ra[X], eps); + EXPECT_near(testra[Y], ra[Y], eps); + EXPECT_near(testrb[X], rb[X], eps); + EXPECT_near(testrb[Y], rb[Y], eps); +} + +TEST(LineTest, RotationToZero) { + Line a(Point(-5,23), Point(15,27)); + Affine mx = a.rotationToZero(X); + Affine my = a.rotationToZero(Y); + + for (unsigned i = 0; i <= 12; ++i) { + double t = -1 + 0.25 * i; + Point p = a.pointAt(t); + Point rx = p * mx; + Point ry = p * my; + //std::cout << rx[X] << " " << ry[Y] << std::endl; + // unfortunately this is precise only to about 1e-14 + EXPECT_NEAR(rx[X], 0, 1e-14); + EXPECT_NEAR(ry[Y], 0, 1e-14); + } +} + +TEST(LineTest, Coefficients) { + std::vector<Line> lines; + lines.emplace_back(Point(1e3,1e3), Point(1,1)); + //the case below will never work without normalizing the line + //lines.emplace_back(Point(1e5,1e5), Point(1e-15,0)); + lines.emplace_back(Point(1e5,1e5), Point(1e5,-1e5)); + lines.emplace_back(Point(-3,10), Point(3,10)); + lines.emplace_back(Point(250,333), Point(-72,121)); + + for (auto & line : lines) { + Coord a, b, c, A, B, C; + line.coefficients(a, b, c); + /*std::cout << format_coord_nice(a) << " " + << format_coord_nice(b) << " " + << format_coord_nice(c) << std::endl;*/ + Line k(a, b, c); + //std::cout << k.initialPoint() << " " << k.finalPoint() << std::endl; + k.coefficients(A, B, C); + /*std::cout << format_coord_nice(A) << " " + << format_coord_nice(B) << " " + << format_coord_nice(C) << std::endl;*/ + EXPECT_DOUBLE_EQ(a, A); + EXPECT_DOUBLE_EQ(b, B); + EXPECT_DOUBLE_EQ(c, C); + + for (unsigned j = 0; j <= 10; ++j) { + double t = j / 10.; + Point p = line.pointAt(t); + /*std::cout << t << " " << p << " " + << A*p[X] + B*p[Y] + C << " " + << A*(p[X]-1) + B*(p[Y]+1) + C << std::endl;*/ + EXPECT_near(A*p[X] + B*p[Y] + C, 0., 2e-11); + EXPECT_not_near(A*(p[X]-1) + B*(p[Y]+1) + C, 0., 1e-6); + } + } +} + +TEST(LineTest, Intersection) { + Line a(Point(0,3), Point(1,2)); + Line b(Point(0,-3), Point(1,-2)); + LineSegment lsa(Point(0,3), Point(1,2)); + LineSegment lsb(Point(0,-3), Point(1,-2)); + LineSegment lsc(Point(3,1), Point(3, -1)); + + std::vector<ShapeIntersection> r1, r2, r3; + + r1 = a.intersect(b); + ASSERT_EQ(r1.size(), 1u); + EXPECT_EQ(r1[0].point(), Point(3,0)); + EXPECT_intersections_valid(a, b, r1, 1e-15); + + r2 = a.intersect(lsc); + ASSERT_EQ(r2.size(), 1u); + EXPECT_EQ(r2[0].point(), Point(3,0)); + EXPECT_intersections_valid(a, lsc, r2, 1e-15); + + r3 = b.intersect(lsc); + ASSERT_EQ(r3.size(), 1u); + EXPECT_EQ(r3[0].point(), Point(3,0)); + EXPECT_intersections_valid(a, lsc, r3, 1e-15); + + EXPECT_TRUE(lsa.intersect(lsb).empty()); + EXPECT_TRUE(lsa.intersect(lsc).empty()); + EXPECT_TRUE(lsb.intersect(lsc).empty()); + EXPECT_TRUE(a.intersect(lsb).empty()); + EXPECT_TRUE(b.intersect(lsa).empty()); +} |