BoundaryIOManager3D.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.geometry.io.euclidean.threed;

  18. import java.util.Collection;
  19. import java.util.stream.Stream;

  20. import org.apache.commons.geometry.euclidean.threed.BoundarySource3D;
  21. import org.apache.commons.geometry.euclidean.threed.PlaneConvexSubset;
  22. import org.apache.commons.geometry.euclidean.threed.Triangle3D;
  23. import org.apache.commons.geometry.euclidean.threed.mesh.TriangleMesh;
  24. import org.apache.commons.geometry.io.core.BoundaryIOManager;
  25. import org.apache.commons.geometry.io.core.GeometryFormat;
  26. import org.apache.commons.geometry.io.core.input.GeometryInput;
  27. import org.apache.commons.geometry.io.core.output.GeometryOutput;
  28. import org.apache.commons.geometry.io.euclidean.threed.obj.ObjBoundaryReadHandler3D;
  29. import org.apache.commons.geometry.io.euclidean.threed.obj.ObjBoundaryWriteHandler3D;
  30. import org.apache.commons.geometry.io.euclidean.threed.stl.StlBoundaryReadHandler3D;
  31. import org.apache.commons.geometry.io.euclidean.threed.stl.StlBoundaryWriteHandler3D;
  32. import org.apache.commons.geometry.io.euclidean.threed.txt.CsvBoundaryReadHandler3D;
  33. import org.apache.commons.geometry.io.euclidean.threed.txt.CsvBoundaryWriteHandler3D;
  34. import org.apache.commons.geometry.io.euclidean.threed.txt.TextBoundaryReadHandler3D;
  35. import org.apache.commons.geometry.io.euclidean.threed.txt.TextBoundaryWriteHandler3D;
  36. import org.apache.commons.numbers.core.Precision;

  37. /** Class managing IO operations for geometric data formats containing 3D region boundaries.
  38.  * IO operation are performed by read and write handlers registered for specific data formats.
  39.  *
  40.  * <p><strong>Implementation note:</strong>Instances of this class are thread-safe as long as the
  41.  * registered handler instances are thread-safe.</p>
  42.  * @see BoundaryReadHandler3D
  43.  * @see BoundaryWriteHandler3D
  44.  * @see <a href="https://en.wikipedia.org/wiki/Boundary_representations">Boundary representations</a>
  45.  */
  46. public class BoundaryIOManager3D extends BoundaryIOManager<
  47.         PlaneConvexSubset,
  48.         BoundarySource3D,
  49.         BoundaryReadHandler3D,
  50.         BoundaryWriteHandler3D> {

  51.     /** Get a {@link FacetDefinitionReader} for reading facet information from the given input.
  52.      * @param in input to read facets from
  53.      * @param fmt format of the input; if null, the format is determined implicitly from the
  54.      *      file extension of the input {@link GeometryInput#getFileName() file name}
  55.      * @return facet definition reader
  56.      * @throws IllegalArgumentException if no read handler can be found for the input format
  57.      * @throws IllegalStateException if a data format error occurs
  58.      * @throws java.io.UncheckedIOException if an I/O error occurs
  59.      */
  60.     public FacetDefinitionReader facetDefinitionReader(final GeometryInput in, final GeometryFormat fmt) {
  61.         return requireReadHandler(in, fmt).facetDefinitionReader(in);
  62.     }

  63.     /** Return a {@link Stream} providing access to all facets from the given input. The underlying input
  64.      * stream is closed when the returned stream is closed. Callers should therefore use the returned stream
  65.      * in a try-with-resources statement to ensure that all resources are properly released.
  66.      * <pre>
  67.      *  try (Stream&lt;FacetDefinition&gt; stream = manager.facets(in, fmt)) {
  68.      *      // access stream content
  69.      *  }
  70.      * </pre>
  71.      * <p>The following exceptions may be thrown during stream iteration:</p>
  72.      * <ul>
  73.      *  <li>{@link IllegalStateException} if a data format error occurs</li>
  74.      *  <li>{@link java.io.UncheckedIOException UncheckedIOException} if an I/O error occurs</li>
  75.      * </ul>
  76.      * @param in input to read from
  77.      * @param fmt format of the input; if null, the format is determined implicitly from the
  78.      *      file extension of the input {@link GeometryInput#getFileName() file name}
  79.      * @return stream providing access to the facets in the input
  80.      * @throws IllegalArgumentException if no read handler can be found for the input format
  81.      * @throws IllegalStateException if a data format error occurs during stream creation
  82.      * @throws java.io.UncheckedIOException if an I/O error occurs during stream creation
  83.      */
  84.     public Stream<FacetDefinition> facets(final GeometryInput in, final GeometryFormat fmt) {
  85.         return requireReadHandler(in, fmt).facets(in);
  86.     }

  87.     /** Return a {@link Stream} providing access to all triangles from the given input. The underlying input
  88.      * stream is closed when the returned stream is closed. Callers should therefore use the returned stream
  89.      * in a try-with-resources statement to ensure that all resources are properly released.
  90.      * <pre>
  91.      *  try (Stream&lt;Triangle3D&gt; stream = manager.triangles(in, fmt, precision)) {
  92.      *      // access stream content
  93.      *  }
  94.      * </pre>
  95.      * <p>The following exceptions may be thrown during stream iteration:</p>
  96.      * <ul>
  97.      *  <li>{@link IllegalArgumentException} if mathematically invalid data is encountered</li>
  98.      *  <li>{@link IllegalStateException} if a data format error occurs</li>
  99.      *  <li>{@link java.io.UncheckedIOException UncheckedIOException} if an I/O error occurs</li>
  100.      * </ul>
  101.      * @param in input to read from
  102.      * @param fmt format of the input; if null, the format is determined implicitly from the
  103.      *      file extension of the input {@link GeometryInput#getFileName() file name}
  104.      * @param precision precision context used for floating point comparisons
  105.      * @return stream providing access to the triangles in the input
  106.      * @throws IllegalArgumentException if no read handler can be found for the input format
  107.      * @throws IllegalStateException if a data format error occurs during stream creation
  108.      * @throws java.io.UncheckedIOException if an I/O error occurs during stream creation
  109.      */
  110.     public Stream<Triangle3D> triangles(final GeometryInput in, final GeometryFormat fmt,
  111.             final Precision.DoubleEquivalence precision) {
  112.         return boundaries(in, fmt, precision)
  113.                 .flatMap(p -> p.toTriangles().stream());
  114.     }

  115.     /** Return a {@link TriangleMesh} containing all triangles from the given input.
  116.      * @param in input to read from
  117.      * @param fmt format of the input; if null, the format is determined implicitly from the
  118.      *      file extension of the input {@link GeometryInput#getFileName() file name}
  119.      * @param precision precision context used for floating point comparisons
  120.      * @return mesh containing all triangles from the input
  121.      * @throws IllegalArgumentException if mathematically invalid data is encountered or no read
  122.      *      handler can be found for the input format
  123.      * @throws IllegalStateException if a data format error occurs
  124.      * @throws java.io.UncheckedIOException if an I/O error occurs
  125.      */
  126.     public TriangleMesh readTriangleMesh(final GeometryInput in, final GeometryFormat fmt,
  127.             final Precision.DoubleEquivalence precision) {
  128.         return requireReadHandler(in, fmt).readTriangleMesh(in, precision);
  129.     }

  130.     /** Write all boundaries in the stream to the output.
  131.      *
  132.      * <p>This method does not explicitly close the {@code boundaries} stream. If callers need to ensure that
  133.      * the stream is closed (for example, if the stream is reading from a file), they should use it in a
  134.      * try-with-resources statement outside of this method.</p>
  135.      * @param boundaries stream containing boundaries to write
  136.      * @param out output to write to
  137.      * @param fmt format of the output; if null, the format is determined implicitly from the
  138.      *      file extension of the output {@link GeometryOutput#getFileName() file name}
  139.      * @throws IllegalArgumentException if no write handler can be found for the output format
  140.      * @throws java.io.UncheckedIOException if an I/O error occurs
  141.      */
  142.     public void write(final Stream<? extends PlaneConvexSubset> boundaries, final GeometryOutput out,
  143.             final GeometryFormat fmt) {
  144.         requireWriteHandler(out, fmt).write(boundaries, out);
  145.     }

  146.     /** Write all facet in the stream to the output.
  147.      *
  148.      * <p>This method does not explicitly close the {@code boundaries} stream. If callers need to ensure that
  149.      * the stream is closed (for example, if the stream is reading from a file), they should use it in a
  150.      * try-with-resources statement outside of this method.</p>
  151.      * @param facets stream containing facets to write
  152.      * @param out output to write to
  153.      * @param fmt format of the output; if null, the format is determined implicitly from the
  154.      *      file extension of the output {@link GeometryOutput#getFileName() file name}
  155.      * @throws IllegalArgumentException if no write handler can be found for the output format
  156.      * @throws java.io.UncheckedIOException if an I/O error occurs
  157.      */
  158.     public void writeFacets(final Stream<? extends FacetDefinition> facets, final GeometryOutput out,
  159.             final GeometryFormat fmt) {
  160.         requireWriteHandler(out, fmt).writeFacets(facets, out);
  161.     }

  162.     /** Write the given facets to the output.
  163.      * @param facets facets to write
  164.      * @param out output to write to
  165.      * @param fmt format of the output; if null, the format is determined implicitly from the
  166.      *      file extension of the output {@link GeometryOutput#getFileName() file name}
  167.      * @throws IllegalArgumentException if no write handler can be found for the output format
  168.      * @throws java.io.UncheckedIOException if an I/O error occurs
  169.      */
  170.     public void writeFacets(final Collection<? extends FacetDefinition> facets, final GeometryOutput out,
  171.             final GeometryFormat fmt) {
  172.         requireWriteHandler(out, fmt).writeFacets(facets, out);
  173.     }

  174.     /** Register default read/write handlers. This method registers a read and write handler
  175.      * for each value in {@link GeometryFormat3D}.
  176.      */
  177.     public void registerDefaultHandlers() {
  178.         // obj
  179.         registerReadHandler(new ObjBoundaryReadHandler3D());
  180.         registerWriteHandler(new ObjBoundaryWriteHandler3D());

  181.         // stl
  182.         registerReadHandler(new StlBoundaryReadHandler3D());
  183.         registerWriteHandler(new StlBoundaryWriteHandler3D());

  184.         // txt
  185.         registerReadHandler(new TextBoundaryReadHandler3D());
  186.         registerWriteHandler(new TextBoundaryWriteHandler3D());

  187.         // csv
  188.         registerReadHandler(new CsvBoundaryReadHandler3D());
  189.         registerWriteHandler(new CsvBoundaryWriteHandler3D());
  190.     }
  191. }