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;
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
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
65 final BoundarySource3D result = handler.read(in, TEST_PRECISION);
66
67
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
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
83 final TriangleMesh result = handler.readTriangleMesh(in, TEST_PRECISION);
84
85
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
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
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
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
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
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
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
144 final StubFacetDefinitionReader reader = new StubFacetDefinitionReader(Arrays.asList(FACET_1, FACET_2));
145 final FacetDefinitionReaderIterator it = new FacetDefinitionReaderIterator(reader);
146
147
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
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
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
181 @Override
182 public GeometryFormat getFormat() {
183 throw new UnsupportedOperationException();
184 }
185
186
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
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
218 @Override
219 public void close() {
220
221 }
222 }
223 }