001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.geometry.euclidean.threed; 018 019import java.util.Arrays; 020import java.util.Collection; 021import java.util.List; 022import java.util.stream.Collectors; 023import java.util.stream.Stream; 024 025import org.apache.commons.geometry.core.partitioning.BoundarySource; 026import org.apache.commons.geometry.euclidean.threed.line.LineConvexSubset3D; 027import org.apache.commons.geometry.euclidean.threed.line.LinecastPoint3D; 028import org.apache.commons.geometry.euclidean.threed.line.Linecastable3D; 029import org.apache.commons.geometry.euclidean.threed.mesh.SimpleTriangleMesh; 030import org.apache.commons.geometry.euclidean.threed.mesh.TriangleMesh; 031import org.apache.commons.numbers.core.Precision; 032 033/** Extension of the {@link BoundarySource} interface for Euclidean 3D space. 034 */ 035public interface BoundarySource3D extends BoundarySource<PlaneConvexSubset>, Linecastable3D { 036 037 /** Return a {@link BoundaryList3D} containing the boundaries in this instance. 038 * @return a {@link BoundaryList3D} containing the boundaries in this instance 039 */ 040 default BoundaryList3D toList() { 041 final List<PlaneConvexSubset> boundaries = boundaryStream() 042 .collect(Collectors.toList()); 043 044 return new BoundaryList3D(boundaries); 045 } 046 047 /** Return a BSP tree constructed from the boundaries contained in this instance. This is 048 * a convenience method for quickly constructing BSP trees and may produce unbalanced trees 049 * with unacceptable performance characteristics when used with large numbers of boundaries. 050 * In these cases, alternate tree construction approaches should be used, such as 051 * {@link RegionBSPTree3D.PartitionedRegionBuilder3D}. 052 * @return a BSP tree constructed from the boundaries in this instance 053 * @see RegionBSPTree3D#partitionedRegionBuilder() 054 */ 055 default RegionBSPTree3D toTree() { 056 final RegionBSPTree3D tree = RegionBSPTree3D.empty(); 057 tree.insert(this); 058 059 return tree; 060 } 061 062 /** Construct a triangle mesh from the boundaries in this instance. 063 * @param precision precision context used in boundaries generated by the resulting mesh 064 * @return a triangle mesh representing the boundaries in this instance 065 * @throws IllegalStateException if any boundary in this boundary source is infinite 066 */ 067 default TriangleMesh toTriangleMesh(final Precision.DoubleEquivalence precision) { 068 return SimpleTriangleMesh.from(this, precision); 069 } 070 071 /** Return the boundaries of this instance as a stream of {@link Triangle3D} 072 * instances. An {@link IllegalStateException} exception is thrown while reading 073 * from the stream if any boundary cannot be converted to a triangle (i.e. if it 074 * has infinite size). 075 * @return a stream of triangles representing the instance boundaries 076 * @see org.apache.commons.geometry.euclidean.threed.PlaneSubset#toTriangles() 077 */ 078 default Stream<Triangle3D> triangleStream() { 079 return boundaryStream().flatMap(b -> b.toTriangles().stream()); 080 } 081 082 /** {@inheritDoc} */ 083 @Override 084 default List<LinecastPoint3D> linecast(final LineConvexSubset3D subset) { 085 return new BoundarySourceLinecaster3D(this).linecast(subset); 086 } 087 088 /** {@inheritDoc} */ 089 @Override 090 default LinecastPoint3D linecastFirst(final LineConvexSubset3D subset) { 091 return new BoundarySourceLinecaster3D(this).linecastFirst(subset); 092 } 093 094 /** Get a {@link Bounds3D} object defining the axis-aligned box containing all vertices 095 * in the boundaries for this instance. Null is returned if any boundary is infinite 096 * or no vertices are found. 097 * @return the bounding box for this instance or null if no valid bounds could be determined 098 */ 099 default Bounds3D getBounds() { 100 return new BoundarySourceBoundsBuilder3D().getBounds(this); 101 } 102 103 /** Return a {@link BoundarySource3D} instance containing the given boundaries. 104 * @param boundaries boundaries to include in the boundary source 105 * @return a boundary source containing the given boundaries 106 */ 107 static BoundarySource3D of(final PlaneConvexSubset... boundaries) { 108 return of(Arrays.asList(boundaries)); 109 } 110 111 /** Return a {@link BoundarySource3D} instance containing the given boundaries. The given 112 * collection is used directly as the source of the boundaries; no copy is made. 113 * @param boundaries boundaries to include in the boundary source 114 * @return a boundary source containing the given boundaries 115 */ 116 static BoundarySource3D of(final Collection<PlaneConvexSubset> boundaries) { 117 return boundaries::stream; 118 } 119}