// This function is designed to choose line segment endpoints that are difficult // to handle correctly. Given two adjacent cube vertices P and Q, it returns // either an edge midpoint, face midpoint, or corner vertex along the edge PQ // and then perturbs it slightly. It also sometimes returns a random point from // anywhere on the sphere. private S2Point PerturbedCornerOrMidpoint(S2Point p, S2Point q) { S2Point a = (S2Testing.Random.Uniform(3) - 1) * p + (S2Testing.Random.Uniform(3) - 1) * q; if (S2Testing.Random.OneIn(10)) { // This perturbation often has no effect except on coordinates that are // zero, in which case the perturbed value is so small that operations on // it often result in underflow. a += Math.Pow(1e-300, S2Testing.Random.RandDouble()) * S2Testing.RandomPoint(); } else if (S2Testing.Random.OneIn(2)) { // For coordinates near 1 (say > 0.5), this perturbation yields values // that are only a few representable values away from the initial value. a += 4 * S2.DoubleEpsilon * S2Testing.RandomPoint(); } else { // A perturbation whose magnitude is in the range [1e-25, 1e-10]. a += 1e-10 * Math.Pow(S2.DoubleError, S2Testing.Random.RandDouble()) * S2Testing.RandomPoint(); } if (a.Norm2() < S2.DoubleMinNorm) { // If a.Norm2 is denormalized, Normalize() loses too much precision. return(PerturbedCornerOrMidpoint(p, q)); } return(a); }