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 * https://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
18 /*
19 * This is not the original file distributed by the Apache Software Foundation
20 * It has been modified by the Hipparchus project
21 */
22 package org.hipparchus.geometry.spherical.oned;
23
24 import org.hipparchus.exception.LocalizedCoreFormats;
25 import org.hipparchus.exception.MathIllegalArgumentException;
26 import org.hipparchus.geometry.partitioning.Region.Location;
27 import org.hipparchus.util.FastMath;
28 import org.hipparchus.util.MathUtils;
29 import org.hipparchus.util.Precision;
30
31
32 /** This class represents an arc on a circle.
33 * @see ArcsSet
34 */
35 public class Arc {
36
37 /** The lower angular bound of the arc. */
38 private final double lower;
39
40 /** The upper angular bound of the arc. */
41 private final double upper;
42
43 /** Middle point of the arc. */
44 private final double middle;
45
46 /** Tolerance below which angles are considered identical. */
47 private final double tolerance;
48
49 /** Simple constructor.
50 * <p>
51 * If either {@code lower} is equals to {@code upper} or
52 * the interval exceeds \( 2 \pi \), the arc is considered
53 * to be the full circle and its initial defining boundaries
54 * will be forgotten. {@code lower} is not allowed to be
55 * greater than {@code upper} (an exception is thrown in this case).
56 * {@code lower} will be canonicalized between 0 and \( 2 \pi \), and
57 * upper shifted accordingly, so the {@link #getInf()} and {@link #getSup()}
58 * may not return the value used at instance construction.
59 * </p>
60 * @param lower lower angular bound of the arc
61 * @param upper upper angular bound of the arc
62 * @param tolerance tolerance below which angles are considered identical
63 * @exception MathIllegalArgumentException if lower is greater than upper
64 * or tolerance is smaller than {@link Sphere1D#SMALLEST_TOLERANCE}
65 */
66 public Arc(final double lower, final double upper, final double tolerance)
67 throws MathIllegalArgumentException {
68 Sphere1D.checkTolerance(tolerance);
69 this.tolerance = tolerance;
70 if (Precision.equals(lower, upper, 0) || (upper - lower) >= MathUtils.TWO_PI) {
71 // the arc must cover the whole circle
72 this.lower = 0;
73 this.upper = MathUtils.TWO_PI;
74 this.middle = FastMath.PI;
75 } else if (lower <= upper) {
76 this.lower = MathUtils.normalizeAngle(lower, FastMath.PI);
77 this.upper = this.lower + (upper - lower);
78 this.middle = 0.5 * (this.lower + this.upper);
79 } else {
80 throw new MathIllegalArgumentException(LocalizedCoreFormats.ENDPOINTS_NOT_AN_INTERVAL,
81 lower, upper, true);
82 }
83 }
84
85 /** Get the lower angular bound of the arc.
86 * @return lower angular bound of the arc,
87 * always between 0 and \( 2 \pi \)
88 */
89 public double getInf() {
90 return lower;
91 }
92
93 /** Get the upper angular bound of the arc.
94 * @return upper angular bound of the arc,
95 * always between {@link #getInf()} and {@link #getInf()} \( + 2 \pi \)
96 */
97 public double getSup() {
98 return upper;
99 }
100
101 /** Get the angular size of the arc.
102 * @return angular size of the arc
103 */
104 public double getSize() {
105 return upper - lower;
106 }
107
108 /** Get the barycenter of the arc.
109 * @return barycenter of the arc
110 */
111 public double getBarycenter() {
112 return middle;
113 }
114
115 /** Get the tolerance below which angles are considered identical.
116 * @return tolerance below which angles are considered identical
117 */
118 public double getTolerance() {
119 return tolerance;
120 }
121
122 /** Check a point with respect to the arc.
123 * @param point point to check
124 * @return a code representing the point status: either {@link
125 * Location#INSIDE}, {@link Location#OUTSIDE} or {@link Location#BOUNDARY}
126 */
127 public Location checkPoint(final double point) {
128 final double normalizedPoint = MathUtils.normalizeAngle(point, middle);
129 if (normalizedPoint < lower - tolerance || normalizedPoint > upper + tolerance) {
130 return Location.OUTSIDE;
131 } else if (normalizedPoint > lower + tolerance && normalizedPoint < upper - tolerance) {
132 return Location.INSIDE;
133 } else {
134 return (getSize() >= MathUtils.TWO_PI - tolerance) ? Location.INSIDE : Location.BOUNDARY;
135 }
136 }
137
138 /**
139 * Get the distance (arc length) from a point to the edge of the arc.
140 *
141 * <p>This method does not use {@link #getTolerance()}.
142 *
143 * @param point to test.
144 * @return offset, negative if the point is inside the arc, positive if it is outside
145 * the arc, or zero if {@code point} is {@link #getInf()} or {@link #getSup()}.
146 */
147 public double getOffset(final double point) {
148 final double normalizedPoint = MathUtils.normalizeAngle(point, middle);
149 if (normalizedPoint < middle) {
150 return lower - normalizedPoint;
151 } else {
152 return normalizedPoint - upper;
153 }
154 }
155
156 /**
157 * Get the distance (arc length) from a point to the edge of the arc.
158 *
159 * <p>This method does not use {@link #getTolerance()}.
160 *
161 * @param point to test.
162 * @return offset, negative if the point is inside the arc, positive if it is outside
163 * the arc, or zero if {@code point} is {@link #getInf()} or {@link #getSup()}.
164 */
165 public double getOffset(final S1Point point) {
166 return getOffset(point.getAlpha());
167 }
168
169 }