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