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.spherical.twod;
    18
    19  import org.apache.commons.geometry.core.GeometryTestUtils;
    20  import org.apache.commons.geometry.euclidean.threed.Vector3D;
    21  import org.apache.commons.geometry.euclidean.threed.rotation.QuaternionRotation;
    22  import org.apache.commons.geometry.spherical.SphericalTestUtils;
    23  import org.apache.commons.numbers.angle.Angle;
    24  import org.junit.jupiter.api.Assertions;
    25  import org.junit.jupiter.api.Test;
    26
    27  class Transform2STest {
    28
    29      private static final double TEST_EPS = 1e-10;
    30
    31      @Test
    32      void testIdentity() {
    33          // act
    34          final Transform2S t = Transform2S.identity();
    35
    36          // assert
    37          Assertions.assertTrue(t.preservesOrientation());
    38          Assertions.assertArrayEquals(new double[] {
    39              1, 0, 0, 0,
    40              0, 1, 0, 0,
    41              0, 0, 1, 0
    42          }, t.getEuclideanTransform().toArray(), 0);
    43
    44          SphericalTestUtils.assertPointsEqual(Point2S.PLUS_I, t.apply(Point2S.PLUS_I), TEST_EPS);
    45          SphericalTestUtils.assertPointsEqual(Point2S.PLUS_J, t.apply(Point2S.PLUS_J), TEST_EPS);
    46          SphericalTestUtils.assertPointsEqual(Point2S.PLUS_K, t.apply(Point2S.PLUS_K), TEST_EPS);
    47
    48          checkInverse(t);
    49      }
    50
    51      @Test
    52      void testRotation() {
    53          // arrange
    54          final Transform2S aroundPole = Transform2S.createRotation(Point2S.PLUS_K, Angle.PI_OVER_TWO);
    55          final Transform2S aroundX = Transform2S.createRotation(Vector3D.Unit.PLUS_X, -Angle.PI_OVER_TWO);
    56          final Transform2S aroundY = Transform2S.createRotation(
    57                  QuaternionRotation.fromAxisAngle(Vector3D.Unit.PLUS_Y, Angle.PI_OVER_TWO));
    58
    59          // act/assert
    60          SphericalTestUtils.assertPointsEqual(Point2S.PLUS_J, aroundPole.apply(Point2S.PLUS_I), TEST_EPS);
    61          SphericalTestUtils.assertPointsEqual(Point2S.MINUS_I, aroundPole.apply(Point2S.PLUS_J), TEST_EPS);
    62          SphericalTestUtils.assertPointsEq(Point2S.PLUS_K, aroundPole.apply(Point2S.PLUS_K), TEST_EPS);
    63          checkInverse(aroundPole);
    64
    65          SphericalTestUtils.assertPointsEqual(Point2S.PLUS_I, aroundX.apply(Point2S.PLUS_I), TEST_EPS);
    66          SphericalTestUtils.assertPointsEq(Point2S.MINUS_K, aroundX.apply(Point2S.PLUS_J), TEST_EPS);
    67          SphericalTestUtils.assertPointsEqual(Point2S.PLUS_J, aroundX.apply(Point2S.PLUS_K), TEST_EPS);
    68          checkInverse(aroundX);
    69
    70          SphericalTestUtils.assertPointsEq(Point2S.MINUS_K, aroundY.apply(Point2S.PLUS_I), TEST_EPS);
    71          SphericalTestUtils.assertPointsEqual(Point2S.PLUS_J, aroundY.apply(Point2S.PLUS_J), TEST_EPS);
    72          SphericalTestUtils.assertPointsEqual(Point2S.PLUS_I, aroundY.apply(Point2S.PLUS_K), TEST_EPS);
    73          checkInverse(aroundY);
    74      }
    75
    76      @Test
    77      void testMultipleRotations() {
    78          // act
    79          final Transform2S t = Transform2S.identity()
    80                  .rotate(Point2S.PLUS_K, Angle.PI_OVER_TWO)
    81                  .rotate(Vector3D.Unit.PLUS_X, -Angle.PI_OVER_TWO)
    82                  .rotate(QuaternionRotation.fromAxisAngle(Vector3D.Unit.PLUS_Y, Angle.PI_OVER_TWO));
    83
    84          // assert
    85          SphericalTestUtils.assertPointsEqual(Point2S.MINUS_I, t.apply(Point2S.PLUS_I), TEST_EPS);
    86          SphericalTestUtils.assertPointsEq(Point2S.PLUS_K, t.apply(Point2S.PLUS_J), TEST_EPS);
    87          SphericalTestUtils.assertPointsEqual(Point2S.PLUS_J, t.apply(Point2S.PLUS_K), TEST_EPS);
    88
    89          checkInverse(t);
    90      }
    91
    92      @Test
    93      void testMultiply() {
    94          // act
    95          final Transform2S t = Transform2S.identity()
    96                  .multiply(Transform2S.createRotation(Point2S.PLUS_K, Angle.PI_OVER_TWO))
    97                  .multiply(Transform2S.createRotation(Point2S.PLUS_J, Angle.PI_OVER_TWO));
    98
    99          // assert
    100         SphericalTestUtils.assertPointsEq(Point2S.MINUS_K, t.apply(Point2S.PLUS_I), TEST_EPS);
    101         SphericalTestUtils.assertPointsEqual(Point2S.MINUS_I, t.apply(Point2S.PLUS_J), TEST_EPS);
    102         SphericalTestUtils.assertPointsEqual(Point2S.PLUS_J, t.apply(Point2S.PLUS_K), TEST_EPS);
    103
    104         checkInverse(t);
    105     }
    106
    107     @Test
    108     void testPremultiply() {
    109         // act
    110         final Transform2S t = Transform2S.identity()
    111                 .premultiply(Transform2S.createRotation(Point2S.PLUS_K, Angle.PI_OVER_TWO))
    112                 .premultiply(Transform2S.createRotation(Point2S.PLUS_J, Angle.PI_OVER_TWO));
    113
    114         // assert
    115         SphericalTestUtils.assertPointsEqual(Point2S.PLUS_J, t.apply(Point2S.PLUS_I), TEST_EPS);
    116         SphericalTestUtils.assertPointsEq(Point2S.PLUS_K, t.apply(Point2S.PLUS_J), TEST_EPS);
    117         SphericalTestUtils.assertPointsEqual(Point2S.PLUS_I, t.apply(Point2S.PLUS_K), TEST_EPS);
    118
    119         checkInverse(t);
    120     }
    121
    122     @Test
    123     void testReflection_point() {
    124         // arrange
    125         final Point2S a = Point2S.of(1, 1);
    126         final Point2S b = Point2S.of(-1, 1);
    127
    128         final Point2S c = Point2S.of(1, Math.PI - 1);
    129         final Point2S d = Point2S.of(-1, Math.PI - 1);
    130
    131         // act
    132         final Transform2S t = Transform2S.createReflection(Point2S.PLUS_I);
    133
    134         // assert
    135         Assertions.assertFalse(t.preservesOrientation());
    136
    137         SphericalTestUtils.assertPointsEqual(Point2S.MINUS_I, t.apply(Point2S.PLUS_I), TEST_EPS);
    138         SphericalTestUtils.assertPointsEqual(Point2S.PLUS_J, t.apply(Point2S.PLUS_J), TEST_EPS);
    139         SphericalTestUtils.assertPointsEq(Point2S.PLUS_K, t.apply(Point2S.PLUS_K), TEST_EPS);
    140
    141         SphericalTestUtils.assertPointsEqual(Point2S.of(Math.PI - 1, 1), t.apply(a), TEST_EPS);
    142         SphericalTestUtils.assertPointsEqual(Point2S.of(Math.PI + 1, 1), t.apply(b), TEST_EPS);
    143
    144         SphericalTestUtils.assertPointsEqual(Point2S.of(Math.PI - 1, Math.PI - 1), t.apply(c), TEST_EPS);
    145         SphericalTestUtils.assertPointsEqual(Point2S.of(Math.PI + 1, Math.PI - 1), t.apply(d), TEST_EPS);
    146
    147         checkInverse(t);
    148     }
    149
    150     @Test
    151     void testReflection_vector() {
    152         // arrange
    153         final Point2S a = Point2S.of(1, 1);
    154         final Point2S b = Point2S.of(-1, 1);
    155
    156         final Point2S c = Point2S.of(1, Math.PI - 1);
    157         final Point2S d = Point2S.of(-1, Math.PI - 1);
    158
    159         // act
    160         final Transform2S t = Transform2S.createReflection(Vector3D.Unit.PLUS_Y);
    161
    162         // assert
    163         Assertions.assertFalse(t.preservesOrientation());
    164
    165         SphericalTestUtils.assertPointsEqual(Point2S.PLUS_I, t.apply(Point2S.PLUS_I), TEST_EPS);
    166         SphericalTestUtils.assertPointsEqual(Point2S.MINUS_J, t.apply(Point2S.PLUS_J), TEST_EPS);
    167         SphericalTestUtils.assertPointsEq(Point2S.PLUS_K, t.apply(Point2S.PLUS_K), TEST_EPS);
    168
    169         SphericalTestUtils.assertPointsEqual(b, t.apply(a), TEST_EPS);
    170         SphericalTestUtils.assertPointsEqual(a, t.apply(b), TEST_EPS);
    171
    172         SphericalTestUtils.assertPointsEqual(d, t.apply(c), TEST_EPS);
    173         SphericalTestUtils.assertPointsEqual(c, t.apply(d), TEST_EPS);
    174
    175         checkInverse(t);
    176     }
    177
    178     @Test
    179     void testDoubleReflection() {
    180         // arrange
    181         final Point2S a = Point2S.of(1, 1);
    182         final Point2S b = Point2S.of(-1, 1);
    183
    184         final Point2S c = Point2S.of(1, Math.PI - 1);
    185         final Point2S d = Point2S.of(-1, Math.PI - 1);
    186
    187         // act
    188         final Transform2S t = Transform2S.identity()
    189                 .reflect(Point2S.PLUS_I)
    190                 .reflect(Vector3D.Unit.PLUS_Y);
    191
    192         // assert
    193         Assertions.assertTrue(t.preservesOrientation());
    194
    195         SphericalTestUtils.assertPointsEqual(Point2S.MINUS_I, t.apply(Point2S.PLUS_I), TEST_EPS);
    196         SphericalTestUtils.assertPointsEqual(Point2S.MINUS_J, t.apply(Point2S.PLUS_J), TEST_EPS);
    197         SphericalTestUtils.assertPointsEq(Point2S.PLUS_K, t.apply(Point2S.PLUS_K), TEST_EPS);
    198
    199         SphericalTestUtils.assertPointsEqual(Point2S.of(Math.PI + 1, 1), t.apply(a), TEST_EPS);
    200         SphericalTestUtils.assertPointsEqual(Point2S.of(Math.PI - 1, 1), t.apply(b), TEST_EPS);
    201
    202         SphericalTestUtils.assertPointsEqual(Point2S.of(Math.PI + 1, Math.PI - 1), t.apply(c), TEST_EPS);
    203         SphericalTestUtils.assertPointsEqual(Point2S.of(Math.PI - 1,  Math.PI - 1), t.apply(d), TEST_EPS);
    204
    205         checkInverse(t);
    206     }
    207
    208     @Test
    209     void testHashcode() {
    210         // arrange
    211         final Transform2S a = Transform2S.createRotation(Point2S.PLUS_I, Angle.PI_OVER_TWO);
    212         final Transform2S b = Transform2S.createRotation(Point2S.PLUS_J, Angle.PI_OVER_TWO);
    213         final Transform2S c = Transform2S.createRotation(Point2S.PLUS_I, Math.PI);
    214         final Transform2S d = Transform2S.createRotation(Point2S.PLUS_I, Angle.PI_OVER_TWO);
    215
    216         // act
    217         final int hash = a.hashCode();
    218
    219         // assert
    220         Assertions.assertEquals(hash, a.hashCode());
    221
    222         Assertions.assertNotEquals(hash, b.hashCode());
    223         Assertions.assertNotEquals(hash, c.hashCode());
    224
    225         Assertions.assertEquals(hash, d.hashCode());
    226     }
    227
    228     @Test
    229     void testEquals() {
    230         // arrange
    231         final Transform2S a = Transform2S.createRotation(Point2S.PLUS_I, Angle.PI_OVER_TWO);
    232         final Transform2S b = Transform2S.createRotation(Point2S.PLUS_J, Angle.PI_OVER_TWO);
    233         final Transform2S c = Transform2S.createRotation(Point2S.PLUS_I, Math.PI);
    234         final Transform2S d = Transform2S.createRotation(Point2S.PLUS_I, Angle.PI_OVER_TWO);
    235
    236         // act/assert
    237         GeometryTestUtils.assertSimpleEqualsCases(a);
    238
    239         Assertions.assertNotEquals(a, b);
    240         Assertions.assertNotEquals(a, c);
    241
    242         Assertions.assertEquals(a, d);
    243         Assertions.assertEquals(d, a);
    244     }
    245
    246     @Test
    247     void testToString() {
    248         // arrange
    249         final Transform2S t = Transform2S.identity();
    250
    251         // act
    252         final String str = t.toString();
    253
    254         // assert
    255         GeometryTestUtils.assertContains("Transform2S", str);
    256         GeometryTestUtils.assertContains("euclideanTransform= [", str);
    257     }
    258
    259     private static void checkInverse(final Transform2S t) {
    260         final Transform2S inv = t.inverse();
    261
    262         // test non-pole points
    263         for (double az = -Angle.TWO_PI; az <= 2 * Angle.TWO_PI; az += 0.2) {
    264             for (double p = 0.1; p < Math.PI; p += 0.2) {
    265
    266                 final Point2S pt = Point2S.of(az, p);
    267
    268                 SphericalTestUtils.assertPointsEqual(pt, inv.apply(t.apply(pt)), TEST_EPS);
    269                 SphericalTestUtils.assertPointsEqual(pt, t.apply(inv.apply(pt)), TEST_EPS);
    270             }
    271         }
    272
    273         // test poles
    274         SphericalTestUtils.assertVectorsEqual(Vector3D.Unit.PLUS_Z,
    275                 inv.apply(t.apply(Point2S.of(1, 0))).getVector(), TEST_EPS);
    276         SphericalTestUtils.assertVectorsEqual(Vector3D.Unit.PLUS_Z,
    277                 t.apply(inv.apply(Point2S.of(-1, 0))).getVector(), TEST_EPS);
    278
    279         SphericalTestUtils.assertVectorsEqual(Vector3D.Unit.MINUS_Z,
    280                 inv.apply(t.apply(Point2S.of(1, Math.PI))).getVector(), TEST_EPS);
    281         SphericalTestUtils.assertVectorsEqual(Vector3D.Unit.MINUS_Z,
    282                 t.apply(inv.apply(Point2S.of(-1, Math.PI))).getVector(), TEST_EPS);
    283     }
    284 }