// y_0 = -m_13 / (2 m_11)
// z_0 = +m_14 / (2 m_11)
// Note that the minors m_11, m_12, m_13 and m_14 all have the last column
// filled with 1.0, hence simplifying the computation
final BigFraction[] c2 = new BigFraction[] {
new BigFraction(vA.getX()), new BigFraction(vB.getX()),
new BigFraction(vC.getX()), new BigFraction(vD.getX())
};
final BigFraction[] c3 = new BigFraction[] {
new BigFraction(vA.getY()), new BigFraction(vB.getY()),
new BigFraction(vC.getY()), new BigFraction(vD.getY())
};
final BigFraction[] c4 = new BigFraction[] {
new BigFraction(vA.getZ()), new BigFraction(vB.getZ()),
new BigFraction(vC.getZ()), new BigFraction(vD.getZ())
};
final BigFraction[] c1 = new BigFraction[] {
c2[0].multiply(c2[0]).add(c3[0].multiply(c3[0])).add(c4[0].multiply(c4[0])),
c2[1].multiply(c2[1]).add(c3[1].multiply(c3[1])).add(c4[1].multiply(c4[1])),
c2[2].multiply(c2[2]).add(c3[2].multiply(c3[2])).add(c4[2].multiply(c4[2])),
c2[3].multiply(c2[3]).add(c3[3].multiply(c3[3])).add(c4[3].multiply(c4[3]))
};
final BigFraction twoM11 = minor(c2, c3, c4).multiply(2);
final BigFraction m12 = minor(c1, c3, c4);
final BigFraction m13 = minor(c1, c2, c4);
final BigFraction m14 = minor(c1, c2, c3);
final BigFraction centerX = m12.divide(twoM11);
final BigFraction centerY = m13.divide(twoM11).negate();
final BigFraction centerZ = m14.divide(twoM11);
final BigFraction dx = c2[0].subtract(centerX);
final BigFraction dy = c3[0].subtract(centerY);
final BigFraction dz = c4[0].subtract(centerZ);
final BigFraction r2 = dx.multiply(dx).add(dy.multiply(dy)).add(dz.multiply(dz));
return new EnclosingBall<Euclidean3D, Vector3D>(new Vector3D(centerX.doubleValue(),
centerY.doubleValue(),
centerZ.doubleValue()),
FastMath.sqrt(r2.doubleValue()),
vA, vB, vC, vD);
}
}
}
}