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 org.apache.commons.geometry.core.Transform;
    20  import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
    21  import org.apache.commons.geometry.euclidean.threed.Bounds3D;
    22  import org.apache.commons.geometry.euclidean.threed.Vector3D;
    23
    24  /** Class representing a line segment in 3D Euclidean space. A line segment is a portion of
    25   * a line with finite start and end points.
    26   *
    27   * <p>Instances of this class are guaranteed to be immutable.</p>
    28   * @see Lines3D
    29   * @see <a href="https://en.wikipedia.org/wiki/Line_segment">Line Segment</a>
    30   */
    31  public final class Segment3D extends LineConvexSubset3D {
    32
    33      /** Start abscissa for the segment. */
    34      private final double start;
    35
    36      /** End abscissa for the segment. */
    37      private final double end;
    38
    39      /** Construct a new instance from a line and two points on the line. The points are projected onto
    40       * the line and must be in order of increasing abscissa. No validation is performed.
    41       * @param line line for the segment
    42       * @param startPoint segment start point
    43       * @param endPoint segment end point
    44       */
    45      Segment3D(final Line3D line, final Vector3D startPoint, final Vector3D endPoint) {
    46          this(line, line.abscissa(startPoint), line.abscissa(endPoint));
    47      }
    48
    49      /** Construct a new instance from a line and two abscissa locations on the line.
    50       * The abscissa locations must be in increasing order. No validation is performed.
    51       * @param line line for the segment
    52       * @param start abscissa start location
    53       * @param end abscissa end location
    54       */
    55      Segment3D(final Line3D line, final double start, final double end) {
    56          super(line);
    57
    58          this.start = start;
    59          this.end = end;
    60      }
    61
    62      /** {@inheritDoc}
    63      *
    64      * <p>This method always returns {@code false}.</p>
    65      */
    66      @Override
    67      public boolean isInfinite() {
    68          return false;
    69      }
    70
    71      /** {@inheritDoc}
    72       *
    73       * <p>This method always returns {@code true}.</p>
    74       */
    75      @Override
    76      public boolean isFinite() {
    77          return true;
    78      }
    79
    80      /** {@inheritDoc} */
    81      @Override
    82      public Vector3D getStartPoint() {
    83          return getLine().toSpace(start);
    84      }
    85
    86      /** {@inheritDoc} */
    87      @Override
    88      public double getSubspaceStart() {
    89          return start;
    90      }
    91
    92      /** {@inheritDoc} */
    93      @Override
    94      public Vector3D getEndPoint() {
    95          return getLine().toSpace(end);
    96      }
    97
    98      /** {@inheritDoc} */
    99      @Override
    100     public double getSubspaceEnd() {
    101         return end;
    102     }
    103
    104     /** {@inheritDoc} */
    105     @Override
    106     public double getSize() {
    107         return end - start;
    108     }
    109
    110     /** {@inheritDoc} */
    111     @Override
    112     public Vector3D getCentroid() {
    113         return getLine().toSpace((0.5 * (end - start)) + start);
    114     }
    115
    116     /** {@inheritDoc} */
    117     @Override
    118     public Bounds3D getBounds() {
    119         return Bounds3D.builder()
    120                 .add(getStartPoint())
    121                 .add(getEndPoint())
    122                 .build();
    123     }
    124
    125     /** {@inheritDoc} */
    126     @Override
    127     public Segment3D transform(final Transform<Vector3D> transform) {
    128         final Vector3D t1 = transform.apply(getStartPoint());
    129         final Vector3D t2 = transform.apply(getEndPoint());
    130
    131         final Line3D tLine = getLine().transform(transform);
    132
    133         return new Segment3D(tLine, t1, t2);
    134     }
    135
    136     /** {@inheritDoc} */
    137     @Override
    138     public String toString() {
    139         final StringBuilder sb = new StringBuilder();
    140         sb.append(getClass().getSimpleName())
    141             .append("[startPoint= ")
    142             .append(getStartPoint())
    143             .append(", endPoint= ")
    144             .append(getEndPoint())
    145             .append(']');
    146
    147         return sb.toString();
    148     }
    149
    150     /** {@inheritDoc} */
    151     @Override
    152     boolean containsAbscissa(final double abscissa) {
    153         final DoublePrecisionContext precision = getLine().getPrecision();
    154         return precision.gte(abscissa, start) &&
    155                 precision.lte(abscissa, end);
    156     }
    157 }