summaryrefslogtreecommitdiffstats
path: root/tests/parallelogram-test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/parallelogram-test.cpp')
-rw-r--r--tests/parallelogram-test.cpp161
1 files changed, 161 insertions, 0 deletions
diff --git a/tests/parallelogram-test.cpp b/tests/parallelogram-test.cpp
new file mode 100644
index 0000000..70ccea1
--- /dev/null
+++ b/tests/parallelogram-test.cpp
@@ -0,0 +1,161 @@
+/** @file
+ * @brief Unit tests for Parallelogram
+ *
+ * Includes all tests from RotatedRect to demonstrate that it is a generalized
+ * version of the rotated rectangle.
+ */
+/*
+ * Authors:
+ * Thomas Holder
+ * Sergei Izmailov
+ *
+ * SPDX-License-Identifier: LGPL-2.1 or MPL-1.1
+ */
+
+#include <2geom/coord.h>
+#include <2geom/parallelogram.h>
+#include <2geom/transforms.h>
+
+#include <gtest/gtest.h>
+
+using namespace Geom;
+
+// Analogous to RotatedRect::from_rect_rotate
+static Parallelogram parallelogram_from_rect_rotate(Rect const &rect, Rotate const &rotate, Point const &point)
+{
+ Affine affine = Translate(-point) * rotate * Translate(point);
+ return Parallelogram(rect) * affine;
+}
+static Parallelogram parallelogram_from_rect_rotate(Rect const &rect, Rotate const &rotate)
+{
+ return parallelogram_from_rect_rotate(rect, rotate, rect.midpoint());
+}
+
+TEST(ParallelogramTest, midpoint)
+{
+ Rect r(-0.5, -0.5, 5.5, 5.5);
+ auto center = Point(2.5, 2.5);
+
+ EXPECT_EQ(r.midpoint(), center);
+ for (double angle : { 0, 1, 25, 45, 90, 135 }) {
+ auto rotated_rect = parallelogram_from_rect_rotate(r, Rotate::from_degrees(angle), Point(0, 0));
+ auto rotated_center = center * Rotate(angle / 180.0 * M_PI);
+ EXPECT_TRUE(Geom::are_near(rotated_rect.midpoint(), rotated_center, 1e-6)) << "Angle = " << angle << " deg";
+ }
+}
+
+TEST(ParallelogramTest, containsPoint1)
+{
+ Rect r(0, 0, 1, 1);
+ auto rotated_rect = r;
+ EXPECT_TRUE(rotated_rect.contains(Point(0, 0)));
+ EXPECT_TRUE(rotated_rect.contains(Point(1, 1)));
+ EXPECT_TRUE(rotated_rect.contains(Point(0.5, 0.5)));
+ EXPECT_FALSE(rotated_rect.contains(Point(1.1, 0.5)));
+ EXPECT_FALSE(rotated_rect.contains(Point(0.5, 1.1)));
+}
+
+TEST(ParallelogramTest, containsPoint2)
+{
+ Rect r(0, 0, 1, 1);
+ auto rotated_rect = parallelogram_from_rect_rotate(r, Rotate::from_degrees(45), Point(0, 0));
+ EXPECT_TRUE(rotated_rect.contains(Point(0, 0)));
+ EXPECT_TRUE(rotated_rect.contains(Point(0, 1.2)));
+ EXPECT_TRUE(rotated_rect.contains(Point(0.5, 0.9)));
+ EXPECT_FALSE(rotated_rect.contains(Point(1, 1)));
+ EXPECT_FALSE(rotated_rect.contains(Point(0.1, 0)));
+}
+
+TEST(ParallelogramTest, intersects_aligned)
+{
+ Rect r(0, 0, 1, 1);
+ auto rotated_rect = r;
+ // point within rect
+ EXPECT_TRUE(rotated_rect.intersects(Rect(-1, -1, 2, 2)));
+ EXPECT_TRUE(rotated_rect.intersects(Rect(0.1, 0.1, 0.2, 0.2)));
+ EXPECT_TRUE(rotated_rect.intersects(Rect(-0.1, -0.1, 0.1, 0.1)));
+ EXPECT_FALSE(rotated_rect.intersects(Rect(-0.2, -0.2, -0.1, -0.1)));
+ EXPECT_FALSE(rotated_rect.intersects(Rect(1.1, 1.1, 1.2, 1.2)));
+ // edge intersection
+ EXPECT_TRUE(rotated_rect.intersects(Rect(0.5, -0.1, 0.6, 1.2)));
+ EXPECT_TRUE(rotated_rect.intersects(Rect(-0.1, 0.5, 1.2, 0.6)));
+}
+
+TEST(ParallelogramTest, bounds)
+{
+ auto r = Rect::from_xywh(1.260, 0.547, 8.523, 11.932);
+ auto rrect = parallelogram_from_rect_rotate(r, Rotate::from_degrees(15.59));
+ auto bbox = rrect.bounds();
+ auto expected_bbox = Rect::from_xywh(-0.186, -0.378, 11.415, 13.783);
+ for (int i = 0; i < 4; i++) {
+ EXPECT_TRUE(Geom::are_near(bbox.corner(i), expected_bbox.corner(i), 1e-3));
+ }
+}
+
+TEST(ParallelogramTest, isSheared)
+{
+ Parallelogram p(Rect(2, 4, 7, 8));
+ EXPECT_FALSE(p.isSheared());
+ p *= Rotate(M_PI / 4.0); // 45°
+ EXPECT_FALSE(p.isSheared());
+ p *= HShear(2);
+ EXPECT_TRUE(p.isSheared());
+}
+
+TEST(ParallelogramTest, area)
+{
+ Rect r(2, 4, 7, 8);
+ Parallelogram p(r);
+ EXPECT_DOUBLE_EQ(p.area(), r.area());
+ p *= Rotate(M_PI / 4.0); // 45°
+ EXPECT_DOUBLE_EQ(p.area(), r.area());
+ p *= HShear(2);
+ EXPECT_DOUBLE_EQ(p.area(), r.area());
+ p *= Scale(2);
+ EXPECT_DOUBLE_EQ(p.area(), r.area() * 4);
+}
+
+class ParallelogramTest
+ : public testing::TestWithParam<std::tuple<Rect /*rect*/, double /*degrees*/, bool /*intersects*/>> {
+
+ void SetUp() override { target = Rect::from_xywh(0, 0, 11, 13); }
+
+ public:
+ Rect target;
+};
+
+TEST_P(ParallelogramTest, intersects)
+{
+ Rect rect;
+ double degrees;
+ bool intersects;
+ std::tie(rect, degrees, intersects) = GetParam();
+ EXPECT_EQ(parallelogram_from_rect_rotate(rect, Rotate::from_degrees(degrees)).intersects(target), intersects)
+ << "ERROR: rect {" << rect << "} rotated by {" << degrees << "} degrees " << (!intersects ? "" : "NOT ")
+ << "intersects with {" << target << "} but MUST " << (intersects ? "" : "NOT");
+}
+
+// clang-format off
+INSTANTIATE_TEST_CASE_P(intesect_non_aligned, ParallelogramTest,
+ testing::Values(
+ std::make_tuple(Rect::from_xywh(10.456, -4.479, 7, 5), 0, true),
+ std::make_tuple(Rect::from_xywh(10.456, -4.479, 7, 5), 15, false),
+ std::make_tuple(Rect::from_xywh(9.929, 12.313, 7, 5), 93.2, false),
+ std::make_tuple(Rect::from_xywh(9.929, 12.313, 7, 5), 91.37, true),
+ std::make_tuple(Rect::from_xywh(-1, 4, 13, 3), 0, true),
+ std::make_tuple(Rect::from_xywh(4, -2, 3, 16), 0, true),
+ std::make_tuple(Rect::from_xywh(-5.113, -3.283, 5.000, 7.000), 11.81, false),
+ std::make_tuple(Rect::from_xywh(-5.113, -3.283, 5.000, 7.000), 13.35, true),
+ std::make_tuple(Rect::from_xywh(1.260, 0.547, 8.523, 11.932), 15.59, true),
+ std::make_tuple(Rect::from_xywh(5.328, 0.404, 11, 2), 28.16, true),
+ std::make_tuple(Rect::from_xywh(4.853, 10.691, 11, 2), -30.4, true),
+ std::make_tuple(Rect::from_xywh(-4.429, 10.752, 11, 2), 29.7, true),
+ std::make_tuple(Rect::from_xywh(-4.538, 0.314, 11, 2), -34.19, true),
+ std::make_tuple(Rect::from_xywh(8.398, -3.790, 2, 11), -34, true),
+ std::make_tuple(Rect::from_xywh(8.614, 6.163, 2, 11), 30.38, true),
+ std::make_tuple(Rect::from_xywh(0.492, 6.904, 2, 11), -37.29, true),
+ std::make_tuple(Rect::from_xywh(0.202, -3.148, 2, 11), 31.12, true)));
+
+// clang-format on
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :