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.twod;
    18
    19  import org.apache.commons.geometry.core.GeometryTestUtils;
    20  import org.apache.commons.geometry.core.RegionLocation;
    21  import org.apache.commons.geometry.core.partitioning.Split;
    22  import org.apache.commons.geometry.euclidean.EuclideanTestUtils;
    23  import org.apache.commons.geometry.euclidean.oned.Interval;
    24  import org.apache.commons.numbers.core.Precision;
    25  import org.junit.jupiter.api.Assertions;
    26  import org.junit.jupiter.api.Test;
    27
    28  class LineSpanningSubsetTest {
    29
    30      private static final double TEST_EPS = 1e-10;
    31
    32      private static final Precision.DoubleEquivalence TEST_PRECISION =
    33              Precision.doubleEquivalenceOfEpsilon(TEST_EPS);
    34
    35      @Test
    36      void testProperties() {
    37          // arrange
    38          final Line line = Lines.fromPoints(Vector2D.ZERO, Vector2D.Unit.PLUS_X, TEST_PRECISION);
    39
    40          // act
    41          final LineSpanningSubset result = new LineSpanningSubset(line);
    42
    43          // assert
    44          Assertions.assertSame(line, result.getHyperplane());
    45          Assertions.assertSame(line, result.getLine());
    46
    47          Assertions.assertTrue(result.isFull());
    48          Assertions.assertFalse(result.isEmpty());
    49          Assertions.assertTrue(result.isInfinite());
    50          Assertions.assertFalse(result.isFinite());
    51
    52          GeometryTestUtils.assertPositiveInfinity(result.getSize());
    53          Assertions.assertNull(result.getCentroid());
    54          Assertions.assertNull(result.getBounds());
    55
    56          Assertions.assertNull(result.getStartPoint());
    57          GeometryTestUtils.assertNegativeInfinity(result.getSubspaceStart());
    58          Assertions.assertNull(result.getEndPoint());
    59          GeometryTestUtils.assertPositiveInfinity(result.getSubspaceEnd());
    60      }
    61
    62      @Test
    63      void testTransform() {
    64          // arrange
    65          final AffineTransformMatrix2D t = AffineTransformMatrix2D.createRotation(-0.5 * Math.PI)
    66                  .translate(Vector2D.Unit.PLUS_X)
    67                  .scale(1, -1);
    68
    69          final LineConvexSubset span =
    70                  Lines.fromPointAndDirection(Vector2D.of(1, 0), Vector2D.Unit.PLUS_X, TEST_PRECISION).span();
    71
    72          // act
    73          final LineConvexSubset result = span.transform(t);
    74
    75          // assert
    76          EuclideanTestUtils.assertCoordinatesEqual(Vector2D.Unit.PLUS_Y, result.getLine().getDirection(), TEST_EPS);
    77      }
    78
    79      @Test
    80      void testReverse() {
    81          // arrange
    82          final LineConvexSubset span =
    83                  Lines.fromPointAndDirection(Vector2D.of(1, 2), Vector2D.Unit.PLUS_X, TEST_PRECISION).span();
    84
    85          // act
    86          final LineConvexSubset rev = span.reverse();
    87
    88          // assert
    89          EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, 2), rev.getLine().getOrigin(), TEST_EPS);
    90          EuclideanTestUtils.assertCoordinatesEqual(Vector2D.Unit.MINUS_X, rev.getLine().getDirection(), TEST_EPS);
    91      }
    92
    93      @Test
    94      void testClosest() {
    95          // arrange
    96          final Vector2D p1 = Vector2D.of(0, -1);
    97          final Vector2D p2 = Vector2D.of(0, 1);
    98          final LineConvexSubset span =
    99                  Lines.fromPointAndDirection(p1, p1.directionTo(p2), TEST_PRECISION).span();
    100
    101         // act/assert
    102         EuclideanTestUtils.assertCoordinatesEqual(p1, span.closest(p1), TEST_EPS);
    103         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, -2), span.closest(Vector2D.of(0, -2)), TEST_EPS);
    104         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, -2), span.closest(Vector2D.of(2, -2)), TEST_EPS);
    105         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, -1), span.closest(Vector2D.of(-1, -1)), TEST_EPS);
    106
    107         EuclideanTestUtils.assertCoordinatesEqual(p2, span.closest(p2), TEST_EPS);
    108         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, 2), span.closest(Vector2D.of(0, 2)), TEST_EPS);
    109         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, 2), span.closest(Vector2D.of(-2, 2)), TEST_EPS);
    110         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, 1), span.closest(Vector2D.of(-1, 1)), TEST_EPS);
    111
    112         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.ZERO, span.closest(Vector2D.ZERO), TEST_EPS);
    113         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, 0.5), span.closest(Vector2D.of(1, 0.5)), TEST_EPS);
    114         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, -0.5), span.closest(Vector2D.of(-2, -0.5)), TEST_EPS);
    115     }
    116
    117     @Test
    118     void testClassify() {
    119         // arrange
    120         final LineConvexSubset span =
    121                 Lines.fromPointAndDirection(Vector2D.of(1, 1), Vector2D.Unit.PLUS_X, TEST_PRECISION).span();
    122
    123         // act/assert
    124         for (double x = -10; x <= 10; x += 1) {
    125             EuclideanTestUtils.assertRegionLocation(span, RegionLocation.INSIDE, Vector2D.of(x, 1 + 1e-11));
    126
    127             EuclideanTestUtils.assertRegionLocation(span, RegionLocation.OUTSIDE,
    128                     Vector2D.of(x, 0), Vector2D.of(x, 2));
    129         }
    130     }
    131
    132     @Test
    133     void testSplit() {
    134         // --- arrange
    135         final Vector2D pt = Vector2D.of(1, 1);
    136
    137         final LineConvexSubset span = Lines.fromPointAndDirection(pt, Vector2D.Unit.PLUS_X, TEST_PRECISION).span();
    138
    139         // --- act
    140         Split<LineConvexSubset> split;
    141
    142         // parallel
    143         split = span.split(Lines.fromPointAndAngle(Vector2D.of(2, 2), 0, TEST_PRECISION));
    144         Assertions.assertNull(split.getMinus());
    145         Assertions.assertSame(span, split.getPlus());
    146
    147         split = span.split(Lines.fromPointAndAngle(Vector2D.of(2, 2), Math.PI, TEST_PRECISION));
    148         Assertions.assertSame(span, split.getMinus());
    149         Assertions.assertNull(split.getPlus());
    150
    151         // coincident
    152         split = span.split(Lines.fromPointAndDirection(pt, Vector2D.Unit.PLUS_X, TEST_PRECISION));
    153         Assertions.assertNull(split.getMinus());
    154         Assertions.assertNull(split.getPlus());
    155
    156         // through point on line
    157         checkSplit(span.split(Lines.fromPointAndAngle(pt, 1, TEST_PRECISION)),
    158                 null, pt,
    159                 pt, null);
    160         checkSplit(span.split(Lines.fromPointAndAngle(pt, -1, TEST_PRECISION)),
    161                 pt, null,
    162                 null, pt);
    163     }
    164
    165     @Test
    166     void testGetInterval() {
    167         // arrange
    168         final LineConvexSubset span =
    169                 Lines.fromPointAndDirection(Vector2D.of(2, -1), Vector2D.Unit.PLUS_X, TEST_PRECISION).span();
    170
    171         // act
    172         final Interval interval = span.getInterval();
    173
    174         // assert
    175         GeometryTestUtils.assertNegativeInfinity(interval.getMin());
    176         GeometryTestUtils.assertPositiveInfinity(interval.getMax());
    177     }
    178
    179     @Test
    180     void testToString() {
    181         // arrange
    182         final LineConvexSubset span =
    183                 Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.Unit.PLUS_X, TEST_PRECISION).span();
    184
    185         // act
    186         final String str = span.toString();
    187
    188         // assert
    189         GeometryTestUtils.assertContains("LineSpanningSubset[origin= (0", str);
    190         GeometryTestUtils.assertContains(", direction= (1", str);
    191     }
    192
    193     private static void checkSplit(final Split<LineConvexSubset> split, final Vector2D minusStart, final Vector2D minusEnd,
    194                                    final Vector2D plusStart, final Vector2D plusEnd) {
    195
    196         final LineConvexSubset minus = split.getMinus();
    197         if (minusStart == null && minusEnd == null) {
    198             Assertions.assertNull(minus);
    199         } else {
    200             checkPoint(minusStart, minus.getStartPoint());
    201             checkPoint(minusEnd, minus.getEndPoint());
    202         }
    203
    204
    205         final LineConvexSubset plus = split.getPlus();
    206         if (plusStart == null && plusEnd == null) {
    207             Assertions.assertNull(plus);
    208         } else {
    209             checkPoint(plusStart, plus.getStartPoint());
    210             checkPoint(plusEnd, plus.getEndPoint());
    211         }
    212     }
    213
    214     private static void checkPoint(final Vector2D expected, final Vector2D pt) {
    215         if (expected == null) {
    216             Assertions.assertNull(pt);
    217         } else {
    218             EuclideanTestUtils.assertCoordinatesEqual(expected, pt, TEST_EPS);
    219         }
    220     }
    221 }