1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
42 final ObjTriangleMeshReader reader = reader("");
43
44
45 Assertions.assertFalse(reader.isFailOnNonPolygonKeywords());
46 }
47
48 @Test
49 void testClose() {
50
51 final CloseCountReader closeReader = new CloseCountReader(new StringReader(""));
52
53
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
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
75 final TriangleMesh mesh = reader.readTriangleMesh();
76
77
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
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
113 final TriangleMesh mesh = reader.readTriangleMesh();
114
115
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
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
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 }