ObjBoundaryWriteHandler3D.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.obj;

  18. import java.nio.charset.Charset;
  19. import java.util.Iterator;
  20. import java.util.function.DoubleFunction;
  21. import java.util.stream.Stream;

  22. import org.apache.commons.geometry.euclidean.threed.BoundarySource3D;
  23. import org.apache.commons.geometry.euclidean.threed.PlaneConvexSubset;
  24. import org.apache.commons.geometry.euclidean.threed.mesh.Mesh;
  25. import org.apache.commons.geometry.io.core.GeometryFormat;
  26. import org.apache.commons.geometry.io.core.internal.GeometryIOUtils;
  27. import org.apache.commons.geometry.io.core.output.GeometryOutput;
  28. import org.apache.commons.geometry.io.euclidean.threed.AbstractBoundaryWriteHandler3D;
  29. import org.apache.commons.geometry.io.euclidean.threed.FacetDefinition;
  30. import org.apache.commons.geometry.io.euclidean.threed.GeometryFormat3D;

  31. /** {@link org.apache.commons.geometry.io.euclidean.threed.BoundaryWriteHandler3D BoundaryWriteHandler3D}
  32.  * implementation for writing OBJ content. Output is written using the UTF-8 charset by default.
  33.  */
  34. public class ObjBoundaryWriteHandler3D extends AbstractBoundaryWriteHandler3D {

  35.     /** The default line separator value. */
  36.     private static final String DEFAULT_LINE_SEPARATOR = "\n";

  37.     /** Default mesh buffer batch size. */
  38.     private static final int DEFAULT_MESH_BUFFER_BATCH_SIZE = -1;

  39.     /** Charset used for text output. */
  40.     private Charset defaultCharset = ObjConstants.DEFAULT_CHARSET;

  41.     /** Line separator string. */
  42.     private String lineSeparator = DEFAULT_LINE_SEPARATOR;

  43.     /** Double format function. */
  44.     private DoubleFunction<String> doubleFormat = Double::toString;

  45.     /** Batch size used for mesh buffer creation. */
  46.     private int meshBufferBatchSize = DEFAULT_MESH_BUFFER_BATCH_SIZE;

  47.     /** {@inheritDoc} */
  48.     @Override
  49.     public GeometryFormat getFormat() {
  50.         return GeometryFormat3D.OBJ;
  51.     }

  52.     /** Get the text output default charset, used if the output does not
  53.      * specify a charset.
  54.      * @return text output default charset
  55.      */
  56.     public Charset getDefaultCharset() {
  57.         return defaultCharset;
  58.     }

  59.     /** Set the text output default charset, used if the output does not
  60.      * specify a charset.
  61.      * @param charset text output default charset
  62.      */
  63.     public void setDefaultCharset(final Charset charset) {
  64.         this.defaultCharset = charset;
  65.     }

  66.     /** Get the line separator. This value defaults to {@value #DEFAULT_LINE_SEPARATOR}.
  67.      * @return the current line separator
  68.      */
  69.     public String getLineSeparator() {
  70.         return lineSeparator;
  71.     }

  72.     /** Set the line separator.
  73.      * @param lineSeparator the line separator to use
  74.      */
  75.     public void setLineSeparator(final String lineSeparator) {
  76.         this.lineSeparator = lineSeparator;
  77.     }

  78.     /** Get the function used to convert double values to strings.
  79.      * @return double format function
  80.      */
  81.     public DoubleFunction<String> getDoubleFormat() {
  82.         return doubleFormat;
  83.     }

  84.     /** Set the function used to convert double values to strings. The given function
  85.      * must be thread-safe if this handler is to be used in a multi-threaded context.
  86.      * @param doubleFormat double format function
  87.      */
  88.     public void setDoubleFormat(final DoubleFunction<String> doubleFormat) {
  89.         this.doubleFormat = doubleFormat;
  90.     }

  91.     /** Get the batch size when generating OBJ mesh content from facet sequences. Larger batch sizes
  92.      * allow for reuse of vertex definitions but at the cost of more memory usage. The buffer size is
  93.      * unlimited if set to {@code -1}. Default value is {@value #DEFAULT_MESH_BUFFER_BATCH_SIZE}.
  94.      * @return mesh buffer batch size
  95.      * @see ObjWriter#meshBuffer(int)
  96.      */
  97.     public int getMeshBufferBatchSize() {
  98.         return meshBufferBatchSize;
  99.     }

  100.     /** Set the batch size when generating OBJ mesh content from facet sequences. Larger batch sizes
  101.      * allow for reuse of vertex definitions but at the cost of more memory usage. Set to {@code -1}
  102.      * to allow unlimited buffer size. Default value is {@value #DEFAULT_MESH_BUFFER_BATCH_SIZE}.
  103.      * @param batchSize mesh buffer batch size; set to {@code -1} to allow unlimited buffer sizes
  104.      * @see ObjWriter#meshBuffer(int)
  105.      */
  106.     public void setMeshBufferBatchSize(final int batchSize) {
  107.         this.meshBufferBatchSize = batchSize;
  108.     }

  109.     /** {@inheritDoc} */
  110.     @Override
  111.     public void write(final BoundarySource3D src, final GeometryOutput out) {
  112.         // write meshes directly instead of iterating through boundaries
  113.         if (src instanceof Mesh) {
  114.             try (ObjWriter writer = createWriter(out)) {
  115.                 writer.writeMesh((Mesh<?>) src);
  116.             }
  117.         } else {
  118.             super.write(src, out);
  119.         }
  120.     }

  121.     /** {@inheritDoc} */
  122.     @Override
  123.     public void write(final Stream<? extends PlaneConvexSubset> boundaries, final GeometryOutput out) {
  124.         try (ObjWriter writer = createWriter(out)) {
  125.             final ObjWriter.MeshBuffer meshBuffer = writer.meshBuffer(meshBufferBatchSize);

  126.             final Iterator<? extends PlaneConvexSubset> it = boundaries.iterator();
  127.             while (it.hasNext()) {
  128.                 meshBuffer.add(it.next());
  129.             }

  130.             meshBuffer.flush();
  131.         }
  132.     }

  133.     /** {@inheritDoc} */
  134.     @Override
  135.     public void writeFacets(final Stream<? extends FacetDefinition> facets, final GeometryOutput out) {
  136.         try (ObjWriter writer = createWriter(out)) {
  137.             final ObjWriter.MeshBuffer meshBuffer = writer.meshBuffer(meshBufferBatchSize);

  138.             final Iterator<? extends FacetDefinition> it = facets.iterator();
  139.             while (it.hasNext()) {
  140.                 meshBuffer.add(it.next());
  141.             }

  142.             meshBuffer.flush();
  143.         }
  144.     }

  145.     /** Construct a new, configured {@link ObjWriter} instance for writing content to the given
  146.      * output stream.
  147.      * @param out output stream to write to
  148.      * @return new {@code OBJWriter} for writing content to the given output stream
  149.      * @throws java.io.UncheckedIOException if an I/O error occurs
  150.      */
  151.     private ObjWriter createWriter(final GeometryOutput out) {
  152.         final ObjWriter writer = new ObjWriter(GeometryIOUtils.createBufferedWriter(out, defaultCharset));
  153.         writer.setLineSeparator(lineSeparator);
  154.         writer.setDoubleFormat(doubleFormat);

  155.         return writer;
  156.     }
  157. }