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.shape;
    18
    19  import java.util.List;
    20
    21  import org.apache.commons.geometry.core.GeometryTestUtils;
    22  import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
    23  import org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext;
    24  import org.apache.commons.geometry.euclidean.EuclideanTestUtils;
    25  import org.apache.commons.geometry.euclidean.twod.AffineTransformMatrix2D;
    26  import org.apache.commons.geometry.euclidean.twod.LineConvexSubset;
    27  import org.apache.commons.geometry.euclidean.twod.RegionBSPTree2D;
    28  import org.apache.commons.geometry.euclidean.twod.Vector2D;
    29  import org.apache.commons.geometry.euclidean.twod.path.LinePath;
    30  import org.apache.commons.geometry.euclidean.twod.rotation.Rotation2D;
    31  import org.junit.Assert;
    32  import org.junit.Test;
    33
    34  public class ParallelogramTest {
    35
    36      private static final double TEST_EPS = 1e-10;
    37
    38      private static final DoublePrecisionContext TEST_PRECISION =
    39              new EpsilonDoublePrecisionContext(TEST_EPS);
    40
    41      @Test
    42      public void testUnitSquare() {
    43          // act
    44          final Parallelogram box = Parallelogram.unitSquare(TEST_PRECISION);
    45
    46          // assert
    47          Assert.assertEquals(1, box.getSize(), TEST_EPS);
    48          Assert.assertEquals(4, box.getBoundarySize(), TEST_EPS);
    49          EuclideanTestUtils.assertCoordinatesEqual(Vector2D.ZERO, box.getCentroid(), TEST_EPS);
    50
    51          final List<Vector2D> vertices = box.getVertices();
    52          Assert.assertEquals(4, vertices.size());
    53          EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-0.5, -0.5), vertices.get(0), TEST_EPS);
    54          EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0.5, -0.5), vertices.get(1), TEST_EPS);
    55          EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0.5, 0.5), vertices.get(2), TEST_EPS);
    56          EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-0.5, 0.5), vertices.get(3), TEST_EPS);
    57      }
    58
    59      @Test
    60      public void testFromTransformedUnitSquare() {
    61          // arrange
    62          final AffineTransformMatrix2D t = AffineTransformMatrix2D.createTranslation(Vector2D.of(1, 0))
    63                  .rotate(Math.PI * 0.25)
    64                  .scale(Vector2D.of(2, 1));
    65
    66          // act
    67          final Parallelogram p = Parallelogram.fromTransformedUnitSquare(t, TEST_PRECISION);
    68
    69          // assert
    70          final double sqrt2 = Math.sqrt(2);
    71          final double invSqrt2 = 1 / sqrt2;
    72
    73          Assert.assertEquals(2, p.getSize(), TEST_EPS);
    74          Assert.assertEquals(4 * Math.sqrt(2.5), p.getBoundarySize(), TEST_EPS);
    75          EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(2 * invSqrt2, invSqrt2), p.getCentroid(), TEST_EPS);
    76
    77          final List<Vector2D> vertices = p.getVertices();
    78          Assert.assertEquals(4, vertices.size());
    79          EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, invSqrt2), vertices.get(0), TEST_EPS);
    80          EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(2 * invSqrt2, 0), vertices.get(1), TEST_EPS);
    81          EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(2 * sqrt2, invSqrt2), vertices.get(2), TEST_EPS);
    82          EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(2 * invSqrt2, sqrt2), vertices.get(3), TEST_EPS);
    83      }
    84
    85      @Test
    86      public void testFromTransformedUnitSquare_transformDoesNotPreserveOrientation() {
    87          // arrange
    88          final AffineTransformMatrix2D t = AffineTransformMatrix2D.createTranslation(Vector2D.of(1, 0))
    89                  .rotate(Math.PI * 0.25)
    90                  .scale(Vector2D.of(-2, 1));
    91
    92          // act
    93          final Parallelogram p = Parallelogram.fromTransformedUnitSquare(t, TEST_PRECISION);
    94
    95          // assert
    96          final double sqrt2 = Math.sqrt(2);
    97          final double invSqrt2 = 1 / sqrt2;
    98
    99          Assert.assertEquals(2, p.getSize(), TEST_EPS);
    100         Assert.assertEquals(4 * Math.sqrt(2.5), p.getBoundarySize(), TEST_EPS);
    101         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-2 * invSqrt2, invSqrt2), p.getCentroid(), TEST_EPS);
    102
    103         final List<Vector2D> vertices = p.getVertices();
    104         Assert.assertEquals(4, vertices.size());
    105         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-2 * sqrt2, invSqrt2), vertices.get(0), TEST_EPS);
    106         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-2 * invSqrt2, 0), vertices.get(1), TEST_EPS);
    107         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, invSqrt2), vertices.get(2), TEST_EPS);
    108         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-2 * invSqrt2, sqrt2), vertices.get(3), TEST_EPS);
    109     }
    110
    111     @Test
    112     public void testFromTransformedUnitSquare_zeroSizeRegion() {
    113         // act/assert
    114         GeometryTestUtils.assertThrows(() -> {
    115             Parallelogram.fromTransformedUnitSquare(AffineTransformMatrix2D.createScale(Vector2D.of(1e-16, 1)),
    116                     TEST_PRECISION);
    117         }, IllegalArgumentException.class);
    118
    119         GeometryTestUtils.assertThrows(() -> {
    120             Parallelogram.fromTransformedUnitSquare(AffineTransformMatrix2D.createScale(Vector2D.of(1, 1e-16)),
    121                     TEST_PRECISION);
    122         }, IllegalArgumentException.class);
    123     }
    124
    125     @Test
    126     public void testAxisAligned_minFirst() {
    127         // act
    128         final Parallelogram box = Parallelogram.axisAligned(Vector2D.of(1, 2), Vector2D.of(3, 4), TEST_PRECISION);
    129
    130         // assert
    131         Assert.assertEquals(1, box.getBoundaryPaths().size());
    132         final LinePath path = box.getBoundaryPaths().get(0);
    133
    134         final List<LineConvexSubset> segments = path.getElements();
    135         Assert.assertEquals(4, segments.size());
    136
    137         assertSegment(segments.get(0), Vector2D.of(1, 2), Vector2D.of(3, 2));
    138         assertSegment(segments.get(1), Vector2D.of(3, 2), Vector2D.of(3, 4));
    139         assertSegment(segments.get(2), Vector2D.of(3, 4), Vector2D.of(1, 4));
    140         assertSegment(segments.get(3), Vector2D.of(1, 4), Vector2D.of(1, 2));
    141     }
    142
    143     @Test
    144     public void testAxisAligned_maxFirst() {
    145         // act
    146         final Parallelogram box = Parallelogram.axisAligned(Vector2D.ZERO, Vector2D.of(-1, -2), TEST_PRECISION);
    147
    148         // assert
    149         Assert.assertEquals(1, box.getBoundaryPaths().size());
    150         final LinePath path = box.getBoundaryPaths().get(0);
    151
    152         final List<LineConvexSubset> segments = path.getElements();
    153         Assert.assertEquals(4, segments.size());
    154
    155         assertSegment(segments.get(0), Vector2D.of(-1, -2), Vector2D.of(0, -2));
    156         assertSegment(segments.get(1), Vector2D.of(0, -2), Vector2D.ZERO);
    157         assertSegment(segments.get(2), Vector2D.ZERO, Vector2D.of(-1, 0));
    158         assertSegment(segments.get(3), Vector2D.of(-1, 0), Vector2D.of(-1, -2));
    159     }
    160
    161     @Test
    162     public void testAxisAligned_illegalArgs() {
    163         // act/assert
    164         GeometryTestUtils.assertThrows(() -> {
    165             Parallelogram.axisAligned(Vector2D.of(1, 1), Vector2D.of(1, 3), TEST_PRECISION);
    166         }, IllegalArgumentException.class);
    167
    168         GeometryTestUtils.assertThrows(() -> {
    169             Parallelogram.axisAligned(Vector2D.of(1, 1), Vector2D.of(3, 1), TEST_PRECISION);
    170         }, IllegalArgumentException.class);
    171
    172         GeometryTestUtils.assertThrows(() -> {
    173             Parallelogram.axisAligned(Vector2D.of(2, 3), Vector2D.of(2, 3), TEST_PRECISION);
    174         }, IllegalArgumentException.class);
    175     }
    176
    177     @Test
    178     public void testBuilder_defaultValues() {
    179         // arrange
    180         final Parallelogram.Builder builder = Parallelogram.builder(TEST_PRECISION);
    181
    182         // act
    183         final Parallelogram p = builder.build();
    184
    185         // assert
    186         Assert.assertEquals(1, p.getSize(), TEST_EPS);
    187         Assert.assertEquals(4, p.getBoundarySize(), TEST_EPS);
    188         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.ZERO, p.getCentroid(), TEST_EPS);
    189
    190         final List<Vector2D> vertices = p.getVertices();
    191         Assert.assertEquals(4, vertices.size());
    192         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-0.5, -0.5), vertices.get(0), TEST_EPS);
    193         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0.5, -0.5), vertices.get(1), TEST_EPS);
    194         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0.5, 0.5), vertices.get(2), TEST_EPS);
    195         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-0.5, 0.5), vertices.get(3), TEST_EPS);
    196     }
    197
    198     @Test
    199     public void testBuilder_rotatedRect_withXDirection() {
    200         // arrange
    201         final Parallelogram.Builder builder = Parallelogram.builder(TEST_PRECISION);
    202
    203         // act
    204         final Parallelogram p = builder
    205                 .setScale(1, 2)
    206                 .setXDirection(Vector2D.Unit.PLUS_Y)
    207                 .setPosition(Vector2D.of(1, 2))
    208                 .build();
    209
    210         // assert
    211         Assert.assertEquals(2, p.getSize(), TEST_EPS);
    212         Assert.assertEquals(6, p.getBoundarySize(), TEST_EPS);
    213         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 2), p.getCentroid(), TEST_EPS);
    214
    215         final List<Vector2D> vertices = p.getVertices();
    216         Assert.assertEquals(4, vertices.size());
    217         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, 1.5), vertices.get(0), TEST_EPS);
    218         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(2, 1.5), vertices.get(1), TEST_EPS);
    219         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(2, 2.5), vertices.get(2), TEST_EPS);
    220         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, 2.5), vertices.get(3), TEST_EPS);
    221     }
    222
    223     @Test
    224     public void testBuilder_rotatedRect_withYDirection() {
    225         // arrange
    226         final Parallelogram.Builder builder = Parallelogram.builder(TEST_PRECISION);
    227
    228         // act
    229         final Parallelogram p = builder
    230                 .setScale(Vector2D.of(2, 1))
    231                 .setYDirection(Vector2D.Unit.MINUS_X)
    232                 .setPosition(Vector2D.of(1, 2))
    233                 .build();
    234
    235         // assert
    236         Assert.assertEquals(2, p.getSize(), TEST_EPS);
    237         Assert.assertEquals(6, p.getBoundarySize(), TEST_EPS);
    238         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 2), p.getCentroid(), TEST_EPS);
    239
    240         final List<Vector2D> vertices = p.getVertices();
    241         Assert.assertEquals(4, vertices.size());
    242         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0.5, 1), vertices.get(0), TEST_EPS);
    243         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1.5, 1), vertices.get(1), TEST_EPS);
    244         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1.5, 3), vertices.get(2), TEST_EPS);
    245         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0.5, 3), vertices.get(3), TEST_EPS);
    246     }
    247
    248     @Test
    249     public void testBuilder_rotatedRect_withRotation() {
    250         // arrange
    251         final Parallelogram.Builder builder = Parallelogram.builder(TEST_PRECISION);
    252
    253         // act
    254         final Parallelogram p = builder
    255                 .setScale(2)
    256                 .setRotation(Rotation2D.of(0.25 * Math.PI))
    257                 .setPosition(Vector2D.of(1, 2))
    258                 .build();
    259
    260         // assert
    261         Assert.assertEquals(4, p.getSize(), TEST_EPS);
    262         Assert.assertEquals(8, p.getBoundarySize(), TEST_EPS);
    263         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 2), p.getCentroid(), TEST_EPS);
    264
    265         final List<Vector2D> vertices = p.getVertices();
    266         Assert.assertEquals(4, vertices.size());
    267
    268         final double sqrt2 = Math.sqrt(2);
    269         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1 - sqrt2, 2), vertices.get(0), TEST_EPS);
    270         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 2 - sqrt2), vertices.get(1), TEST_EPS);
    271         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1 + sqrt2, 2), vertices.get(2), TEST_EPS);
    272         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 2 + sqrt2), vertices.get(3), TEST_EPS);
    273     }
    274
    275     @Test
    276     public void testToTree() {
    277         // act
    278         final RegionBSPTree2D tree = Parallelogram.axisAligned(Vector2D.ZERO, Vector2D.of(1, 4), TEST_PRECISION)
    279                 .toTree();
    280
    281         // assert
    282         Assert.assertFalse(tree.isFull());
    283         Assert.assertFalse(tree.isEmpty());
    284
    285         Assert.assertEquals(4, tree.getSize(), TEST_EPS);
    286         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0.5, 2), tree.getCentroid(), TEST_EPS);
    287     }
    288
    289     private static void assertSegment(final LineConvexSubset segment, final Vector2D start, final Vector2D end) {
    290         EuclideanTestUtils.assertCoordinatesEqual(start, segment.getStartPoint(), TEST_EPS);
    291         EuclideanTestUtils.assertCoordinatesEqual(end, segment.getEndPoint(), TEST_EPS);
    292     }
    293 }