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.obj;
    18
    19  import java.io.StringReader;
    20  import java.util.Arrays;
    21  import java.util.regex.Pattern;
    22
    23  import org.apache.commons.geometry.core.GeometryTestUtils;
    24  import org.apache.commons.geometry.euclidean.EuclideanTestUtils;
    25  import org.apache.commons.geometry.euclidean.threed.Vector3D;
    26  import org.apache.commons.geometry.euclidean.threed.mesh.TriangleMesh;
    27  import org.apache.commons.geometry.io.core.test.CloseCountReader;
    28  import org.apache.commons.numbers.core.Precision;
    29  import org.junit.jupiter.api.Assertions;
    30  import org.junit.jupiter.api.Test;
    31
    32  class ObjTriangleMeshReaderTest {
    33
    34      private static final double TEST_EPS = 1e-10;
    35
    36      private static final Precision.DoubleEquivalence TEST_PRECISION =
    37              Precision.doubleEquivalenceOfEpsilon(TEST_EPS);
    38
    39      @Test
    40      void testDefaults() {
    41          // arrange
    42          final ObjTriangleMeshReader reader = reader("");
    43
    44          // act/assert
    45          Assertions.assertFalse(reader.isFailOnNonPolygonKeywords());
    46      }
    47
    48      @Test
    49      void testClose() {
    50          // arrange
    51          final CloseCountReader closeReader = new CloseCountReader(new StringReader(""));
    52
    53          // act/assert
    54          try (ObjTriangleMeshReader reader = new ObjTriangleMeshReader(closeReader, TEST_PRECISION)) {
    55              Assertions.assertEquals(0, closeReader.getCloseCount());
    56          }
    57
    58          Assertions.assertEquals(1, closeReader.getCloseCount());
    59      }
    60
    61      @Test
    62      void testReadTriangleMesh_withNormal() {
    63          // arrange
    64          final ObjTriangleMeshReader reader = reader(
    65                  "o test\n\n" +
    66                  "v 0 0 0\r\n" +
    67                  "v 0.5 0 0\n" +
    68                  "v 1 1 0\r" +
    69                  "v 0 1 0\n" +
    70                  "vn 0 0 -1\n" +
    71                  "f 1//1 2//1 3//1 4//1\n" +
    72                  "curv non-polygon data\n");
    73
    74          // act
    75          final TriangleMesh mesh = reader.readTriangleMesh();
    76
    77          // assert
    78          Assertions.assertEquals(4, mesh.getVertexCount());
    79          Assertions.assertEquals(2, mesh.getFaceCount());
    80
    81          final TriangleMesh.Face face1 = mesh.getFace(0);
    82
    83          EuclideanTestUtils.assertVertexLoopSequence(Arrays.asList(
    84                  Vector3D.of(0.5, 0, 0), Vector3D.of(0, 1, 0), Vector3D.of(1, 1, 0)
    85              ), face1.getVertices(), TEST_PRECISION);
    86
    87          EuclideanTestUtils.assertCoordinatesEqual(Vector3D.Unit.MINUS_Z,
    88                  face1.getPolygon().getPlane().getNormal(), TEST_EPS);
    89
    90          final TriangleMesh.Face face2 = mesh.getFace(1);
    91
    92          EuclideanTestUtils.assertVertexLoopSequence(Arrays.asList(
    93                  Vector3D.ZERO, Vector3D.of(0, 1, 0), Vector3D.of(0.5, 0, 0)
    94              ), face2.getVertices(), TEST_PRECISION);
    95
    96          EuclideanTestUtils.assertCoordinatesEqual(Vector3D.Unit.MINUS_Z,
    97                  face2.getPolygon().getPlane().getNormal(), TEST_EPS);
    98      }
    99
    100     @Test
    101     void testReadTriangleMesh_withoutNormal() {
    102         // arrange
    103         final ObjTriangleMeshReader reader = reader(
    104                 "o test\n\n" +
    105                 "v -1 0 0\n" +
    106                 "v 0 0 0\r\n" +
    107                 "v 1 0 0\n" +
    108                 "v 1 1 0\r" +
    109                 "v -2 0 0\n" +
    110                 "f 2 3 4\n");
    111
    112         // act
    113         final TriangleMesh mesh = reader.readTriangleMesh();
    114
    115         // assert
    116         Assertions.assertEquals(5, mesh.getVertexCount());
    117         Assertions.assertEquals(1, mesh.getFaceCount());
    118
    119         final TriangleMesh.Face face = mesh.getFace(0);
    120
    121         EuclideanTestUtils.assertVertexLoopSequence(Arrays.asList(
    122                     Vector3D.ZERO, Vector3D.of(1, 0, 0), Vector3D.of(1, 1, 0)
    123                 ), face.getVertices(), TEST_PRECISION);
    124
    125         EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(0, 0, 1),
    126                 face.getPolygon().getPlane().getNormal(), TEST_EPS);
    127     }
    128
    129     @Test
    130     void testReadTriangleMesh_failOnNonPolygon() {
    131         // arrange
    132         final ObjTriangleMeshReader reader = reader(
    133                 "o test\n\n" +
    134                 "v 0 0 0\r\n" +
    135                 "v 1 0 0\n" +
    136                 "v 1 1 0\r" +
    137                 "v 0 1 0\n" +
    138                 "vn 0 0 1\n" +
    139                 "f 1//1 2//1 3//1\n" +
    140                 "curv non-polygon data\n");
    141
    142         reader.setFailOnNonPolygonKeywords(true);
    143
    144         // act/assert
    145         GeometryTestUtils.assertThrowsWithMessage(
    146                 () -> reader.readTriangleMesh(),
    147                 IllegalStateException.class, Pattern.compile("^Parsing failed.*"));
    148     }
    149
    150     private static ObjTriangleMeshReader reader(final String str) {
    151         return new ObjTriangleMeshReader(new StringReader(str), TEST_PRECISION);
    152     }
    153 }