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.twod;
018
019import java.util.Collections;
020import java.util.List;
021
022import org.apache.commons.geometry.core.Transform;
023import org.apache.commons.geometry.core.partitioning.Hyperplane;
024import org.apache.commons.geometry.core.partitioning.HyperplaneConvexSubset;
025import org.apache.commons.geometry.core.partitioning.Split;
026import org.apache.commons.geometry.euclidean.oned.Interval;
027
028/** Class representing a convex subset of a line in 2D Euclidean space. Instances
029 * need not be finite, in which case the start or end point (or both) will be null.
030 * Line segments and rays are examples of convex line subsets.
031 * @see Lines
032 */
033public abstract class LineConvexSubset extends LineSubset implements HyperplaneConvexSubset<Vector2D> {
034
035    /** Construct a new instance for the given line.
036     * @param line line containing this line subset
037     */
038    LineConvexSubset(final Line line) {
039        super(line);
040    }
041
042    /** {@inheritDoc} */
043    @Override
044    public List<LineConvexSubset> toConvex() {
045        return Collections.singletonList(this);
046    }
047
048    /** {@inheritDoc}
049     *
050     * <p>This method always returns {@code false}.</p>
051     */
052    @Override
053    public boolean isEmpty() {
054        return false;
055    }
056
057    /** Get the start point for the subset.
058     * @return the start point for the subset, or null if no start point exists
059     */
060    public abstract Vector2D getStartPoint();
061
062    /** Get the 1D start location of the subset or {@link Double#NEGATIVE_INFINITY} if
063     * no start location exists.
064     * @return the 1D start location of the subset or {@link Double#NEGATIVE_INFINITY} if
065     *      no start location exists.
066     */
067    public abstract double getSubspaceStart();
068
069    /** Get the end point for the subset.
070     * @return the end point for the subset, or null if no end point exists.
071     */
072    public abstract Vector2D getEndPoint();
073
074    /** Get the 1D end location of the subset or {@link Double#POSITIVE_INFINITY} if
075     * no end location exists.
076     * @return the 1D end location of the subset or {@link Double#POSITIVE_INFINITY} if
077     *      no end location exists
078     */
079    public abstract double getSubspaceEnd();
080
081    /** {@inheritDoc} */
082    @Override
083    public Interval getSubspaceRegion() {
084        final double start = getSubspaceStart();
085        final double end = getSubspaceEnd();
086
087        return Interval.of(start, end, getPrecision());
088    }
089
090    /** Get the 1D interval for the region. This method is an alias for {@link #getSubspaceRegion()}.
091     * @return the 1D interval for the region.
092     */
093    public Interval getInterval() {
094        return getSubspaceRegion();
095    }
096
097    /** {@inheritDoc} */
098    @Override
099    public Split<LineConvexSubset> split(final Hyperplane<Vector2D> splitter) {
100        final Line thisLine = getLine();
101        final Line splitterLine = (Line) splitter;
102
103        final Vector2D intersection = splitterLine.intersection(thisLine);
104        if (intersection == null) {
105            return getNonIntersectingSplitResult(splitterLine, this);
106        }
107        return splitOnIntersection(splitterLine, intersection);
108    }
109
110    /** {@inheritDoc} */
111    @Override
112    public Vector2D closest(final Vector2D pt) {
113        final Line line = getLine();
114        final double abscissa = line.abscissa(pt);
115
116        return line.toSpace(closestAbscissa(abscissa));
117    }
118
119    /** {@inheritDoc} */
120    @Override
121    public abstract LineConvexSubset transform(Transform<Vector2D> transform);
122
123    /** {@inheritDoc} */
124    @Override
125    public abstract LineConvexSubset reverse();
126
127    /** Get the closest value in the subspace region to the given abscissa.
128     * @param abscissa input abscissa
129     * @return the closest value in the subspace region to the given abscissa
130     */
131    abstract double closestAbscissa(double abscissa);
132
133    /** Split this instance using the given splitter line and intersection point.
134     * @param splitter splitter line
135     * @param intersection intersection point between the splitter line and the line
136     *      for this instance
137     * @return the result of splitting this instance with the given splitter line and intersection
138     *      point
139     */
140    abstract Split<LineConvexSubset> splitOnIntersection(Line splitter, Vector2D intersection);
141}