1 /* 2 * Copyright 2005 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.common.geometry; 17 18 import com.google.common.annotations.VisibleForTesting; 19 import com.google.common.base.Preconditions; 20 21 public final strictfp class S2 { 22 23 // Declare some frequently used constants 24 public static final double M_PI = Math.PI; 25 public static final double M_1_PI = 1.0 / Math.PI; 26 public static final double M_PI_2 = Math.PI / 2.0; 27 public static final double M_PI_4 = Math.PI / 4.0; 28 public static final double M_SQRT2 = Math.sqrt(2); 29 public static final double M_E = Math.E; 30 31 // Together these flags define a cell orientation. If SWAP_MASK 32 // is true, then canonical traversal order is flipped around the 33 // diagonal (i.e. i and j are swapped with each other). If 34 // INVERT_MASK is true, then the traversal order is rotated by 180 35 // degrees (i.e. the bits of i and j are inverted, or equivalently, 36 // the axis directions are reversed). 37 public static final int SWAP_MASK = 0x01; 38 public static final int INVERT_MASK = 0x02; 39 40 // Number of bits in the mantissa of a double. 41 private static final int EXPONENT_SHIFT = 52; 42 // Mask to extract the exponent from a double. 43 private static final long EXPONENT_MASK = 0x7ff0000000000000L; 44 45 /** 46 * If v is non-zero, return an integer {@code exp} such that 47 * {@code (0.5 <= |v|*2^(-exp) < 1)}. If v is zero, return 0. 48 * 49 * <p>Note that this arguably a bad definition of exponent because it makes 50 * {@code exp(9) == 4}. In decimal this would be like saying that the 51 * exponent of 1234 is 4, when in scientific 'exponent' notation 1234 is 52 * {@code 1.234 x 10^3}. 53 * 54 * TODO(dbeaumont): Replace this with "DoubleUtils.getExponent(v) - 1" ? 55 */ 56 @VisibleForTesting exp(double v)57 static int exp(double v) { 58 if (v == 0) { 59 return 0; 60 } 61 long bits = Double.doubleToLongBits(v); 62 return (int) ((EXPONENT_MASK & bits) >> EXPONENT_SHIFT) - 1022; 63 } 64 65 /** Mapping Hilbert traversal order to orientation adjustment mask. */ 66 private static final int[] POS_TO_ORIENTATION = 67 {SWAP_MASK, 0, 0, INVERT_MASK + SWAP_MASK}; 68 69 /** 70 * Returns an XOR bit mask indicating how the orientation of a child subcell 71 * is related to the orientation of its parent cell. The returned value can 72 * be XOR'd with the parent cell's orientation to give the orientation of 73 * the child cell. 74 * 75 * @param position the position of the subcell in the Hilbert traversal, in 76 * the range [0,3]. 77 * @return a bit mask containing some combination of {@link #SWAP_MASK} and 78 * {@link #INVERT_MASK}. 79 * @throws IllegalArgumentException if position is out of bounds. 80 */ posToOrientation(int position)81 public static int posToOrientation(int position) { 82 Preconditions.checkArgument(0 <= position && position < 4); 83 return POS_TO_ORIENTATION[position]; 84 } 85 86 /** Mapping from cell orientation + Hilbert traversal to IJ-index. */ 87 private static final int[][] POS_TO_IJ = { 88 // 0 1 2 3 89 {0, 1, 3, 2}, // canonical order: (0,0), (0,1), (1,1), (1,0) 90 {0, 2, 3, 1}, // axes swapped: (0,0), (1,0), (1,1), (0,1) 91 {3, 2, 0, 1}, // bits inverted: (1,1), (1,0), (0,0), (0,1) 92 {3, 1, 0, 2}, // swapped & inverted: (1,1), (0,1), (0,0), (1,0) 93 }; 94 95 /** 96 * Return the IJ-index of the subcell at the given position in the Hilbert 97 * curve traversal with the given orientation. This is the inverse of 98 * {@link #ijToPos}. 99 * 100 * @param orientation the subcell orientation, in the range [0,3]. 101 * @param position the position of the subcell in the Hilbert traversal, in 102 * the range [0,3]. 103 * @return the IJ-index where {@code 0->(0,0), 1->(0,1), 2->(1,0), 3->(1,1)}. 104 * @throws IllegalArgumentException if either parameter is out of bounds. 105 */ posToIJ(int orientation, int position)106 public static int posToIJ(int orientation, int position) { 107 Preconditions.checkArgument(0 <= orientation && orientation < 4); 108 Preconditions.checkArgument(0 <= position && position < 4); 109 return POS_TO_IJ[orientation][position]; 110 } 111 112 /** Mapping from Hilbert traversal order + cell orientation to IJ-index. */ 113 private static final int IJ_TO_POS[][] = { 114 // (0,0) (0,1) (1,0) (1,1) 115 {0, 1, 3, 2}, // canonical order 116 {0, 3, 1, 2}, // axes swapped 117 {2, 3, 1, 0}, // bits inverted 118 {2, 1, 3, 0}, // swapped & inverted 119 }; 120 121 /** 122 * Returns the order in which a specified subcell is visited by the Hilbert 123 * curve. This is the inverse of {@link #posToIJ}. 124 * 125 * @param orientation the subcell orientation, in the range [0,3]. 126 * @param ijIndex the subcell index where 127 * {@code 0->(0,0), 1->(0,1), 2->(1,0), 3->(1,1)}. 128 * @return the position of the subcell in the Hilbert traversal, in the range 129 * [0,3]. 130 * @throws IllegalArgumentException if either parameter is out of bounds. 131 */ ijToPos(int orientation, int ijIndex)132 public static final int ijToPos(int orientation, int ijIndex) { 133 Preconditions.checkArgument(0 <= orientation && orientation < 4); 134 Preconditions.checkArgument(0 <= ijIndex && ijIndex < 4); 135 return IJ_TO_POS[orientation][ijIndex]; 136 } 137 138 /** 139 * Defines an area or a length cell metric. 140 */ 141 public static class Metric { 142 143 private final double deriv; 144 private final int dim; 145 146 /** 147 * Defines a cell metric of the given dimension (1 == length, 2 == area). 148 */ Metric(int dim, double deriv)149 public Metric(int dim, double deriv) { 150 this.deriv = deriv; 151 this.dim = dim; 152 } 153 154 /** 155 * The "deriv" value of a metric is a derivative, and must be multiplied by 156 * a length or area in (s,t)-space to get a useful value. 157 */ deriv()158 public double deriv() { 159 return deriv; 160 } 161 162 /** Return the value of a metric for cells at the given level. */ getValue(int level)163 public double getValue(int level) { 164 return StrictMath.scalb(deriv, dim * (1 - level)); 165 } 166 167 /** 168 * Return the level at which the metric has approximately the given value. 169 * For example, S2::kAvgEdge.GetClosestLevel(0.1) returns the level at which 170 * the average cell edge length is approximately 0.1. The return value is 171 * always a valid level. 172 */ getClosestLevel(double value)173 public int getClosestLevel(double value) { 174 return getMinLevel(M_SQRT2 * value); 175 } 176 177 /** 178 * Return the minimum level such that the metric is at most the given value, 179 * or S2CellId::kMaxLevel if there is no such level. For example, 180 * S2::kMaxDiag.GetMinLevel(0.1) returns the minimum level such that all 181 * cell diagonal lengths are 0.1 or smaller. The return value is always a 182 * valid level. 183 */ getMinLevel(double value)184 public int getMinLevel(double value) { 185 if (value <= 0) { 186 return S2CellId.MAX_LEVEL; 187 } 188 189 // This code is equivalent to computing a floating-point "level" 190 // value and rounding up. 191 int exponent = exp(value / ((1 << dim) * deriv)); 192 int level = Math.max(0, 193 Math.min(S2CellId.MAX_LEVEL, -((exponent - 1) >> (dim - 1)))); 194 // assert (level == S2CellId.MAX_LEVEL || getValue(level) <= value); 195 // assert (level == 0 || getValue(level - 1) > value); 196 return level; 197 } 198 199 /** 200 * Return the maximum level such that the metric is at least the given 201 * value, or zero if there is no such level. For example, 202 * S2.kMinWidth.GetMaxLevel(0.1) returns the maximum level such that all 203 * cells have a minimum width of 0.1 or larger. The return value is always a 204 * valid level. 205 */ getMaxLevel(double value)206 public int getMaxLevel(double value) { 207 if (value <= 0) { 208 return S2CellId.MAX_LEVEL; 209 } 210 211 // This code is equivalent to computing a floating-point "level" 212 // value and rounding down. 213 int exponent = exp((1 << dim) * deriv / value); 214 int level = Math.max(0, 215 Math.min(S2CellId.MAX_LEVEL, ((exponent - 1) >> (dim - 1)))); 216 // assert (level == 0 || getValue(level) >= value); 217 // assert (level == S2CellId.MAX_LEVEL || getValue(level + 1) < value); 218 return level; 219 } 220 221 } 222 223 /** 224 * Return a unique "origin" on the sphere for operations that need a fixed 225 * reference point. It should *not* be a point that is commonly used in edge 226 * tests in order to avoid triggering code to handle degenerate cases. (This 227 * rules out the north and south poles.) 228 */ origin()229 public static S2Point origin() { 230 return new S2Point(0, 1, 0); 231 } 232 233 /** 234 * Return true if the given point is approximately unit length (this is mainly 235 * useful for assertions). 236 */ isUnitLength(S2Point p)237 public static boolean isUnitLength(S2Point p) { 238 return Math.abs(p.norm2() - 1) <= 1e-15; 239 } 240 241 /** 242 * Return true if edge AB crosses CD at a point that is interior to both 243 * edges. Properties: 244 * 245 * (1) SimpleCrossing(b,a,c,d) == SimpleCrossing(a,b,c,d) (2) 246 * SimpleCrossing(c,d,a,b) == SimpleCrossing(a,b,c,d) 247 */ simpleCrossing(S2Point a, S2Point b, S2Point c, S2Point d)248 public static boolean simpleCrossing(S2Point a, S2Point b, S2Point c, S2Point d) { 249 // We compute SimpleCCW() for triangles ACB, CBD, BDA, and DAC. All 250 // of these triangles need to have the same orientation (CW or CCW) 251 // for an intersection to exist. Note that this is slightly more 252 // restrictive than the corresponding definition for planar edges, 253 // since we need to exclude pairs of line segments that would 254 // otherwise "intersect" by crossing two antipodal points. 255 256 S2Point ab = S2Point.crossProd(a, b); 257 S2Point cd = S2Point.crossProd(c, d); 258 double acb = -ab.dotProd(c); 259 double cbd = -cd.dotProd(b); 260 double bda = ab.dotProd(d); 261 double dac = cd.dotProd(a); 262 263 return (acb * cbd > 0) && (cbd * bda > 0) && (bda * dac > 0); 264 } 265 266 /** 267 * Return a vector "c" that is orthogonal to the given unit-length vectors "a" 268 * and "b". This function is similar to a.CrossProd(b) except that it does a 269 * better job of ensuring orthogonality when "a" is nearly parallel to "b", 270 * and it returns a non-zero result even when a == b or a == -b. 271 * 272 * It satisfies the following properties (RCP == RobustCrossProd): 273 * 274 * (1) RCP(a,b) != 0 for all a, b (2) RCP(b,a) == -RCP(a,b) unless a == b or 275 * a == -b (3) RCP(-a,b) == -RCP(a,b) unless a == b or a == -b (4) RCP(a,-b) 276 * == -RCP(a,b) unless a == b or a == -b 277 */ robustCrossProd(S2Point a, S2Point b)278 public static S2Point robustCrossProd(S2Point a, S2Point b) { 279 // The direction of a.CrossProd(b) becomes unstable as (a + b) or (a - b) 280 // approaches zero. This leads to situations where a.CrossProd(b) is not 281 // very orthogonal to "a" and/or "b". We could fix this using Gram-Schmidt, 282 // but we also want b.RobustCrossProd(a) == -b.RobustCrossProd(a). 283 // 284 // The easiest fix is to just compute the cross product of (b+a) and (b-a). 285 // Given that "a" and "b" are unit-length, this has good orthogonality to 286 // "a" and "b" even if they differ only in the lowest bit of one component. 287 288 // assert (isUnitLength(a) && isUnitLength(b)); 289 S2Point x = S2Point.crossProd(S2Point.add(b, a), S2Point.sub(b, a)); 290 if (!x.equals(new S2Point(0, 0, 0))) { 291 return x; 292 } 293 294 // The only result that makes sense mathematically is to return zero, but 295 // we find it more convenient to return an arbitrary orthogonal vector. 296 return ortho(a); 297 } 298 299 /** 300 * Return a unit-length vector that is orthogonal to "a". Satisfies Ortho(-a) 301 * = -Ortho(a) for all a. 302 */ ortho(S2Point a)303 public static S2Point ortho(S2Point a) { 304 // The current implementation in S2Point has the property we need, 305 // i.e. Ortho(-a) = -Ortho(a) for all a. 306 return a.ortho(); 307 } 308 309 /** 310 * Return the area of triangle ABC. The method used is about twice as 311 * expensive as Girard's formula, but it is numerically stable for both large 312 * and very small triangles. The points do not need to be normalized. The area 313 * is always positive. 314 * 315 * The triangle area is undefined if it contains two antipodal points, and 316 * becomes numerically unstable as the length of any edge approaches 180 317 * degrees. 318 */ area(S2Point a, S2Point b, S2Point c)319 static double area(S2Point a, S2Point b, S2Point c) { 320 // This method is based on l'Huilier's theorem, 321 // 322 // tan(E/4) = sqrt(tan(s/2) tan((s-a)/2) tan((s-b)/2) tan((s-c)/2)) 323 // 324 // where E is the spherical excess of the triangle (i.e. its area), 325 // a, b, c, are the side lengths, and 326 // s is the semiperimeter (a + b + c) / 2 . 327 // 328 // The only significant source of error using l'Huilier's method is the 329 // cancellation error of the terms (s-a), (s-b), (s-c). This leads to a 330 // *relative* error of about 1e-16 * s / min(s-a, s-b, s-c). This compares 331 // to a relative error of about 1e-15 / E using Girard's formula, where E is 332 // the true area of the triangle. Girard's formula can be even worse than 333 // this for very small triangles, e.g. a triangle with a true area of 1e-30 334 // might evaluate to 1e-5. 335 // 336 // So, we prefer l'Huilier's formula unless dmin < s * (0.1 * E), where 337 // dmin = min(s-a, s-b, s-c). This basically includes all triangles 338 // except for extremely long and skinny ones. 339 // 340 // Since we don't know E, we would like a conservative upper bound on 341 // the triangle area in terms of s and dmin. It's possible to show that 342 // E <= k1 * s * sqrt(s * dmin), where k1 = 2*sqrt(3)/Pi (about 1). 343 // Using this, it's easy to show that we should always use l'Huilier's 344 // method if dmin >= k2 * s^5, where k2 is about 1e-2. Furthermore, 345 // if dmin < k2 * s^5, the triangle area is at most k3 * s^4, where 346 // k3 is about 0.1. Since the best case error using Girard's formula 347 // is about 1e-15, this means that we shouldn't even consider it unless 348 // s >= 3e-4 or so. 349 350 // We use volatile doubles to force the compiler to truncate all of these 351 // quantities to 64 bits. Otherwise it may compute a value of dmin > 0 352 // simply because it chose to spill one of the intermediate values to 353 // memory but not one of the others. 354 final double sa = b.angle(c); 355 final double sb = c.angle(a); 356 final double sc = a.angle(b); 357 final double s = 0.5 * (sa + sb + sc); 358 if (s >= 3e-4) { 359 // Consider whether Girard's formula might be more accurate. 360 double s2 = s * s; 361 double dmin = s - Math.max(sa, Math.max(sb, sc)); 362 if (dmin < 1e-2 * s * s2 * s2) { 363 // This triangle is skinny enough to consider Girard's formula. 364 double area = girardArea(a, b, c); 365 if (dmin < s * (0.1 * area)) { 366 return area; 367 } 368 } 369 } 370 // Use l'Huilier's formula. 371 return 4 372 * Math.atan( 373 Math.sqrt( 374 Math.max(0.0, 375 Math.tan(0.5 * s) * Math.tan(0.5 * (s - sa)) * Math.tan(0.5 * (s - sb)) 376 * Math.tan(0.5 * (s - sc))))); 377 } 378 379 /** 380 * Return the area of the triangle computed using Girard's formula. This is 381 * slightly faster than the Area() method above is not accurate for very small 382 * triangles. 383 */ girardArea(S2Point a, S2Point b, S2Point c)384 public static double girardArea(S2Point a, S2Point b, S2Point c) { 385 // This is equivalent to the usual Girard's formula but is slightly 386 // more accurate, faster to compute, and handles a == b == c without 387 // a special case. 388 389 S2Point ab = S2Point.crossProd(a, b); 390 S2Point bc = S2Point.crossProd(b, c); 391 S2Point ac = S2Point.crossProd(a, c); 392 return Math.max(0.0, ab.angle(ac) - ab.angle(bc) + bc.angle(ac)); 393 } 394 395 /** 396 * Like Area(), but returns a positive value for counterclockwise triangles 397 * and a negative value otherwise. 398 */ signedArea(S2Point a, S2Point b, S2Point c)399 public static double signedArea(S2Point a, S2Point b, S2Point c) { 400 return area(a, b, c) * robustCCW(a, b, c); 401 } 402 403 // About centroids: 404 // ---------------- 405 // 406 // There are several notions of the "centroid" of a triangle. First, there 407 // // is the planar centroid, which is simply the centroid of the ordinary 408 // (non-spherical) triangle defined by the three vertices. Second, there is 409 // the surface centroid, which is defined as the intersection of the three 410 // medians of the spherical triangle. It is possible to show that this 411 // point is simply the planar centroid projected to the surface of the 412 // sphere. Finally, there is the true centroid (mass centroid), which is 413 // defined as the area integral over the spherical triangle of (x,y,z) 414 // divided by the triangle area. This is the point that the triangle would 415 // rotate around if it was spinning in empty space. 416 // 417 // The best centroid for most purposes is the true centroid. Unlike the 418 // planar and surface centroids, the true centroid behaves linearly as 419 // regions are added or subtracted. That is, if you split a triangle into 420 // pieces and compute the average of their centroids (weighted by triangle 421 // area), the result equals the centroid of the original triangle. This is 422 // not true of the other centroids. 423 // 424 // Also note that the surface centroid may be nowhere near the intuitive 425 // "center" of a spherical triangle. For example, consider the triangle 426 // with vertices A=(1,eps,0), B=(0,0,1), C=(-1,eps,0) (a quarter-sphere). 427 // The surface centroid of this triangle is at S=(0, 2*eps, 1), which is 428 // within a distance of 2*eps of the vertex B. Note that the median from A 429 // (the segment connecting A to the midpoint of BC) passes through S, since 430 // this is the shortest path connecting the two endpoints. On the other 431 // hand, the true centroid is at M=(0, 0.5, 0.5), which when projected onto 432 // the surface is a much more reasonable interpretation of the "center" of 433 // this triangle. 434 435 /** 436 * Return the centroid of the planar triangle ABC. This can be normalized to 437 * unit length to obtain the "surface centroid" of the corresponding spherical 438 * triangle, i.e. the intersection of the three medians. However, note that 439 * for large spherical triangles the surface centroid may be nowhere near the 440 * intuitive "center" (see example above). 441 */ planarCentroid(S2Point a, S2Point b, S2Point c)442 public static S2Point planarCentroid(S2Point a, S2Point b, S2Point c) { 443 return new S2Point((a.x + b.x + c.x) / 3.0, (a.y + b.y + c.y) / 3.0, (a.z + b.z + c.z) / 3.0); 444 } 445 446 /** 447 * Returns the true centroid of the spherical triangle ABC multiplied by the 448 * signed area of spherical triangle ABC. The reasons for multiplying by the 449 * signed area are (1) this is the quantity that needs to be summed to compute 450 * the centroid of a union or difference of triangles, and (2) it's actually 451 * easier to calculate this way. 452 */ trueCentroid(S2Point a, S2Point b, S2Point c)453 public static S2Point trueCentroid(S2Point a, S2Point b, S2Point c) { 454 // I couldn't find any references for computing the true centroid of a 455 // spherical triangle... I have a truly marvellous demonstration of this 456 // formula which this margin is too narrow to contain :) 457 458 // assert (isUnitLength(a) && isUnitLength(b) && isUnitLength(c)); 459 double sina = S2Point.crossProd(b, c).norm(); 460 double sinb = S2Point.crossProd(c, a).norm(); 461 double sinc = S2Point.crossProd(a, b).norm(); 462 double ra = (sina == 0) ? 1 : (Math.asin(sina) / sina); 463 double rb = (sinb == 0) ? 1 : (Math.asin(sinb) / sinb); 464 double rc = (sinc == 0) ? 1 : (Math.asin(sinc) / sinc); 465 466 // Now compute a point M such that M.X = rX * det(ABC) / 2 for X in A,B,C. 467 S2Point x = new S2Point(a.x, b.x, c.x); 468 S2Point y = new S2Point(a.y, b.y, c.y); 469 S2Point z = new S2Point(a.z, b.z, c.z); 470 S2Point r = new S2Point(ra, rb, rc); 471 return new S2Point(0.5 * S2Point.crossProd(y, z).dotProd(r), 472 0.5 * S2Point.crossProd(z, x).dotProd(r), 0.5 * S2Point.crossProd(x, y).dotProd(r)); 473 } 474 475 /** 476 * Return true if the points A, B, C are strictly counterclockwise. Return 477 * false if the points are clockwise or colinear (i.e. if they are all 478 * contained on some great circle). 479 * 480 * Due to numerical errors, situations may arise that are mathematically 481 * impossible, e.g. ABC may be considered strictly CCW while BCA is not. 482 * However, the implementation guarantees the following: 483 * 484 * If SimpleCCW(a,b,c), then !SimpleCCW(c,b,a) for all a,b,c. 485 * 486 * In other words, ABC and CBA are guaranteed not to be both CCW 487 */ simpleCCW(S2Point a, S2Point b, S2Point c)488 public static boolean simpleCCW(S2Point a, S2Point b, S2Point c) { 489 // We compute the signed volume of the parallelepiped ABC. The usual 490 // formula for this is (AxB).C, but we compute it here using (CxA).B 491 // in order to ensure that ABC and CBA are not both CCW. This follows 492 // from the following identities (which are true numerically, not just 493 // mathematically): 494 // 495 // (1) x.CrossProd(y) == -(y.CrossProd(x)) 496 // (2) (-x).DotProd(y) == -(x.DotProd(y)) 497 498 return S2Point.crossProd(c, a).dotProd(b) > 0; 499 } 500 501 /** 502 * WARNING! This requires arbitrary precision arithmetic to be truly robust. 503 * This means that for nearly colinear AB and AC, this function may return the 504 * wrong answer. 505 * 506 * <p> 507 * Like SimpleCCW(), but returns +1 if the points are counterclockwise and -1 508 * if the points are clockwise. It satisfies the following conditions: 509 * 510 * (1) RobustCCW(a,b,c) == 0 if and only if a == b, b == c, or c == a (2) 511 * RobustCCW(b,c,a) == RobustCCW(a,b,c) for all a,b,c (3) RobustCCW(c,b,a) 512 * ==-RobustCCW(a,b,c) for all a,b,c 513 * 514 * In other words: 515 * 516 * (1) The result is zero if and only if two points are the same. (2) 517 * Rotating the order of the arguments does not affect the result. (3) 518 * Exchanging any two arguments inverts the result. 519 * 520 * This function is essentially like taking the sign of the determinant of 521 * a,b,c, except that it has additional logic to make sure that the above 522 * properties hold even when the three points are coplanar, and to deal with 523 * the limitations of floating-point arithmetic. 524 * 525 * Note: a, b and c are expected to be of unit length. Otherwise, the results 526 * are undefined. 527 */ robustCCW(S2Point a, S2Point b, S2Point c)528 public static int robustCCW(S2Point a, S2Point b, S2Point c) { 529 return robustCCW(a, b, c, S2Point.crossProd(a, b)); 530 } 531 532 /** 533 * A more efficient version of RobustCCW that allows the precomputed 534 * cross-product of A and B to be specified. 535 * 536 * Note: a, b and c are expected to be of unit length. Otherwise, the results 537 * are undefined 538 */ robustCCW(S2Point a, S2Point b, S2Point c, S2Point aCrossB)539 public static int robustCCW(S2Point a, S2Point b, S2Point c, S2Point aCrossB) { 540 // assert (isUnitLength(a) && isUnitLength(b) && isUnitLength(c)); 541 542 // There are 14 multiplications and additions to compute the determinant 543 // below. Since all three points are normalized, it is possible to show 544 // that the average rounding error per operation does not exceed 2**-54, 545 // the maximum rounding error for an operation whose result magnitude is in 546 // the range [0.5,1). Therefore, if the absolute value of the determinant 547 // is greater than 2*14*(2**-54), the determinant will have the same sign 548 // even if the arguments are rotated (which produces a mathematically 549 // equivalent result but with potentially different rounding errors). 550 final double kMinAbsValue = 1.6e-15; // 2 * 14 * 2**-54 551 552 double det = aCrossB.dotProd(c); 553 554 // Double-check borderline cases in debug mode. 555 // assert ((Math.abs(det) < kMinAbsValue) || (Math.abs(det) > 1000 * kMinAbsValue) 556 // || (det * expensiveCCW(a, b, c) > 0)); 557 558 if (det > kMinAbsValue) { 559 return 1; 560 } 561 562 if (det < -kMinAbsValue) { 563 return -1; 564 } 565 566 return expensiveCCW(a, b, c); 567 } 568 569 /** 570 * A relatively expensive calculation invoked by RobustCCW() if the sign of 571 * the determinant is uncertain. 572 */ expensiveCCW(S2Point a, S2Point b, S2Point c)573 private static int expensiveCCW(S2Point a, S2Point b, S2Point c) { 574 // Return zero if and only if two points are the same. This ensures (1). 575 if (a.equals(b) || b.equals(c) || c.equals(a)) { 576 return 0; 577 } 578 579 // Now compute the determinant in a stable way. Since all three points are 580 // unit length and we know that the determinant is very close to zero, this 581 // means that points are very nearly colinear. Furthermore, the most common 582 // situation is where two points are nearly identical or nearly antipodal. 583 // To get the best accuracy in this situation, it is important to 584 // immediately reduce the magnitude of the arguments by computing either 585 // A+B or A-B for each pair of points. Note that even if A and B differ 586 // only in their low bits, A-B can be computed very accurately. On the 587 // other hand we can't accurately represent an arbitrary linear combination 588 // of two vectors as would be required for Gaussian elimination. The code 589 // below chooses the vertex opposite the longest edge as the "origin" for 590 // the calculation, and computes the different vectors to the other two 591 // vertices. This minimizes the sum of the lengths of these vectors. 592 // 593 // This implementation is very stable numerically, but it still does not 594 // return consistent results in all cases. For example, if three points are 595 // spaced far apart from each other along a great circle, the sign of the 596 // result will basically be random (although it will still satisfy the 597 // conditions documented in the header file). The only way to return 598 // consistent results in all cases is to compute the result using 599 // arbitrary-precision arithmetic. I considered using the Gnu MP library, 600 // but this would be very expensive (up to 2000 bits of precision may be 601 // needed to store the intermediate results) and seems like overkill for 602 // this problem. The MP library is apparently also quite particular about 603 // compilers and compilation options and would be a pain to maintain. 604 605 // We want to handle the case of nearby points and nearly antipodal points 606 // accurately, so determine whether A+B or A-B is smaller in each case. 607 double sab = (a.dotProd(b) > 0) ? -1 : 1; 608 double sbc = (b.dotProd(c) > 0) ? -1 : 1; 609 double sca = (c.dotProd(a) > 0) ? -1 : 1; 610 S2Point vab = S2Point.add(a, S2Point.mul(b, sab)); 611 S2Point vbc = S2Point.add(b, S2Point.mul(c, sbc)); 612 S2Point vca = S2Point.add(c, S2Point.mul(a, sca)); 613 double dab = vab.norm2(); 614 double dbc = vbc.norm2(); 615 double dca = vca.norm2(); 616 617 // Sort the difference vectors to find the longest edge, and use the 618 // opposite vertex as the origin. If two difference vectors are the same 619 // length, we break ties deterministically to ensure that the symmetry 620 // properties guaranteed in the header file will be true. 621 double sign; 622 if (dca < dbc || (dca == dbc && a.lessThan(b))) { 623 if (dab < dbc || (dab == dbc && a.lessThan(c))) { 624 // The "sab" factor converts A +/- B into B +/- A. 625 sign = S2Point.crossProd(vab, vca).dotProd(a) * sab; // BC is longest 626 // edge 627 } else { 628 sign = S2Point.crossProd(vca, vbc).dotProd(c) * sca; // AB is longest 629 // edge 630 } 631 } else { 632 if (dab < dca || (dab == dca && b.lessThan(c))) { 633 sign = S2Point.crossProd(vbc, vab).dotProd(b) * sbc; // CA is longest 634 // edge 635 } else { 636 sign = S2Point.crossProd(vca, vbc).dotProd(c) * sca; // AB is longest 637 // edge 638 } 639 } 640 if (sign > 0) { 641 return 1; 642 } 643 if (sign < 0) { 644 return -1; 645 } 646 647 // The points A, B, and C are numerically indistinguishable from coplanar. 648 // This may be due to roundoff error, or the points may in fact be exactly 649 // coplanar. We handle this situation by perturbing all of the points by a 650 // vector (eps, eps**2, eps**3) where "eps" is an infinitesmally small 651 // positive number (e.g. 1 divided by a googolplex). The perturbation is 652 // done symbolically, i.e. we compute what would happen if the points were 653 // perturbed by this amount. It turns out that this is equivalent to 654 // checking whether the points are ordered CCW around the origin first in 655 // the Y-Z plane, then in the Z-X plane, and then in the X-Y plane. 656 657 int ccw = 658 planarOrderedCCW(new R2Vector(a.y, a.z), new R2Vector(b.y, b.z), new R2Vector(c.y, c.z)); 659 if (ccw == 0) { 660 ccw = 661 planarOrderedCCW(new R2Vector(a.z, a.x), new R2Vector(b.z, b.x), new R2Vector(c.z, c.x)); 662 if (ccw == 0) { 663 ccw = planarOrderedCCW( 664 new R2Vector(a.x, a.y), new R2Vector(b.x, b.y), new R2Vector(c.x, c.y)); 665 // assert (ccw != 0); 666 } 667 } 668 return ccw; 669 } 670 671 planarCCW(R2Vector a, R2Vector b)672 public static int planarCCW(R2Vector a, R2Vector b) { 673 // Return +1 if the edge AB is CCW around the origin, etc. 674 double sab = (a.dotProd(b) > 0) ? -1 : 1; 675 R2Vector vab = R2Vector.add(a, R2Vector.mul(b, sab)); 676 double da = a.norm2(); 677 double db = b.norm2(); 678 double sign; 679 if (da < db || (da == db && a.lessThan(b))) { 680 sign = a.crossProd(vab) * sab; 681 } else { 682 sign = vab.crossProd(b); 683 } 684 if (sign > 0) { 685 return 1; 686 } 687 if (sign < 0) { 688 return -1; 689 } 690 return 0; 691 } 692 planarOrderedCCW(R2Vector a, R2Vector b, R2Vector c)693 public static int planarOrderedCCW(R2Vector a, R2Vector b, R2Vector c) { 694 int sum = 0; 695 sum += planarCCW(a, b); 696 sum += planarCCW(b, c); 697 sum += planarCCW(c, a); 698 if (sum > 0) { 699 return 1; 700 } 701 if (sum < 0) { 702 return -1; 703 } 704 return 0; 705 } 706 707 /** 708 * Return true if the edges OA, OB, and OC are encountered in that order while 709 * sweeping CCW around the point O. You can think of this as testing whether 710 * A <= B <= C with respect to a continuous CCW ordering around O. 711 * 712 * Properties: 713 * <ol> 714 * <li>If orderedCCW(a,b,c,o) && orderedCCW(b,a,c,o), then a == b</li> 715 * <li>If orderedCCW(a,b,c,o) && orderedCCW(a,c,b,o), then b == c</li> 716 * <li>If orderedCCW(a,b,c,o) && orderedCCW(c,b,a,o), then a == b == c</li> 717 * <li>If a == b or b == c, then orderedCCW(a,b,c,o) is true</li> 718 * <li>Otherwise if a == c, then orderedCCW(a,b,c,o) is false</li> 719 * </ol> 720 */ orderedCCW(S2Point a, S2Point b, S2Point c, S2Point o)721 public static boolean orderedCCW(S2Point a, S2Point b, S2Point c, S2Point o) { 722 // The last inequality below is ">" rather than ">=" so that we return true 723 // if A == B or B == C, and otherwise false if A == C. Recall that 724 // RobustCCW(x,y,z) == -RobustCCW(z,y,x) for all x,y,z. 725 726 int sum = 0; 727 if (robustCCW(b, o, a) >= 0) { 728 ++sum; 729 } 730 if (robustCCW(c, o, b) >= 0) { 731 ++sum; 732 } 733 if (robustCCW(a, o, c) > 0) { 734 ++sum; 735 } 736 return sum >= 2; 737 } 738 739 /** 740 * Return the angle at the vertex B in the triangle ABC. The return value is 741 * always in the range [0, Pi]. The points do not need to be normalized. 742 * Ensures that Angle(a,b,c) == Angle(c,b,a) for all a,b,c. 743 * 744 * The angle is undefined if A or C is diametrically opposite from B, and 745 * becomes numerically unstable as the length of edge AB or BC approaches 180 746 * degrees. 747 */ angle(S2Point a, S2Point b, S2Point c)748 public static double angle(S2Point a, S2Point b, S2Point c) { 749 return S2Point.crossProd(a, b).angle(S2Point.crossProd(c, b)); 750 } 751 752 /** 753 * Return the exterior angle at the vertex B in the triangle ABC. The return 754 * value is positive if ABC is counterclockwise and negative otherwise. If you 755 * imagine an ant walking from A to B to C, this is the angle that the ant 756 * turns at vertex B (positive = left, negative = right). Ensures that 757 * TurnAngle(a,b,c) == -TurnAngle(c,b,a) for all a,b,c. 758 * 759 * @param a 760 * @param b 761 * @param c 762 * @return the exterior angle at the vertex B in the triangle ABC 763 */ turnAngle(S2Point a, S2Point b, S2Point c)764 public static double turnAngle(S2Point a, S2Point b, S2Point c) { 765 // This is a bit less efficient because we compute all 3 cross products, but 766 // it ensures that turnAngle(a,b,c) == -turnAngle(c,b,a) for all a,b,c. 767 double outAngle = S2Point.crossProd(b, a).angle(S2Point.crossProd(c, b)); 768 return (robustCCW(a, b, c) > 0) ? outAngle : -outAngle; 769 } 770 771 /** 772 * Return true if two points are within the given distance of each other 773 * (mainly useful for testing). 774 */ approxEquals(S2Point a, S2Point b, double maxError)775 public static boolean approxEquals(S2Point a, S2Point b, double maxError) { 776 return a.angle(b) <= maxError; 777 } 778 approxEquals(S2Point a, S2Point b)779 public static boolean approxEquals(S2Point a, S2Point b) { 780 return approxEquals(a, b, 1e-15); 781 } 782 approxEquals(double a, double b, double maxError)783 public static boolean approxEquals(double a, double b, double maxError) { 784 return Math.abs(a - b) <= maxError; 785 } 786 approxEquals(double a, double b)787 public static boolean approxEquals(double a, double b) { 788 return approxEquals(a, b, 1e-15); 789 } 790 791 // Don't instantiate S2()792 private S2() { 793 } 794 } 795