AbstractBoundaryReadHandler3D.java
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.apache.commons.geometry.io.euclidean.threed;
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.List;
- import java.util.NoSuchElementException;
- import java.util.Spliterator;
- import java.util.Spliterators;
- import java.util.stream.Stream;
- import java.util.stream.StreamSupport;
- import org.apache.commons.geometry.euclidean.threed.BoundaryList3D;
- import org.apache.commons.geometry.euclidean.threed.BoundarySource3D;
- import org.apache.commons.geometry.euclidean.threed.PlaneConvexSubset;
- import org.apache.commons.geometry.euclidean.threed.Triangle3D;
- import org.apache.commons.geometry.euclidean.threed.mesh.SimpleTriangleMesh;
- import org.apache.commons.geometry.euclidean.threed.mesh.TriangleMesh;
- import org.apache.commons.geometry.io.core.input.GeometryInput;
- import org.apache.commons.geometry.io.core.internal.GeometryIOUtils;
- import org.apache.commons.numbers.core.Precision;
- /** Abstract base class for {@link BoundaryReadHandler3D} implementations.
- */
- public abstract class AbstractBoundaryReadHandler3D implements BoundaryReadHandler3D {
- /** {@inheritDoc} */
- @Override
- public BoundarySource3D read(final GeometryInput in, final Precision.DoubleEquivalence precision) {
- // read the input as a simple list of boundaries
- final List<PlaneConvexSubset> list = new ArrayList<>();
- try (FacetDefinitionReader reader = facetDefinitionReader(in)) {
- FacetDefinition facet;
- while ((facet = reader.readFacet()) != null) {
- list.add(FacetDefinitions.toPolygon(facet, precision));
- }
- }
- return new BoundaryList3D(list);
- }
- /** {@inheritDoc} */
- @Override
- public TriangleMesh readTriangleMesh(final GeometryInput in, final Precision.DoubleEquivalence precision) {
- final SimpleTriangleMesh.Builder meshBuilder = SimpleTriangleMesh.builder(precision);
- try (FacetDefinitionReader reader = facetDefinitionReader(in)) {
- FacetDefinition facet;
- while ((facet = reader.readFacet()) != null) {
- for (final Triangle3D tri : FacetDefinitions.toPolygon(facet, precision).toTriangles()) {
- meshBuilder.addFaceUsingVertices(
- tri.getPoint1(),
- tri.getPoint2(),
- tri.getPoint3()
- );
- }
- }
- }
- return meshBuilder.build();
- }
- /** {@inheritDoc} */
- @Override
- public Stream<PlaneConvexSubset> boundaries(final GeometryInput in, final Precision.DoubleEquivalence precision) {
- return facets(in)
- .map(f -> FacetDefinitions.toPolygon(f, precision));
- }
- /** {@inheritDoc} */
- @Override
- public Stream<FacetDefinition> facets(final GeometryInput in) {
- return GeometryIOUtils.createCloseableStream(inputStream -> {
- final FacetDefinitionReader fdReader = facetDefinitionReader(in);
- final FacetDefinitionReaderIterator it = new FacetDefinitionReaderIterator(fdReader);
- return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.ORDERED), false);
- }, in::getInputStream);
- }
- /** Class exposing a {@link FacetDefinitionReader} as an iterator.
- */
- static final class FacetDefinitionReaderIterator implements Iterator<FacetDefinition> {
- /** Reader supplying the facets for iteration. */
- private final FacetDefinitionReader reader;
- /** Number of facets read from the reader. */
- private int loadCount = 0;
- /** Next facet to return from the instance; may be null. */
- private FacetDefinition next;
- /** Construct a new iterator instance that iterates through the facets available from the
- * argument.
- * @param reader read supplying facets for iteration
- */
- FacetDefinitionReaderIterator(final FacetDefinitionReader reader) {
- this.reader = reader;
- }
- /** {@inheritDoc} */
- @Override
- public boolean hasNext() {
- ensureLoaded();
- return next != null;
- }
- /** {@inheritDoc} */
- @Override
- public FacetDefinition next() {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- final FacetDefinition result = next;
- loadNext();
- return result;
- }
- /** Ensure that the instance has attempted to load at least one facet from
- * the underlying reader.
- */
- private void ensureLoaded() {
- if (loadCount < 1) {
- loadNext();
- }
- }
- /** Load the next facet from the underlying reader.
- */
- private void loadNext() {
- ++loadCount;
- next = reader.readFacet();
- }
- }
- }