GreatArc.java
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.apache.commons.geometry.spherical.twod;
- import java.util.Collections;
- import java.util.List;
- import org.apache.commons.geometry.core.Transform;
- import org.apache.commons.geometry.core.partitioning.Hyperplane;
- import org.apache.commons.geometry.core.partitioning.HyperplaneConvexSubset;
- import org.apache.commons.geometry.core.partitioning.Split;
- import org.apache.commons.geometry.core.partitioning.SplitLocation;
- import org.apache.commons.geometry.spherical.oned.AngularInterval;
- import org.apache.commons.geometry.spherical.oned.CutAngle;
- import org.apache.commons.geometry.spherical.oned.CutAngles;
- import org.apache.commons.geometry.spherical.oned.Transform1S;
- /** Class representing a single, <em>convex</em> angular interval in a {@link GreatCircle}. Convex
- * angular intervals are those where the shortest path between all pairs of points in the
- * interval are completely contained in the interval. In the case of paths that tie for the
- * shortest length, it is sufficient that one of the paths is completely contained in the
- * interval. In spherical 2D space, convex arcs either fill the entire great circle or have
- * an angular size of less than or equal to {@code pi} radians.
- *
- * <p>Instances of this class are guaranteed to be immutable.</p>
- * @see GreatCircles
- */
- public final class GreatArc extends GreatCircleSubset implements HyperplaneConvexSubset<Point2S> {
- /** The interval representing the region of the great circle contained in the arc.
- */
- private final AngularInterval.Convex interval;
- /** Create a new instance from a great circle and the interval embedded in it.
- * @param circle defining great circle instance
- * @param interval convex angular interval embedded in the great circle
- */
- GreatArc(final GreatCircle circle, final AngularInterval.Convex interval) {
- super(circle);
- this.interval = interval;
- }
- /** Return the start point of the arc, or null if the arc represents the full space.
- * @return the start point of the arc, or null if the arc represents the full space.
- */
- public Point2S getStartPoint() {
- if (!interval.isFull()) {
- return getCircle().toSpace(interval.getMinBoundary().getPoint());
- }
- return null;
- }
- /** Return the end point of the arc, or null if the arc represents the full space.
- * @return the end point of the arc, or null if the arc represents the full space.
- */
- public Point2S getEndPoint() {
- if (!interval.isFull()) {
- return getCircle().toSpace(interval.getMaxBoundary().getPoint());
- }
- return null;
- }
- /** Return the midpoint of the arc, or null if the arc represents the full space.
- * @return the midpoint of the arc, or null if the arc represents the full space.
- */
- public Point2S getMidPoint() {
- if (!interval.isFull()) {
- return getCircle().toSpace(interval.getMidPoint());
- }
- return null;
- }
- /** Get the angular interval for the arc.
- * @return the angular interval for the arc
- * @see #getSubspaceRegion()
- */
- public AngularInterval.Convex getInterval() {
- return interval;
- }
- /** {@inheritDoc} */
- @Override
- public AngularInterval.Convex getSubspaceRegion() {
- return getInterval();
- }
- /** {@inheritDoc} */
- @Override
- public List<GreatArc> toConvex() {
- return Collections.singletonList(this);
- }
- /** {@inheritDoc} */
- @Override
- public Split<GreatArc> split(final Hyperplane<Point2S> splitter) {
- final GreatCircle splitterCircle = (GreatCircle) splitter;
- final GreatCircle thisCircle = getCircle();
- final Point2S intersection = splitterCircle.intersection(thisCircle);
- GreatArc minus = null;
- GreatArc plus = null;
- if (intersection != null) {
- // use a negative-facing cut angle to account for the fact that the great circle
- // poles point to the minus side of the circle
- final CutAngle subSplitter = CutAngles.createNegativeFacing(
- thisCircle.toSubspace(intersection), splitterCircle.getPrecision());
- final Split<AngularInterval.Convex> subSplit = interval.splitDiameter(subSplitter);
- final SplitLocation subLoc = subSplit.getLocation();
- if (subLoc == SplitLocation.MINUS) {
- minus = this;
- } else if (subLoc == SplitLocation.PLUS) {
- plus = this;
- } else if (subLoc == SplitLocation.BOTH) {
- minus = GreatCircles.arcFromInterval(thisCircle, subSplit.getMinus());
- plus = GreatCircles.arcFromInterval(thisCircle, subSplit.getPlus());
- }
- }
- return new Split<>(minus, plus);
- }
- /** {@inheritDoc} */
- @Override
- public GreatArc transform(final Transform<Point2S> transform) {
- return new GreatArc(getCircle().transform(transform), interval);
- }
- /** {@inheritDoc} */
- @Override
- public GreatArc reverse() {
- return new GreatArc(
- getCircle().reverse(),
- interval.transform(Transform1S.createNegation()));
- }
- /** Return a string representation of this great arc.
- *
- * <p>In order to keep the string representation short but useful, the exact format of the return
- * value depends on the properties of the arc. See below for examples.
- *
- * <ul>
- * <li>Full arc
- * <ul>
- * <li>{@code GreatArc[full= true, circle= GreatCircle[pole= (0.0, 0.0, 1.0), x= (1.0, 0.0, 0.0), y= (0.0, 1.0, 0.0)]}</li>
- * </ul>
- * </li>
- * <li>Non-full arc
- * <ul>
- * <li>{@code GreatArc[start= (1.0, 1.5707963267948966), end= (2.0, 1.5707963267948966)}</li>
- * </ul>
- * </li>
- * </ul>
- */
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder();
- sb.append(this.getClass().getSimpleName()).append('[');
- if (isFull()) {
- sb.append("full= true, circle= ")
- .append(getCircle());
- } else {
- sb.append("start= ")
- .append(getStartPoint())
- .append(", end= ")
- .append(getEndPoint());
- }
- return sb.toString();
- }
- }