• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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