public static Matrix4d buildCanonicalOrientation(Point4d a, Point4d b) { /* local scratch variables; will be transformed */ Point4d pa = new Point4d(a.x, a.y, a.z, a.w); Point4d pb = new Point4d(b.x, b.y, b.z, b.w); Point4d pivot = findPivotPoint(pa, pb); Matrix4d retval = buildTranslation(ORIGIN4, pivot); Matrix4d t1 = buildTranslation(pivot, ORIGIN4); t1.transform(pa); t1.transform(pb); retval *= buildTranslation(ORIGIN4, pa); Matrix4d t2 = buildTranslation(pa, ORIGIN4); t2.transform(pa); t2.transform(pb); /* calculate spherical coordinates (rho, phi, theta) of pb */ // Projection to affine coordinates is necessary so that we can // directly reference the x, y, and z components in the following // calculations. pb.project(); float rho = HyperbolicMath.vectorLength(pb); float phi = Mathf.Acos(pb.x / rho); float theta = Mathf.Atan2(pb.z, pb.y); if (phi == 0.0f) { /* rotate line to achieve alignment on positive x-axis */ retval *= buildXRotation(theta); retval *= buildZRotation(phi); } return(retval); }