1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.geometry.euclidean.twod.shape;
18
19 import java.util.List;
20
21 import org.apache.commons.geometry.core.GeometryTestUtils;
22 import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
23 import org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext;
24 import org.apache.commons.geometry.euclidean.EuclideanTestUtils;
25 import org.apache.commons.geometry.euclidean.twod.AffineTransformMatrix2D;
26 import org.apache.commons.geometry.euclidean.twod.LineConvexSubset;
27 import org.apache.commons.geometry.euclidean.twod.RegionBSPTree2D;
28 import org.apache.commons.geometry.euclidean.twod.Vector2D;
29 import org.apache.commons.geometry.euclidean.twod.path.LinePath;
30 import org.apache.commons.geometry.euclidean.twod.rotation.Rotation2D;
31 import org.junit.Assert;
32 import org.junit.Test;
33
34 public class ParallelogramTest {
35
36 private static final double TEST_EPS = 1e-10;
37
38 private static final DoublePrecisionContext TEST_PRECISION =
39 new EpsilonDoublePrecisionContext(TEST_EPS);
40
41 @Test
42 public void testUnitSquare() {
43
44 final Parallelogram box = Parallelogram.unitSquare(TEST_PRECISION);
45
46
47 Assert.assertEquals(1, box.getSize(), TEST_EPS);
48 Assert.assertEquals(4, box.getBoundarySize(), TEST_EPS);
49 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.ZERO, box.getCentroid(), TEST_EPS);
50
51 final List<Vector2D> vertices = box.getVertices();
52 Assert.assertEquals(4, vertices.size());
53 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-0.5, -0.5), vertices.get(0), TEST_EPS);
54 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0.5, -0.5), vertices.get(1), TEST_EPS);
55 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0.5, 0.5), vertices.get(2), TEST_EPS);
56 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-0.5, 0.5), vertices.get(3), TEST_EPS);
57 }
58
59 @Test
60 public void testFromTransformedUnitSquare() {
61
62 final AffineTransformMatrix2D t = AffineTransformMatrix2D.createTranslation(Vector2D.of(1, 0))
63 .rotate(Math.PI * 0.25)
64 .scale(Vector2D.of(2, 1));
65
66
67 final Parallelogram p = Parallelogram.fromTransformedUnitSquare(t, TEST_PRECISION);
68
69
70 final double sqrt2 = Math.sqrt(2);
71 final double invSqrt2 = 1 / sqrt2;
72
73 Assert.assertEquals(2, p.getSize(), TEST_EPS);
74 Assert.assertEquals(4 * Math.sqrt(2.5), p.getBoundarySize(), TEST_EPS);
75 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(2 * invSqrt2, invSqrt2), p.getCentroid(), TEST_EPS);
76
77 final List<Vector2D> vertices = p.getVertices();
78 Assert.assertEquals(4, vertices.size());
79 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, invSqrt2), vertices.get(0), TEST_EPS);
80 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(2 * invSqrt2, 0), vertices.get(1), TEST_EPS);
81 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(2 * sqrt2, invSqrt2), vertices.get(2), TEST_EPS);
82 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(2 * invSqrt2, sqrt2), vertices.get(3), TEST_EPS);
83 }
84
85 @Test
86 public void testFromTransformedUnitSquare_transformDoesNotPreserveOrientation() {
87
88 final AffineTransformMatrix2D t = AffineTransformMatrix2D.createTranslation(Vector2D.of(1, 0))
89 .rotate(Math.PI * 0.25)
90 .scale(Vector2D.of(-2, 1));
91
92
93 final Parallelogram p = Parallelogram.fromTransformedUnitSquare(t, TEST_PRECISION);
94
95
96 final double sqrt2 = Math.sqrt(2);
97 final double invSqrt2 = 1 / sqrt2;
98
99 Assert.assertEquals(2, p.getSize(), TEST_EPS);
100 Assert.assertEquals(4 * Math.sqrt(2.5), p.getBoundarySize(), TEST_EPS);
101 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-2 * invSqrt2, invSqrt2), p.getCentroid(), TEST_EPS);
102
103 final List<Vector2D> vertices = p.getVertices();
104 Assert.assertEquals(4, vertices.size());
105 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-2 * sqrt2, invSqrt2), vertices.get(0), TEST_EPS);
106 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-2 * invSqrt2, 0), vertices.get(1), TEST_EPS);
107 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, invSqrt2), vertices.get(2), TEST_EPS);
108 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-2 * invSqrt2, sqrt2), vertices.get(3), TEST_EPS);
109 }
110
111 @Test
112 public void testFromTransformedUnitSquare_zeroSizeRegion() {
113
114 GeometryTestUtils.assertThrows(() -> {
115 Parallelogram.fromTransformedUnitSquare(AffineTransformMatrix2D.createScale(Vector2D.of(1e-16, 1)),
116 TEST_PRECISION);
117 }, IllegalArgumentException.class);
118
119 GeometryTestUtils.assertThrows(() -> {
120 Parallelogram.fromTransformedUnitSquare(AffineTransformMatrix2D.createScale(Vector2D.of(1, 1e-16)),
121 TEST_PRECISION);
122 }, IllegalArgumentException.class);
123 }
124
125 @Test
126 public void testAxisAligned_minFirst() {
127
128 final Parallelogram box = Parallelogram.axisAligned(Vector2D.of(1, 2), Vector2D.of(3, 4), TEST_PRECISION);
129
130
131 Assert.assertEquals(1, box.getBoundaryPaths().size());
132 final LinePath path = box.getBoundaryPaths().get(0);
133
134 final List<LineConvexSubset> segments = path.getElements();
135 Assert.assertEquals(4, segments.size());
136
137 assertSegment(segments.get(0), Vector2D.of(1, 2), Vector2D.of(3, 2));
138 assertSegment(segments.get(1), Vector2D.of(3, 2), Vector2D.of(3, 4));
139 assertSegment(segments.get(2), Vector2D.of(3, 4), Vector2D.of(1, 4));
140 assertSegment(segments.get(3), Vector2D.of(1, 4), Vector2D.of(1, 2));
141 }
142
143 @Test
144 public void testAxisAligned_maxFirst() {
145
146 final Parallelogram box = Parallelogram.axisAligned(Vector2D.ZERO, Vector2D.of(-1, -2), TEST_PRECISION);
147
148
149 Assert.assertEquals(1, box.getBoundaryPaths().size());
150 final LinePath path = box.getBoundaryPaths().get(0);
151
152 final List<LineConvexSubset> segments = path.getElements();
153 Assert.assertEquals(4, segments.size());
154
155 assertSegment(segments.get(0), Vector2D.of(-1, -2), Vector2D.of(0, -2));
156 assertSegment(segments.get(1), Vector2D.of(0, -2), Vector2D.ZERO);
157 assertSegment(segments.get(2), Vector2D.ZERO, Vector2D.of(-1, 0));
158 assertSegment(segments.get(3), Vector2D.of(-1, 0), Vector2D.of(-1, -2));
159 }
160
161 @Test
162 public void testAxisAligned_illegalArgs() {
163
164 GeometryTestUtils.assertThrows(() -> {
165 Parallelogram.axisAligned(Vector2D.of(1, 1), Vector2D.of(1, 3), TEST_PRECISION);
166 }, IllegalArgumentException.class);
167
168 GeometryTestUtils.assertThrows(() -> {
169 Parallelogram.axisAligned(Vector2D.of(1, 1), Vector2D.of(3, 1), TEST_PRECISION);
170 }, IllegalArgumentException.class);
171
172 GeometryTestUtils.assertThrows(() -> {
173 Parallelogram.axisAligned(Vector2D.of(2, 3), Vector2D.of(2, 3), TEST_PRECISION);
174 }, IllegalArgumentException.class);
175 }
176
177 @Test
178 public void testBuilder_defaultValues() {
179
180 final Parallelogram.Builder builder = Parallelogram.builder(TEST_PRECISION);
181
182
183 final Parallelogram p = builder.build();
184
185
186 Assert.assertEquals(1, p.getSize(), TEST_EPS);
187 Assert.assertEquals(4, p.getBoundarySize(), TEST_EPS);
188 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.ZERO, p.getCentroid(), TEST_EPS);
189
190 final List<Vector2D> vertices = p.getVertices();
191 Assert.assertEquals(4, vertices.size());
192 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-0.5, -0.5), vertices.get(0), TEST_EPS);
193 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0.5, -0.5), vertices.get(1), TEST_EPS);
194 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0.5, 0.5), vertices.get(2), TEST_EPS);
195 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-0.5, 0.5), vertices.get(3), TEST_EPS);
196 }
197
198 @Test
199 public void testBuilder_rotatedRect_withXDirection() {
200
201 final Parallelogram.Builder builder = Parallelogram.builder(TEST_PRECISION);
202
203
204 final Parallelogram p = builder
205 .setScale(1, 2)
206 .setXDirection(Vector2D.Unit.PLUS_Y)
207 .setPosition(Vector2D.of(1, 2))
208 .build();
209
210
211 Assert.assertEquals(2, p.getSize(), TEST_EPS);
212 Assert.assertEquals(6, p.getBoundarySize(), TEST_EPS);
213 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 2), p.getCentroid(), TEST_EPS);
214
215 final List<Vector2D> vertices = p.getVertices();
216 Assert.assertEquals(4, vertices.size());
217 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, 1.5), vertices.get(0), TEST_EPS);
218 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(2, 1.5), vertices.get(1), TEST_EPS);
219 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(2, 2.5), vertices.get(2), TEST_EPS);
220 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, 2.5), vertices.get(3), TEST_EPS);
221 }
222
223 @Test
224 public void testBuilder_rotatedRect_withYDirection() {
225
226 final Parallelogram.Builder builder = Parallelogram.builder(TEST_PRECISION);
227
228
229 final Parallelogram p = builder
230 .setScale(Vector2D.of(2, 1))
231 .setYDirection(Vector2D.Unit.MINUS_X)
232 .setPosition(Vector2D.of(1, 2))
233 .build();
234
235
236 Assert.assertEquals(2, p.getSize(), TEST_EPS);
237 Assert.assertEquals(6, p.getBoundarySize(), TEST_EPS);
238 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 2), p.getCentroid(), TEST_EPS);
239
240 final List<Vector2D> vertices = p.getVertices();
241 Assert.assertEquals(4, vertices.size());
242 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0.5, 1), vertices.get(0), TEST_EPS);
243 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1.5, 1), vertices.get(1), TEST_EPS);
244 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1.5, 3), vertices.get(2), TEST_EPS);
245 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0.5, 3), vertices.get(3), TEST_EPS);
246 }
247
248 @Test
249 public void testBuilder_rotatedRect_withRotation() {
250
251 final Parallelogram.Builder builder = Parallelogram.builder(TEST_PRECISION);
252
253
254 final Parallelogram p = builder
255 .setScale(2)
256 .setRotation(Rotation2D.of(0.25 * Math.PI))
257 .setPosition(Vector2D.of(1, 2))
258 .build();
259
260
261 Assert.assertEquals(4, p.getSize(), TEST_EPS);
262 Assert.assertEquals(8, p.getBoundarySize(), TEST_EPS);
263 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 2), p.getCentroid(), TEST_EPS);
264
265 final List<Vector2D> vertices = p.getVertices();
266 Assert.assertEquals(4, vertices.size());
267
268 final double sqrt2 = Math.sqrt(2);
269 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1 - sqrt2, 2), vertices.get(0), TEST_EPS);
270 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 2 - sqrt2), vertices.get(1), TEST_EPS);
271 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1 + sqrt2, 2), vertices.get(2), TEST_EPS);
272 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 2 + sqrt2), vertices.get(3), TEST_EPS);
273 }
274
275 @Test
276 public void testToTree() {
277
278 final RegionBSPTree2D tree = Parallelogram.axisAligned(Vector2D.ZERO, Vector2D.of(1, 4), TEST_PRECISION)
279 .toTree();
280
281
282 Assert.assertFalse(tree.isFull());
283 Assert.assertFalse(tree.isEmpty());
284
285 Assert.assertEquals(4, tree.getSize(), TEST_EPS);
286 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0.5, 2), tree.getCentroid(), TEST_EPS);
287 }
288
289 private static void assertSegment(final LineConvexSubset segment, final Vector2D start, final Vector2D end) {
290 EuclideanTestUtils.assertCoordinatesEqual(start, segment.getStartPoint(), TEST_EPS);
291 EuclideanTestUtils.assertCoordinatesEqual(end, segment.getEndPoint(), TEST_EPS);
292 }
293 }