Come trovo la circumsfera di un tetraedro?


9

Sto cercando l'equazione più minimizzata per trovare le coordinate centrali e il raggio di una circumsfera del tetraedro con quattro punti 3D.

Quello che ho trovato su Internet riguarda principalmente la circonferenza di un triangolo tridimensionale piatto, o alcune definizioni matematiche approssimative, o alcuni casi molto singoli come i tetraedri regolari. Comunque sono riuscito a trovare l'equazione qui sotto ma mi sono perso qualcosa:

    ->  ->      ->
let d1, d2, and d3 three vectors of any face of the triangle :

    | d1x  d1y  d1z |   | x |   | d1^2 |
2 * | d2x  d2y  d2z | * | y | = | d2^2 |
    | d3x  d3y  d3z |   | z |   | d3^2 |

La mia conoscenza in questo campo ha i suoi limiti ma penso di poter gestire matrici e operazioni vettoriali. Ma la parte giusta dell'equazione è il quadrato della norma di ciascun vettore? (che sono in un vettore). L'equazione è valida? È solo lo scrittore che ha dimenticato pigramente di scrivere | d1 | ^ 2? Oppure è un modo comune per definire alcune proprietà matematiche.

PS: è per un'implementazione della triangolazione Delaunay. L'equazione (numero 9) è nel seguente link: https://www2.mps.mpg.de/homes/daly/CSDS/t4h/tetra.htm


4
Prova matematica stackexchange.
Majte

Grazie ho trovato un modo per calcolare la circumsfera lì!
herme5,


3
@ herme5, sentiti libero di pubblicare la tua risposta qui su come stai calcolando la risposta. Molte persone potrebbero venire qui in futuro sperando di trovare la risposta e la condivisione sarà preziosa per loro. È assolutamente accettabile pubblicare la tua risposta e persino accettarla.
Tim Holt,

2
Grazie per l'avviso @TimHolt. Lo farò ! Tuttavia non sono più sicuro di come l'ho fatto, è stato più di 2 anni fa! fammi trovare e dare un'occhiata alla mia vecchia implementazione
herme5,

Risposte:


2

Mentre questo è un filo antico, ho pensato che potrebbe essere bello per i posteri avere un po 'di riferimento. La fonte della formula è tratta da Geometric Tools for Computer Graphics di Philip J. Schneider e David H. Eberly. Qualcosa da notare, secondo il testo

Il tetraedro V0, V1, V2, V3 è ordinato in modo che sia isomorfo a quello canonico (0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1 ).

A quanto ho capito, l'isomorfismo , l' può avere diversi significati quando usato in geometria. Se intende isomorfo rispetto alla teoria dei grafi, il codice seguente dovrebbe comportarsi correttamente, poiché la topologia di qualsiasi tetraedro è la stessa (K4, un grafico completo). Ho testato i risultati della funzione contro il wolfram alpha usando varie permutazioni nell'ordinamento dei vertici canonici e non ho visto alcuna differenza nel risultato. Se l'ordinamento si rivela un problema, suggerisco di esaminare la normale del triangolo formato dai vertici V1, V2, V3 al momento dell'input a questa funzione e di trattare i punti come un mezzo spazio con un test del punto-prodotto per capire se quel triangolo è rivolto nella direzione giusta. In caso contrario, un semplice di uno qualsiasi dei due vertici del triangolo invertirà la direzione del normale e potreste continuare. Ma come ho detto, non ho visto alcuna differenza con varie permutazioni.std::swap

Ecco il codice tradotto senza usare le matrici per evitare confusione nell'implementazione, è abbastanza semplice;

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);
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.