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 java.util.List;
20  
21  import org.apache.commons.geometry.core.GeometryTestUtils;
22  import org.apache.commons.geometry.core.Transform;
23  import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
24  import org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext;
25  import org.apache.commons.geometry.euclidean.EuclideanTestUtils;
26  import org.apache.commons.geometry.euclidean.oned.Interval;
27  import org.apache.commons.geometry.euclidean.oned.RegionBSPTree1D;
28  import org.apache.commons.geometry.euclidean.threed.AffineTransformMatrix3D;
29  import org.apache.commons.geometry.euclidean.threed.Bounds3D;
30  import org.apache.commons.geometry.euclidean.threed.Vector3D;
31  import org.apache.commons.geometry.euclidean.threed.rotation.QuaternionRotation;
32  import org.apache.commons.numbers.angle.PlaneAngleRadians;
33  import org.junit.Assert;
34  import org.junit.Test;
35  
36  public class EmbeddedTreeLineSubset3DTest {
37  
38      private static final double TEST_EPS = 1e-10;
39  
40      private static final DoublePrecisionContext TEST_PRECISION =
41              new EpsilonDoublePrecisionContext(TEST_EPS);
42  
43      private final Line3D testLine = Lines3D.fromPointAndDirection(Vector3D.ZERO, Vector3D.of(1, 1, 0), TEST_PRECISION);
44  
45      @Test
46      public void testCtor_default() {
47          // act
48          final EmbeddedTreeLineSubset3D sub = new EmbeddedTreeLineSubset3D(testLine);
49  
50          // assert
51          Assert.assertSame(testLine, sub.getLine());
52          Assert.assertTrue(sub.getSubspaceRegion().isEmpty());
53          Assert.assertEquals(0, sub.getSize(), TEST_EPS);
54      }
55  
56      @Test
57      public void testCtor_true() {
58          // act
59          final EmbeddedTreeLineSubset3D sub = new EmbeddedTreeLineSubset3D(testLine, true);
60  
61          // assert
62          Assert.assertSame(testLine, sub.getLine());
63          Assert.assertTrue(sub.getSubspaceRegion().isFull());
64          GeometryTestUtils.assertPositiveInfinity(sub.getSize());
65      }
66  
67      @Test
68      public void testCtor_false() {
69          // act
70          final EmbeddedTreeLineSubset3D sub = new EmbeddedTreeLineSubset3D(testLine, false);
71  
72          // assert
73          Assert.assertSame(testLine, sub.getLine());
74          Assert.assertTrue(sub.getSubspaceRegion().isEmpty());
75          Assert.assertEquals(0, sub.getSize(), TEST_EPS);
76      }
77  
78      @Test
79      public void testCtor_lineAndRegion() {
80          // arrange
81          final RegionBSPTree1D tree = RegionBSPTree1D.empty();
82  
83          // act
84          final EmbeddedTreeLineSubset3D sub = new EmbeddedTreeLineSubset3D(testLine, tree);
85  
86          // assert
87          Assert.assertSame(testLine, sub.getLine());
88          Assert.assertSame(tree, sub.getSubspaceRegion());
89          Assert.assertEquals(0, sub.getSize(), TEST_EPS);
90      }
91  
92      @Test
93      public void testProperties_full() {
94          // arrange
95          final EmbeddedTreeLineSubset3D full = new EmbeddedTreeLineSubset3D(testLine, true);
96  
97          // act/assert
98          Assert.assertTrue(full.isInfinite());
99          Assert.assertFalse(full.isFinite());
100 
101         GeometryTestUtils.assertPositiveInfinity(full.getSize());
102         Assert.assertNull(full.getCentroid());
103         Assert.assertNull(full.getBounds());
104     }
105 
106     @Test
107     public void testProperties_empty() {
108         // arrange
109         final EmbeddedTreeLineSubset3D empty = new EmbeddedTreeLineSubset3D(testLine, false);
110 
111         // act/assert
112         Assert.assertFalse(empty.isInfinite());
113         Assert.assertTrue(empty.isFinite());
114 
115         Assert.assertEquals(0, empty.getSize(), TEST_EPS);
116         Assert.assertNull(empty.getCentroid());
117         Assert.assertNull(empty.getBounds());
118     }
119 
120     @Test
121     public void testProperties_half() {
122         // arrange
123         final EmbeddedTreeLineSubset3D half = new EmbeddedTreeLineSubset3D(testLine, false);
124         half.getSubspaceRegion().add(Interval.min(1, TEST_PRECISION));
125 
126         // act/assert
127         Assert.assertTrue(half.isInfinite());
128         Assert.assertFalse(half.isFinite());
129 
130         GeometryTestUtils.assertPositiveInfinity(half.getSize());
131         Assert.assertNull(half.getCentroid());
132         Assert.assertNull(half.getBounds());
133     }
134 
135     @Test
136     public void testProperties_finite() {
137         // arrange
138         final Line3D line = Lines3D.fromPointAndDirection(Vector3D.of(0, 0, 1), Vector3D.of(1, 1, 0), TEST_PRECISION);
139         final EmbeddedTreeLineSubset3D sub = new EmbeddedTreeLineSubset3D(line);
140 
141         final double sqrt2 = Math.sqrt(2);
142         sub.getSubspaceRegion().add(Interval.of(0, sqrt2, TEST_PRECISION));
143         sub.getSubspaceRegion().add(Interval.of(-2 * sqrt2, -sqrt2, TEST_PRECISION));
144 
145         // act/assert
146         Assert.assertFalse(sub.isInfinite());
147         Assert.assertTrue(sub.isFinite());
148 
149         Assert.assertEquals(2 * sqrt2, sub.getSize(), TEST_EPS);
150         EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(-0.5, -0.5, 1), sub.getCentroid(), TEST_EPS);
151 
152         final Bounds3D bounds = sub.getBounds();
153         EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(-2, -2, 1), bounds.getMin(), TEST_EPS);
154         EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(1, 1, 1), bounds.getMax(), TEST_EPS);
155     }
156 
157     @Test
158     public void testTransform_full() {
159         // arrange
160         final EmbeddedTreeLineSubset3D sub = new EmbeddedTreeLineSubset3D(testLine, true);
161 
162         final Transform<Vector3D> transform = AffineTransformMatrix3D.identity()
163                 .translate(Vector3D.of(1, 0, 0))
164                 .scale(Vector3D.of(2, 1, 1))
165                 .rotate(QuaternionRotation.fromAxisAngle(Vector3D.Unit.PLUS_Y, PlaneAngleRadians.PI_OVER_TWO));
166 
167         // act
168         final EmbeddedTreeLineSubset3D result = sub.transform(transform);
169 
170         // assert
171         final Line3D resultLine = result.getLine();
172 
173         final Vector3D expectedOrigin = Lines3D.fromPoints(Vector3D.of(0, 0, -2), Vector3D.of(0, 1, -4), TEST_PRECISION)
174                 .getOrigin();
175 
176         EuclideanTestUtils.assertCoordinatesEqual(expectedOrigin, resultLine.getOrigin(), TEST_EPS);
177         EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(0, 1, -2).normalize(), resultLine.getDirection(), TEST_EPS);
178 
179         Assert.assertTrue(result.getSubspaceRegion().isFull());
180     }
181 
182     @Test
183     public void testTransform_finite() {
184         // arrange
185         final RegionBSPTree1D tree = RegionBSPTree1D.empty();
186         tree.add(Interval.of(
187                 testLine.toSubspace(Vector3D.of(1, 1, 0)).getX(),
188                 testLine.toSubspace(Vector3D.of(2, 2, 0)).getX(), TEST_PRECISION));
189 
190         final EmbeddedTreeLineSubset3D sub = new EmbeddedTreeLineSubset3D(testLine, tree);
191 
192         final Transform<Vector3D> transform = AffineTransformMatrix3D.identity()
193                 .translate(Vector3D.of(1, 0, 0))
194                 .scale(Vector3D.of(2, 1, 1))
195                 .rotate(QuaternionRotation.fromAxisAngle(Vector3D.Unit.PLUS_Y, PlaneAngleRadians.PI_OVER_TWO));
196 
197         // act
198         final EmbeddedTreeLineSubset3D result = sub.transform(transform);
199 
200         // assert
201         final Line3D resultLine = result.getLine();
202 
203         final Vector3D expectedOrigin = Lines3D.fromPoints(Vector3D.of(0, 0, -2), Vector3D.of(0, 1, -4), TEST_PRECISION)
204                 .getOrigin();
205 
206         EuclideanTestUtils.assertCoordinatesEqual(expectedOrigin, resultLine.getOrigin(), TEST_EPS);
207         EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(0, 1, -2).normalize(), resultLine.getDirection(), TEST_EPS);
208 
209         Assert.assertFalse(result.getSubspaceRegion().isFull());
210 
211         final List<Interval> intervals = result.getSubspaceRegion().toIntervals();
212         Assert.assertEquals(1, intervals.size());
213 
214         final Interval resultInterval = intervals.get(0);
215         EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(0, 1, -4),
216                 resultLine.toSpace(resultInterval.getMin()), TEST_EPS);
217         EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(0, 2, -6),
218                 resultLine.toSpace(resultInterval.getMax()), TEST_EPS);
219     }
220 
221     @Test
222     public void testToConvex_full() {
223         // arrange
224         final EmbeddedTreeLineSubset3D sub = new EmbeddedTreeLineSubset3D(testLine, true);
225 
226         // act
227         final List<LineConvexSubset3D> segments = sub.toConvex();
228 
229         // assert
230         Assert.assertEquals(1, segments.size());
231         Assert.assertTrue(segments.get(0).getSubspaceRegion().isFull());
232     }
233 
234     @Test
235     public void testToConvex_finite() {
236         // arrange
237         final RegionBSPTree1D tree = RegionBSPTree1D.empty();
238         tree.add(Interval.of(
239                 testLine.toSubspace(Vector3D.of(1, 1, 0)).getX(),
240                 testLine.toSubspace(Vector3D.of(2, 2, 0)).getX(), TEST_PRECISION));
241 
242         final EmbeddedTreeLineSubset3D sub = new EmbeddedTreeLineSubset3D(testLine, tree);
243 
244         // act
245         final List<LineConvexSubset3D> segments = sub.toConvex();
246 
247         // assert
248         Assert.assertEquals(1, segments.size());
249 
250         final LineConvexSubset3D segment = segments.get(0);
251         EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(1, 1, 0), segment.getStartPoint(), TEST_EPS);
252         EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(2, 2, 0), segment.getEndPoint(), TEST_EPS);
253     }
254 
255     @Test
256     public void testToString() {
257         // arrange
258         final EmbeddedTreeLineSubset3D sub = new EmbeddedTreeLineSubset3D(testLine);
259 
260         // act
261         final String str = sub.toString();
262 
263         // assert
264         Assert.assertTrue(str.contains("EmbeddedTreeLineSubset3D[lineOrigin= "));
265         Assert.assertTrue(str.contains(", lineDirection= "));
266         Assert.assertTrue(str.contains(", region= "));
267     }
268 }