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 19 import java.net.URL; 20 import java.nio.file.Path; 21 import java.util.Collection; 22 import java.util.stream.Stream; 23 24 import org.apache.commons.geometry.euclidean.threed.BoundarySource3D; 25 import org.apache.commons.geometry.euclidean.threed.PlaneConvexSubset; 26 import org.apache.commons.geometry.euclidean.threed.Triangle3D; 27 import org.apache.commons.geometry.euclidean.threed.mesh.TriangleMesh; 28 import org.apache.commons.geometry.io.core.GeometryFormat; 29 import org.apache.commons.geometry.io.core.input.FileGeometryInput; 30 import org.apache.commons.geometry.io.core.input.GeometryInput; 31 import org.apache.commons.geometry.io.core.input.UrlGeometryInput; 32 import org.apache.commons.geometry.io.core.output.FileGeometryOutput; 33 import org.apache.commons.geometry.io.core.output.GeometryOutput; 34 import org.apache.commons.numbers.core.Precision; 35 36 /** Utility class providing convenient access to 3D IO functionality. The static read and write methods here 37 * delegate to a default {@link #getDefaultManager() BoundaryIOManager3D} instance. The default 38 * configuration should be sufficient for most purposes. If customization is required, consider directly 39 * creating and configuring and a {@link BoundaryIOManager3D} instance. 40 * 41 * <p><strong>Examples</strong></p> 42 * <p>The example below reads an OBJ file as a stream of triangles, transforms each triangle, and writes the 43 * result as a CSV file. The data formats are inferred from the input and output file extensions.</p> 44 * <pre> 45 * GeometryInput input = new FileGeometryInput(Paths.get("orig.obj")); 46 * GeometryOutput scaledOutput = new FileGeometryOutput(Paths.get("scaled.csv")); 47 * AffineTransformMatrix3D transform = AffineTransformMatrix3D.createScale(2); 48 * 49 * // Use the input triangle stream in a try-with-resources statement to ensure 50 * // all resources are properly released. 51 * try (Stream<Triangle3D> stream = IO3D.triangles(input, null, precision)) { 52 * IO3D.write(stream.map(t -> t.transform(transform)), scaledOutput, null); 53 * } 54 * </pre> 55 * @see BoundaryIOManager3D 56 */ 57 public final class IO3D { 58 59 /** Utility class; no instantiation. */ 60 private IO3D() {} 61 62 /** Get a {@link FacetDefinitionReader} for reading facet information from the given file path. 63 * The data format is determined by the file extension of the argument. 64 * @param path path to obtain a reader for 65 * @return facet definition reader 66 * @throws IllegalArgumentException if no handler has been registered with the 67 * {@link #getDefaultManager() default manager} for the input format 68 * @throws IllegalStateException if a data format error occurs 69 * @throws java.io.UncheckedIOException if an I/O error occurs 70 * @see BoundaryIOManager3D#facetDefinitionReader(GeometryInput, GeometryFormat) 71 */ 72 public static FacetDefinitionReader facetDefinitionReader(final Path path) { 73 return facetDefinitionReader(new FileGeometryInput(path), null); 74 } 75 76 /** Get a {@link FacetDefinitionReader} for reading facet information from the given URL. 77 * The data format is determined by the file extension of the argument. 78 * @param url URL to read from 79 * @return facet definition reader 80 * @throws IllegalArgumentException if no handler has been registered with the 81 * {@link #getDefaultManager() default manager} for the input format 82 * @throws IllegalStateException if a data format error occurs 83 * @throws java.io.UncheckedIOException if an I/O error occurs 84 * @see BoundaryIOManager3D#facetDefinitionReader(GeometryInput, GeometryFormat) 85 */ 86 public static FacetDefinitionReader facetDefinitionReader(final URL url) { 87 return facetDefinitionReader(new UrlGeometryInput(url), null); 88 } 89 90 /** Get a {@link FacetDefinitionReader} for reading facet information from the given input. 91 * @param in input to read from 92 * @param fmt format of the input; if null, the format is determined implicitly from the 93 * file extension of the input {@link GeometryInput#getFileName() file name} 94 * @return facet definition reader 95 * @throws IllegalArgumentException if no handler has been registered with the 96 * {@link #getDefaultManager() default manager} for the input format 97 * @throws IllegalStateException if a data format error occurs 98 * @throws java.io.UncheckedIOException if an I/O error occurs 99 * @see BoundaryIOManager3D#facetDefinitionReader(GeometryInput, GeometryFormat) 100 */ 101 public static FacetDefinitionReader facetDefinitionReader(final GeometryInput in, final GeometryFormat fmt) { 102 return getDefaultManager().facetDefinitionReader(in, fmt); 103 } 104 105 /** Return a {@link Stream} providing access to all facets from the given file path. The data format 106 * is determined by the file extension of the argument. 107 * 108 * <p>The underlying input stream is closed when the returned stream is closed. Callers should 109 * therefore use the returned stream in a try-with-resources statement to ensure that all 110 * resources are properly released. Ex: 111 * </p> 112 * <pre> 113 * try (Stream<FacetDefinition> stream = IO3D.facets(path)) { 114 * // access stream content 115 * } 116 * </pre> 117 * <p>The following exceptions may be thrown during stream iteration: 118 * <ul> 119 * <li>{@link IllegalStateException} if a data format error occurs</li> 120 * <li>{@link java.io.UncheckedIOException UncheckedIOException} if an I/O error occurs</li> 121 * </ul> 122 * @param path file path to read from 123 * @return stream providing access to the facets in the specified file 124 * @throws IllegalArgumentException if no handler has been registered with the 125 * {@link #getDefaultManager() default manager} for the input format 126 * @throws IllegalStateException if a data format error occurs during stream creation 127 * @throws java.io.UncheckedIOException if an I/O error occurs during stream creation 128 * @see BoundaryIOManager3D#facets(GeometryInput, GeometryFormat) 129 */ 130 public static Stream<FacetDefinition> facets(final Path path) { 131 return facets(new FileGeometryInput(path), null); 132 } 133 134 /** Return a {@link Stream} providing access to all facets from the given URL. he data format 135 * is determined by the file extension of the argument. 136 * 137 * <p>The underlying input stream is closed when the returned stream is closed. Callers should 138 * therefore use the returned stream in a try-with-resources statement to ensure that all 139 * resources are properly released. Ex: 140 * </p> 141 * <pre> 142 * try (Stream<FacetDefinition> stream = IO3D.facets(url)) { 143 * // access stream content 144 * } 145 * </pre> 146 * <p>The following exceptions may be thrown during stream iteration: 147 * <ul> 148 * <li>{@link IllegalStateException} if a data format error occurs</li> 149 * <li>{@link java.io.UncheckedIOException UncheckedIOException} if an I/O error occurs</li> 150 * </ul> 151 * @param url URL to read from 152 * @return stream providing access to the facets from the specified URL 153 * @throws IllegalArgumentException if no handler has been registered with the 154 * {@link #getDefaultManager() default manager} for the input format 155 * @throws IllegalStateException if a data format error occurs during stream creation 156 * @throws java.io.UncheckedIOException if an I/O error occurs during stream creation 157 * @see BoundaryIOManager3D#facets(GeometryInput, GeometryFormat) 158 */ 159 public static Stream<FacetDefinition> facets(final URL url) { 160 return facets(new UrlGeometryInput(url), null); 161 } 162 163 /** Return a {@link Stream} providing access to all facets from the given input. The underlying input 164 * stream is closed when the returned stream is closed. Callers should therefore use the returned stream 165 * in a try-with-resources statement to ensure that all resources are properly released. 166 * <pre> 167 * try (Stream<FacetDefinition> stream = IO3D.facets(in, fmt)) { 168 * // access stream content 169 * } 170 * </pre> 171 * <p>The following exceptions may be thrown during stream iteration: 172 * <ul> 173 * <li>{@link IllegalStateException} if a data format error occurs</li> 174 * <li>{@link java.io.UncheckedIOException UncheckedIOException} if an I/O error occurs</li> 175 * </ul> 176 * @param in input to read from 177 * @param fmt format of the input; if null, the format is determined implicitly from the 178 * file extension of the input {@link GeometryInput#getFileName() file name} 179 * @return stream providing access to the facets in the input 180 * @throws IllegalArgumentException if no read handler has been registered with the 181 * {@link #getDefaultManager() default manager} for the input format 182 * @throws IllegalStateException if a data format error occurs during stream creation 183 * @throws java.io.UncheckedIOException if an I/O error occurs during stream creation 184 * @see BoundaryIOManager3D#facets(GeometryInput, GeometryFormat) 185 */ 186 public static Stream<FacetDefinition> facets(final GeometryInput in, final GeometryFormat fmt) { 187 return getDefaultManager().facets(in, fmt); 188 } 189 190 /** Return a {@link Stream} providing access to all boundaries from the given file path. The 191 * data format is determined by the file extension of the argument. 192 * 193 * <p>The underlying input stream is closed when the returned stream is closed. Callers should 194 * therefore use the returned stream in a try-with-resources statement to ensure that all 195 * resources are properly released. Ex: 196 * </p> 197 * <pre> 198 * try (Stream<PlaneConvexSubset> stream = IO3D.boundaries(path, precision)) { 199 * // access stream content 200 * } 201 * </pre> 202 * <p>The following exceptions may be thrown during stream iteration: 203 * <ul> 204 * <li>{@link IllegalArgumentException} if mathematically invalid data is encountered</li> 205 * <li>{@link IllegalStateException} if a data format error occurs</li> 206 * <li>{@link java.io.UncheckedIOException UncheckedIOException} if an I/O error occurs</li> 207 * </ul> 208 * @param path file path to read from 209 * @param precision precision context used for floating point comparisons 210 * @return stream providing access to the boundaries in the specified file 211 * @throws IllegalArgumentException if no read handler has been registered with the 212 * {@link #getDefaultManager() default manager} for the input format 213 * @throws IllegalStateException if a data format error occurs during stream creation 214 * @throws java.io.UncheckedIOException if an I/O error occurs during stream creation 215 * @see BoundaryIOManager3D#boundaries(GeometryInput, GeometryFormat, Precision.DoubleEquivalence) 216 */ 217 public static Stream<PlaneConvexSubset> boundaries(final Path path, final Precision.DoubleEquivalence precision) { 218 return boundaries(new FileGeometryInput(path), null, precision); 219 } 220 221 /** Return a {@link Stream} providing access to all boundaries from the given URL. The data 222 * format is determined by the file extension of the argument. 223 * 224 * <p>The underlying input stream is closed when the returned stream is closed. Callers should 225 * therefore use the returned stream in a try-with-resources statement to ensure that all 226 * resources are properly released. Ex: 227 * </p> 228 * <pre> 229 * try (Stream<PlaneConvexSubset> stream = IO3D.boundaries(url, precision)) { 230 * // access stream content 231 * } 232 * </pre> 233 * <p>The following exceptions may be thrown during stream iteration: 234 * <ul> 235 * <li>{@link IllegalArgumentException} if mathematically invalid data is encountered</li> 236 * <li>{@link IllegalStateException} if a data format error occurs</li> 237 * <li>{@link java.io.UncheckedIOException UncheckedIOException} if an I/O error occurs</li> 238 * </ul> 239 * @param url URL to read from 240 * @param precision precision context used for floating point comparisons 241 * @return stream providing access to the boundaries in the specified URL 242 * @throws IllegalArgumentException if no read handler has been registered with the 243 * {@link #getDefaultManager() default manager} for the input format 244 * @throws IllegalStateException if a data format error occurs during stream creation 245 * @throws java.io.UncheckedIOException if an I/O error occurs during stream creation 246 * @see BoundaryIOManager3D#boundaries(GeometryInput, GeometryFormat, Precision.DoubleEquivalence) 247 */ 248 public static Stream<PlaneConvexSubset> boundaries(final URL url, final Precision.DoubleEquivalence precision) { 249 return boundaries(new UrlGeometryInput(url), null, precision); 250 } 251 252 /** Return a {@link Stream} providing access to all boundaries from the given input. The underlying input 253 * stream is closed when the returned stream is closed. Callers should therefore use the returned stream 254 * in a try-with-resources statement to ensure that all resources are properly released. Ex: 255 * <pre> 256 * try (Stream<H> stream = IO3D.boundaries(in, fmt, precision)) { 257 * // access stream content 258 * } 259 * </pre> 260 * <p>The following exceptions may be thrown during stream iteration: 261 * <ul> 262 * <li>{@link IllegalArgumentException} if mathematically invalid data is encountered</li> 263 * <li>{@link IllegalStateException} if a data format error occurs</li> 264 * <li>{@link java.io.UncheckedIOException UncheckedIOException} if an I/O error occurs</li> 265 * </ul> 266 * @param in input to read boundaries from 267 * @param fmt format of the input; if null, the format is determined implicitly from the 268 * file extension of the input {@link GeometryInput#getFileName() file name} 269 * @param precision precision context used for floating point comparisons 270 * @return stream providing access to the boundaries in the input 271 * @throws IllegalArgumentException if no read handler is registered with the 272 * {@link #getDefaultManager() default manager} for the input format 273 * @throws IllegalStateException if a data format error occurs during stream creation 274 * @throws java.io.UncheckedIOException if an I/O error occurs during stream creation 275 * @see BoundaryIOManager3D#boundaries(GeometryInput, GeometryFormat, Precision.DoubleEquivalence) 276 */ 277 public static Stream<PlaneConvexSubset> boundaries(final GeometryInput in, final GeometryFormat fmt, 278 final Precision.DoubleEquivalence precision) { 279 return getDefaultManager().boundaries(in, fmt, precision); 280 } 281 282 /** Return a {@link Stream} providing access to all triangles from the given file path. The data 283 * format is determined by the file extension of the argument. 284 * 285 * <p>The underlying input stream is closed when the returned stream is closed. Callers should 286 * therefore use the returned stream in a try-with-resources statement to ensure that all 287 * resources are properly released. Ex: 288 * </p> 289 * <pre> 290 * try (Stream<Triangle3D> stream = IO3D.triangles(path, precision)) { 291 * // access stream content 292 * } 293 * </pre> 294 * <p>The following exceptions may be thrown during stream iteration: 295 * <ul> 296 * <li>{@link IllegalArgumentException} if mathematically invalid data is encountered</li> 297 * <li>{@link IllegalStateException} if a data format error occurs</li> 298 * <li>{@link java.io.UncheckedIOException UncheckedIOException} if an I/O error occurs</li> 299 * </ul> 300 * @param path file path to read from 301 * @param precision precision context used for floating point comparisons 302 * @return stream providing access to the triangles in the specified file 303 * @throws IllegalArgumentException if no read handler is registered with the 304 * {@link #getDefaultManager() default manager} for the input format 305 * @throws IllegalStateException if a data format error occurs during stream creation 306 * @throws java.io.UncheckedIOException if an I/O error occurs during stream creation 307 * @see BoundaryIOManager3D#triangles(GeometryInput, GeometryFormat, Precision.DoubleEquivalence) 308 */ 309 public static Stream<Triangle3D> triangles(final Path path, final Precision.DoubleEquivalence precision) { 310 return triangles(new FileGeometryInput(path), null, precision); 311 } 312 313 /** Return a {@link Stream} providing access to all triangles from the given URL. The data format 314 * is determined by the file extension of the argument. 315 * 316 * <p>The underlying input stream is closed when the returned stream is closed. Callers should 317 * therefore use the returned stream in a try-with-resources statement to ensure that all 318 * resources are properly released. Ex: 319 * </p> 320 * <pre> 321 * try (Stream<Triangle3D> stream = IO3D.triangles(url, precision)) { 322 * // access stream content 323 * } 324 * </pre> 325 * <p>The following exceptions may be thrown during stream iteration: 326 * <ul> 327 * <li>{@link IllegalArgumentException} if mathematically invalid data is encountered</li> 328 * <li>{@link IllegalStateException} if a data format error occurs</li> 329 * <li>{@link java.io.UncheckedIOException UncheckedIOException} if an I/O error occurs</li> 330 * </ul> 331 * @param url URL to read from 332 * @param precision precision context used for floating point comparisons 333 * @return stream providing access to the triangles from the specified URL 334 * @throws IllegalArgumentException if no read handler is registered with the 335 * {@link #getDefaultManager() default manager} for the input format 336 * @throws IllegalStateException if a data format error occurs during stream creation 337 * @throws java.io.UncheckedIOException if an I/O error occurs during stream creation 338 * @see BoundaryIOManager3D#triangles(GeometryInput, GeometryFormat, Precision.DoubleEquivalence) 339 */ 340 public static Stream<Triangle3D> triangles(final URL url, final Precision.DoubleEquivalence precision) { 341 return triangles(new UrlGeometryInput(url), null, precision); 342 } 343 344 /** Return a {@link Stream} providing access to all triangles from the given input. The underlying input 345 * stream is closed when the returned stream is closed. Callers should therefore use the returned stream 346 * in a try-with-resources statement to ensure that all resources are properly released. 347 * <pre> 348 * try (Stream<Triangle3D> stream = IO3D.triangles(in, fmt, precision)) { 349 * // access stream content 350 * } 351 * </pre> 352 * <p>The following exceptions may be thrown during stream iteration: 353 * <ul> 354 * <li>{@link IllegalArgumentException} if mathematically invalid data is encountered</li> 355 * <li>{@link IllegalStateException} if a data format error occurs</li> 356 * <li>{@link java.io.UncheckedIOException UncheckedIOException} if an I/O error occurs</li> 357 * </ul> 358 * @param in input to read from 359 * @param fmt format of the input; if null, the format is determined implicitly from the 360 * file extension of the input {@link GeometryInput#getFileName() file name} 361 * @param precision precision context used for floating point comparisons 362 * @return stream providing access to the triangles in the input 363 * @throws IllegalArgumentException if no read handler is registered with the 364 * {@link #getDefaultManager() default manager} for the input format 365 * @throws IllegalStateException if a data format error occurs during stream creation 366 * @throws java.io.UncheckedIOException if an I/O error occurs during stream creation 367 * @see BoundaryIOManager3D#triangles(GeometryInput, GeometryFormat, Precision.DoubleEquivalence) 368 */ 369 public static Stream<Triangle3D> triangles(final GeometryInput in, final GeometryFormat fmt, 370 final Precision.DoubleEquivalence precision) { 371 return getDefaultManager().triangles(in, fmt, precision); 372 } 373 374 /** Return a {@link BoundarySource3D} containing all boundaries from the file at the 375 * given path. The data format is determined from the file extension. A runtime exception may be 376 * thrown if mathematically invalid boundaries are encountered. 377 * @param path file path to read from 378 * @param precision precision context used for floating point comparisons 379 * @return object containing all boundaries from the file at the given path 380 * @throws IllegalArgumentException if mathematically invalid data is encountered or no read handler 381 * is registered with the {@link #getDefaultManager() default manager} for the input format 382 * @throws IllegalStateException if a data format error occurs 383 * @throws java.io.UncheckedIOException if an I/O error occurs 384 * @see BoundaryIOManager3D#read(GeometryInput, GeometryFormat, Precision.DoubleEquivalence) 385 */ 386 public static BoundarySource3D read(final Path path, final Precision.DoubleEquivalence precision) { 387 return read(new FileGeometryInput(path), null, precision); 388 } 389 390 /** Return a {@link BoundarySource3D} containing all boundaries from the given URL. The data 391 * format is determined from the file extension of the URL path. A runtime exception may be 392 * thrown if mathematically invalid boundaries are encountered. 393 * @param url URL to read from 394 * @param precision precision context used for floating point comparisons 395 * @return object containing all boundaries from the given URL 396 * @throws IllegalArgumentException if mathematically invalid data is encountered or no read handler 397 * is registered with the {@link #getDefaultManager() default manager} for the input format 398 * @throws IllegalStateException if a data format error occurs 399 * @throws java.io.UncheckedIOException if an I/O error occurs 400 * @see BoundaryIOManager3D#read(GeometryInput, GeometryFormat, Precision.DoubleEquivalence) 401 */ 402 public static BoundarySource3D read(final URL url, final Precision.DoubleEquivalence precision) { 403 return read(new UrlGeometryInput(url), null, precision); 404 } 405 406 /** Return a {@link BoundarySource3D} containing all boundaries from the given input. A runtime 407 * exception may be thrown if mathematically invalid boundaries are encountered. 408 * @param in input to read boundaries from 409 * @param fmt format of the input; if null, the format is determined implicitly from the 410 * file extension of the input {@link GeometryInput#getFileName() file name} 411 * @param precision precision context used for floating point comparisons 412 * @return object containing all boundaries from the input 413 * @throws IllegalArgumentException if mathematically invalid data is encountered or no read handler 414 * is registered with the {@link #getDefaultManager() default manager} for the input format 415 * @throws IllegalStateException if a data format error occurs 416 * @throws java.io.UncheckedIOException if an I/O error occurs 417 * @see BoundaryIOManager3D#read(GeometryInput, GeometryFormat, Precision.DoubleEquivalence) 418 */ 419 public static BoundarySource3D read(final GeometryInput in, final GeometryFormat fmt, 420 final Precision.DoubleEquivalence precision) { 421 return getDefaultManager().read(in, fmt, precision); 422 } 423 424 /** Return a {@link TriangleMesh} containing all triangles from the given file path. The data 425 * format is determined from the file extension of the path. A runtime exception may be 426 * thrown if mathematically invalid boundaries are encountered. 427 * @param path file path to read from 428 * @param precision precision context used for floating point comparisons 429 * @return mesh containing all triangles from the given file path 430 * @throws IllegalArgumentException if mathematically invalid data is encountered or no read handler 431 * is registered with the {@link #getDefaultManager() default manager} for the input format 432 * @throws IllegalStateException if a data format error occurs 433 * @throws java.io.UncheckedIOException if an I/O error occurs 434 * @see BoundaryIOManager3D#readTriangleMesh(GeometryInput, GeometryFormat, Precision.DoubleEquivalence) 435 */ 436 public static TriangleMesh readTriangleMesh(final Path path, final Precision.DoubleEquivalence precision) { 437 return readTriangleMesh(new FileGeometryInput(path), null, precision); 438 } 439 440 /** Return a {@link TriangleMesh} containing all triangles from the given URL. The data 441 * format is determined from the file extension of the URL path. A runtime exception may be 442 * thrown if mathematically invalid boundaries are encountered. 443 * @param url URL to read from 444 * @param precision precision context used for floating point comparisons 445 * @return mesh containing all triangles from the given URL 446 * @throws IllegalArgumentException if mathematically invalid data is encountered or no read handler 447 * is registered with the {@link #getDefaultManager() default manager} for the input format 448 * @throws IllegalStateException if a data format error occurs 449 * @throws java.io.UncheckedIOException if an I/O error occurs 450 * @see BoundaryIOManager3D#readTriangleMesh(GeometryInput, GeometryFormat, Precision.DoubleEquivalence) 451 */ 452 public static TriangleMesh readTriangleMesh(final URL url, final Precision.DoubleEquivalence precision) { 453 return readTriangleMesh(new UrlGeometryInput(url), null, precision); 454 } 455 456 /** Return a {@link TriangleMesh} containing all triangles from the given input. A runtime exception 457 * may be thrown if mathematically invalid boundaries are encountered. 458 * @param in input to read from 459 * @param fmt format of the input; if null, the format is determined implicitly from the 460 * file extension of the input {@link GeometryInput#getFileName() file name} 461 * @param precision precision context used for floating point comparisons 462 * @return a mesh containing all triangles from the input 463 * @throws IllegalArgumentException if mathematically invalid data is encountered or no read handler 464 * is registered with the {@link #getDefaultManager() default manager} for the input format 465 * @throws IllegalStateException if a data format error occurs 466 * @throws java.io.UncheckedIOException if an I/O error occurs 467 * @see BoundaryIOManager3D#readTriangleMesh(GeometryInput, GeometryFormat, Precision.DoubleEquivalence) 468 */ 469 public static TriangleMesh readTriangleMesh(final GeometryInput in, final GeometryFormat fmt, 470 final Precision.DoubleEquivalence precision) { 471 return getDefaultManager().readTriangleMesh(in, fmt, precision); 472 } 473 474 /** Write all boundaries in the stream to given file path. The data format is determined by 475 * the file extension of the target path. If the target path already exists, it is overwritten. 476 * 477 * <p>This method does not explicitly close the {@code boundaries} stream. Callers should use the stream 478 * in a try-with-resources statement outside of this method if the stream is required to be closed.</p> 479 * @param boundaries stream containing boundaries to write 480 * @param path file path to write to 481 * @throws IllegalArgumentException if no write handler is registered with the 482 * {@link #getDefaultManager() default manager} for the output format 483 * @throws java.io.UncheckedIOException if an I/O error occurs 484 * @see BoundaryIOManager3D#write(Stream, GeometryOutput, GeometryFormat) 485 */ 486 public static void write(final Stream<? extends PlaneConvexSubset> boundaries, final Path path) { 487 write(boundaries, new FileGeometryOutput(path), null); 488 } 489 490 /** Write all boundaries in the stream to the output. 491 * 492 * <p>This method does not explicitly close the {@code boundaries} stream. Callers should use the stream 493 * in a try-with-resources statement outside of this method if the stream is required to be closed.</p> 494 * @param boundaries stream containing boundaries to write 495 * @param out output to write to 496 * @param fmt format of the output; if null, the format is determined implicitly from the 497 * file extension of the output {@link GeometryOutput#getFileName() file name} 498 * @throws IllegalArgumentException if no write handler is registered with the 499 * {@link #getDefaultManager() default manager} for the output format 500 * @throws java.io.UncheckedIOException if an I/O error occurs 501 * @see BoundaryIOManager3D#write(Stream, GeometryOutput, GeometryFormat) 502 */ 503 public static void write(final Stream<? extends PlaneConvexSubset> boundaries, final GeometryOutput out, 504 final GeometryFormat fmt) { 505 getDefaultManager().write(boundaries, out, fmt); 506 } 507 508 /** Write all boundaries from {@code src} to the given file path. The data format 509 * is determined by the file extension of the target path. If the target path already exists, 510 * it is overwritten. 511 * @param src boundary source containing the boundaries to write 512 * @param path file path to write to 513 * @throws IllegalArgumentException if no write handler is registered with the 514 * {@link #getDefaultManager() default manager} for the output format 515 * @throws java.io.UncheckedIOException if an I/O error occurs 516 * @see org.apache.commons.geometry.io.core.BoundaryIOManager#write( 517 * org.apache.commons.geometry.core.partitioning.BoundarySource, GeometryOutput, GeometryFormat) 518 */ 519 public static void write(final BoundarySource3D src, final Path path) { 520 write(src, new FileGeometryOutput(path), null); 521 } 522 523 /** Write all boundaries from {@code src} to the given output. 524 * @param src boundary source containing the boundaries to write 525 * @param out output to write to 526 * @param fmt format of the output; if null, the format is determined implicitly from the 527 * file extension of the output {@link GeometryOutput#getFileName() file name} 528 * @throws IllegalArgumentException if no write handler is registered with the 529 * {@link #getDefaultManager() default manager} for the output format 530 * @throws java.io.UncheckedIOException if an I/O error occurs 531 * @see org.apache.commons.geometry.io.core.BoundaryIOManager#write( 532 * org.apache.commons.geometry.core.partitioning.BoundarySource, GeometryOutput, GeometryFormat) 533 */ 534 public static void write(final BoundarySource3D src, final GeometryOutput out, final GeometryFormat fmt) { 535 getDefaultManager().write(src, out, fmt); 536 } 537 538 /** Write the given facets to the file path. The data format is determined by the file extension of 539 * the target path. If the target path already exists, it is overwritten. 540 * @param facets facets to write 541 * @param path path to write to 542 * @throws IllegalArgumentException if no write handler is registered with the 543 * {@link #getDefaultManager() default manager} for the output format 544 * @throws java.io.UncheckedIOException if an I/O error occurs 545 * @see BoundaryIOManager3D#writeFacets(Collection, GeometryOutput, GeometryFormat) 546 */ 547 public static void writeFacets(final Collection<? extends FacetDefinition> facets, final Path path) { 548 writeFacets(facets, new FileGeometryOutput(path), null); 549 } 550 551 /** Write the given collection of facets to the output. 552 * @param facets facets to write 553 * @param out output to write to 554 * @param fmt format of the output; if null, the format is determined implicitly from the 555 * file extension of the output {@link GeometryOutput#getFileName() file name} 556 * @throws IllegalArgumentException if no write handler is registered with the 557 * {@link #getDefaultManager() default manager} for the output format 558 * @throws java.io.UncheckedIOException if an I/O error occurs 559 * @see BoundaryIOManager3D#writeFacets(Collection, GeometryOutput, GeometryFormat) 560 */ 561 public static void writeFacets(final Collection<? extends FacetDefinition> facets, final GeometryOutput out, 562 final GeometryFormat fmt) { 563 getDefaultManager().writeFacets(facets, out, fmt); 564 } 565 566 /** Write all facets in the stream to the file path. The data format is determined by the file 567 * extension of the target path. If the target path already exists, it is overwritten. 568 * 569 * <p>This method does not explicitly close the {@code facets} stream. Callers should use the stream 570 * in a try-with-resources statement outside of this method if the stream is required to be closed.</p> 571 * @param facets stream containing facets to write 572 * @param path path to write to 573 * @throws IllegalArgumentException if no write handler is registered with the 574 * {@link #getDefaultManager() default manager} for the output format 575 * @throws java.io.UncheckedIOException if an I/O error occurs 576 * @see BoundaryIOManager3D#writeFacets(Stream, GeometryOutput, GeometryFormat) 577 */ 578 public static void writeFacets(final Stream<? extends FacetDefinition> facets, final Path path) { 579 writeFacets(facets, new FileGeometryOutput(path), null); 580 } 581 582 /** Write all facets in the stream to the output. 583 * 584 * <p>This method does not explicitly close the {@code facets} stream. Callers should use the stream 585 * in a try-with-resources statement outside of this method if the stream is required to be closed.</p> 586 * @param facets stream containing facets to write 587 * @param out output to write to 588 * @param fmt format of the output; if null, the format is determined implicitly from the 589 * file extension of the output {@link GeometryOutput#getFileName() file name} 590 * @throws IllegalArgumentException if no write handler is registered with the 591 * {@link #getDefaultManager() default manager} for the output format 592 * @throws java.io.UncheckedIOException if an I/O error occurs 593 * @see BoundaryIOManager3D#writeFacets(Stream, GeometryOutput, GeometryFormat) 594 */ 595 public static void writeFacets(final Stream<? extends FacetDefinition> facets, final GeometryOutput out, 596 final GeometryFormat fmt) { 597 getDefaultManager().writeFacets(facets, out, fmt); 598 } 599 600 /** Get the default {@link BoundaryIOManager3D} instance. 601 * @return the default {@link BoundaryIOManager3D} instance 602 */ 603 public static BoundaryIOManager3D getDefaultManager() { 604 return ManagerHolder.DEFAULT_MANAGER; 605 } 606 607 /** Class holding a reference to the default IO manager instance. 608 */ 609 private static final class ManagerHolder { 610 611 /** Default IO manager instance. */ 612 private static final BoundaryIOManager3D DEFAULT_MANAGER; 613 614 static { 615 DEFAULT_MANAGER = new BoundaryIOManager3D(); 616 DEFAULT_MANAGER.registerDefaultHandlers(); 617 } 618 619 /** Utility class; no instantiation. */ 620 private ManagerHolder() {} 621 } 622 }