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.ByteArrayOutputStream;
20 import java.nio.charset.StandardCharsets;
21 import java.text.DecimalFormat;
22 import java.text.DecimalFormatSymbols;
23 import java.util.Arrays;
24 import java.util.List;
25 import java.util.Locale;
26 import java.util.stream.Collectors;
27
28 import org.apache.commons.geometry.euclidean.threed.BoundarySource3D;
29 import org.apache.commons.geometry.euclidean.threed.Vector3D;
30 import org.apache.commons.geometry.euclidean.threed.mesh.SimpleTriangleMesh;
31 import org.apache.commons.geometry.io.core.output.StreamGeometryOutput;
32 import org.apache.commons.geometry.io.euclidean.threed.FacetDefinition;
33 import org.apache.commons.geometry.io.euclidean.threed.FacetDefinitions;
34 import org.apache.commons.geometry.io.euclidean.threed.GeometryFormat3D;
35 import org.apache.commons.geometry.io.euclidean.threed.SimpleFacetDefinition;
36 import org.apache.commons.numbers.core.Precision;
37 import org.junit.jupiter.api.Assertions;
38 import org.junit.jupiter.api.Test;
39
40 class ObjBoundaryWriteHandler3DTest {
41
42 private static final double TEST_EPS = 1e-10;
43
44 private static final Precision.DoubleEquivalence TEST_PRECISION =
45 Precision.doubleEquivalenceOfEpsilon(TEST_EPS);
46
47 private static final List<FacetDefinition> FACETS = Arrays.asList(
48 new SimpleFacetDefinition(Arrays.asList(Vector3D.ZERO, Vector3D.of(1.0 / 3.0, 0, 0), Vector3D.of(1, 1, 0), Vector3D.of(0, 1, 0))),
49 new SimpleFacetDefinition(Arrays.asList(Vector3D.ZERO, Vector3D.of(0, -1, 0), Vector3D.of(1.0 / 3.0, 0, 0))));
50
51 private final ByteArrayOutputStream out = new ByteArrayOutputStream();
52
53 private final ObjBoundaryWriteHandler3D handler = new ObjBoundaryWriteHandler3D();
54
55 @Test
56 void testProperties() {
57
58 Assertions.assertEquals(GeometryFormat3D.OBJ, handler.getFormat());
59 Assertions.assertEquals(StandardCharsets.UTF_8, handler.getDefaultCharset());
60 Assertions.assertEquals("\n", handler.getLineSeparator());
61 Assertions.assertNotNull(handler.getDoubleFormat());
62 Assertions.assertEquals(-1, handler.getMeshBufferBatchSize());
63 }
64
65 @Test
66 void testWriteFacets() {
67
68 final DecimalFormat fmt =
69 new DecimalFormat("0.0#####", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
70
71
72 handler.setDoubleFormat(fmt::format);
73 handler.writeFacets(FACETS, new StreamGeometryOutput(out));
74
75
76 Assertions.assertEquals(
77 "v 0.0 0.0 0.0\n" +
78 "v 0.333333 0.0 0.0\n" +
79 "v 1.0 1.0 0.0\n" +
80 "v 0.0 1.0 0.0\n" +
81 "v 0.0 -1.0 0.0\n" +
82 "f 1 2 3 4\n" +
83 "f 1 5 2\n", new String(out.toByteArray(), StandardCharsets.UTF_8));
84 }
85
86 @Test
87 void testWriteFacets_usesOutputCharset() {
88
89 final DecimalFormat fmt =
90 new DecimalFormat("0.0#####", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
91
92
93 handler.setDoubleFormat(fmt::format);
94 handler.writeFacets(FACETS, new StreamGeometryOutput(out, null, StandardCharsets.UTF_16));
95
96
97 Assertions.assertEquals(
98 "v 0.0 0.0 0.0\n" +
99 "v 0.333333 0.0 0.0\n" +
100 "v 1.0 1.0 0.0\n" +
101 "v 0.0 1.0 0.0\n" +
102 "v 0.0 -1.0 0.0\n" +
103 "f 1 2 3 4\n" +
104 "f 1 5 2\n", new String(out.toByteArray(), StandardCharsets.UTF_16));
105 }
106
107 @Test
108 void testWriteFacets_customConfig() {
109
110
111 final DecimalFormat fmt =
112 new DecimalFormat("0.0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
113
114 handler.setDefaultCharset(StandardCharsets.UTF_16);
115 handler.setLineSeparator("\r\n");
116 handler.setDoubleFormat(fmt::format);
117 handler.setMeshBufferBatchSize(1);
118
119
120 handler.writeFacets(FACETS, new StreamGeometryOutput(out));
121
122
123 Assertions.assertEquals(
124 "v 0.0 0.0 0.0\r\n" +
125 "v 0.3 0.0 0.0\r\n" +
126 "v 1.0 1.0 0.0\r\n" +
127 "v 0.0 1.0 0.0\r\n" +
128 "f 1 2 3 4\r\n" +
129 "v 0.0 0.0 0.0\r\n" +
130 "v 0.0 -1.0 0.0\r\n" +
131 "v 0.3 0.0 0.0\r\n" +
132 "f 5 6 7\r\n", new String(out.toByteArray(), StandardCharsets.UTF_16));
133 }
134
135 @Test
136 void testWrite() {
137
138 final BoundarySource3D src = BoundarySource3D.of(FACETS.stream()
139 .map(f -> FacetDefinitions.toPolygon(f, TEST_PRECISION))
140 .collect(Collectors.toList()));
141
142
143 handler.write(src, new StreamGeometryOutput(out));
144
145
146 Assertions.assertEquals(
147 "v 0.0 0.0 0.0\n" +
148 "v 0.3333333333333333 0.0 0.0\n" +
149 "v 1.0 1.0 0.0\n" +
150 "v 0.0 1.0 0.0\n" +
151 "v 0.0 -1.0 0.0\n" +
152 "f 1 2 3 4\n" +
153 "f 1 5 2\n", new String(out.toByteArray(), StandardCharsets.UTF_8));
154 }
155
156 @Test
157 void testWrite_customConfig() {
158
159 final BoundarySource3D src = BoundarySource3D.of(FACETS.stream()
160 .map(f -> FacetDefinitions.toPolygon(f, TEST_PRECISION))
161 .collect(Collectors.toList()));
162
163
164 final DecimalFormat fmt =
165 new DecimalFormat("0.0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
166
167 handler.setDefaultCharset(StandardCharsets.UTF_16);
168 handler.setLineSeparator("\r\n");
169 handler.setDoubleFormat(fmt::format);
170 handler.setMeshBufferBatchSize(1);
171
172
173 handler.write(src, new StreamGeometryOutput(out));
174
175
176 Assertions.assertEquals(
177 "v 0.0 0.0 0.0\r\n" +
178 "v 0.3 0.0 0.0\r\n" +
179 "v 1.0 1.0 0.0\r\n" +
180 "v 0.0 1.0 0.0\r\n" +
181 "f 1 2 3 4\r\n" +
182 "v 0.0 0.0 0.0\r\n" +
183 "v 0.0 -1.0 0.0\r\n" +
184 "v 0.3 0.0 0.0\r\n" +
185 "f 5 6 7\r\n", new String(out.toByteArray(), StandardCharsets.UTF_16));
186 }
187
188 @Test
189 void testWrite_mesh() {
190
191 final SimpleTriangleMesh.Builder builder = SimpleTriangleMesh.builder(TEST_PRECISION);
192 builder.addFaceAndVertices(Vector3D.ZERO, Vector3D.of(1, 0, 0), Vector3D.of(0, 1, 0));
193 builder.addVertex(Vector3D.of(2, 3, 4));
194
195 final BoundarySource3D src = builder.build();
196
197
198 handler.write(src, new StreamGeometryOutput(out));
199
200
201 Assertions.assertEquals(
202 "v 0.0 0.0 0.0\n" +
203 "v 1.0 0.0 0.0\n" +
204 "v 0.0 1.0 0.0\n" +
205 "v 2.0 3.0 4.0\n" +
206 "f 1 2 3\n", new String(out.toByteArray(), StandardCharsets.UTF_8));
207 }
208 }