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 java.util.List;
    20
    21  import org.apache.commons.geometry.core.GeometryTestUtils;
    22  import org.apache.commons.geometry.core.partitioning.Split;
    23  import org.apache.commons.geometry.core.partitioning.SplitLocation;
    24  import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
    25  import org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext;
    26  import org.apache.commons.geometry.euclidean.EuclideanTestUtils;
    27  import org.apache.commons.geometry.euclidean.oned.Interval;
    28  import org.apache.commons.geometry.euclidean.oned.RegionBSPTree1D;
    29  import org.apache.commons.numbers.angle.PlaneAngleRadians;
    30  import org.junit.Assert;
    31  import org.junit.Test;
    32
    33  public class EmbeddedTreeLineSubsetTest {
    34
    35      private static final double TEST_EPS = 1e-10;
    36
    37      private static final DoublePrecisionContext TEST_PRECISION =
    38              new EpsilonDoublePrecisionContext(TEST_EPS);
    39
    40      private static final Line DEFAULT_TEST_LINE =
    41              Lines.fromPointAndDirection(Vector2D.of(0, 1), Vector2D.Unit.PLUS_X, TEST_PRECISION);
    42
    43      @Test
    44      public void testCtor_lineOnly() {
    45          // act
    46          final EmbeddedTreeLineSubset sub = new EmbeddedTreeLineSubset(DEFAULT_TEST_LINE);
    47
    48          // assert
    49          Assert.assertSame(DEFAULT_TEST_LINE, sub.getLine());
    50          Assert.assertSame(TEST_PRECISION, sub.getPrecision());
    51
    52          Assert.assertFalse(sub.isFull());
    53          Assert.assertTrue(sub.isEmpty());
    54          Assert.assertFalse(sub.isInfinite());
    55          Assert.assertTrue(sub.isFinite());
    56
    57          Assert.assertEquals(0, sub.getSize(), TEST_EPS);
    58          Assert.assertNull(sub.getCentroid());
    59      }
    60
    61      @Test
    62      public void testCtor_lineAndBoolean() {
    63          // act
    64          final EmbeddedTreeLineSubset sub = new EmbeddedTreeLineSubset(DEFAULT_TEST_LINE, true);
    65
    66          // assert
    67          Assert.assertSame(DEFAULT_TEST_LINE, sub.getLine());
    68          Assert.assertSame(TEST_PRECISION, sub.getPrecision());
    69
    70          Assert.assertTrue(sub.isFull());
    71          Assert.assertFalse(sub.isEmpty());
    72          Assert.assertTrue(sub.isInfinite());
    73          Assert.assertFalse(sub.isFinite());
    74
    75          GeometryTestUtils.assertPositiveInfinity(sub.getSize());
    76          Assert.assertNull(sub.getCentroid());
    77      }
    78
    79      @Test
    80      public void testCtor_lineAndRegion() {
    81          // arrange
    82          final RegionBSPTree1D tree = RegionBSPTree1D.full();
    83
    84          // act
    85          final EmbeddedTreeLineSubset sub = new EmbeddedTreeLineSubset(DEFAULT_TEST_LINE, tree);
    86
    87          // assert
    88          Assert.assertSame(DEFAULT_TEST_LINE, sub.getLine());
    89          Assert.assertSame(tree, sub.getSubspaceRegion());
    90          Assert.assertSame(TEST_PRECISION, sub.getPrecision());
    91
    92          Assert.assertTrue(sub.isFull());
    93          Assert.assertFalse(sub.isEmpty());
    94          Assert.assertTrue(sub.isInfinite());
    95          Assert.assertFalse(sub.isFinite());
    96
    97          GeometryTestUtils.assertPositiveInfinity(sub.getSize());
    98          Assert.assertNull(sub.getCentroid());
    99      }
    100
    101     @Test
    102     public void testToConvex_full() {
    103         // arrange
    104         final EmbeddedTreeLineSubset sub = new EmbeddedTreeLineSubset(DEFAULT_TEST_LINE, true);
    105
    106         // act
    107         final List<LineConvexSubset> segments = sub.toConvex();
    108
    109         // assert
    110         Assert.assertEquals(1, segments.size());
    111
    112         final LineConvexSubset seg = segments.get(0);
    113         Assert.assertTrue(seg.isFull());
    114     }
    115
    116     @Test
    117     public void testToConvex_empty() {
    118         // arrange
    119         final EmbeddedTreeLineSubset sub = new EmbeddedTreeLineSubset(DEFAULT_TEST_LINE, false);
    120
    121         // act
    122         final List<LineConvexSubset> segments = sub.toConvex();
    123
    124         // assert
    125         Assert.assertEquals(0, segments.size());
    126     }
    127
    128     @Test
    129     public void testToConvex_finiteAndInfiniteSegments() {
    130         // arrange
    131         final EmbeddedTreeLineSubset sub = new EmbeddedTreeLineSubset(DEFAULT_TEST_LINE, false);
    132         final RegionBSPTree1D tree = sub.getSubspaceRegion();
    133         tree.add(Interval.max(-2.0, TEST_PRECISION));
    134         tree.add(Interval.of(-1, 2, TEST_PRECISION));
    135
    136         // act
    137         final List<LineConvexSubset> segments = sub.toConvex();
    138
    139         // assert
    140         Assert.assertEquals(2, segments.size());
    141
    142         Assert.assertNull(segments.get(0).getStartPoint());
    143         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-2, 1), segments.get(0).getEndPoint(), TEST_EPS);
    144
    145         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-1, 1), segments.get(1).getStartPoint(), TEST_EPS);
    146         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(2, 1), segments.get(1).getEndPoint(), TEST_EPS);
    147     }
    148
    149     @Test
    150     public void testAdd_lineSegment() {
    151         // arrange
    152         final Line line = Lines.fromPointAndAngle(Vector2D.of(0, 1), 0.0, TEST_PRECISION);
    153         final Line otherLine = Lines.fromPointAndAngle(Vector2D.of(0, 1), 1e-11, TEST_PRECISION);
    154
    155         final EmbeddedTreeLineSubset subset = new EmbeddedTreeLineSubset(line);
    156
    157         // act
    158         subset.add(Lines.subsetFromInterval(line, 2, 4));
    159         subset.add(Lines.subsetFromInterval(otherLine, 1, 3));
    160         subset.add(Lines.segmentFromPoints(Vector2D.of(-3, 1), Vector2D.of(-1, 1), TEST_PRECISION));
    161
    162         // assert
    163         Assert.assertFalse(subset.isFull());
    164         Assert.assertFalse(subset.isEmpty());
    165
    166         final List<LineConvexSubset> segments = subset.toConvex();
    167
    168         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-3, 1), segments.get(0).getStartPoint(), TEST_EPS);
    169         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-1, 1), segments.get(0).getEndPoint(), TEST_EPS);
    170
    171         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 1), segments.get(1).getStartPoint(), TEST_EPS);
    172         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(4, 1), segments.get(1).getEndPoint(), TEST_EPS);
    173
    174         Assert.assertEquals(5, subset.getSize(), TEST_EPS);
    175         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0.7, 1), subset.getCentroid(), TEST_EPS);
    176     }
    177
    178     @Test
    179     public void testAdd_subset() {
    180         // arrange
    181         final Line line = Lines.fromPointAndAngle(Vector2D.of(0, 1), 0.0, TEST_PRECISION);
    182
    183         final EmbeddedTreeLineSubset a = new EmbeddedTreeLineSubset(line);
    184         final RegionBSPTree1D aTree = a.getSubspaceRegion();
    185         aTree.add(Interval.max(-3, TEST_PRECISION));
    186         aTree.add(Interval.of(1, 2, TEST_PRECISION));
    187
    188         final EmbeddedTreeLineSubset b = new EmbeddedTreeLineSubset(line);
    189         final RegionBSPTree1D bTree = b.getSubspaceRegion();
    190         bTree.add(Interval.of(2, 4, TEST_PRECISION));
    191         bTree.add(Interval.of(-4, -2, TEST_PRECISION));
    192
    193         final EmbeddedTreeLineSubset subset = new EmbeddedTreeLineSubset(line);
    194
    195         final int aTreeCount = aTree.count();
    196         final int bTreeCount = bTree.count();
    197
    198         // act
    199         subset.add(a);
    200         subset.add(b);
    201
    202         // assert
    203         Assert.assertFalse(subset.isFull());
    204         Assert.assertFalse(subset.isEmpty());
    205
    206         final List<LineConvexSubset> segments = subset.toConvex();
    207
    208         Assert.assertEquals(2, segments.size());
    209
    210         Assert.assertNull(segments.get(0).getStartPoint());
    211         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-2, 1), segments.get(0).getEndPoint(), TEST_EPS);
    212
    213         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 1), segments.get(1).getStartPoint(), TEST_EPS);
    214         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(4, 1), segments.get(1).getEndPoint(), TEST_EPS);
    215
    216         Assert.assertEquals(aTreeCount, aTree.count());
    217         Assert.assertEquals(bTreeCount, bTree.count());
    218
    219         GeometryTestUtils.assertPositiveInfinity(subset.getSize());
    220         Assert.assertNull(subset.getCentroid());
    221     }
    222
    223     @Test
    224     public void testAdd_argumentsFromDifferentLine() {
    225         // arrange
    226         final Line line = Lines.fromPointAndAngle(Vector2D.of(0, 1), 0.0, TEST_PRECISION);
    227         final Line otherLine = Lines.fromPointAndAngle(Vector2D.of(0, 1), 1e-2, TEST_PRECISION);
    228
    229         final EmbeddedTreeLineSubset subset = new EmbeddedTreeLineSubset(line);
    230
    231         // act/assert
    232         GeometryTestUtils.assertThrows(() -> {
    233             subset.add(Lines.subsetFromInterval(otherLine, 0, 1));
    234         }, IllegalArgumentException.class);
    235
    236         GeometryTestUtils.assertThrows(() -> {
    237             subset.add(new EmbeddedTreeLineSubset(otherLine));
    238         }, IllegalArgumentException.class);
    239     }
    240
    241     @Test
    242     public void testGetBounds_noBounds() {
    243         // arrange
    244         final Line line = Lines.fromPointAndAngle(Vector2D.of(1, 0), 0.25 * Math.PI, TEST_PRECISION);
    245
    246         final EmbeddedTreeLineSubset full = new EmbeddedTreeLineSubset(line, RegionBSPTree1D.full());
    247         final EmbeddedTreeLineSubset empty = new EmbeddedTreeLineSubset(line, RegionBSPTree1D.empty());
    248         final EmbeddedTreeLineSubset halfFull = new EmbeddedTreeLineSubset(line, Interval.min(1.0, TEST_PRECISION).toTree());
    249
    250         // act/assert
    251         Assert.assertNull(full.getBounds());
    252         Assert.assertNull(empty.getBounds());
    253         Assert.assertNull(halfFull.getBounds());
    254     }
    255
    256     @Test
    257     public void testGetBounds_hasBounds() {
    258         // arrange
    259         final Line line = Lines.fromPoints(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION);
    260
    261         final EmbeddedTreeLineSubset subset = new EmbeddedTreeLineSubset(line, false);
    262
    263         final double sqrt2 = Math.sqrt(2);
    264         subset.getSubspaceRegion().add(Interval.of(-2 * sqrt2, -sqrt2, TEST_PRECISION));
    265         subset.getSubspaceRegion().add(Interval.of(0, sqrt2, TEST_PRECISION));
    266
    267         // act
    268         final Bounds2D bounds = subset.getBounds();
    269
    270         // assert
    271         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-2, -2), bounds.getMin(), TEST_EPS);
    272         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 1), bounds.getMax(), TEST_EPS);
    273     }
    274
    275     @Test
    276     public void testSplit_both_anglePositive() {
    277         // arrange
    278         final RegionBSPTree1D subRegion = RegionBSPTree1D.empty();
    279         subRegion.add(Interval.of(0,  2, TEST_PRECISION));
    280         subRegion.add(Interval.of(3,  4, TEST_PRECISION));
    281
    282         final Line line = Lines.fromPointAndAngle(Vector2D.ZERO, 0.0, TEST_PRECISION);
    283         final EmbeddedTreeLineSubset subset = new EmbeddedTreeLineSubset(line, subRegion);
    284
    285         final Line splitter = Lines.fromPointAndAngle(Vector2D.of(1, 0), 0.1 * PlaneAngleRadians.PI, TEST_PRECISION);
    286
    287         // act
    288         final Split<EmbeddedTreeLineSubset> split = subset.split(splitter);
    289
    290         // assert
    291         Assert.assertEquals(SplitLocation.BOTH, split.getLocation());
    292
    293         final List<LineConvexSubset> minusSegments = split.getMinus().toConvex();
    294         Assert.assertEquals(1, minusSegments.size());
    295         checkFiniteSegment(minusSegments.get(0), Vector2D.ZERO, Vector2D.of(1, 0));
    296
    297         final List<LineConvexSubset> plusSegments = split.getPlus().toConvex();
    298         Assert.assertEquals(2, plusSegments.size());
    299         checkFiniteSegment(plusSegments.get(0), Vector2D.of(1, 0), Vector2D.of(2, 0));
    300         checkFiniteSegment(plusSegments.get(1), Vector2D.of(3, 0), Vector2D.of(4, 0));
    301     }
    302
    303     @Test
    304     public void testSplit_both_angleNegative() {
    305         // arrange
    306         final RegionBSPTree1D subRegion = RegionBSPTree1D.empty();
    307         subRegion.add(Interval.of(0,  2, TEST_PRECISION));
    308         subRegion.add(Interval.of(3,  4, TEST_PRECISION));
    309
    310         final Line line = Lines.fromPointAndAngle(Vector2D.ZERO, 0.0, TEST_PRECISION);
    311         final EmbeddedTreeLineSubset subset = new EmbeddedTreeLineSubset(line, subRegion);
    312
    313         final Line splitter = Lines.fromPointAndAngle(Vector2D.of(1, 0), -0.9 * PlaneAngleRadians.PI, TEST_PRECISION);
    314
    315         // act
    316         final Split<EmbeddedTreeLineSubset> split = subset.split(splitter);
    317
    318         // assert
    319         Assert.assertEquals(SplitLocation.BOTH, split.getLocation());
    320
    321         final List<LineConvexSubset> minusSegments = split.getMinus().toConvex();
    322         Assert.assertEquals(2, minusSegments.size());
    323         checkFiniteSegment(minusSegments.get(0), Vector2D.of(1, 0), Vector2D.of(2, 0));
    324         checkFiniteSegment(minusSegments.get(1), Vector2D.of(3, 0), Vector2D.of(4, 0));
    325
    326         final List<LineConvexSubset> plusSegments = split.getPlus().toConvex();
    327         Assert.assertEquals(1, plusSegments.size());
    328         checkFiniteSegment(plusSegments.get(0), Vector2D.ZERO, Vector2D.of(1, 0));
    329     }
    330
    331     @Test
    332     public void testSplit_intersection_plusOnly() {
    333         // arrange
    334         final RegionBSPTree1D subRegion = RegionBSPTree1D.empty();
    335         subRegion.add(Interval.of(0,  2, TEST_PRECISION));
    336         subRegion.add(Interval.of(3,  4, TEST_PRECISION));
    337
    338         final Line line = Lines.fromPointAndAngle(Vector2D.ZERO, 0.0, TEST_PRECISION);
    339         final EmbeddedTreeLineSubset subset = new EmbeddedTreeLineSubset(line, subRegion);
    340
    341         final Line splitter = Lines.fromPointAndAngle(Vector2D.of(-1, 0), 0.1 * PlaneAngleRadians.PI, TEST_PRECISION);
    342
    343         // act
    344         final Split<EmbeddedTreeLineSubset> split = subset.split(splitter);
    345
    346         // assert
    347         Assert.assertEquals(SplitLocation.PLUS, split.getLocation());
    348
    349         Assert.assertNull(split.getMinus());
    350         Assert.assertSame(subset, split.getPlus());
    351     }
    352
    353     @Test
    354     public void testSplit_intersection_minusOnly() {
    355         // arrange
    356         final RegionBSPTree1D subRegion = RegionBSPTree1D.empty();
    357         subRegion.add(Interval.of(0,  2, TEST_PRECISION));
    358         subRegion.add(Interval.of(3,  4, TEST_PRECISION));
    359
    360         final Line line = Lines.fromPointAndAngle(Vector2D.ZERO, 0.0, TEST_PRECISION);
    361         final EmbeddedTreeLineSubset subset = new EmbeddedTreeLineSubset(line, subRegion);
    362
    363         final Line splitter = Lines.fromPointAndAngle(Vector2D.of(10, 0), 0.1 * PlaneAngleRadians.PI, TEST_PRECISION);
    364
    365         // act
    366         final Split<EmbeddedTreeLineSubset> split = subset.split(splitter);
    367
    368         // assert
    369         Assert.assertEquals(SplitLocation.MINUS, split.getLocation());
    370
    371         Assert.assertSame(subset, split.getMinus());
    372         Assert.assertNull(split.getPlus());
    373     }
    374
    375     @Test
    376     public void testSplit_parallel_plus() {
    377         // arrange
    378         final RegionBSPTree1D subRegion = RegionBSPTree1D.empty();
    379         subRegion.add(Interval.of(0,  2, TEST_PRECISION));
    380         subRegion.add(Interval.of(3,  4, TEST_PRECISION));
    381
    382         final Line line = Lines.fromPointAndAngle(Vector2D.ZERO, 0.0, TEST_PRECISION);
    383         final EmbeddedTreeLineSubset subset = new EmbeddedTreeLineSubset(line, subRegion);
    384
    385         final Line splitter = Lines.fromPointAndAngle(Vector2D.of(0, 1), 0.0, TEST_PRECISION);
    386
    387         // act
    388         final Split<EmbeddedTreeLineSubset> split = subset.split(splitter);
    389
    390         // assert
    391         Assert.assertEquals(SplitLocation.PLUS, split.getLocation());
    392
    393         Assert.assertNull(split.getMinus());
    394         Assert.assertSame(subset, split.getPlus());
    395     }
    396
    397     @Test
    398     public void testSplit_parallel_minus() {
    399         // arrange
    400         final RegionBSPTree1D subRegion = RegionBSPTree1D.empty();
    401         subRegion.add(Interval.of(0,  2, TEST_PRECISION));
    402         subRegion.add(Interval.of(3,  4, TEST_PRECISION));
    403
    404         final Line line = Lines.fromPointAndAngle(Vector2D.ZERO, 0.0, TEST_PRECISION);
    405         final EmbeddedTreeLineSubset subset = new EmbeddedTreeLineSubset(line, subRegion);
    406
    407         final Line splitter = Lines.fromPointAndAngle(Vector2D.of(0, -1), 0.0, TEST_PRECISION);
    408
    409         // act
    410         final Split<EmbeddedTreeLineSubset> split = subset.split(splitter);
    411
    412         // assert
    413         Assert.assertEquals(SplitLocation.MINUS, split.getLocation());
    414
    415         Assert.assertSame(subset, split.getMinus());
    416         Assert.assertNull(split.getPlus());
    417     }
    418
    419     @Test
    420     public void testSplit_coincident_sameDirection() {
    421         // arrange
    422         final RegionBSPTree1D subRegion = RegionBSPTree1D.empty();
    423         subRegion.add(Interval.of(0,  2, TEST_PRECISION));
    424         subRegion.add(Interval.of(3,  4, TEST_PRECISION));
    425
    426         final Line line = Lines.fromPointAndAngle(Vector2D.ZERO, 0.0, TEST_PRECISION);
    427         final EmbeddedTreeLineSubset subset = new EmbeddedTreeLineSubset(line, subRegion);
    428
    429         final Line splitter = Lines.fromPointAndAngle(Vector2D.ZERO, 0.0, TEST_PRECISION);
    430
    431         // act
    432         final Split<EmbeddedTreeLineSubset> split = subset.split(splitter);
    433
    434         // assert
    435         Assert.assertEquals(SplitLocation.NEITHER, split.getLocation());
    436
    437         Assert.assertNull(split.getMinus());
    438         Assert.assertNull(split.getPlus());
    439     }
    440
    441     @Test
    442     public void testSplit_coincident_oppositeDirection() {
    443         // arrange
    444         final RegionBSPTree1D subRegion = RegionBSPTree1D.empty();
    445         subRegion.add(Interval.of(0,  2, TEST_PRECISION));
    446         subRegion.add(Interval.of(3,  4, TEST_PRECISION));
    447
    448         final Line line = Lines.fromPointAndAngle(Vector2D.ZERO, 0.0, TEST_PRECISION);
    449         final EmbeddedTreeLineSubset subset = new EmbeddedTreeLineSubset(line, subRegion);
    450
    451         final Line splitter = Lines.fromPointAndAngle(Vector2D.ZERO, PlaneAngleRadians.PI, TEST_PRECISION);
    452
    453         // act
    454         final Split<EmbeddedTreeLineSubset> split = subset.split(splitter);
    455
    456         // assert
    457         Assert.assertEquals(SplitLocation.NEITHER, split.getLocation());
    458
    459         Assert.assertNull(split.getMinus());
    460         Assert.assertNull(split.getPlus());
    461     }
    462
    463     @Test
    464     public void testTransform() {
    465         // arrange
    466         final AffineTransformMatrix2D mat = AffineTransformMatrix2D
    467                 .createRotation(Vector2D.of(0, 1), PlaneAngleRadians.PI_OVER_TWO)
    468                 .scale(Vector2D.of(3, 2));
    469
    470         final EmbeddedTreeLineSubset subset = new EmbeddedTreeLineSubset(Lines.fromPointAndAngle(Vector2D.ZERO, 0.0, TEST_PRECISION));
    471         subset.getSubspaceRegion().add(Interval.of(0, 1, TEST_PRECISION));
    472         subset.getSubspaceRegion().add(Interval.min(3, TEST_PRECISION));
    473
    474         // act
    475         final EmbeddedTreeLineSubset transformed = subset.transform(mat);
    476
    477         // assert
    478         Assert.assertNotSame(subset, transformed);
    479
    480         final List<LineConvexSubset> originalSegments = subset.toConvex();
    481         Assert.assertEquals(2, originalSegments.size());
    482         checkFiniteSegment(originalSegments.get(0), Vector2D.ZERO, Vector2D.Unit.PLUS_X);
    483         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(3, 0), originalSegments.get(1).getStartPoint(), TEST_EPS);
    484         Assert.assertNull(originalSegments.get(1).getEndPoint());
    485
    486         final List<LineConvexSubset> transformedSegments = transformed.toConvex();
    487         Assert.assertEquals(2, transformedSegments.size());
    488         checkFiniteSegment(transformedSegments.get(0), Vector2D.of(3, 2), Vector2D.of(3, 4));
    489         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(3, 8), transformedSegments.get(1).getStartPoint(), TEST_EPS);
    490         Assert.assertNull(transformedSegments.get(1).getEndPoint());
    491     }
    492
    493     @Test
    494     public void testTransform_reflection() {
    495         // arrange
    496         final AffineTransformMatrix2D mat = AffineTransformMatrix2D.createScale(Vector2D.of(-1, 2));
    497
    498         final EmbeddedTreeLineSubset subset =
    499                 new EmbeddedTreeLineSubset(Lines.fromPointAndAngle(Vector2D.of(0, 1), 0.0, TEST_PRECISION));
    500         subset.getSubspaceRegion().add(Interval.of(0, 1, TEST_PRECISION));
    501
    502         // act
    503         final EmbeddedTreeLineSubset transformed = subset.transform(mat);
    504
    505         // assert
    506         Assert.assertNotSame(subset, transformed);
    507
    508         final List<LineConvexSubset> originalSegments = subset.toConvex();
    509         Assert.assertEquals(1, originalSegments.size());
    510         checkFiniteSegment(originalSegments.get(0), Vector2D.of(0, 1), Vector2D.of(1, 1));
    511
    512         final List<LineConvexSubset> transformedSegments = transformed.toConvex();
    513         Assert.assertEquals(1, transformedSegments.size());
    514         checkFiniteSegment(transformedSegments.get(0), Vector2D.of(0, 2), Vector2D.of(-1, 2));
    515     }
    516
    517     @Test
    518     public void testToString() {
    519         // arrange
    520         final EmbeddedTreeLineSubset sub = new EmbeddedTreeLineSubset(DEFAULT_TEST_LINE);
    521
    522         // act
    523         final String str = sub.toString();
    524
    525         // assert
    526         Assert.assertTrue(str.contains("EmbeddedTreeLineSubset[lineOrigin= "));
    527         Assert.assertTrue(str.contains(", lineDirection= "));
    528         Assert.assertTrue(str.contains(", region= "));
    529     }
    530
    531     private static void checkFiniteSegment(final LineConvexSubset segment, final Vector2D start, final Vector2D end) {
    532         Assert.assertFalse(segment.isInfinite());
    533
    534         EuclideanTestUtils.assertCoordinatesEqual(start, segment.getStartPoint(), TEST_EPS);
    535         EuclideanTestUtils.assertCoordinatesEqual(end, segment.getEndPoint(), TEST_EPS);
    536     }
    537 }