Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
parallelogram-test.cpp
Go to the documentation of this file.
1
7/*
8 * Authors:
9 * Thomas Holder
10 * Sergei Izmailov
11 *
12 * SPDX-License-Identifier: LGPL-2.1 or MPL-1.1
13 */
14
15#include <2geom/coord.h>
16#include <2geom/parallelogram.h>
17#include <2geom/transforms.h>
18
19#include <gtest/gtest.h>
20
21using namespace Geom;
22
23// Analogous to RotatedRect::from_rect_rotate
24static Parallelogram parallelogram_from_rect_rotate(Rect const &rect, Rotate const &rotate, Point const &point)
25{
26 Affine affine = Translate(-point) * rotate * Translate(point);
27 return Parallelogram(rect) * affine;
28}
29static Parallelogram parallelogram_from_rect_rotate(Rect const &rect, Rotate const &rotate)
30{
31 return parallelogram_from_rect_rotate(rect, rotate, rect.midpoint());
32}
33
34TEST(ParallelogramTest, midpoint)
35{
36 Rect r(-0.5, -0.5, 5.5, 5.5);
37 auto center = Point(2.5, 2.5);
38
39 EXPECT_EQ(r.midpoint(), center);
40 for (double angle : { 0, 1, 25, 45, 90, 135 }) {
41 auto rotated_rect = parallelogram_from_rect_rotate(r, Rotate::from_degrees(angle), Point(0, 0));
42 auto rotated_center = center * Rotate(angle / 180.0 * M_PI);
43 EXPECT_TRUE(Geom::are_near(rotated_rect.midpoint(), rotated_center, 1e-6)) << "Angle = " << angle << " deg";
44 }
45}
46
47TEST(ParallelogramTest, containsPoint1)
48{
49 Rect r(0, 0, 1, 1);
50 auto rotated_rect = r;
51 EXPECT_TRUE(rotated_rect.contains(Point(0, 0)));
52 EXPECT_TRUE(rotated_rect.contains(Point(1, 1)));
53 EXPECT_TRUE(rotated_rect.contains(Point(0.5, 0.5)));
54 EXPECT_FALSE(rotated_rect.contains(Point(1.1, 0.5)));
55 EXPECT_FALSE(rotated_rect.contains(Point(0.5, 1.1)));
56}
57
58TEST(ParallelogramTest, containsPoint2)
59{
60 Rect r(0, 0, 1, 1);
61 auto rotated_rect = parallelogram_from_rect_rotate(r, Rotate::from_degrees(45), Point(0, 0));
62 EXPECT_TRUE(rotated_rect.contains(Point(0, 0)));
63 EXPECT_TRUE(rotated_rect.contains(Point(0, 1.2)));
64 EXPECT_TRUE(rotated_rect.contains(Point(0.5, 0.9)));
65 EXPECT_FALSE(rotated_rect.contains(Point(1, 1)));
66 EXPECT_FALSE(rotated_rect.contains(Point(0.1, 0)));
67}
68
69TEST(ParallelogramTest, intersects_aligned)
70{
71 Rect r(0, 0, 1, 1);
72 auto rotated_rect = r;
73 // point within rect
74 EXPECT_TRUE(rotated_rect.intersects(Rect(-1, -1, 2, 2)));
75 EXPECT_TRUE(rotated_rect.intersects(Rect(0.1, 0.1, 0.2, 0.2)));
76 EXPECT_TRUE(rotated_rect.intersects(Rect(-0.1, -0.1, 0.1, 0.1)));
77 EXPECT_FALSE(rotated_rect.intersects(Rect(-0.2, -0.2, -0.1, -0.1)));
78 EXPECT_FALSE(rotated_rect.intersects(Rect(1.1, 1.1, 1.2, 1.2)));
79 // edge intersection
80 EXPECT_TRUE(rotated_rect.intersects(Rect(0.5, -0.1, 0.6, 1.2)));
81 EXPECT_TRUE(rotated_rect.intersects(Rect(-0.1, 0.5, 1.2, 0.6)));
82}
83
84TEST(ParallelogramTest, bounds)
85{
86 auto r = Rect::from_xywh(1.260, 0.547, 8.523, 11.932);
87 auto rrect = parallelogram_from_rect_rotate(r, Rotate::from_degrees(15.59));
88 auto bbox = rrect.bounds();
89 auto expected_bbox = Rect::from_xywh(-0.186, -0.378, 11.415, 13.783);
90 for (int i = 0; i < 4; i++) {
91 EXPECT_TRUE(Geom::are_near(bbox.corner(i), expected_bbox.corner(i), 1e-3));
92 }
93}
94
95TEST(ParallelogramTest, isSheared)
96{
97 Parallelogram p(Rect(2, 4, 7, 8));
98 EXPECT_FALSE(p.isSheared());
99 p *= Rotate(M_PI / 4.0); // 45°
100 EXPECT_FALSE(p.isSheared());
101 p *= HShear(2);
102 EXPECT_TRUE(p.isSheared());
103}
104
105TEST(ParallelogramTest, area)
106{
107 Rect r(2, 4, 7, 8);
108 Parallelogram p(r);
109 EXPECT_DOUBLE_EQ(p.area(), r.area());
110 p *= Rotate(M_PI / 4.0); // 45°
111 EXPECT_DOUBLE_EQ(p.area(), r.area());
112 p *= HShear(2);
113 EXPECT_DOUBLE_EQ(p.area(), r.area());
114 p *= Scale(2);
115 EXPECT_DOUBLE_EQ(p.area(), r.area() * 4);
116}
117
118class ParallelogramTest
119 : public testing::TestWithParam<std::tuple<Rect /*rect*/, double /*degrees*/, bool /*intersects*/>> {
120
121 void SetUp() override { target = Rect::from_xywh(0, 0, 11, 13); }
122
123 public:
124 Rect target;
125};
126
127TEST_P(ParallelogramTest, intersects)
128{
129 Rect rect;
130 double degrees;
131 bool intersects;
132 std::tie(rect, degrees, intersects) = GetParam();
133 EXPECT_EQ(parallelogram_from_rect_rotate(rect, Rotate::from_degrees(degrees)).intersects(target), intersects)
134 << "ERROR: rect {" << rect << "} rotated by {" << degrees << "} degrees " << (!intersects ? "" : "NOT ")
135 << "intersects with {" << target << "} but MUST " << (intersects ? "" : "NOT");
136}
137
138// clang-format off
139INSTANTIATE_TEST_CASE_P(intesect_non_aligned, ParallelogramTest,
140 testing::Values(
141 std::make_tuple(Rect::from_xywh(10.456, -4.479, 7, 5), 0, true),
142 std::make_tuple(Rect::from_xywh(10.456, -4.479, 7, 5), 15, false),
143 std::make_tuple(Rect::from_xywh(9.929, 12.313, 7, 5), 93.2, false),
144 std::make_tuple(Rect::from_xywh(9.929, 12.313, 7, 5), 91.37, true),
145 std::make_tuple(Rect::from_xywh(-1, 4, 13, 3), 0, true),
146 std::make_tuple(Rect::from_xywh(4, -2, 3, 16), 0, true),
147 std::make_tuple(Rect::from_xywh(-5.113, -3.283, 5.000, 7.000), 11.81, false),
148 std::make_tuple(Rect::from_xywh(-5.113, -3.283, 5.000, 7.000), 13.35, true),
149 std::make_tuple(Rect::from_xywh(1.260, 0.547, 8.523, 11.932), 15.59, true),
150 std::make_tuple(Rect::from_xywh(5.328, 0.404, 11, 2), 28.16, true),
151 std::make_tuple(Rect::from_xywh(4.853, 10.691, 11, 2), -30.4, true),
152 std::make_tuple(Rect::from_xywh(-4.429, 10.752, 11, 2), 29.7, true),
153 std::make_tuple(Rect::from_xywh(-4.538, 0.314, 11, 2), -34.19, true),
154 std::make_tuple(Rect::from_xywh(8.398, -3.790, 2, 11), -34, true),
155 std::make_tuple(Rect::from_xywh(8.614, 6.163, 2, 11), 30.38, true),
156 std::make_tuple(Rect::from_xywh(0.492, 6.904, 2, 11), -37.29, true),
157 std::make_tuple(Rect::from_xywh(0.202, -3.148, 2, 11), 31.12, true)));
158
159// clang-format on
160
161// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Geom::IntRect bounds
Definition canvas.cpp:182
3x3 matrix representing an affine transformation.
Definition affine.h:70
C area() const
Compute the rectangle's area.
CPoint midpoint() const
Get the point in the geometric center of the rectangle.
Horizontal shearing.
Definition transforms.h:257
Paralellogram, representing a linear transformation of a rectangle.
bool isSheared(Coord eps=EPSILON) const
True if this parallelogram does not have right angles.
Coord area() const
Area (non-negative)
Two-dimensional point that doubles as a vector.
Definition point.h:66
Axis aligned, non-empty rectangle.
Definition rect.h:92
Rotation around the origin.
Definition transforms.h:187
Scaling from the origin.
Definition transforms.h:150
Translation by a vector.
Definition transforms.h:115
Integral and real coordinate types and some basic utilities.
Various utility functions.
Definition affine.h:22
static double area(Geom::Point a, Geom::Point b, Geom::Point c)
@ intersects
Definition geom.cpp:16
TEST(AffineTest, Equality)
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
TEST_P(ParallelogramTest, intersects)
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)))
static Parallelogram parallelogram_from_rect_rotate(Rect const &rect, Rotate const &rotate, Point const &point)
Affine transformation classes.