이것은 고대의 실이지만 후손이 조금 언급하는 것이 좋을 것이라고 생각했습니다. 공식의 출처는 Philip J. Schneider와 David H. Eberly의 컴퓨터 그래픽 용 기하학적 도구 에서 나온 것 입니다 . 본문에 따르면 주목할 점
4 면체 V0, V1, V2, V3은 정식 1 (0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1과 동형이되도록 정렬됩니다. )
동 형사상을 이해함에 따라 지오메트리에 사용될 때 몇 가지 다른 의미가있을 수 있습니다. 그래프 이론과 관련하여 동형을 의미하는 경우 4 면체의 토폴로지가 동일하므로 다음 코드가 올바르게 작동해야합니다 (K4, 완전한 그래프). 나는 볼프람 알파에 대해 함수의 결과를 테스트 정식 정점의 순서에 다양한 순열을 사용하여, 나는 결과에 차이를 보지 못했다. 순서가 문제가되면이 함수에 입력 할 때 꼭짓점 V1, V2, V3에 의해 형성된 삼각형의 법선을 검사하고 점-제품 테스트로 점을 반 공백처럼 처리하여 알아내는 것이 좋습니다. 그 삼각형이 올바른 방향을 향하고 있다면 그렇지 않은 경우 간단한std::swap
삼각형의 정점 중 어느 하나의 정점은 법선의 방향을 반대로하여 계속 진행할 수 있습니다. 그러나 내가 말했듯이 다양한 순열과 아무런 차이가 없었습니다.
구현 혼동을 피하기 위해 행렬을 사용하지 않고 번역 된 코드는 다음과 같습니다.
void Circumsphere(const Vec3& v0, const Vec3& v1, const Vec3& v2, const Vec3& v3, Vec3* center, float* radius)
{
//Create the rows of our "unrolled" 3x3 matrix
Vec3 Row1 = v1 - v0;
float sqLength1 = length2(Row1);
Vec3 Row2 = v2 - v0;
float sqLength2 = length2(Row2);
Vec3 Row3 = v3 - v0;
float sqLength3 = length2(Row3);
//Compute the determinant of said matrix
const float determinant = Row1.x * (Row2.y * Row3.z - Row3.y * Row2.z)
- Row2.x * (Row1.y * Row3.z - Row3.y * Row1.z)
+ Row3.x * (Row1.y * Row2.z - Row2.y * Row1.z);
// Compute the volume of the tetrahedron, and precompute a scalar quantity for re-use in the formula
const float volume = determinant / 6.f;
const float iTwelveVolume = 1.f / (volume * 12.f);
center->x = v0.x + iTwelveVolume * ( ( Row2.y * Row3.z - Row3.y * Row2.z) * sqLength1 - (Row1.y * Row3.z - Row3.y * Row1.z) * sqLength2 + (Row1.y * Row2.z - Row2.y * Row1.z) * sqLength3 );
center->y = v0.y + iTwelveVolume * (-( Row2.x * Row3.z - Row3.x * Row2.z) * sqLength1 + (Row1.x * Row3.z - Row3.x * Row1.z) * sqLength2 - (Row1.x * Row2.z - Row2.x * Row1.z) * sqLength3 );
center->z = v0.z + iTwelveVolume * ( ( Row2.x * Row3.y - Row3.x * Row2.y) * sqLength1 - (Row1.x * Row3.y - Row3.x * Row1.y) * sqLength2 + (Row1.x * Row2.y - Row2.x * Row1.y) * sqLength3 );
//Once we know the center, the radius is clearly the distance to any vertex
*radius = length(*center - v0);
}