View Javadoc
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 }