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.geometry.Point; 25 import org.hipparchus.geometry.Space; 26 import org.hipparchus.geometry.euclidean.twod.Vector2D; 27 import org.hipparchus.util.FastMath; 28 import org.hipparchus.util.MathUtils; 29 import org.hipparchus.util.SinCos; 30 31 /** This class represents a point on the 1-sphere. 32 * <p>Instances of this class are guaranteed to be immutable.</p> 33 */ 34 public class S1Point implements Point<Sphere1D> { 35 36 // CHECKSTYLE: stop ConstantName 37 /** A vector with all coordinates set to NaN. */ 38 public static final S1Point NaN = new S1Point(Double.NaN, Vector2D.NaN); 39 // CHECKSTYLE: resume ConstantName 40 41 /** Serializable UID. */ 42 private static final long serialVersionUID = 20131218L; 43 44 /** Azimuthal angle \( \alpha \). */ 45 private final double alpha; 46 47 /** Corresponding 2D normalized vector. */ 48 private final Vector2D vector; 49 50 /** Simple constructor. 51 * Build a vector from its coordinates 52 * @param alpha azimuthal angle \( \alpha \) 53 * @see #getAlpha() 54 */ 55 public S1Point(final double alpha) { 56 this(MathUtils.normalizeAngle(alpha, FastMath.PI), buildVector(alpha)); 57 } 58 59 /** Build a point from its internal components. 60 * @param alpha azimuthal angle \( \alpha \) 61 * @param vector corresponding vector 62 */ 63 private S1Point(final double alpha, final Vector2D vector) { 64 this.alpha = alpha; 65 this.vector = vector; 66 } 67 68 /** Get the azimuthal angle \( \alpha \). 69 * @return azimuthal angle \( \alpha \) 70 * @see #S1Point(double) 71 */ 72 public double getAlpha() { 73 return alpha; 74 } 75 76 /** Get the corresponding normalized vector in the 2D euclidean space. 77 * @return normalized vector 78 */ 79 public Vector2D getVector() { 80 return vector; 81 } 82 83 /** {@inheritDoc} */ 84 @Override 85 public Space getSpace() { 86 return Sphere1D.getInstance(); 87 } 88 89 /** {@inheritDoc} */ 90 @Override 91 public boolean isNaN() { 92 return Double.isNaN(alpha); 93 } 94 95 /** {@inheritDoc} */ 96 @Override 97 public double distance(final Point<Sphere1D> point) { 98 return distance(this, (S1Point) point); 99 } 100 101 /** Compute the distance (angular separation) between two points. 102 * @param p1 first vector 103 * @param p2 second vector 104 * @return the angular separation between p1 and p2 105 */ 106 public static double distance(S1Point p1, S1Point p2) { 107 return Vector2D.angle(p1.vector, p2.vector); 108 } 109 110 /** 111 * Test for the equality of two points on the 1-sphere. 112 * <p> 113 * If all coordinates of two points are exactly the same, and none are 114 * {@code Double.NaN}, the two points are considered to be equal. 115 * </p> 116 * <p> 117 * {@code NaN} coordinates are considered to affect globally the point 118 * and be equals to each other - i.e, if either (or all) coordinates of the 119 * point are equal to {@code Double.NaN}, the point is equal to 120 * {@link #NaN}. 121 * </p> 122 * 123 * @param other Object to test for equality to this 124 * @return true if two points on the 1-sphere objects are equal, false if 125 * object is null, not an instance of S1Point, or 126 * not equal to this S1Point instance 127 * 128 */ 129 @Override 130 public boolean equals(Object other) { 131 132 if (this == other) { 133 return true; 134 } 135 136 if (other instanceof S1Point) { 137 final S1Point rhs = (S1Point) other; 138 return alpha == rhs.alpha || isNaN() && rhs.isNaN(); 139 } 140 141 return false; 142 143 } 144 145 /** 146 * Test for the equality of two points on the 1-sphere. 147 * <p> 148 * If all coordinates of two points are exactly the same, and none are 149 * {@code Double.NaN}, the two points are considered to be equal. 150 * </p> 151 * <p> 152 * In compliance with IEEE754 handling, if any coordinates of any of the 153 * two points are {@code NaN}, then the points are considered different. 154 * This implies that {@link #NaN S1Point.NaN}.equals({@link #NaN S1Point.NaN}) 155 * returns {@code false} despite the instance is checked against itself. 156 * </p> 157 * 158 * @param other Object to test for equality to this 159 * @return true if two points objects are equal, false if 160 * object is null, not an instance of S1Point, or 161 * not equal to this S1Point instance 162 * @since 2.1 163 */ 164 public boolean equalsIeee754(Object other) { 165 166 if (this == other && !isNaN()) { 167 return true; 168 } 169 170 if (other instanceof S1Point) { 171 final S1Point rhs = (S1Point) other; 172 return alpha == rhs.alpha; 173 } 174 175 return false; 176 177 } 178 179 /** 180 * Get a hashCode for the point. 181 * <p> 182 * All NaN values have the same hash code.</p> 183 * 184 * @return a hash code value for this object 185 */ 186 @Override 187 public int hashCode() { 188 if (isNaN()) { 189 return 542; 190 } 191 return 1759 * MathUtils.hash(alpha); 192 } 193 194 /** 195 * Build the 2D vector corresponding to the given angle. 196 * @param alpha angle 197 * @return the corresponding 2D vector 198 */ 199 private static Vector2D buildVector(final double alpha) { 200 final SinCos sc = FastMath.sinCos(alpha); 201 return new Vector2D(sc.cos(), sc.sin()); 202 } 203 204 }