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 java.util.Arrays;
    20  import java.util.Collections;
    21  import java.util.List;
    22
    23  import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
    24  import org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext;
    25  import org.apache.commons.geometry.euclidean.threed.Vector3D;
    26  import org.apache.commons.geometry.spherical.SphericalTestUtils;
    27  import org.apache.commons.numbers.angle.PlaneAngleRadians;
    28  import org.junit.Assert;
    29  import org.junit.Test;
    30
    31  public class AbstractGreatArcPathConnectorTest {
    32
    33      private static final double TEST_EPS = 1e-10;
    34
    35      private static final DoublePrecisionContext TEST_PRECISION =
    36              new EpsilonDoublePrecisionContext(TEST_EPS);
    37
    38      private static final GreatCircle XY_PLANE = GreatCircles.fromPoleAndU(
    39              Vector3D.Unit.PLUS_Z, Vector3D.Unit.PLUS_X, TEST_PRECISION);
    40
    41      private static final GreatCircle XZ_PLANE = GreatCircles.fromPoleAndU(
    42              Vector3D.Unit.PLUS_Y, Vector3D.Unit.PLUS_X, TEST_PRECISION);
    43
    44      private final TestConnector connector = new TestConnector();
    45
    46      @Test
    47      public void testConnectAll_emptyCollection() {
    48          // act
    49          final List<GreatArcPath> paths = connector.connectAll(Collections.emptyList());
    50
    51          // assert
    52          Assert.assertEquals(0, paths.size());
    53      }
    54
    55      @Test
    56      public void testConnectAll_singleFullArc() {
    57          // act
    58          connector.add(Collections.singletonList(XY_PLANE.span()));
    59          final List<GreatArcPath> paths = connector.connectAll();
    60
    61          // assert
    62          Assert.assertEquals(1, paths.size());
    63
    64          final GreatArcPath a = paths.get(0);
    65          Assert.assertEquals(1, a.getArcs().size());
    66          Assert.assertSame(XY_PLANE, a.getStartArc().getCircle());
    67      }
    68
    69      @Test
    70      public void testConnectAll_twoFullArcs() {
    71          // act
    72          connector.add(XZ_PLANE.span());
    73          final List<GreatArcPath> paths = connector.connectAll(Collections.singletonList(XY_PLANE.span()));
    74
    75          // assert
    76          Assert.assertEquals(2, paths.size());
    77
    78          final GreatArcPath a = paths.get(0);
    79          Assert.assertEquals(1, a.getArcs().size());
    80          Assert.assertSame(XY_PLANE, a.getStartArc().getCircle());
    81
    82          final GreatArcPath b = paths.get(1);
    83          Assert.assertEquals(1, b.getArcs().size());
    84          Assert.assertSame(XZ_PLANE, b.getStartArc().getCircle());
    85      }
    86
    87      @Test
    88      public void testConnectAll_singleLune() {
    89          // arrange
    90          final GreatCircle upperBound = GreatCircles.fromPoleAndU(
    91                  Vector3D.of(0, 1, -1), Vector3D.Unit.PLUS_X, TEST_PRECISION);
    92
    93          connector.add(XY_PLANE.arc(0, PlaneAngleRadians.PI));
    94          connector.add(upperBound.arc(PlaneAngleRadians.PI, 0));
    95
    96          // act
    97          final List<GreatArcPath> paths = connector.connectAll();
    98
    99          // assert
    100         Assert.assertEquals(1, paths.size());
    101
    102         final GreatArcPath a = paths.get(0);
    103         Assert.assertEquals(2, a.getArcs().size());
    104         Assert.assertSame(XY_PLANE, a.getStartArc().getCircle());
    105         Assert.assertSame(upperBound, a.getEndArc().getCircle());
    106     }
    107
    108     @Test
    109     public void testConnectAll_singleLune_pathsNotOrientedCorrectly() {
    110         // arrange
    111         final GreatCircle upperBound = GreatCircles.fromPoleAndU(
    112                 Vector3D.of(0, 1, -1), Vector3D.Unit.PLUS_X, TEST_PRECISION);
    113
    114         connector.add(XY_PLANE.arc(0, PlaneAngleRadians.PI));
    115         connector.add(upperBound.arc(0, PlaneAngleRadians.PI));
    116
    117         // act
    118         final List<GreatArcPath> paths = connector.connectAll();
    119
    120         // assert
    121         Assert.assertEquals(2, paths.size());
    122
    123         final GreatArcPath a = paths.get(0);
    124         Assert.assertEquals(1, a.getArcs().size());
    125         Assert.assertSame(XY_PLANE, a.getStartArc().getCircle());
    126
    127         final GreatArcPath b = paths.get(1);
    128         Assert.assertEquals(1, b.getArcs().size());
    129         Assert.assertSame(upperBound, b.getStartArc().getCircle());
    130     }
    131
    132     @Test
    133     public void testConnectAll_largeTriangle() {
    134         // arrange
    135         final Point2S p1 = Point2S.PLUS_I;
    136         final Point2S p2 = Point2S.PLUS_J;
    137         final Point2S p3 = Point2S.PLUS_K;
    138
    139         // act
    140         final List<GreatArcPath> paths = connector.connectAll(Arrays.asList(
    141                     GreatCircles.arcFromPoints(p1, p2, TEST_PRECISION),
    142                     GreatCircles.arcFromPoints(p2, p3, TEST_PRECISION),
    143                     GreatCircles.arcFromPoints(p3, p1, TEST_PRECISION)
    144                 ));
    145
    146         // assert
    147         Assert.assertEquals(1, paths.size());
    148
    149         final GreatArcPath a = paths.get(0);
    150         Assert.assertEquals(3, a.getArcs().size());
    151
    152         assertPathPoints(a, p3, p1, p2, p3);
    153     }
    154
    155     @Test
    156     public void testConnectAll_smallTriangleWithDisconnectedLuneAndArc() {
    157         // arrange
    158         final Point2S p1 = Point2S.of(0, 0);
    159         final Point2S p2 = Point2S.of(0, 0.1 * PlaneAngleRadians.PI);
    160         final Point2S p3 = Point2S.of(0.1, 0.1 * PlaneAngleRadians.PI);
    161
    162         final GreatArc luneEdge1 = GreatCircles.fromPoints(
    163                     Point2S.PLUS_J,
    164                     Point2S.MINUS_I,
    165                     TEST_PRECISION)
    166                 .arc(0, PlaneAngleRadians.PI);
    167         final GreatArc luneEdge2 = GreatCircles.fromPoints(
    168                     Point2S.MINUS_J,
    169                     Point2S.of(PlaneAngleRadians.PI_OVER_TWO, 0.4 * PlaneAngleRadians.PI),
    170                     TEST_PRECISION)
    171                 .arc(0, PlaneAngleRadians.PI);
    172
    173         final GreatArc separateArc = GreatCircles.arcFromPoints(
    174                 Point2S.of(-PlaneAngleRadians.PI_OVER_TWO, 0.7 * PlaneAngleRadians.PI),
    175                 Point2S.of(-PlaneAngleRadians.PI_OVER_TWO, 0.8 * PlaneAngleRadians.PI),
    176                 TEST_PRECISION);
    177
    178         // act
    179         final List<GreatArcPath> paths = connector.connectAll(Arrays.asList(
    180                     luneEdge1,
    181                     GreatCircles.arcFromPoints(p2, p3, TEST_PRECISION),
    182                     separateArc,
    183                     GreatCircles.arcFromPoints(p1, p2, TEST_PRECISION),
    184                     GreatCircles.arcFromPoints(p3, p1, TEST_PRECISION),
    185                     luneEdge2
    186                 ));
    187
    188         // assert
    189         Assert.assertEquals(3, paths.size());
    190
    191         final GreatArcPath triangle = paths.get(0);
    192         Assert.assertEquals(3, triangle.getArcs().size());
    193         assertPathPoints(triangle, p1, p2, p3, p1);
    194
    195         final GreatArcPath lune = paths.get(1);
    196         Assert.assertEquals(2, lune.getArcs().size());
    197         Assert.assertSame(luneEdge1, lune.getStartArc());
    198         Assert.assertSame(luneEdge2, lune.getEndArc());
    199
    200         final GreatArcPath separate = paths.get(2);
    201         Assert.assertEquals(1, separate.getArcs().size());
    202         Assert.assertSame(separateArc, separate.getStartArc());
    203     }
    204
    205     @Test
    206     public void testConnectAll_choosesBestPointLikeConnection() {
    207         // arrange
    208         final DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-1);
    209
    210         final Point2S p1 = Point2S.PLUS_I;
    211         final Point2S p2 = Point2S.of(1, PlaneAngleRadians.PI_OVER_TWO);
    212         final Point2S p3 = Point2S.of(1.001, 0.491 * PlaneAngleRadians.PI);
    213         final Point2S p4 = Point2S.of(1.001, 0.502 * PlaneAngleRadians.PI);
    214
    215         connector.add(GreatCircles.arcFromPoints(p2, p3, TEST_PRECISION));
    216         connector.add(GreatCircles.arcFromPoints(p2, p4, TEST_PRECISION));
    217         connector.add(GreatCircles.arcFromPoints(p1, p2, precision));
    218
    219         // act
    220         final List<GreatArcPath> paths = connector.connectAll();
    221
    222         // assert
    223         Assert.assertEquals(2, paths.size());
    224
    225         final GreatArcPath a = paths.get(0);
    226         Assert.assertEquals(2, a.getArcs().size());
    227         assertPathPoints(a, p1, p2, p4);
    228
    229         final GreatArcPath b = paths.get(1);
    230         Assert.assertEquals(1, b.getArcs().size());
    231         assertPathPoints(b, p2, p3);
    232     }
    233
    234     @Test
    235     public void testConnect() {
    236         // arrange
    237         final GreatArc arcA = GreatCircles.arcFromPoints(Point2S.PLUS_I, Point2S.PLUS_J, TEST_PRECISION);
    238         final GreatArc arcB = GreatCircles.arcFromPoints(Point2S.PLUS_J, Point2S.MINUS_I, TEST_PRECISION);
    239         final GreatArc arcC = GreatCircles.arcFromPoints(Point2S.PLUS_J, Point2S.PLUS_K, TEST_PRECISION);
    240
    241         // act
    242         connector.connect(Arrays.asList(
    243                     arcB,
    244                     arcA
    245                 ));
    246
    247         connector.connect(Collections.singletonList(arcC));
    248
    249         final List<GreatArcPath> paths = connector.connectAll();
    250
    251         // assert
    252         Assert.assertEquals(2, paths.size());
    253
    254         final GreatArcPath a = paths.get(0);
    255         Assert.assertEquals(2, a.getArcs().size());
    256         assertPathPoints(a, Point2S.PLUS_I, Point2S.PLUS_J, Point2S.MINUS_I);
    257
    258         final GreatArcPath b = paths.get(1);
    259         Assert.assertEquals(1, b.getArcs().size());
    260         assertPathPoints(b, Point2S.PLUS_J, Point2S.PLUS_K);
    261     }
    262
    263     @Test
    264     public void testConnectorCanBeReused() {
    265         // arrange
    266         final GreatArc a = GreatCircles.arcFromPoints(Point2S.PLUS_I, Point2S.PLUS_J, TEST_PRECISION);
    267         final GreatArc b = GreatCircles.arcFromPoints(Point2S.MINUS_I, Point2S.MINUS_J, TEST_PRECISION);
    268
    269         // act
    270         final List<GreatArcPath> path1 = connector.connectAll(Collections.singletonList(a));
    271         final List<GreatArcPath> path2 = connector.connectAll(Collections.singletonList(b));
    272
    273         // assert
    274         Assert.assertEquals(1, path1.size());
    275         assertPathPoints(path1.get(0), Point2S.PLUS_I, Point2S.PLUS_J);
    276
    277         Assert.assertEquals(1, path2.size());
    278         assertPathPoints(path2.get(0), Point2S.MINUS_I, Point2S.MINUS_J);
    279     }
    280
    281     private static void assertPathPoints(final GreatArcPath path, final Point2S... points) {
    282         final List<Point2S> expectedPoints = Arrays.asList(points);
    283         final List<Point2S> actualPoints = path.getVertices();
    284
    285         final String msg = "Expected path points to equal " + expectedPoints + " but was " + actualPoints;
    286         Assert.assertEquals(msg, expectedPoints.size(), actualPoints.size());
    287
    288         for (int i = 0; i < expectedPoints.size(); ++i) {
    289             SphericalTestUtils.assertPointsEq(expectedPoints.get(i), actualPoints.get(i), TEST_EPS);
    290         }
    291     }
    292
    293     private static class TestConnector extends AbstractGreatArcConnector {
    294
    295         @Override
    296         protected ConnectableGreatArc selectConnection(final ConnectableGreatArc incoming,
    297                                                        final List<ConnectableGreatArc> outgoing) {
    298
    299             // just choose the first element
    300             return outgoing.get(0);
    301         }
    302     }
    303 }