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.util.ArrayList;
20 import java.util.Iterator;
21 import java.util.List;
22 import java.util.NoSuchElementException;
23 import java.util.Spliterator;
24 import java.util.Spliterators;
25 import java.util.stream.Stream;
26 import java.util.stream.StreamSupport;
27
28 import org.apache.commons.geometry.euclidean.threed.BoundaryList3D;
29 import org.apache.commons.geometry.euclidean.threed.BoundarySource3D;
30 import org.apache.commons.geometry.euclidean.threed.PlaneConvexSubset;
31 import org.apache.commons.geometry.euclidean.threed.Triangle3D;
32 import org.apache.commons.geometry.euclidean.threed.mesh.SimpleTriangleMesh;
33 import org.apache.commons.geometry.euclidean.threed.mesh.TriangleMesh;
34 import org.apache.commons.geometry.io.core.input.GeometryInput;
35 import org.apache.commons.geometry.io.core.internal.GeometryIOUtils;
36 import org.apache.commons.numbers.core.Precision;
37
38
39
40 public abstract class AbstractBoundaryReadHandler3D implements BoundaryReadHandler3D {
41
42
43 @Override
44 public BoundarySource3D read(final GeometryInput in, final Precision.DoubleEquivalence precision) {
45
46 final List<PlaneConvexSubset> list = new ArrayList<>();
47
48 try (FacetDefinitionReader reader = facetDefinitionReader(in)) {
49 FacetDefinition facet;
50 while ((facet = reader.readFacet()) != null) {
51 list.add(FacetDefinitions.toPolygon(facet, precision));
52 }
53 }
54
55 return new BoundaryList3D(list);
56 }
57
58
59 @Override
60 public TriangleMesh readTriangleMesh(final GeometryInput in, final Precision.DoubleEquivalence precision) {
61 final SimpleTriangleMesh.Builder meshBuilder = SimpleTriangleMesh.builder(precision);
62
63 try (FacetDefinitionReader reader = facetDefinitionReader(in)) {
64 FacetDefinition facet;
65 while ((facet = reader.readFacet()) != null) {
66 for (final Triangle3D tri : FacetDefinitions.toPolygon(facet, precision).toTriangles()) {
67 meshBuilder.addFaceUsingVertices(
68 tri.getPoint1(),
69 tri.getPoint2(),
70 tri.getPoint3()
71 );
72 }
73 }
74 }
75
76 return meshBuilder.build();
77 }
78
79
80 @Override
81 public Stream<PlaneConvexSubset> boundaries(final GeometryInput in, final Precision.DoubleEquivalence precision) {
82 return facets(in)
83 .map(f -> FacetDefinitions.toPolygon(f, precision));
84 }
85
86
87 @Override
88 public Stream<FacetDefinition> facets(final GeometryInput in) {
89 return GeometryIOUtils.createCloseableStream(inputStream -> {
90 final FacetDefinitionReader fdReader = facetDefinitionReader(in);
91 final FacetDefinitionReaderIterator it = new FacetDefinitionReaderIterator(fdReader);
92
93 return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.ORDERED), false);
94 }, in::getInputStream);
95 }
96
97
98
99 static final class FacetDefinitionReaderIterator implements Iterator<FacetDefinition> {
100
101
102 private final FacetDefinitionReader reader;
103
104
105 private int loadCount = 0;
106
107
108 private FacetDefinition next;
109
110
111
112
113
114 FacetDefinitionReaderIterator(final FacetDefinitionReader reader) {
115 this.reader = reader;
116 }
117
118
119 @Override
120 public boolean hasNext() {
121 ensureLoaded();
122 return next != null;
123 }
124
125
126 @Override
127 public FacetDefinition next() {
128 if (!hasNext()) {
129 throw new NoSuchElementException();
130 }
131
132 final FacetDefinition result = next;
133 loadNext();
134
135 return result;
136 }
137
138
139
140
141 private void ensureLoaded() {
142 if (loadCount < 1) {
143 loadNext();
144 }
145 }
146
147
148
149 private void loadNext() {
150 ++loadCount;
151 next = reader.readFacet();
152 }
153 }
154 }