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;
022
023/** Class representing a ray in 3D Euclidean space. A ray is a portion of a line consisting of
024 * a single start point and extending to infinity along the direction of the line.
025 *
026 * <p>Instances of this class are guaranteed to be immutable.</p>
027 * @see ReverseRay3D
028 * @see Lines3D
029 * @see <a href="https://en.wikipedia.org/wiki/Line_(geometry)#Ray">Ray</a>
030 */
031public final class Ray3D extends LineConvexSubset3D {
032
033    /** The start abscissa value for the ray. */
034    private final double start;
035
036    /** Construct a ray from a line and a start point. The start point is projected
037     * onto the line. No validation is performed.
038     * @param line line for the ray
039     * @param startPoint start point for the ray
040     */
041    Ray3D(final Line3D line, final Vector3D startPoint) {
042        this(line, line.abscissa(startPoint));
043    }
044
045    /** Construct a ray from a line and a 1D start location. No validation is performed.
046     * @param line line for the ray
047     * @param start 1D start location
048     */
049    Ray3D(final Line3D line, final double start) {
050        super(line);
051
052        this.start = start;
053    }
054
055    /** {@inheritDoc}
056    *
057    * <p>This method always returns {@code true}.</p>
058    */
059    @Override
060    public boolean isInfinite() {
061        return true;
062    }
063
064    /** {@inheritDoc}
065    *
066    * <p>This method always returns {@code false}.</p>
067    */
068    @Override
069    public boolean isFinite() {
070        return false;
071    }
072
073    /** {@inheritDoc}
074    *
075    * <p>This method always returns {@link Double#POSITIVE_INFINITY}.</p>
076    */
077    @Override
078    public double getSize() {
079        return Double.POSITIVE_INFINITY;
080    }
081
082    @Override
083    public Vector3D getStartPoint() {
084        return getLine().toSpace(start);
085    }
086
087    /** {@inheritDoc} */
088    @Override
089    public double getSubspaceStart() {
090        return start;
091    }
092
093    /** {@inheritDoc}
094    *
095    * <p>This method always returns {@code null}.</p>
096    */
097    @Override
098    public Vector3D getEndPoint() {
099        return null;
100    }
101
102    /** {@inheritDoc}
103    *
104    * <p>This method always returns {@link Double#POSITIVE_INFINITY}.</p>
105    */
106    @Override
107    public double getSubspaceEnd() {
108        return Double.POSITIVE_INFINITY;
109    }
110
111    /** {@inheritDoc}
112     *
113     * <p>This method always returns {@code null}.</p>
114     */
115    @Override
116    public Vector3D getCentroid() {
117        return null; // infinite; no center
118    }
119
120   /** {@inheritDoc}
121    *
122    * <p>This method always returns {@code null}.</p>
123    */
124    @Override
125    public Bounds3D getBounds() {
126        return null; // infinite; no bounds
127    }
128
129    /** Get the direction of the ray. This is a convenience method for {@code ray.getLine().getDirection()}.
130     * @return the direction of the ray
131     */
132    public Vector3D getDirection() {
133        return getLine().getDirection();
134    }
135
136    /** {@inheritDoc} */
137    @Override
138    public Ray3D transform(final Transform<Vector3D> transform) {
139        final Line3D tLine = getLine().transform(transform);
140        final Vector3D tStart = transform.apply(getStartPoint());
141
142        return new Ray3D(tLine, tStart);
143    }
144
145    /** {@inheritDoc} */
146    @Override
147    public String toString() {
148        final StringBuilder sb = new StringBuilder();
149        sb.append(getClass().getSimpleName())
150            .append("[startPoint= ")
151            .append(getStartPoint())
152            .append(", direction= ")
153            .append(getLine().getDirection())
154            .append(']');
155
156        return sb.toString();
157    }
158
159    /** {@inheritDoc} */
160    @Override
161    boolean containsAbscissa(final double abscissa) {
162        return getLine().getPrecision().gte(abscissa, start);
163    }
164}