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.line; 018 019import org.apache.commons.geometry.core.Transform; 020import org.apache.commons.geometry.euclidean.threed.Bounds3D; 021import org.apache.commons.geometry.euclidean.threed.Vector3D; 022import org.apache.commons.numbers.core.Precision; 023 024/** Class representing a line segment in 3D Euclidean space. A line segment is a portion of 025 * a line with finite start and end points. 026 * 027 * <p>Instances of this class are guaranteed to be immutable.</p> 028 * @see Lines3D 029 * @see <a href="https://en.wikipedia.org/wiki/Line_segment">Line Segment</a> 030 */ 031public final class Segment3D extends LineConvexSubset3D { 032 033 /** Start abscissa for the segment. */ 034 private final double start; 035 036 /** End abscissa for the segment. */ 037 private final double end; 038 039 /** Construct a new instance from a line and two points on the line. The points are projected onto 040 * the line and must be in order of increasing abscissa. No validation is performed. 041 * @param line line for the segment 042 * @param startPoint segment start point 043 * @param endPoint segment end point 044 */ 045 Segment3D(final Line3D line, final Vector3D startPoint, final Vector3D endPoint) { 046 this(line, line.abscissa(startPoint), line.abscissa(endPoint)); 047 } 048 049 /** Construct a new instance from a line and two abscissa locations on the line. 050 * The abscissa locations must be in increasing order. No validation is performed. 051 * @param line line for the segment 052 * @param start abscissa start location 053 * @param end abscissa end location 054 */ 055 Segment3D(final Line3D line, final double start, final double end) { 056 super(line); 057 058 this.start = start; 059 this.end = end; 060 } 061 062 /** {@inheritDoc} 063 * 064 * <p>This method always returns {@code false}.</p> 065 */ 066 @Override 067 public boolean isInfinite() { 068 return false; 069 } 070 071 /** {@inheritDoc} 072 * 073 * <p>This method always returns {@code true}.</p> 074 */ 075 @Override 076 public boolean isFinite() { 077 return true; 078 } 079 080 /** {@inheritDoc} */ 081 @Override 082 public Vector3D getStartPoint() { 083 return getLine().toSpace(start); 084 } 085 086 /** {@inheritDoc} */ 087 @Override 088 public double getSubspaceStart() { 089 return start; 090 } 091 092 /** {@inheritDoc} */ 093 @Override 094 public Vector3D getEndPoint() { 095 return getLine().toSpace(end); 096 } 097 098 /** {@inheritDoc} */ 099 @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 Precision.DoubleEquivalence precision = getLine().getPrecision(); 154 return precision.gte(abscissa, start) && 155 precision.lte(abscissa, end); 156 } 157}