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.precision.DoublePrecisionContext;
    20  import org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext;
    21  import org.apache.commons.geometry.euclidean.twod.shape.Parallelogram;
    22  import org.junit.Test;
    23
    24  public class BoundarySourceLinecaster2DTest {
    25
    26      private static final double TEST_EPS = 1e-10;
    27
    28      private static final DoublePrecisionContext TEST_PRECISION =
    29              new EpsilonDoublePrecisionContext(TEST_EPS);
    30
    31      private static final BoundarySource2D UNIT_SQUARE =
    32              Parallelogram.axisAligned(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION);
    33
    34      @Test
    35      public void testLinecast_line_simple() {
    36          // arrange
    37          final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(UNIT_SQUARE);
    38
    39          // act/assert
    40
    41          // no intersections
    42          LinecastChecker2D.with(linecaster)
    43              .expectNothing()
    44              .whenGiven(Lines.fromPointAndDirection(Vector2D.of(0, 4), Vector2D.Unit.MINUS_X, TEST_PRECISION));
    45
    46          // through center; two directions
    47          LinecastChecker2D.with(linecaster)
    48              .expect(Vector2D.of(0, 0.5), Vector2D.Unit.MINUS_X)
    49              .and(Vector2D.of(1, 0.5), Vector2D.Unit.PLUS_X)
    50              .whenGiven(Lines.fromPointAndDirection(Vector2D.of(0.5, 0.5), Vector2D.Unit.PLUS_X, TEST_PRECISION));
    51
    52          LinecastChecker2D.with(linecaster)
    53              .expect(Vector2D.of(1, 0.5), Vector2D.Unit.PLUS_X)
    54              .and(Vector2D.of(0, 0.5), Vector2D.Unit.MINUS_X)
    55              .whenGiven(Lines.fromPointAndDirection(Vector2D.of(0.5, 0.5), Vector2D.Unit.MINUS_X, TEST_PRECISION));
    56      }
    57
    58      @Test
    59      public void testLinecast_line_alongFace() {
    60          // arrange
    61          final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(UNIT_SQUARE);
    62
    63          // act/assert
    64          LinecastChecker2D.with(linecaster)
    65              .expect(Vector2D.of(0, 1), Vector2D.Unit.MINUS_X)
    66              .and(Vector2D.of(1, 1), Vector2D.Unit.PLUS_X)
    67              .whenGiven(Lines.fromPointAndDirection(Vector2D.of(0, 1), Vector2D.Unit.PLUS_X, TEST_PRECISION));
    68      }
    69
    70      @Test
    71      public void testLinecast_line_corners() {
    72          // arrange
    73          final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(UNIT_SQUARE);
    74
    75          // act/assert
    76
    77          // through single corner vertex
    78          LinecastChecker2D.with(linecaster)
    79              .expect(Vector2D.of(1, 1), Vector2D.Unit.PLUS_Y)
    80              .and(Vector2D.of(1, 1), Vector2D.Unit.PLUS_X)
    81              .whenGiven(Lines.fromPointAndDirection(Vector2D.of(0, 2), Vector2D.of(1, -1), TEST_PRECISION));
    82
    83          // through two corner vertices
    84          LinecastChecker2D.with(linecaster)
    85              .expect(Vector2D.ZERO, Vector2D.Unit.MINUS_X)
    86              .and(Vector2D.ZERO, Vector2D.Unit.MINUS_Y)
    87              .and(Vector2D.of(1, 1), Vector2D.Unit.PLUS_Y)
    88              .and(Vector2D.of(1, 1), Vector2D.Unit.PLUS_X)
    89              .whenGiven(Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION));
    90      }
    91
    92      @Test
    93      public void testLinecast_line_removesDuplicatePoints() {
    94          // arrange
    95          final BoundarySource2D src = BoundarySource2D.from(
    96                      Lines.segmentFromPoints(Vector2D.of(-1, -1), Vector2D.ZERO, TEST_PRECISION),
    97                      Lines.segmentFromPoints(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION)
    98                  );
    99          final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(src);
    100
    101         // act/assert
    102         LinecastChecker2D.with(linecaster)
    103             .expect(Vector2D.ZERO, Vector2D.Unit.from(1, -1))
    104             .whenGiven(Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.Unit.PLUS_X, TEST_PRECISION));
    105     }
    106
    107     @Test
    108     public void testLinecast_segment_simple() {
    109         // arrange
    110         final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(UNIT_SQUARE);
    111
    112         // act/assert
    113
    114         // no intersections; underlying line does not intersect
    115         LinecastChecker2D.with(linecaster)
    116             .expectNothing()
    117             .whenGiven(Lines.fromPointAndDirection(Vector2D.of(0, 4), Vector2D.Unit.MINUS_X, TEST_PRECISION)
    118                     .segment(-10, 10));
    119
    120         // no intersections; underlying line does intersect
    121         LinecastChecker2D.with(linecaster)
    122             .expectNothing()
    123             .whenGiven(Lines.fromPointAndDirection(Vector2D.of(0.5, 0.5), Vector2D.Unit.PLUS_X, TEST_PRECISION)
    124                     .segment(2, 10));
    125
    126         // no boundaries excluded; two directions
    127         LinecastChecker2D.with(linecaster)
    128             .expect(Vector2D.of(0, 0.5), Vector2D.Unit.MINUS_X)
    129             .and(Vector2D.of(1, 0.5), Vector2D.Unit.PLUS_X)
    130             .whenGiven(Lines.fromPointAndDirection(Vector2D.of(0.5, 0.5), Vector2D.Unit.PLUS_X, TEST_PRECISION)
    131                     .segment(-10, 10));
    132
    133         LinecastChecker2D.with(linecaster)
    134             .expect(Vector2D.of(1, 0.5), Vector2D.Unit.PLUS_X)
    135             .and(Vector2D.of(0, 0.5), Vector2D.Unit.MINUS_X)
    136             .whenGiven(Lines.fromPointAndDirection(Vector2D.of(0.5, 0.5), Vector2D.Unit.MINUS_X, TEST_PRECISION)
    137                     .segment(-10, 10));
    138     }
    139
    140     @Test
    141     public void testLinecast_segment_boundaryExcluded() {
    142         // arrange
    143         final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(UNIT_SQUARE);
    144
    145         // act/assert
    146         final Vector2D center = Vector2D.of(0.5, 0.5);
    147         LinecastChecker2D.with(linecaster)
    148             .expect(Vector2D.of(1, 0.5), Vector2D.Unit.PLUS_X)
    149             .whenGiven(Lines.fromPointAndDirection(center, Vector2D.Unit.PLUS_X, TEST_PRECISION)
    150                     .rayFrom(center));
    151
    152         LinecastChecker2D.with(linecaster)
    153             .expect(Vector2D.of(1, 0.5), Vector2D.Unit.PLUS_X)
    154             .whenGiven(Lines.fromPointAndDirection(center, Vector2D.Unit.MINUS_X, TEST_PRECISION)
    155                     .reverseRayTo(center));
    156     }
    157
    158     @Test
    159     public void testLinecast_segment_startEndPointsOnBoundaries() {
    160         // arrange
    161         final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(UNIT_SQUARE);
    162
    163         // act/assert
    164         LinecastChecker2D.with(linecaster)
    165             .expect(Vector2D.of(1, 0.5), Vector2D.Unit.PLUS_X)
    166             .and(Vector2D.of(0, 0.5), Vector2D.Unit.MINUS_X)
    167             .whenGiven(Lines.segmentFromPoints(Vector2D.of(1, 0.5), Vector2D.of(0, 0.5), TEST_PRECISION));
    168     }
    169
    170     @Test
    171     public void testLinecast_segment_alongFace() {
    172         // arrange
    173         final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(UNIT_SQUARE);
    174
    175         // act/assert
    176
    177         // includes two intersecting boundaries
    178         LinecastChecker2D.with(linecaster)
    179             .expect(Vector2D.of(0, 1), Vector2D.Unit.MINUS_X)
    180             .and(Vector2D.of(1, 1), Vector2D.Unit.PLUS_X)
    181             .whenGiven(Lines.segmentFromPoints(Vector2D.of(-1, 1), Vector2D.of(2, 1), TEST_PRECISION));
    182
    183         // one intersecting boundary
    184         LinecastChecker2D.with(linecaster)
    185             .expect(Vector2D.of(1, 1), Vector2D.Unit.PLUS_X)
    186             .whenGiven(Lines.segmentFromPoints(Vector2D.of(0.25, 1), Vector2D.of(2, 1), TEST_PRECISION));
    187
    188         // no intersecting boundary
    189         LinecastChecker2D.with(linecaster)
    190             .expectNothing()
    191             .whenGiven(Lines.segmentFromPoints(Vector2D.of(0.25, 1), Vector2D.of(0.75, 1), TEST_PRECISION));
    192     }
    193
    194     @Test
    195     public void testLinecast_segment_corners() {
    196         // arrange
    197         final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(UNIT_SQUARE);
    198
    199         // act/assert
    200
    201         // through corner
    202         LinecastChecker2D.with(linecaster)
    203             .expect(Vector2D.of(1, 1), Vector2D.Unit.PLUS_Y)
    204             .and(Vector2D.of(1, 1), Vector2D.Unit.PLUS_X)
    205             .whenGiven(Lines.segmentFromPoints(Vector2D.of(0, 2), Vector2D.of(2, 0), TEST_PRECISION));
    206
    207         // starts on corner
    208         LinecastChecker2D.with(linecaster)
    209             .expect(Vector2D.of(1, 1), Vector2D.Unit.PLUS_Y)
    210             .and(Vector2D.of(1, 1), Vector2D.Unit.PLUS_X)
    211             .whenGiven(Lines.segmentFromPoints(Vector2D.of(1, 1), Vector2D.of(2, 0), TEST_PRECISION));
    212
    213         // ends on corner
    214         LinecastChecker2D.with(linecaster)
    215             .expect(Vector2D.of(1, 1), Vector2D.Unit.PLUS_Y)
    216             .and(Vector2D.of(1, 1), Vector2D.Unit.PLUS_X)
    217             .whenGiven(Lines.segmentFromPoints(Vector2D.of(0, 2), Vector2D.of(1, 1), TEST_PRECISION));
    218     }
    219
    220     @Test
    221     public void testLinecast_segment_removesDuplicatePoints() {
    222         // arrange
    223         final BoundarySource2D src = BoundarySource2D.from(
    224                     Lines.segmentFromPoints(Vector2D.of(-1, -1), Vector2D.ZERO, TEST_PRECISION),
    225                     Lines.segmentFromPoints(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION)
    226                 );
    227         final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(src);
    228
    229         // act/assert
    230         LinecastChecker2D.with(linecaster)
    231             .expect(Vector2D.ZERO, Vector2D.Unit.from(1, -1))
    232             .whenGiven(Lines.segmentFromPoints(Vector2D.ZERO, Vector2D.Unit.PLUS_X, TEST_PRECISION));
    233     }
    234 }
    235