View Javadoc
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.euclidean.threed.line;
18  
19  import java.util.ArrayList;
20  import java.util.List;
21  
22  import org.apache.commons.geometry.core.Transform;
23  import org.apache.commons.geometry.euclidean.oned.Interval;
24  import org.apache.commons.geometry.euclidean.oned.RegionBSPTree1D;
25  import org.apache.commons.geometry.euclidean.oned.Vector1D;
26  import org.apache.commons.geometry.euclidean.threed.Bounds3D;
27  import org.apache.commons.geometry.euclidean.threed.Vector3D;
28  import org.apache.commons.geometry.euclidean.threed.line.Line3D.SubspaceTransform;
29  
30  /** Class representing an arbitrary subset of a line in 3D Euclidean space using a
31   * {@link RegionBSPTree1D}. This class can represent convex, non-convex, finite,
32   * infinite, and empty regions.
33   *
34   * <p>This class is mutable and <em>not</em> thread safe.</p>
35   */
36  public final class EmbeddedTreeLineSubset3D extends LineSubset3D {
37      /** The 1D region representing the area on the line. */
38      private final RegionBSPTree1D region;
39  
40      /** Construct a new, empty subset for the given line.
41       * @param line line defining the subset
42       */
43      public EmbeddedTreeLineSubset3D(final Line3D line) {
44          this(line, false);
45      }
46  
47      /** Construct a new subset for the given line. If {@code full}
48       * is true, then the subset will cover the entire line; otherwise,
49       * it will be empty.
50       * @param line line defining the subset
51       * @param full if true, the subset will cover the entire space;
52       *      otherwise it will be empty
53       */
54      public EmbeddedTreeLineSubset3D(final Line3D line, final boolean full) {
55          this(line, new RegionBSPTree1D(full));
56      }
57  
58      /** Construct a new instance from its defining line and subspace region.
59       * @param line line defining the subset
60       * @param region subspace region for the subset
61       */
62      public EmbeddedTreeLineSubset3D(final Line3D line, final RegionBSPTree1D region) {
63          super(line);
64  
65          this.region = region;
66      }
67  
68      /** {@inheritDoc} */
69      @Override
70      public double getSize() {
71          return region.getSize();
72      }
73  
74      /** {@inheritDoc} */
75      @Override
76      public RegionBSPTree1D getSubspaceRegion() {
77          return region;
78      }
79  
80      /** {@inheritDoc} */
81      @Override
82      public Vector3D getCentroid() {
83          final Vector1D subcenter = region.getCentroid();
84          return subcenter != null ?
85                  getLine().toSpace(subcenter) :
86                  null;
87      }
88  
89      /** {@inheritDoc} */
90      @Override
91      public Bounds3D getBounds() {
92          final double min = region.getMin();
93          final double max = region.getMax();
94  
95          if (Double.isFinite(min) && Double.isFinite(max)) {
96              final Line3D line = getLine();
97  
98              return Bounds3D.builder()
99                      .add(line.toSpace(min))
100                     .add(line.toSpace(max))
101                     .build();
102         }
103 
104         return null;
105     }
106 
107     /** Transform this instance.
108      * @param transform the transform to apply
109      * @return a new, transformed instance
110      */
111     public EmbeddedTreeLineSubset3D transform(final Transform<Vector3D> transform) {
112         final SubspaceTransform st = getLine().subspaceTransform(transform);
113 
114         final RegionBSPTree1D tRegion = RegionBSPTree1D.empty();
115         tRegion.copy(region);
116         tRegion.transform(st.getTransform());
117 
118         return new EmbeddedTreeLineSubset3D(st.getLine(), tRegion);
119     }
120 
121     /** Return a list of {@link LineConvexSubset3D} instances representing the same region
122      * as this instance.
123      * @return a list of {@link LineConvexSubset3D} instances representing the same region
124      *      as this instance.
125      */
126     public List<LineConvexSubset3D> toConvex() {
127         final List<Interval> intervals = region.toIntervals();
128 
129         final Line3D line = getLine();
130         final List<LineConvexSubset3D> convex = new ArrayList<>(intervals.size());
131 
132         for (final Interval interval : intervals) {
133             convex.add(Lines3D.subsetFromInterval(line, interval));
134         }
135 
136         return convex;
137     }
138 
139     /** {@inheritDoc} */
140     @Override
141     public String toString() {
142         final Line3D line = getLine();
143 
144         final StringBuilder sb = new StringBuilder();
145         sb.append(this.getClass().getSimpleName())
146             .append('[')
147             .append("lineOrigin= ")
148             .append(line.getOrigin())
149             .append(", lineDirection= ")
150             .append(line.getDirection())
151             .append(", region= ")
152             .append(region)
153             .append(']');
154 
155         return sb.toString();
156     }
157 }