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 }