private void TestEllipsoidInOctant(EllipsoidClosestPoint_t func) { using (var unused = new WithRandomSeed(4)) { Vector3 abc = new Vector3(4, 3, 2); for (int theta = 0; theta < 360; theta += 7) { for (int phi = 0; phi < 180; phi += 7) { for (float bump = -1; bump <= 4f; bump += .32f) { // Find a spot on the ellipsoid, bump it out by its normal Vector3 pointOnEllipse = EllipsoidSphericalToCartesian(abc, new Vector2(theta, phi)); Vector3 normal = NormalAtEllipsoid(abc, pointOnEllipse); Vector3 bumped = pointOnEllipse + normal * bump; // pointOnEllipse is guaranteed to be the closest point to "bumped" as long as we // haven't bumped the point into a different octant. if (GetOctant(bumped) != GetOctant(pointOnEllipse)) { continue; } AssertAlmostEqual(pointOnEllipse, func(abc, bumped), message: (theta, phi, bump)); } } } } }
// Tests random points both inside and outside the ellipsoid private void TestEllipsoidRandomPoints(EllipsoidClosestPoint_t func) { Vector3 he = new Vector3(4, 3, 2); for (int i = 0; i < 100; ++i) { Vector3 point = CMul(he, Random.onUnitSphere * 2); Vector3 cp = func(he, point); Vector3 surfaceNormal = NormalAtEllipsoid(he, cp); // We don't have ground truth, so instead we verify this invariant: // The normal at cp is parallel to (point - cp). Vector3 delta = (point - cp); Vector3 err = delta - (Vector3.Dot(surfaceNormal, delta) * surfaceNormal); AssertAlmostEqual(err, Vector3.zero, message: point); } }