gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

predicates.go (27138B)


      1 // Copyright 2016 Google Inc. All rights reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 package s2
     16 
     17 // This file contains various predicates that are guaranteed to produce
     18 // correct, consistent results. They are also relatively efficient. This is
     19 // achieved by computing conservative error bounds and falling back to high
     20 // precision or even exact arithmetic when the result is uncertain. Such
     21 // predicates are useful in implementing robust algorithms.
     22 //
     23 // See also EdgeCrosser, which implements various exact
     24 // edge-crossing predicates more efficiently than can be done here.
     25 
     26 import (
     27 	"math"
     28 	"math/big"
     29 
     30 	"github.com/golang/geo/r3"
     31 	"github.com/golang/geo/s1"
     32 )
     33 
     34 const (
     35 	// If any other machine architectures need to be suppported, these next three
     36 	// values will need to be updated.
     37 
     38 	// epsilon is a small number that represents a reasonable level of noise between two
     39 	// values that can be considered to be equal.
     40 	epsilon = 1e-15
     41 	// dblEpsilon is a smaller number for values that require more precision.
     42 	// This is the C++ DBL_EPSILON equivalent.
     43 	dblEpsilon = 2.220446049250313e-16
     44 	// dblError is the C++ value for S2 rounding_epsilon().
     45 	dblError = 1.110223024625156e-16
     46 
     47 	// maxDeterminantError is the maximum error in computing (AxB).C where all vectors
     48 	// are unit length. Using standard inequalities, it can be shown that
     49 	//
     50 	//  fl(AxB) = AxB + D where |D| <= (|AxB| + (2/sqrt(3))*|A|*|B|) * e
     51 	//
     52 	// where "fl()" denotes a calculation done in floating-point arithmetic,
     53 	// |x| denotes either absolute value or the L2-norm as appropriate, and
     54 	// e is a reasonably small value near the noise level of floating point
     55 	// number accuracy. Similarly,
     56 	//
     57 	//  fl(B.C) = B.C + d where |d| <= (|B.C| + 2*|B|*|C|) * e .
     58 	//
     59 	// Applying these bounds to the unit-length vectors A,B,C and neglecting
     60 	// relative error (which does not affect the sign of the result), we get
     61 	//
     62 	//  fl((AxB).C) = (AxB).C + d where |d| <= (3 + 2/sqrt(3)) * e
     63 	maxDeterminantError = 1.8274 * dblEpsilon
     64 
     65 	// detErrorMultiplier is the factor to scale the magnitudes by when checking
     66 	// for the sign of set of points with certainty. Using a similar technique to
     67 	// the one used for maxDeterminantError, the error is at most:
     68 	//
     69 	//   |d| <= (3 + 6/sqrt(3)) * |A-C| * |B-C| * e
     70 	//
     71 	// If the determinant magnitude is larger than this value then we know
     72 	// its sign with certainty.
     73 	detErrorMultiplier = 3.2321 * dblEpsilon
     74 )
     75 
     76 // Direction is an indication of the ordering of a set of points.
     77 type Direction int
     78 
     79 // These are the three options for the direction of a set of points.
     80 const (
     81 	Clockwise        Direction = -1
     82 	Indeterminate    Direction = 0
     83 	CounterClockwise Direction = 1
     84 )
     85 
     86 // newBigFloat constructs a new big.Float with maximum precision.
     87 func newBigFloat() *big.Float { return new(big.Float).SetPrec(big.MaxPrec) }
     88 
     89 // Sign returns true if the points A, B, C are strictly counterclockwise,
     90 // and returns false if the points are clockwise or collinear (i.e. if they are all
     91 // contained on some great circle).
     92 //
     93 // Due to numerical errors, situations may arise that are mathematically
     94 // impossible, e.g. ABC may be considered strictly CCW while BCA is not.
     95 // However, the implementation guarantees the following:
     96 //
     97 // If Sign(a,b,c), then !Sign(c,b,a) for all a,b,c.
     98 func Sign(a, b, c Point) bool {
     99 	// NOTE(dnadasi): In the C++ API the equivalent method here was known as "SimpleSign".
    100 
    101 	// We compute the signed volume of the parallelepiped ABC. The usual
    102 	// formula for this is (A ⨯ B) · C, but we compute it here using (C ⨯ A) · B
    103 	// in order to ensure that ABC and CBA are not both CCW. This follows
    104 	// from the following identities (which are true numerically, not just
    105 	// mathematically):
    106 	//
    107 	//     (1) x ⨯ y == -(y ⨯ x)
    108 	//     (2) -x · y == -(x · y)
    109 	return c.Cross(a.Vector).Dot(b.Vector) > 0
    110 }
    111 
    112 // RobustSign returns a Direction representing the ordering of the points.
    113 // CounterClockwise is returned if the points are in counter-clockwise order,
    114 // Clockwise for clockwise, and Indeterminate if any two points are the same (collinear),
    115 // or the sign could not completely be determined.
    116 //
    117 // This function has additional logic to make sure that the above properties hold even
    118 // when the three points are coplanar, and to deal with the limitations of
    119 // floating-point arithmetic.
    120 //
    121 // RobustSign satisfies the following conditions:
    122 //
    123 //  (1) RobustSign(a,b,c) == Indeterminate if and only if a == b, b == c, or c == a
    124 //  (2) RobustSign(b,c,a) == RobustSign(a,b,c) for all a,b,c
    125 //  (3) RobustSign(c,b,a) == -RobustSign(a,b,c) for all a,b,c
    126 //
    127 // In other words:
    128 //
    129 //  (1) The result is Indeterminate if and only if two points are the same.
    130 //  (2) Rotating the order of the arguments does not affect the result.
    131 //  (3) Exchanging any two arguments inverts the result.
    132 //
    133 // On the other hand, note that it is not true in general that
    134 // RobustSign(-a,b,c) == -RobustSign(a,b,c), or any similar identities
    135 // involving antipodal points.
    136 func RobustSign(a, b, c Point) Direction {
    137 	sign := triageSign(a, b, c)
    138 	if sign == Indeterminate {
    139 		sign = expensiveSign(a, b, c)
    140 	}
    141 	return sign
    142 }
    143 
    144 // stableSign reports the direction sign of the points in a numerically stable way.
    145 // Unlike triageSign, this method can usually compute the correct determinant sign
    146 // even when all three points are as collinear as possible. For example if three
    147 // points are spaced 1km apart along a random line on the Earth's surface using
    148 // the nearest representable points, there is only a 0.4% chance that this method
    149 // will not be able to find the determinant sign. The probability of failure
    150 // decreases as the points get closer together; if the collinear points are 1 meter
    151 // apart, the failure rate drops to 0.0004%.
    152 //
    153 // This method could be extended to also handle nearly-antipodal points, but antipodal
    154 // points are rare in practice so it seems better to simply fall back to
    155 // exact arithmetic in that case.
    156 func stableSign(a, b, c Point) Direction {
    157 	ab := b.Sub(a.Vector)
    158 	ab2 := ab.Norm2()
    159 	bc := c.Sub(b.Vector)
    160 	bc2 := bc.Norm2()
    161 	ca := a.Sub(c.Vector)
    162 	ca2 := ca.Norm2()
    163 
    164 	// Now compute the determinant ((A-C)x(B-C)).C, where the vertices have been
    165 	// cyclically permuted if necessary so that AB is the longest edge. (This
    166 	// minimizes the magnitude of cross product.)  At the same time we also
    167 	// compute the maximum error in the determinant.
    168 
    169 	// The two shortest edges, pointing away from their common point.
    170 	var e1, e2, op r3.Vector
    171 	if ab2 >= bc2 && ab2 >= ca2 {
    172 		// AB is the longest edge.
    173 		e1, e2, op = ca, bc, c.Vector
    174 	} else if bc2 >= ca2 {
    175 		// BC is the longest edge.
    176 		e1, e2, op = ab, ca, a.Vector
    177 	} else {
    178 		// CA is the longest edge.
    179 		e1, e2, op = bc, ab, b.Vector
    180 	}
    181 
    182 	det := -e1.Cross(e2).Dot(op)
    183 	maxErr := detErrorMultiplier * math.Sqrt(e1.Norm2()*e2.Norm2())
    184 
    185 	// If the determinant isn't zero, within maxErr, we know definitively the point ordering.
    186 	if det > maxErr {
    187 		return CounterClockwise
    188 	}
    189 	if det < -maxErr {
    190 		return Clockwise
    191 	}
    192 	return Indeterminate
    193 }
    194 
    195 // triageSign returns the direction sign of the points. It returns Indeterminate if two
    196 // points are identical or the result is uncertain. Uncertain cases can be resolved, if
    197 // desired, by calling expensiveSign.
    198 //
    199 // The purpose of this method is to allow additional cheap tests to be done without
    200 // calling expensiveSign.
    201 func triageSign(a, b, c Point) Direction {
    202 	det := a.Cross(b.Vector).Dot(c.Vector)
    203 	if det > maxDeterminantError {
    204 		return CounterClockwise
    205 	}
    206 	if det < -maxDeterminantError {
    207 		return Clockwise
    208 	}
    209 	return Indeterminate
    210 }
    211 
    212 // expensiveSign reports the direction sign of the points. It returns Indeterminate
    213 // if two of the input points are the same. It uses multiple-precision arithmetic
    214 // to ensure that its results are always self-consistent.
    215 func expensiveSign(a, b, c Point) Direction {
    216 	// Return Indeterminate if and only if two points are the same.
    217 	// This ensures RobustSign(a,b,c) == Indeterminate if and only if a == b, b == c, or c == a.
    218 	// ie. Property 1 of RobustSign.
    219 	if a == b || b == c || c == a {
    220 		return Indeterminate
    221 	}
    222 
    223 	// Next we try recomputing the determinant still using floating-point
    224 	// arithmetic but in a more precise way. This is more expensive than the
    225 	// simple calculation done by triageSign, but it is still *much* cheaper
    226 	// than using arbitrary-precision arithmetic. This optimization is able to
    227 	// compute the correct determinant sign in virtually all cases except when
    228 	// the three points are truly collinear (e.g., three points on the equator).
    229 	detSign := stableSign(a, b, c)
    230 	if detSign != Indeterminate {
    231 		return detSign
    232 	}
    233 
    234 	// Otherwise fall back to exact arithmetic and symbolic permutations.
    235 	return exactSign(a, b, c, true)
    236 }
    237 
    238 // exactSign reports the direction sign of the points computed using high-precision
    239 // arithmetic and/or symbolic perturbations.
    240 func exactSign(a, b, c Point, perturb bool) Direction {
    241 	// Sort the three points in lexicographic order, keeping track of the sign
    242 	// of the permutation. (Each exchange inverts the sign of the determinant.)
    243 	permSign := CounterClockwise
    244 	pa := &a
    245 	pb := &b
    246 	pc := &c
    247 	if pa.Cmp(pb.Vector) > 0 {
    248 		pa, pb = pb, pa
    249 		permSign = -permSign
    250 	}
    251 	if pb.Cmp(pc.Vector) > 0 {
    252 		pb, pc = pc, pb
    253 		permSign = -permSign
    254 	}
    255 	if pa.Cmp(pb.Vector) > 0 {
    256 		pa, pb = pb, pa
    257 		permSign = -permSign
    258 	}
    259 
    260 	// Construct multiple-precision versions of the sorted points and compute
    261 	// their precise 3x3 determinant.
    262 	xa := r3.PreciseVectorFromVector(pa.Vector)
    263 	xb := r3.PreciseVectorFromVector(pb.Vector)
    264 	xc := r3.PreciseVectorFromVector(pc.Vector)
    265 	xbCrossXc := xb.Cross(xc)
    266 	det := xa.Dot(xbCrossXc)
    267 
    268 	// The precision of big.Float is high enough that the result should always
    269 	// be exact enough (no rounding was performed).
    270 
    271 	// If the exact determinant is non-zero, we're done.
    272 	detSign := Direction(det.Sign())
    273 	if detSign == Indeterminate && perturb {
    274 		// Otherwise, we need to resort to symbolic perturbations to resolve the
    275 		// sign of the determinant.
    276 		detSign = symbolicallyPerturbedSign(xa, xb, xc, xbCrossXc)
    277 	}
    278 	return permSign * detSign
    279 }
    280 
    281 // symbolicallyPerturbedSign reports the sign of the determinant of three points
    282 // A, B, C under a model where every possible Point is slightly perturbed by
    283 // a unique infinitesmal amount such that no three perturbed points are
    284 // collinear and no four points are coplanar. The perturbations are so small
    285 // that they do not change the sign of any determinant that was non-zero
    286 // before the perturbations, and therefore can be safely ignored unless the
    287 // determinant of three points is exactly zero (using multiple-precision
    288 // arithmetic). This returns CounterClockwise or Clockwise according to the
    289 // sign of the determinant after the symbolic perturbations are taken into account.
    290 //
    291 // Since the symbolic perturbation of a given point is fixed (i.e., the
    292 // perturbation is the same for all calls to this method and does not depend
    293 // on the other two arguments), the results of this method are always
    294 // self-consistent. It will never return results that would correspond to an
    295 // impossible configuration of non-degenerate points.
    296 //
    297 // This requires that the 3x3 determinant of A, B, C must be exactly zero.
    298 // And the points must be distinct, with A < B < C in lexicographic order.
    299 //
    300 // Reference:
    301 //   "Simulation of Simplicity" (Edelsbrunner and Muecke, ACM Transactions on
    302 //   Graphics, 1990).
    303 //
    304 func symbolicallyPerturbedSign(a, b, c, bCrossC r3.PreciseVector) Direction {
    305 	// This method requires that the points are sorted in lexicographically
    306 	// increasing order. This is because every possible Point has its own
    307 	// symbolic perturbation such that if A < B then the symbolic perturbation
    308 	// for A is much larger than the perturbation for B.
    309 	//
    310 	// Alternatively, we could sort the points in this method and keep track of
    311 	// the sign of the permutation, but it is more efficient to do this before
    312 	// converting the inputs to the multi-precision representation, and this
    313 	// also lets us re-use the result of the cross product B x C.
    314 	//
    315 	// Every input coordinate x[i] is assigned a symbolic perturbation dx[i].
    316 	// We then compute the sign of the determinant of the perturbed points,
    317 	// i.e.
    318 	//               | a.X+da.X  a.Y+da.Y  a.Z+da.Z |
    319 	//               | b.X+db.X  b.Y+db.Y  b.Z+db.Z |
    320 	//               | c.X+dc.X  c.Y+dc.Y  c.Z+dc.Z |
    321 	//
    322 	// The perturbations are chosen such that
    323 	//
    324 	//   da.Z > da.Y > da.X > db.Z > db.Y > db.X > dc.Z > dc.Y > dc.X
    325 	//
    326 	// where each perturbation is so much smaller than the previous one that we
    327 	// don't even need to consider it unless the coefficients of all previous
    328 	// perturbations are zero. In fact, it is so small that we don't need to
    329 	// consider it unless the coefficient of all products of the previous
    330 	// perturbations are zero. For example, we don't need to consider the
    331 	// coefficient of db.Y unless the coefficient of db.Z *da.X is zero.
    332 	//
    333 	// The follow code simply enumerates the coefficients of the perturbations
    334 	// (and products of perturbations) that appear in the determinant above, in
    335 	// order of decreasing perturbation magnitude. The first non-zero
    336 	// coefficient determines the sign of the result. The easiest way to
    337 	// enumerate the coefficients in the correct order is to pretend that each
    338 	// perturbation is some tiny value "eps" raised to a power of two:
    339 	//
    340 	// eps**     1      2      4      8     16     32     64    128    256
    341 	//        da.Z   da.Y   da.X   db.Z   db.Y   db.X   dc.Z   dc.Y   dc.X
    342 	//
    343 	// Essentially we can then just count in binary and test the corresponding
    344 	// subset of perturbations at each step. So for example, we must test the
    345 	// coefficient of db.Z*da.X before db.Y because eps**12 > eps**16.
    346 	//
    347 	// Of course, not all products of these perturbations appear in the
    348 	// determinant above, since the determinant only contains the products of
    349 	// elements in distinct rows and columns. Thus we don't need to consider
    350 	// da.Z*da.Y, db.Y *da.Y, etc. Furthermore, sometimes different pairs of
    351 	// perturbations have the same coefficient in the determinant; for example,
    352 	// da.Y*db.X and db.Y*da.X have the same coefficient (c.Z). Therefore
    353 	// we only need to test this coefficient the first time we encounter it in
    354 	// the binary order above (which will be db.Y*da.X).
    355 	//
    356 	// The sequence of tests below also appears in Table 4-ii of the paper
    357 	// referenced above, if you just want to look it up, with the following
    358 	// translations: [a,b,c] -> [i,j,k] and [0,1,2] -> [1,2,3]. Also note that
    359 	// some of the signs are different because the opposite cross product is
    360 	// used (e.g., B x C rather than C x B).
    361 
    362 	detSign := bCrossC.Z.Sign() // da.Z
    363 	if detSign != 0 {
    364 		return Direction(detSign)
    365 	}
    366 	detSign = bCrossC.Y.Sign() // da.Y
    367 	if detSign != 0 {
    368 		return Direction(detSign)
    369 	}
    370 	detSign = bCrossC.X.Sign() // da.X
    371 	if detSign != 0 {
    372 		return Direction(detSign)
    373 	}
    374 
    375 	detSign = newBigFloat().Sub(newBigFloat().Mul(c.X, a.Y), newBigFloat().Mul(c.Y, a.X)).Sign() // db.Z
    376 	if detSign != 0 {
    377 		return Direction(detSign)
    378 	}
    379 	detSign = c.X.Sign() // db.Z * da.Y
    380 	if detSign != 0 {
    381 		return Direction(detSign)
    382 	}
    383 	detSign = -(c.Y.Sign()) // db.Z * da.X
    384 	if detSign != 0 {
    385 		return Direction(detSign)
    386 	}
    387 
    388 	detSign = newBigFloat().Sub(newBigFloat().Mul(c.Z, a.X), newBigFloat().Mul(c.X, a.Z)).Sign() // db.Y
    389 	if detSign != 0 {
    390 		return Direction(detSign)
    391 	}
    392 	detSign = c.Z.Sign() // db.Y * da.X
    393 	if detSign != 0 {
    394 		return Direction(detSign)
    395 	}
    396 
    397 	// The following test is listed in the paper, but it is redundant because
    398 	// the previous tests guarantee that C == (0, 0, 0).
    399 	// (c.Y*a.Z - c.Z*a.Y).Sign() // db.X
    400 
    401 	detSign = newBigFloat().Sub(newBigFloat().Mul(a.X, b.Y), newBigFloat().Mul(a.Y, b.X)).Sign() // dc.Z
    402 	if detSign != 0 {
    403 		return Direction(detSign)
    404 	}
    405 	detSign = -(b.X.Sign()) // dc.Z * da.Y
    406 	if detSign != 0 {
    407 		return Direction(detSign)
    408 	}
    409 	detSign = b.Y.Sign() // dc.Z * da.X
    410 	if detSign != 0 {
    411 		return Direction(detSign)
    412 	}
    413 	detSign = a.X.Sign() // dc.Z * db.Y
    414 	if detSign != 0 {
    415 		return Direction(detSign)
    416 	}
    417 	return CounterClockwise // dc.Z * db.Y * da.X
    418 }
    419 
    420 // CompareDistances returns -1, 0, or +1 according to whether AX < BX, A == B,
    421 // or AX > BX respectively. Distances are measured with respect to the positions
    422 // of X, A, and B as though they were reprojected to lie exactly on the surface of
    423 // the unit sphere. Furthermore, this method uses symbolic perturbations to
    424 // ensure that the result is non-zero whenever A != B, even when AX == BX
    425 // exactly, or even when A and B project to the same point on the sphere.
    426 // Such results are guaranteed to be self-consistent, i.e. if AB < BC and
    427 // BC < AC, then AB < AC.
    428 func CompareDistances(x, a, b Point) int {
    429 	// We start by comparing distances using dot products (i.e., cosine of the
    430 	// angle), because (1) this is the cheapest technique, and (2) it is valid
    431 	// over the entire range of possible angles. (We can only use the sin^2
    432 	// technique if both angles are less than 90 degrees or both angles are
    433 	// greater than 90 degrees.)
    434 	sign := triageCompareCosDistances(x, a, b)
    435 	if sign != 0 {
    436 		return sign
    437 	}
    438 
    439 	// Optimization for (a == b) to avoid falling back to exact arithmetic.
    440 	if a == b {
    441 		return 0
    442 	}
    443 
    444 	// It is much better numerically to compare distances using cos(angle) if
    445 	// the distances are near 90 degrees and sin^2(angle) if the distances are
    446 	// near 0 or 180 degrees. We only need to check one of the two angles when
    447 	// making this decision because the fact that the test above failed means
    448 	// that angles "a" and "b" are very close together.
    449 	cosAX := a.Dot(x.Vector)
    450 	if cosAX > 1/math.Sqrt2 {
    451 		// Angles < 45 degrees.
    452 		sign = triageCompareSin2Distances(x, a, b)
    453 	} else if cosAX < -1/math.Sqrt2 {
    454 		// Angles > 135 degrees. sin^2(angle) is decreasing in this range.
    455 		sign = -triageCompareSin2Distances(x, a, b)
    456 	}
    457 	// C++ adds an additional check here using 80-bit floats.
    458 	// This is skipped in Go because we only have 32 and 64 bit floats.
    459 
    460 	if sign != 0 {
    461 		return sign
    462 	}
    463 
    464 	sign = exactCompareDistances(r3.PreciseVectorFromVector(x.Vector), r3.PreciseVectorFromVector(a.Vector), r3.PreciseVectorFromVector(b.Vector))
    465 	if sign != 0 {
    466 		return sign
    467 	}
    468 	return symbolicCompareDistances(x, a, b)
    469 }
    470 
    471 // cosDistance returns cos(XY) where XY is the angle between X and Y, and the
    472 // maximum error amount in the result. This requires X and Y be normalized.
    473 func cosDistance(x, y Point) (cos, err float64) {
    474 	cos = x.Dot(y.Vector)
    475 	return cos, 9.5*dblError*math.Abs(cos) + 1.5*dblError
    476 }
    477 
    478 // sin2Distance returns sin**2(XY), where XY is the angle between X and Y,
    479 // and the maximum error amount in the result. This requires X and Y be normalized.
    480 func sin2Distance(x, y Point) (sin2, err float64) {
    481 	// The (x-y).Cross(x+y) trick eliminates almost all of error due to x
    482 	// and y being not quite unit length. This method is extremely accurate
    483 	// for small distances; the *relative* error in the result is O(dblError) for
    484 	// distances as small as dblError.
    485 	n := x.Sub(y.Vector).Cross(x.Add(y.Vector))
    486 	sin2 = 0.25 * n.Norm2()
    487 	err = ((21+4*math.Sqrt(3))*dblError*sin2 +
    488 		32*math.Sqrt(3)*dblError*dblError*math.Sqrt(sin2) +
    489 		768*dblError*dblError*dblError*dblError)
    490 	return sin2, err
    491 }
    492 
    493 // triageCompareCosDistances returns -1, 0, or +1 according to whether AX < BX,
    494 // A == B, or AX > BX by comparing the distances between them using cosDistance.
    495 func triageCompareCosDistances(x, a, b Point) int {
    496 	cosAX, cosAXerror := cosDistance(a, x)
    497 	cosBX, cosBXerror := cosDistance(b, x)
    498 	diff := cosAX - cosBX
    499 	err := cosAXerror + cosBXerror
    500 	if diff > err {
    501 		return -1
    502 	}
    503 	if diff < -err {
    504 		return 1
    505 	}
    506 	return 0
    507 }
    508 
    509 // triageCompareSin2Distances returns -1, 0, or +1 according to whether AX < BX,
    510 // A == B, or AX > BX by comparing the distances between them using sin2Distance.
    511 func triageCompareSin2Distances(x, a, b Point) int {
    512 	sin2AX, sin2AXerror := sin2Distance(a, x)
    513 	sin2BX, sin2BXerror := sin2Distance(b, x)
    514 	diff := sin2AX - sin2BX
    515 	err := sin2AXerror + sin2BXerror
    516 	if diff > err {
    517 		return 1
    518 	}
    519 	if diff < -err {
    520 		return -1
    521 	}
    522 	return 0
    523 }
    524 
    525 // exactCompareDistances returns -1, 0, or 1 after comparing using the values as
    526 // PreciseVectors.
    527 func exactCompareDistances(x, a, b r3.PreciseVector) int {
    528 	// This code produces the same result as though all points were reprojected
    529 	// to lie exactly on the surface of the unit sphere. It is based on testing
    530 	// whether x.Dot(a.Normalize()) < x.Dot(b.Normalize()), reformulated
    531 	// so that it can be evaluated using exact arithmetic.
    532 	cosAX := x.Dot(a)
    533 	cosBX := x.Dot(b)
    534 
    535 	// If the two values have different signs, we need to handle that case now
    536 	// before squaring them below.
    537 	aSign := cosAX.Sign()
    538 	bSign := cosBX.Sign()
    539 	if aSign != bSign {
    540 		// If cos(AX) > cos(BX), then AX < BX.
    541 		if aSign > bSign {
    542 			return -1
    543 		}
    544 		return 1
    545 	}
    546 	cosAX2 := newBigFloat().Mul(cosAX, cosAX)
    547 	cosBX2 := newBigFloat().Mul(cosBX, cosBX)
    548 	cmp := newBigFloat().Sub(cosBX2.Mul(cosBX2, a.Norm2()), cosAX2.Mul(cosAX2, b.Norm2()))
    549 	return aSign * cmp.Sign()
    550 }
    551 
    552 // symbolicCompareDistances returns -1, 0, or +1 given three points such that AX == BX
    553 // (exactly) according to whether AX < BX, AX == BX, or AX > BX after symbolic
    554 // perturbations are taken into account.
    555 func symbolicCompareDistances(x, a, b Point) int {
    556 	// Our symbolic perturbation strategy is based on the following model.
    557 	// Similar to "simulation of simplicity", we assign a perturbation to every
    558 	// point such that if A < B, then the symbolic perturbation for A is much,
    559 	// much larger than the symbolic perturbation for B. We imagine that
    560 	// rather than projecting every point to lie exactly on the unit sphere,
    561 	// instead each point is positioned on its own tiny pedestal that raises it
    562 	// just off the surface of the unit sphere. This means that the distance AX
    563 	// is actually the true distance AX plus the (symbolic) heights of the
    564 	// pedestals for A and X. The pedestals are infinitesmally thin, so they do
    565 	// not affect distance measurements except at the two endpoints. If several
    566 	// points project to exactly the same point on the unit sphere, we imagine
    567 	// that they are placed on separate pedestals placed close together, where
    568 	// the distance between pedestals is much, much less than the height of any
    569 	// pedestal. (There are a finite number of Points, and therefore a finite
    570 	// number of pedestals, so this is possible.)
    571 	//
    572 	// If A < B, then A is on a higher pedestal than B, and therefore AX > BX.
    573 	switch a.Cmp(b.Vector) {
    574 	case -1:
    575 		return 1
    576 	case 1:
    577 		return -1
    578 	default:
    579 		return 0
    580 	}
    581 }
    582 
    583 var (
    584 	// ca45Degrees is a predefined ChordAngle representing (approximately) 45 degrees.
    585 	ca45Degrees = s1.ChordAngleFromSquaredLength(2 - math.Sqrt2)
    586 )
    587 
    588 // CompareDistance returns -1, 0, or +1 according to whether the distance XY is
    589 // respectively less than, equal to, or greater than the provided chord angle. Distances are measured
    590 // with respect to the positions of all points as though they are projected to lie
    591 // exactly on the surface of the unit sphere.
    592 func CompareDistance(x, y Point, r s1.ChordAngle) int {
    593 	// As with CompareDistances, we start by comparing dot products because
    594 	// the sin^2 method is only valid when the distance XY and the limit "r" are
    595 	// both less than 90 degrees.
    596 	sign := triageCompareCosDistance(x, y, float64(r))
    597 	if sign != 0 {
    598 		return sign
    599 	}
    600 
    601 	// Unlike with CompareDistances, it's not worth using the sin^2 method
    602 	// when the distance limit is near 180 degrees because the ChordAngle
    603 	// representation itself has has a rounding error of up to 2e-8 radians for
    604 	// distances near 180 degrees.
    605 	if r < ca45Degrees {
    606 		sign = triageCompareSin2Distance(x, y, float64(r))
    607 		if sign != 0 {
    608 			return sign
    609 		}
    610 	}
    611 	return exactCompareDistance(r3.PreciseVectorFromVector(x.Vector), r3.PreciseVectorFromVector(y.Vector), big.NewFloat(float64(r)).SetPrec(big.MaxPrec))
    612 }
    613 
    614 // triageCompareCosDistance returns -1, 0, or +1 according to whether the distance XY is
    615 // less than, equal to, or greater than r2 respectively using cos distance.
    616 func triageCompareCosDistance(x, y Point, r2 float64) int {
    617 	cosXY, cosXYError := cosDistance(x, y)
    618 	cosR := 1.0 - 0.5*r2
    619 	cosRError := 2.0 * dblError * cosR
    620 	diff := cosXY - cosR
    621 	err := cosXYError + cosRError
    622 	if diff > err {
    623 		return -1
    624 	}
    625 	if diff < -err {
    626 		return 1
    627 	}
    628 	return 0
    629 }
    630 
    631 // triageCompareSin2Distance returns -1, 0, or +1 according to whether the distance XY is
    632 // less than, equal to, or greater than r2 respectively using sin^2 distance.
    633 func triageCompareSin2Distance(x, y Point, r2 float64) int {
    634 	// Only valid for distance limits < 90 degrees.
    635 	sin2XY, sin2XYError := sin2Distance(x, y)
    636 	sin2R := r2 * (1.0 - 0.25*r2)
    637 	sin2RError := 3.0 * dblError * sin2R
    638 	diff := sin2XY - sin2R
    639 	err := sin2XYError + sin2RError
    640 	if diff > err {
    641 		return 1
    642 	}
    643 	if diff < -err {
    644 		return -1
    645 	}
    646 	return 0
    647 }
    648 
    649 var (
    650 	bigOne  = big.NewFloat(1.0).SetPrec(big.MaxPrec)
    651 	bigHalf = big.NewFloat(0.5).SetPrec(big.MaxPrec)
    652 )
    653 
    654 // exactCompareDistance returns -1, 0, or +1 after comparing using PreciseVectors.
    655 func exactCompareDistance(x, y r3.PreciseVector, r2 *big.Float) int {
    656 	// This code produces the same result as though all points were reprojected
    657 	// to lie exactly on the surface of the unit sphere.  It is based on
    658 	// comparing the cosine of the angle XY (when both points are projected to
    659 	// lie exactly on the sphere) to the given threshold.
    660 	cosXY := x.Dot(y)
    661 	cosR := newBigFloat().Sub(bigOne, newBigFloat().Mul(bigHalf, r2))
    662 
    663 	// If the two values have different signs, we need to handle that case now
    664 	// before squaring them below.
    665 	xySign := cosXY.Sign()
    666 	rSign := cosR.Sign()
    667 	if xySign != rSign {
    668 		if xySign > rSign {
    669 			return -1
    670 		}
    671 		return 1 // If cos(XY) > cos(r), then XY < r.
    672 	}
    673 	cmp := newBigFloat().Sub(
    674 		newBigFloat().Mul(
    675 			newBigFloat().Mul(cosR, cosR), newBigFloat().Mul(x.Norm2(), y.Norm2())),
    676 		newBigFloat().Mul(cosXY, cosXY))
    677 	return xySign * cmp.Sign()
    678 }
    679 
    680 // TODO(roberts): Differences from C++
    681 // CompareEdgeDistance
    682 // CompareEdgeDirections
    683 // EdgeCircumcenterSign
    684 // GetVoronoiSiteExclusion
    685 // GetClosestVertex
    686 // TriageCompareLineSin2Distance
    687 // TriageCompareLineCos2Distance
    688 // TriageCompareLineDistance
    689 // TriageCompareEdgeDistance
    690 // ExactCompareLineDistance
    691 // ExactCompareEdgeDistance
    692 // TriageCompareEdgeDirections
    693 // ExactCompareEdgeDirections
    694 // ArePointsAntipodal
    695 // ArePointsLinearlyDependent
    696 // GetCircumcenter
    697 // TriageEdgeCircumcenterSign
    698 // ExactEdgeCircumcenterSign
    699 // UnperturbedSign
    700 // SymbolicEdgeCircumcenterSign
    701 // ExactVoronoiSiteExclusion