View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.geometry.euclidean.threed.line;
18  
19  import org.apache.commons.geometry.core.GeometryTestUtils;
20  import org.apache.commons.geometry.euclidean.EuclideanTestUtils;
21  import org.apache.commons.geometry.euclidean.oned.Interval;
22  import org.apache.commons.geometry.euclidean.threed.AffineTransformMatrix3D;
23  import org.apache.commons.geometry.euclidean.threed.Vector3D;
24  import org.apache.commons.geometry.euclidean.threed.rotation.QuaternionRotation;
25  import org.apache.commons.numbers.core.Precision;
26  import org.junit.jupiter.api.Assertions;
27  import org.junit.jupiter.api.Test;
28  
29  class ReverseRay3DTest {
30  
31      private static final double TEST_EPS = 1e-10;
32  
33      private static final Precision.DoubleEquivalence TEST_PRECISION =
34              Precision.doubleEquivalenceOfEpsilon(TEST_EPS);
35  
36      @Test
37      void testFromPointAndDirection() {
38          // arrange
39          final Vector3D pt = Vector3D.of(1, 1, 2);
40  
41          // act
42          final ReverseRay3D revRay = Lines3D.reverseRayFromPointAndDirection(pt, Vector3D.Unit.PLUS_Z, TEST_PRECISION);
43  
44          // assert
45          Assertions.assertTrue(revRay.isInfinite());
46          Assertions.assertFalse(revRay.isFinite());
47  
48          Assertions.assertNull(revRay.getStartPoint());
49          EuclideanTestUtils.assertCoordinatesEqual(pt, revRay.getEndPoint(), TEST_EPS);
50  
51          EuclideanTestUtils.assertCoordinatesEqual(Vector3D.Unit.PLUS_Z, revRay.getLine().getDirection(), TEST_EPS);
52  
53          GeometryTestUtils.assertNegativeInfinity(revRay.getSubspaceStart());
54          Assertions.assertEquals(2, revRay.getSubspaceEnd(), TEST_EPS);
55  
56          GeometryTestUtils.assertPositiveInfinity(revRay.getSize());
57  
58          Assertions.assertNull(revRay.getCentroid());
59          Assertions.assertNull(revRay.getBounds());
60      }
61  
62      @Test
63      void testFromPointAndDirection_invalidArgs() {
64          // arrange
65          final Vector3D pt = Vector3D.of(0, 2, 4);
66          final Vector3D dir = Vector3D.of(1e-11, 0, 0);
67  
68          // act/assert
69          GeometryTestUtils.assertThrowsWithMessage(() -> {
70              Lines3D.reverseRayFromPointAndDirection(pt, dir, TEST_PRECISION);
71          }, IllegalArgumentException.class, "Line direction cannot be zero");
72      }
73  
74      @Test
75      void testFromPoint() {
76          // arrange
77          final Vector3D pt = Vector3D.of(-2, -1, 2);
78  
79          final Line3D line = Lines3D.fromPointAndDirection(Vector3D.of(1, 0, 2), Vector3D.Unit.PLUS_Y, TEST_PRECISION);
80  
81          // act
82          final ReverseRay3D revRay = Lines3D.reverseRayFromPoint(line, pt);
83  
84          // assert
85          Assertions.assertTrue(revRay.isInfinite());
86          Assertions.assertFalse(revRay.isFinite());
87  
88          Assertions.assertNull(revRay.getStartPoint());
89          EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(1, -1, 2), revRay.getEndPoint(), TEST_EPS);
90  
91          GeometryTestUtils.assertNegativeInfinity(revRay.getSubspaceStart());
92          Assertions.assertEquals(-1, revRay.getSubspaceEnd(), TEST_EPS);
93  
94          GeometryTestUtils.assertPositiveInfinity(revRay.getSize());
95  
96          Assertions.assertNull(revRay.getCentroid());
97          Assertions.assertNull(revRay.getBounds());
98      }
99  
100     @Test
101     void testFromPoint_invalidArgs() {
102         // arrange
103         final Line3D line = Lines3D.fromPointAndDirection(Vector3D.ZERO, Vector3D.Unit.PLUS_X, TEST_PRECISION);
104 
105         // act/assert
106         GeometryTestUtils.assertThrowsWithMessage(() -> {
107             Lines3D.reverseRayFromPoint(line, Vector3D.NaN);
108         }, IllegalArgumentException.class, "Invalid reverse ray end location: NaN");
109 
110         GeometryTestUtils.assertThrowsWithMessage(() -> {
111             Lines3D.reverseRayFromPoint(line, Vector3D.NEGATIVE_INFINITY);
112         }, IllegalArgumentException.class, "Invalid reverse ray end location: NaN");
113 
114         GeometryTestUtils.assertThrowsWithMessage(() -> {
115             Lines3D.reverseRayFromPoint(line, Vector3D.POSITIVE_INFINITY);
116         }, IllegalArgumentException.class, "Invalid reverse ray end location: NaN");
117     }
118 
119     @Test
120     void testFromLocation() {
121         // arrange
122         final Line3D line = Lines3D.fromPointAndDirection(Vector3D.of(-1, 0, 0), Vector3D.Unit.PLUS_Z, TEST_PRECISION);
123 
124         // act
125         final ReverseRay3D revRay = Lines3D.reverseRayFromLocation(line, -1);
126 
127         // assert
128         Assertions.assertTrue(revRay.isInfinite());
129         Assertions.assertFalse(revRay.isFinite());
130 
131         Assertions.assertNull(revRay.getStartPoint());
132         EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(-1, 0, -1), revRay.getEndPoint(), TEST_EPS);
133 
134         GeometryTestUtils.assertNegativeInfinity(revRay.getSubspaceStart());
135         Assertions.assertEquals(-1, revRay.getSubspaceEnd(), TEST_EPS);
136 
137         GeometryTestUtils.assertPositiveInfinity(revRay.getSize());
138 
139         Assertions.assertNull(revRay.getCentroid());
140         Assertions.assertNull(revRay.getBounds());
141     }
142 
143     @Test
144     void testTransform() {
145         // arrange
146         final AffineTransformMatrix3D t = QuaternionRotation.fromAxisAngle(Vector3D.Unit.PLUS_Y, 0.5 * Math.PI)
147                 .toMatrix()
148                 .translate(Vector3D.Unit.PLUS_Y);
149 
150         final ReverseRay3D revRay = Lines3D.reverseRayFromPointAndDirection(Vector3D.of(1, 0, 0), Vector3D.Unit.PLUS_X, TEST_PRECISION);
151 
152         // act
153         final ReverseRay3D result = revRay.transform(t);
154 
155         // assert
156         Assertions.assertNull(result.getStartPoint());
157         EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(0, 1, -1), result.getEndPoint(), TEST_EPS);
158 
159         EuclideanTestUtils.assertCoordinatesEqual(Vector3D.Unit.MINUS_Z, result.getLine().getDirection(), TEST_EPS);
160     }
161 
162     @Test
163     void testTransform_reflection() {
164         // arrange
165         final AffineTransformMatrix3D t = QuaternionRotation.fromAxisAngle(Vector3D.Unit.PLUS_Y, 0.5 * Math.PI)
166                 .toMatrix()
167                 .translate(Vector3D.Unit.PLUS_Y)
168                 .scale(1, 1, -2);
169 
170         final ReverseRay3D revRay = Lines3D.reverseRayFromPointAndDirection(Vector3D.of(1, 0, 0), Vector3D.Unit.PLUS_X, TEST_PRECISION);
171 
172         // act
173         final ReverseRay3D result = revRay.transform(t);
174 
175         // assert
176         Assertions.assertNull(result.getStartPoint());
177         EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(0, 1, 2), result.getEndPoint(), TEST_EPS);
178 
179         EuclideanTestUtils.assertCoordinatesEqual(Vector3D.Unit.PLUS_Z, result.getLine().getDirection(), TEST_EPS);
180     }
181 
182     @Test
183     void testContains() {
184         // arrange
185         final Vector3D p0 = Vector3D.of(1, 1, 1);
186 
187         final Vector3D delta = Vector3D.of(1e-12, 1e-12, 1e-12);
188 
189         final ReverseRay3D revRay = Lines3D.reverseRayFromPointAndDirection(Vector3D.of(1, 1, 1), Vector3D.Unit.PLUS_X, TEST_PRECISION);
190 
191         // act/assert
192         Assertions.assertFalse(revRay.contains(Vector3D.of(2, 2, 2)));
193         Assertions.assertFalse(revRay.contains(Vector3D.of(1.1, 1, 1)));
194         Assertions.assertFalse(revRay.contains(Vector3D.of(100, 1, 1)));
195 
196         Assertions.assertTrue(revRay.contains(p0));
197         Assertions.assertTrue(revRay.contains(p0.add(delta)));
198 
199         Assertions.assertTrue(revRay.contains(Vector3D.of(-1000, 1, 1)));
200     }
201 
202     @Test
203     void testGetInterval() {
204         // arrange
205         final ReverseRay3D revRay = Lines3D.reverseRayFromPointAndDirection(Vector3D.of(2, -1, 3), Vector3D.Unit.PLUS_Y, TEST_PRECISION);
206 
207         // act
208         final Interval interval = revRay.getInterval();
209 
210         // assert
211         GeometryTestUtils.assertNegativeInfinity(interval.getMin());
212         Assertions.assertEquals(-1, interval.getMax(), TEST_EPS);
213 
214         Assertions.assertSame(revRay.getLine().getPrecision(), interval.getMaxBoundary().getPrecision());
215     }
216 
217     @Test
218     void testToString() {
219         // arrange
220         final ReverseRay3D revRay = Lines3D.reverseRayFromPointAndDirection(Vector3D.ZERO, Vector3D.Unit.PLUS_X, TEST_PRECISION);
221 
222         // act
223         final String str = revRay.toString();
224 
225         // assert
226         GeometryTestUtils.assertContains("ReverseRay3D[direction= (1", str);
227         GeometryTestUtils.assertContains(", endPoint= (0", str);
228     }
229 }