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.io.euclidean.threed;
    18
    19  import java.io.ByteArrayInputStream;
    20  import java.util.Arrays;
    21  import java.util.Collection;
    22  import java.util.Iterator;
    23  import java.util.List;
    24  import java.util.NoSuchElementException;
    25  import java.util.stream.Collectors;
    26  import java.util.stream.Stream;
    27
    28  import org.apache.commons.geometry.core.GeometryTestUtils;
    29  import org.apache.commons.geometry.euclidean.threed.BoundaryList3D;
    30  import org.apache.commons.geometry.euclidean.threed.BoundarySource3D;
    31  import org.apache.commons.geometry.euclidean.threed.PlaneConvexSubset;
    32  import org.apache.commons.geometry.euclidean.threed.Vector3D;
    33  import org.apache.commons.geometry.euclidean.threed.mesh.SimpleTriangleMesh;
    34  import org.apache.commons.geometry.euclidean.threed.mesh.TriangleMesh;
    35  import org.apache.commons.geometry.io.core.GeometryFormat;
    36  import org.apache.commons.geometry.io.core.input.GeometryInput;
    37  import org.apache.commons.geometry.io.core.input.StreamGeometryInput;
    38  import org.apache.commons.geometry.io.core.test.CloseCountInputStream;
    39  import org.apache.commons.geometry.io.euclidean.threed.AbstractBoundaryReadHandler3D.FacetDefinitionReaderIterator;
    40  import org.apache.commons.numbers.core.Precision;
    41  import org.junit.jupiter.api.Assertions;
    42  import org.junit.jupiter.api.Test;
    43
    44  class AbstractBoundaryReadHandler3DTest {
    45
    46      private static final double TEST_EPS = 1e-10;
    47
    48      private static final Precision.DoubleEquivalence TEST_PRECISION = Precision.doubleEquivalenceOfEpsilon(TEST_EPS);
    49
    50      private static final FacetDefinition FACET_1 = new SimpleFacetDefinition(Arrays.asList(
    51              Vector3D.ZERO, Vector3D.of(1, 0, 0), Vector3D.of(1, 1, 0), Vector3D.of(0, 1, 0)));
    52
    53      private static final FacetDefinition FACET_2 = new SimpleFacetDefinition(Arrays.asList(
    54              Vector3D.ZERO, Vector3D.of(0, 1, 0), Vector3D.of(-1, 1, 0), Vector3D.of(-1, 0, 0)));
    55
    56      @Test
    57      void testRead() {
    58          // arrange
    59          final List<FacetDefinition> facets = Arrays.asList(FACET_1, FACET_2);
    60          final TestReadHandler3D handler = new TestReadHandler3D(facets);
    61
    62          final GeometryInput in = new StreamGeometryInput(new ByteArrayInputStream(new byte[0]));
    63
    64          // act
    65          final BoundarySource3D result = handler.read(in, TEST_PRECISION);
    66
    67          // assert
    68          Assertions.assertSame(in, handler.inArg);
    69
    70          Assertions.assertEquals(BoundaryList3D.class, result.getClass());
    71          Assertions.assertEquals(2, result.toList().getBoundaries().size());
    72      }
    73
    74      @Test
    75      void testReadTriangleMesh() {
    76          // arrange
    77          final List<FacetDefinition> facets = Arrays.asList(FACET_1, FACET_2);
    78          final TestReadHandler3D handler = new TestReadHandler3D(facets);
    79
    80          final GeometryInput in = new StreamGeometryInput(new ByteArrayInputStream(new byte[0]));
    81
    82          // act
    83          final TriangleMesh result = handler.readTriangleMesh(in, TEST_PRECISION);
    84
    85          // assert
    86          Assertions.assertSame(in, handler.inArg);
    87
    88          Assertions.assertEquals(SimpleTriangleMesh.class, result.getClass());
    89          Assertions.assertEquals(6, result.getVertexCount());
    90          Assertions.assertEquals(4, result.getFaceCount());
    91      }
    92
    93      @Test
    94      void testBoundaries() {
    95          // arrange
    96          final List<FacetDefinition> facets = Arrays.asList(FACET_1, FACET_2);
    97          final TestReadHandler3D handler = new TestReadHandler3D(facets);
    98
    99          final CloseCountInputStream inputStream = new CloseCountInputStream(new ByteArrayInputStream(new byte[0]));
    100         final GeometryInput in = new StreamGeometryInput(inputStream);
    101
    102         // act
    103         final List<PlaneConvexSubset> list;
    104         try (Stream<PlaneConvexSubset> stream = handler.boundaries(in, TEST_PRECISION)) {
    105             list = stream.collect(Collectors.toList());
    106
    107             Assertions.assertEquals(0, inputStream.getCloseCount());
    108         }
    109
    110         // assert
    111         Assertions.assertSame(in, handler.inArg);
    112
    113         Assertions.assertEquals(2, list.size());
    114         Assertions.assertEquals(1, inputStream.getCloseCount());
    115     }
    116
    117     @Test
    118     void testFacets() {
    119         // arrange
    120         final List<FacetDefinition> facets = Arrays.asList(FACET_1, FACET_2);
    121         final TestReadHandler3D handler = new TestReadHandler3D(facets);
    122
    123         final CloseCountInputStream inputStream = new CloseCountInputStream(new ByteArrayInputStream(new byte[0]));
    124         final GeometryInput in = new StreamGeometryInput(inputStream);
    125
    126         // act
    127         final List<FacetDefinition> list;
    128         try (Stream<FacetDefinition> stream = handler.facets(in)) {
    129             list = stream.collect(Collectors.toList());
    130
    131             Assertions.assertEquals(0, inputStream.getCloseCount());
    132         }
    133
    134         // assert
    135         Assertions.assertSame(in, handler.inArg);
    136
    137         Assertions.assertEquals(2, list.size());
    138         Assertions.assertEquals(1, inputStream.getCloseCount());
    139     }
    140
    141     @Test
    142     void testFacetIterator() {
    143         // arrange
    144         final StubFacetDefinitionReader reader = new StubFacetDefinitionReader(Arrays.asList(FACET_1, FACET_2));
    145         final FacetDefinitionReaderIterator it = new FacetDefinitionReaderIterator(reader);
    146
    147         // act/assert
    148         Assertions.assertTrue(it.hasNext());
    149         Assertions.assertSame(FACET_1, it.next());
    150
    151         Assertions.assertTrue(it.hasNext());
    152         Assertions.assertSame(FACET_2, it.next());
    153
    154         Assertions.assertFalse(it.hasNext());
    155         Assertions.assertThrows(NoSuchElementException.class, it::next);
    156     }
    157
    158     @Test
    159     void testFacetIterator_readFails() {
    160         // arrange
    161         final StubFacetDefinitionReader reader = new StubFacetDefinitionReader(Arrays.asList(FACET_1, FACET_2));
    162         reader.fail = true;
    163
    164         final FacetDefinitionReaderIterator it = new FacetDefinitionReaderIterator(reader);
    165
    166         // act/assert
    167         GeometryTestUtils.assertThrowsWithMessage(it::next, IllegalStateException.class, "Read failure");
    168     }
    169
    170     private static final class TestReadHandler3D extends AbstractBoundaryReadHandler3D {
    171
    172         private final Collection<FacetDefinition> facets;
    173
    174         private GeometryInput inArg;
    175
    176         TestReadHandler3D(final Collection<FacetDefinition> facets) {
    177             this.facets = facets;
    178         }
    179
    180         /** {@inheritDoc} */
    181         @Override
    182         public GeometryFormat getFormat() {
    183             throw new UnsupportedOperationException();
    184         }
    185
    186         /** {@inheritDoc} */
    187         @Override
    188         public FacetDefinitionReader facetDefinitionReader(final GeometryInput in) {
    189             this.inArg = in;
    190
    191             return new StubFacetDefinitionReader(facets);
    192         }
    193     }
    194
    195     private static final class StubFacetDefinitionReader implements FacetDefinitionReader {
    196
    197         private final Iterator<FacetDefinition> iterator;
    198
    199         private boolean fail = false;
    200
    201         StubFacetDefinitionReader(final Collection<FacetDefinition> facets) {
    202             this.iterator = facets.iterator();
    203         }
    204
    205         /** {@inheritDoc} */
    206         @Override
    207         public FacetDefinition readFacet() {
    208             if (fail) {
    209                 throw new IllegalStateException("Read failure");
    210             }
    211
    212             return iterator.hasNext() ?
    213                 iterator.next() :
    214                 null;
    215         }
    216
    217         /** {@inheritDoc} */
    218         @Override
    219         public void close() {
    220             // do nothing
    221         }
    222     }
    223 }