使用@Rhialto,对角落案例进行额外的简化和测试:
// c1 is the signed chord distance A to (B1 projected to the xz plane)
// c1*c1 + h1*h1 = d1*d1
// c1 = +/- sqrt(d1*d1 - h1*h1) (choose sign later)
// c1 = Cord(r, theta) = fabs(r*2*sin(theta/2))
// theta = asin(c1/(r*2))*2
//
// theta is < 0 when d2 > sqrt(h2*h2 + sqrt(2)*r*sqrt(2)*r)
// theta is < 0 when d2 > sqrt(h2*h2 + 2*r*r)
// theta is < 0 when d2*d2 > h2*h2 + 2*r*r
#define h1 (0.1)
#define h2 (0.25)
#define r (1.333)
#define h1Squared (h1*h1)
#define rSquared (r*r)
#define rSquaredTimes2 (r*r*2)
#define rTimes2 (r*2)
#define d2Big (h2*h2 + 2*r*r)
// Various steps to avoid issues with d1 < 0, d2 < 0, d1 ~= h1 and theta near pi
double zashu(double d1, double d2) {
double c1Squared = d1*d1 - h1Squared;
if (c1Squared < 0.0)
c1Squared = 0.0; // _May_ be needed when in select times |d1| ~= |h1|
double a = sqrt(c1Squared) / rTimes2;
double theta = (a <= 1.0) ? asin(a)*2.0 : asin(1.0)*2.0; // Possible a is _just_ greater than 1.0
if (d2*d2 > d2Big) // this could be done with fabs(d2) > pre_computed_sqrt(d2Big)
theta = -theta;
return theta;
}