1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.geometry.euclidean.threed;
18
19 import org.apache.commons.geometry.core.GeometryTestUtils;
20 import org.apache.commons.geometry.euclidean.EuclideanTestUtils;
21 import org.apache.commons.geometry.euclidean.threed.EmbeddingPlane.SubspaceTransform;
22 import org.apache.commons.geometry.euclidean.threed.rotation.QuaternionRotation;
23 import org.apache.commons.geometry.euclidean.twod.AffineTransformMatrix2D;
24 import org.apache.commons.geometry.euclidean.twod.Vector2D;
25 import org.apache.commons.numbers.angle.Angle;
26 import org.apache.commons.numbers.core.Precision;
27 import org.junit.jupiter.api.Assertions;
28 import org.junit.jupiter.api.Test;
29
30 class EmbeddingPlaneTest {
31
32 private static final double TEST_EPS = 1e-10;
33
34 private static final Precision.DoubleEquivalence TEST_PRECISION =
35 Precision.doubleEquivalenceOfEpsilon(TEST_EPS);
36
37 @Test
38 void testFromPointAndPlaneVectors() {
39
40 final Vector3D pt = Vector3D.of(1, 2, 3);
41
42
43 checkPlane(Planes.fromPointAndPlaneVectors(pt, Vector3D.of(2, 0, 0), Vector3D.of(3, 0.1, 0), TEST_PRECISION),
44 Vector3D.of(0, 0, 3), Vector3D.Unit.PLUS_X, Vector3D.Unit.PLUS_Y);
45
46 checkPlane(Planes.fromPointAndPlaneVectors(pt, Vector3D.of(2, 0, 0), Vector3D.of(3, -0.1, 0), TEST_PRECISION),
47 Vector3D.of(0, 0, 3), Vector3D.Unit.PLUS_X, Vector3D.Unit.MINUS_Y);
48
49 checkPlane(Planes.fromPointAndPlaneVectors(pt, Vector3D.of(0, 0.1, 0), Vector3D.of(0, -3, 1), TEST_PRECISION),
50 Vector3D.of(1, 0, 0), Vector3D.Unit.PLUS_Y, Vector3D.Unit.PLUS_Z);
51 }
52
53 @Test
54 void testFromPointAndPlaneVectors_illegalArguments() {
55
56 final Vector3D pt = Vector3D.of(1, 2, 3);
57
58
59
60
61 Assertions.assertThrows(IllegalArgumentException.class, () -> Planes.fromPointAndPlaneVectors(pt, Vector3D.of(0, 0, 1), Vector3D.of(0, 0, 1), TEST_PRECISION));
62
63 Assertions.assertThrows(IllegalArgumentException.class, () -> Planes.fromPointAndPlaneVectors(pt, Vector3D.of(0, 0, 1), Vector3D.ZERO, TEST_PRECISION));
64
65 Assertions.assertThrows(IllegalArgumentException.class, () -> Planes.fromPointAndPlaneVectors(pt, Vector3D.of(0, 0, 1), Vector3D.of(0, 0, 2), TEST_PRECISION));
66
67 Assertions.assertThrows(IllegalArgumentException.class, () -> Planes.fromPointAndPlaneVectors(pt, Vector3D.of(0, 0, 1), Vector3D.of(0, 0, -2), TEST_PRECISION));
68 }
69
70 @Test
71 void testGetEmbedding() {
72
73 final EmbeddingPlane plane = Planes.fromPointAndPlaneVectors(Vector3D.ZERO,
74 Vector3D.Unit.PLUS_X, Vector3D.Unit.MINUS_Y, TEST_PRECISION);
75
76
77 Assertions.assertSame(plane, plane.getEmbedding());
78 }
79
80 @Test
81 void testPointAt() {
82
83 final Vector3D pt = Vector3D.of(0, 0, 1);
84 final EmbeddingPlane plane = Planes.fromPointAndPlaneVectors(pt,
85 Vector3D.Unit.PLUS_Y, Vector3D.Unit.MINUS_X, TEST_PRECISION);
86
87
88 EuclideanTestUtils.assertCoordinatesEqual(pt, plane.pointAt(Vector2D.ZERO, 0), TEST_EPS);
89 EuclideanTestUtils.assertCoordinatesEqual(Vector3D.ZERO, plane.pointAt(Vector2D.ZERO, -1), TEST_EPS);
90 EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(0, 0, -1), plane.pointAt(Vector2D.ZERO, -2), TEST_EPS);
91 EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(0, 0, 2), plane.pointAt(Vector2D.ZERO, 1), TEST_EPS);
92
93 EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(-1, 2, 1), plane.pointAt(Vector2D.of(2, 1), 0), TEST_EPS);
94 EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(4, -3, 6), plane.pointAt(Vector2D.of(-3, -4), 5), TEST_EPS);
95 }
96
97 @Test
98 void testReverse() {
99
100 final Vector3D pt = Vector3D.of(0, 0, 1);
101 final EmbeddingPlane plane = Planes.fromPointAndPlaneVectors(pt,
102 Vector3D.Unit.PLUS_X, Vector3D.Unit.PLUS_Y, TEST_PRECISION);
103
104
105 final EmbeddingPlane reversed = plane.reverse();
106
107
108 checkPlane(reversed, pt, Vector3D.Unit.PLUS_Y, Vector3D.Unit.PLUS_X);
109
110 Assertions.assertTrue(reversed.contains(Vector3D.of(1, 1, 1)));
111 Assertions.assertTrue(reversed.contains(Vector3D.of(-1, -1, 1)));
112 Assertions.assertFalse(reversed.contains(Vector3D.ZERO));
113
114 Assertions.assertEquals(1.0, reversed.offset(Vector3D.ZERO), TEST_EPS);
115 }
116
117 @Test
118 void testTransform_rotationAroundPoint() {
119
120 final Vector3D pt = Vector3D.of(0, 0, 1);
121 final EmbeddingPlane plane = Planes.fromPointAndPlaneVectors(pt, Vector3D.Unit.PLUS_Y, Vector3D.Unit.MINUS_X, TEST_PRECISION);
122
123 final AffineTransformMatrix3D mat = AffineTransformMatrix3D.createRotation(pt,
124 QuaternionRotation.fromAxisAngle(Vector3D.Unit.PLUS_Y, Angle.PI_OVER_TWO));
125
126
127 final EmbeddingPlane result = plane.transform(mat);
128
129
130 checkPlane(result, Vector3D.ZERO, Vector3D.Unit.PLUS_Y, Vector3D.Unit.PLUS_Z);
131 }
132
133 @Test
134 void testTransform_asymmetricScaling() {
135
136 final Vector3D pt = Vector3D.of(0, 1, 0);
137 final EmbeddingPlane plane = Planes.fromPointAndPlaneVectors(pt, Vector3D.Unit.MINUS_Z, Vector3D.of(-1, 1, 0), TEST_PRECISION);
138
139 final AffineTransformMatrix3D mat = AffineTransformMatrix3D.createScale(2, 1, 1);
140
141
142 final EmbeddingPlane result = plane.transform(mat);
143
144
145 final Vector3D expectedU = Vector3D.Unit.MINUS_Z;
146 final Vector3D expectedV = Vector3D.Unit.of(-2, 1, 0);
147 final Vector3D expectedNormal = Vector3D.Unit.of(1, 2, 0);
148
149 final Vector3D transformedPt = mat.apply(plane.getOrigin());
150 final Vector3D expectedOrigin = transformedPt.project(expectedNormal);
151
152 checkPlane(result, expectedOrigin, expectedU, expectedV);
153
154 Assertions.assertTrue(result.contains(transformedPt));
155 Assertions.assertFalse(plane.contains(transformedPt));
156 }
157
158 @Test
159 void testTransform_negateOneComponent() {
160
161 final Vector3D pt = Vector3D.of(0, 0, 1);
162 final EmbeddingPlane plane = Planes.fromPointAndPlaneVectors(pt, Vector3D.Unit.PLUS_X, Vector3D.Unit.PLUS_Y, TEST_PRECISION);
163
164 final AffineTransformMatrix3D transform = AffineTransformMatrix3D.from(v -> Vector3D.of(-v.getX(), v.getY(), v.getZ()));
165
166
167 final EmbeddingPlane result = plane.transform(transform);
168
169
170 checkPlane(result, Vector3D.of(0, 0, 1), Vector3D.Unit.MINUS_X, Vector3D.Unit.PLUS_Y);
171 }
172
173 @Test
174 void testTransform_negateTwoComponents() {
175
176 final Vector3D pt = Vector3D.of(0, 0, 1);
177 final EmbeddingPlane plane = Planes.fromPointAndPlaneVectors(pt, Vector3D.Unit.PLUS_X, Vector3D.Unit.PLUS_Y, TEST_PRECISION);
178
179 final AffineTransformMatrix3D transform = AffineTransformMatrix3D.from(v -> Vector3D.of(-v.getX(), -v.getY(), v.getZ()));
180
181
182 final EmbeddingPlane result = plane.transform(transform);
183
184
185 checkPlane(result, Vector3D.of(0, 0, 1), Vector3D.Unit.MINUS_X, Vector3D.Unit.MINUS_Y);
186 }
187
188 @Test
189 void testTransform_negateAllComponents() {
190
191 final Vector3D pt = Vector3D.of(0, 0, 1);
192 final EmbeddingPlane plane = Planes.fromPointAndPlaneVectors(pt,
193 Vector3D.Unit.PLUS_X, Vector3D.Unit.PLUS_Y, TEST_PRECISION);
194
195 final AffineTransformMatrix3D transform = AffineTransformMatrix3D.from(Vector3D::negate);
196
197
198 final EmbeddingPlane result = plane.transform(transform);
199
200
201 checkPlane(result, Vector3D.of(0, 0, -1), Vector3D.Unit.MINUS_X, Vector3D.Unit.MINUS_Y);
202 }
203
204 @Test
205 void testTransform_consistency() {
206
207 final Vector3D pt = Vector3D.of(1, 2, 3);
208 final Vector3D normal = Vector3D.Unit.from(1, 1, 1);
209 final Vector3D u = normal.orthogonal(Vector3D.Unit.PLUS_X);
210 final Vector3D v = normal.cross(u).normalize();
211
212 final EmbeddingPlane plane = Planes.fromPointAndPlaneVectors(pt, u, v, TEST_PRECISION);
213
214 final Vector3D p1 = plane.project(Vector3D.of(4, 5, 6));
215 final Vector3D p2 = plane.project(Vector3D.of(-7, -8, -9));
216 final Vector3D p3 = plane.project(Vector3D.of(10, -11, 12));
217
218 final Vector3D notOnPlane1 = plane.getOrigin().add(plane.getNormal());
219 final Vector3D notOnPlane2 = plane.getOrigin().subtract(plane.getNormal());
220
221 EuclideanTestUtils.permuteSkipZero(-4, 4, 1, (a, b, c) -> {
222 final AffineTransformMatrix3D t = AffineTransformMatrix3D.identity()
223 .rotate(Vector3D.of(-1, 2, 3),
224 QuaternionRotation.fromAxisAngle(Vector3D.Unit.PLUS_X, 0.3 * a))
225 .scale(Math.max(a, 1), Math.max(b, 1), Math.max(c, 1))
226 .translate(c, b, a);
227
228
229 final EmbeddingPlane result = plane.transform(t);
230
231
232 Vector3D expectedNormal = t.normalTransform().apply(plane.getNormal()).normalize();
233 if (!t.preservesOrientation()) {
234 expectedNormal = expectedNormal.negate();
235 }
236
237 EuclideanTestUtils.assertCoordinatesEqual(expectedNormal, result.getNormal(), TEST_EPS);
238
239 Assertions.assertTrue(result.contains(t.apply(p1)));
240 Assertions.assertTrue(result.contains(t.apply(p2)));
241 Assertions.assertTrue(result.contains(t.apply(p3)));
242
243 Assertions.assertFalse(result.contains(t.apply(notOnPlane1)));
244 Assertions.assertFalse(result.contains(t.apply(notOnPlane2)));
245 });
246 }
247
248 @Test
249 void testRotate() {
250
251 final Vector3D p1 = Vector3D.of(1.2, 3.4, -5.8);
252 final Vector3D p2 = Vector3D.of(3.4, -5.8, 1.2);
253 final Vector3D p3 = Vector3D.of(-2.0, 4.3, 0.7);
254 EmbeddingPlane plane = Planes.fromPoints(p1, p2, p3, TEST_PRECISION).getEmbedding();
255 final Vector3D oldNormal = plane.getNormal();
256
257
258 plane = plane.rotate(p2, QuaternionRotation.fromAxisAngle(p2.subtract(p1), 1.7));
259 Assertions.assertTrue(plane.contains(p1));
260 Assertions.assertTrue(plane.contains(p2));
261 Assertions.assertFalse(plane.contains(p3));
262
263 plane = plane.rotate(p2, QuaternionRotation.fromAxisAngle(oldNormal, 0.1));
264 Assertions.assertFalse(plane.contains(p1));
265 Assertions.assertTrue(plane.contains(p2));
266 Assertions.assertFalse(plane.contains(p3));
267
268 plane = plane.rotate(p1, QuaternionRotation.fromAxisAngle(oldNormal, 0.1));
269 Assertions.assertFalse(plane.contains(p1));
270 Assertions.assertFalse(plane.contains(p2));
271 Assertions.assertFalse(plane.contains(p3));
272 }
273
274 @Test
275 void testTranslate() {
276
277 final Vector3D p1 = Vector3D.of(1.2, 3.4, -5.8);
278 final Vector3D p2 = Vector3D.of(3.4, -5.8, 1.2);
279 final Vector3D p3 = Vector3D.of(-2.0, 4.3, 0.7);
280 EmbeddingPlane plane = Planes.fromPoints(p1, p2, p3, TEST_PRECISION).getEmbedding();
281
282
283 plane = plane.translate(Vector3D.Sum.create()
284 .addScaled(2.0, plane.getU())
285 .addScaled(-1.5, plane.getV()).get());
286 Assertions.assertTrue(plane.contains(p1));
287 Assertions.assertTrue(plane.contains(p2));
288 Assertions.assertTrue(plane.contains(p3));
289
290 plane = plane.translate(plane.getNormal().multiply(-1.2));
291 Assertions.assertFalse(plane.contains(p1));
292 Assertions.assertFalse(plane.contains(p2));
293 Assertions.assertFalse(plane.contains(p3));
294
295 plane = plane.translate(plane.getNormal().multiply(+1.2));
296 Assertions.assertTrue(plane.contains(p1));
297 Assertions.assertTrue(plane.contains(p2));
298 Assertions.assertTrue(plane.contains(p3));
299 }
300
301 @Test
302 void testSubspaceTransform() {
303
304 final EmbeddingPlane plane = Planes.fromPointAndPlaneVectors(Vector3D.of(0, 0, 1),
305 Vector3D.Unit.PLUS_X, Vector3D.Unit.PLUS_Y, TEST_PRECISION);
306
307
308 checkSubspaceTransform(plane.subspaceTransform(AffineTransformMatrix3D.createScale(2, 3, 4)),
309 Vector3D.of(0, 0, 4), Vector3D.Unit.PLUS_X, Vector3D.Unit.PLUS_Y,
310 Vector3D.of(0, 0, 4), Vector3D.of(2, 0, 4), Vector3D.of(0, 3, 4));
311
312 checkSubspaceTransform(plane.subspaceTransform(AffineTransformMatrix3D.createTranslation(2, 3, 4)),
313 Vector3D.of(0, 0, 5), Vector3D.Unit.PLUS_X, Vector3D.Unit.PLUS_Y,
314 Vector3D.of(2, 3, 5), Vector3D.of(3, 3, 5), Vector3D.of(2, 4, 5));
315
316 checkSubspaceTransform(plane.subspaceTransform(QuaternionRotation.fromAxisAngle(Vector3D.Unit.PLUS_Y, Angle.PI_OVER_TWO)),
317 Vector3D.of(1, 0, 0), Vector3D.Unit.MINUS_Z, Vector3D.Unit.PLUS_Y,
318 Vector3D.of(1, 0, 0), Vector3D.of(1, 0, -1), Vector3D.of(1, 1, 0));
319 }
320
321 private void checkSubspaceTransform(final SubspaceTransform st,
322 final Vector3D origin, final Vector3D u, final Vector3D v,
323 final Vector3D tOrigin, final Vector3D tU, final Vector3D tV) {
324
325 final EmbeddingPlane plane = st.getPlane();
326 final AffineTransformMatrix2D transform = st.getTransform();
327
328 checkPlane(plane, origin, u, v);
329
330 EuclideanTestUtils.assertCoordinatesEqual(tOrigin, plane.toSpace(transform.apply(Vector2D.ZERO)), TEST_EPS);
331 EuclideanTestUtils.assertCoordinatesEqual(tU, plane.toSpace(transform.apply(Vector2D.Unit.PLUS_X)), TEST_EPS);
332 EuclideanTestUtils.assertCoordinatesEqual(tV, plane.toSpace(transform.apply(Vector2D.Unit.PLUS_Y)), TEST_EPS);
333 }
334
335 @Test
336 void testSubspaceTransform_transformsPointsCorrectly() {
337
338 final EmbeddingPlane plane = Planes.fromPointAndPlaneVectors(Vector3D.of(1, 2, 3),
339 Vector3D.of(-1, -1, 1), Vector3D.of(-1, 1, 1), TEST_PRECISION);
340
341 EuclideanTestUtils.permuteSkipZero(-2, 2, 0.5, (a, b, c) -> {
342
343 final AffineTransformMatrix3D transform = AffineTransformMatrix3D.createTranslation(Vector3D.of(a, b, c))
344 .rotate(QuaternionRotation.fromAxisAngle(Vector3D.of(b, c, a), Math.PI * c))
345 .scale(0.1, 4, 8);
346
347
348 final SubspaceTransform st = plane.subspaceTransform(transform);
349
350
351 EuclideanTestUtils.permute(-5, 5, 1, (x, y) -> {
352 final Vector2D subPt = Vector2D.of(x, y);
353 final Vector3D expected = transform.apply(plane.toSpace(subPt));
354 final Vector3D actual = st.getPlane().toSpace(
355 st.getTransform().apply(subPt));
356
357 EuclideanTestUtils.assertCoordinatesEqual(expected, actual, TEST_EPS);
358 });
359 });
360 }
361
362 @Test
363 void testEq_stdAndEmbedding() {
364
365 final Plane stdPlane = Planes.fromPointAndNormal(Vector3D.of(1, 1, 1), Vector3D.Unit.PLUS_Z, TEST_PRECISION);
366 final EmbeddingPlane embeddingPlane = Planes.fromPointAndPlaneVectors(Vector3D.of(1, 1, 1),
367 Vector3D.of(1, 1, 0), Vector3D.of(-1, 1, 0), TEST_PRECISION);
368
369 final EmbeddingPlane nonEqEmbeddingPlane = Planes.fromPointAndPlaneVectors(Vector3D.of(1, 1, 1),
370 Vector3D.of(1, 1, 1), Vector3D.of(-1, 1, 1), TEST_PRECISION);
371
372
373 Assertions.assertTrue(stdPlane.eq(embeddingPlane, TEST_PRECISION));
374 Assertions.assertTrue(embeddingPlane.eq(stdPlane, TEST_PRECISION));
375
376 Assertions.assertFalse(stdPlane.eq(nonEqEmbeddingPlane, TEST_PRECISION));
377 Assertions.assertFalse(nonEqEmbeddingPlane.eq(stdPlane, TEST_PRECISION));
378 }
379
380 @Test
381 void testSimilarOrientation_stdAndEmbedding() {
382
383 final Plane stdPlane = Planes.fromPointAndNormal(Vector3D.of(1, 1, 1), Vector3D.Unit.PLUS_Z, TEST_PRECISION);
384 final EmbeddingPlane embeddingPlane = Planes.fromPointAndPlaneVectors(Vector3D.of(1, 1, 1),
385 Vector3D.of(1, 1, 1), Vector3D.of(-1, 1, 1), TEST_PRECISION);
386
387 final EmbeddingPlane nonSimilarEmbeddingPlane = Planes.fromPointAndPlaneVectors(Vector3D.of(1, 1, 1),
388 Vector3D.Unit.PLUS_Y, Vector3D.Unit.PLUS_X, TEST_PRECISION);
389
390
391 Assertions.assertTrue(stdPlane.similarOrientation(embeddingPlane));
392 Assertions.assertTrue(embeddingPlane.similarOrientation(stdPlane));
393
394 Assertions.assertFalse(stdPlane.similarOrientation(nonSimilarEmbeddingPlane));
395 Assertions.assertFalse(nonSimilarEmbeddingPlane.similarOrientation(stdPlane));
396 }
397
398 @Test
399 void testHashCode() {
400
401 final Vector3D pt = Vector3D.of(1, 2, 3);
402 final Vector3D u = Vector3D.Unit.PLUS_X;
403 final Vector3D v = Vector3D.Unit.PLUS_Y;
404
405 final EmbeddingPlane a = Planes.fromPointAndPlaneVectors(pt, u, v, TEST_PRECISION);
406 final EmbeddingPlane b = Planes.fromPointAndPlaneVectors(Vector3D.of(1, 2, 4), u, v, TEST_PRECISION);
407 final EmbeddingPlane c = Planes.fromPointAndPlaneVectors(pt, Vector3D.of(1, 1, 0), v, TEST_PRECISION);
408 final EmbeddingPlane d = Planes.fromPointAndPlaneVectors(pt, u, Vector3D.Unit.MINUS_Y, TEST_PRECISION);
409 final EmbeddingPlane e = Planes.fromPointAndPlaneVectors(pt, u, v, Precision.doubleEquivalenceOfEpsilon(1e-8));
410 final EmbeddingPlane f = Planes.fromPointAndPlaneVectors(pt, u, v, TEST_PRECISION);
411
412
413 final int hash = a.hashCode();
414
415 Assertions.assertEquals(hash, a.hashCode());
416
417 Assertions.assertNotEquals(hash, b.hashCode());
418 Assertions.assertNotEquals(hash, c.hashCode());
419 Assertions.assertNotEquals(hash, d.hashCode());
420 Assertions.assertNotEquals(hash, e.hashCode());
421
422 Assertions.assertEquals(hash, f.hashCode());
423 }
424
425 @Test
426 void testEquals() {
427
428 final Vector3D pt = Vector3D.of(1, 2, 3);
429 final Vector3D u = Vector3D.Unit.PLUS_X;
430 final Vector3D v = Vector3D.Unit.PLUS_Y;
431
432 final EmbeddingPlane a = Planes.fromPointAndPlaneVectors(pt, u, v, TEST_PRECISION);
433 final EmbeddingPlane b = Planes.fromPointAndPlaneVectors(Vector3D.of(1, 2, 4), u, v, TEST_PRECISION);
434 final EmbeddingPlane c = Planes.fromPointAndPlaneVectors(pt, Vector3D.Unit.MINUS_X, v, TEST_PRECISION);
435 final EmbeddingPlane d = Planes.fromPointAndPlaneVectors(pt, u, Vector3D.Unit.MINUS_Y, TEST_PRECISION);
436 final EmbeddingPlane e = Planes.fromPointAndPlaneVectors(pt, u, v, Precision.doubleEquivalenceOfEpsilon(1e-8));
437 final EmbeddingPlane f = Planes.fromPointAndPlaneVectors(pt, u, v, TEST_PRECISION);
438
439 final Plane stdPlane = Planes.fromPointAndNormal(pt, Vector3D.Unit.PLUS_Z, TEST_PRECISION);
440
441
442 GeometryTestUtils.assertSimpleEqualsCases(a);
443
444 Assertions.assertNotEquals(a, b);
445 Assertions.assertNotEquals(a, c);
446 Assertions.assertNotEquals(a, d);
447 Assertions.assertNotEquals(a, e);
448
449 Assertions.assertEquals(a, f);
450 Assertions.assertEquals(f, a);
451
452 Assertions.assertNotEquals(a, stdPlane);
453 }
454
455 @Test
456 void testToString() {
457
458 final EmbeddingPlane plane = Planes.fromPointAndPlaneVectors(Vector3D.ZERO,
459 Vector3D.Unit.PLUS_X, Vector3D.Unit.PLUS_Y, TEST_PRECISION);
460
461
462 final String str = plane.toString();
463
464
465 Assertions.assertTrue(str.startsWith("EmbeddingPlane["));
466 Assertions.assertTrue(str.matches(".*origin= \\(0(\\.0)?, 0(\\.0)?\\, 0(\\.0)?\\).*"));
467 Assertions.assertTrue(str.matches(".*u= \\(1(\\.0)?, 0(\\.0)?\\, 0(\\.0)?\\).*"));
468 Assertions.assertTrue(str.matches(".*v= \\(0(\\.0)?, 1(\\.0)?\\, 0(\\.0)?\\).*"));
469 Assertions.assertTrue(str.matches(".*w= \\(0(\\.0)?, 0(\\.0)?\\, 1(\\.0)?\\).*"));
470 }
471
472 private static void checkPlane(final EmbeddingPlane plane, final Vector3D origin, Vector3D u, Vector3D v) {
473 u = u.normalize();
474 v = v.normalize();
475 final Vector3D w = u.cross(v);
476
477 EuclideanTestUtils.assertCoordinatesEqual(origin, plane.getOrigin(), TEST_EPS);
478 Assertions.assertTrue(plane.contains(origin));
479
480 EuclideanTestUtils.assertCoordinatesEqual(u, plane.getU(), TEST_EPS);
481 Assertions.assertEquals(1.0, plane.getU().norm(), TEST_EPS);
482
483 EuclideanTestUtils.assertCoordinatesEqual(v, plane.getV(), TEST_EPS);
484 Assertions.assertEquals(1.0, plane.getV().norm(), TEST_EPS);
485
486 EuclideanTestUtils.assertCoordinatesEqual(w, plane.getW(), TEST_EPS);
487 Assertions.assertEquals(1.0, plane.getW().norm(), TEST_EPS);
488
489 EuclideanTestUtils.assertCoordinatesEqual(w, plane.getNormal(), TEST_EPS);
490 Assertions.assertEquals(1.0, plane.getNormal().norm(), TEST_EPS);
491
492 final double offset = plane.getOriginOffset();
493 Assertions.assertEquals(Vector3D.ZERO.distance(plane.getOrigin()), Math.abs(offset), TEST_EPS);
494 EuclideanTestUtils.assertCoordinatesEqual(origin, plane.getNormal().multiply(-offset), TEST_EPS);
495 }
496 }