[Gelöst]Volumenberechnung mit Tetraedern...



  • Hallo Leute !
    Ich programmiere im Moment ein Programm in dem ich u.a. das von einer im dreidimensionalen Raum zufällig verstreuten Punktemenge induzierte Volumen berechne.
    Dazu trianguliere ich die Punktemenge im Raum, d.h. ich bilde Tetraeder, die die Punkte der Punktemenge verbinden. Das läuft alles wunderbar. Verwende übrigens das Programm "Tetgen" hierzu.
    Meine generierten Punkte erstrecken sich über den positiven und negativen Raum.

    Das Problem ist, dass ich für das Volumen scheinbar falsche Ergebnisse bekomme.
    z.b: negative Volumenwerte, Volumina größer Eins obwohl alle Punkte im Einheitskubus liegen...

    Ich verwende folgende Methode zur Berechnung der einzelnen Tetraeder-Volumina und addiere die Ergebnisse immer zur globalen Volumenvariable hinzu:

    float Vec::volumen(Vec *a,Vec *b,Vec *c,Vec *d)
    	{
    	int i;
    	float mat[3][3];
    	float s1,s2,s3,s4,s5,s6;
    
    	mat[0][0] = a->x - b->x;
    	mat[0][1] = a->x - b->y;
    	mat[0][2] = a->x - b->z;
    
    	mat[1][0] = a->x - c->x;
    	mat[1][1] = a->x - c->y;
    	mat[1][2] = a->x - c->z;
    
    	mat[2][0] = a->x - d->x;
    	mat[2][1] = a->x - d->y;
    	mat[2][2] = a->x - d->z;
    
    	s1=mat[0][0]*mat[1][1]*mat[2][2];
    	s2=mat[0][1]*mat[1][2]*mat[2][0];
    	s3=mat[0][2]*mat[1][0]*mat[2][1];
    	s4=mat[0][2]*mat[1][1]*mat[2][0];
    	s5=mat[0][0]*mat[2][1]*mat[1][2];
    	s6=mat[2][2]*mat[1][0]*mat[0][1];
    	return (s1+s2+s3-s4-s5-s6)/6;
    	}
    

    Was mach ich falsch ?

    Danke....



  • Habe Kanten

    e1 = a-b;
    e2 = a-c;
    e3 = a-d;

    volumen = 1/6 * (e1(e2 xe3));



  • Ja genau das habe ich auch versucht....
    Habe eine Kreuzprodukt- und Skalarprodukt-funktion definiert, die folgendemaßen aussehen:

    1.Variante:

    float Vec::scale(Vec *a,Vec *b){
    	float c;
    
    	c = a->x*b->x+a->y*b->y+a->z*b->z;
    
    	return c;
    	}
    
    	Vec* Vec::cross(Vec *a, Vec *b){
    	Vec* c = new Vec();
    
    	c->x = a->y * b->z - a->z * b->y;
    	c->y = a->z * b->x - a->x * b->z;
    	c->z = a->x * b->y - a->y * b->x;
    
    	return c;
    	}
    

    Volumenberechnung sieht dann so aus:
    Für jedes Teraeder kommt dieser Ausdruck einmal vor

    Volumen+=(fabs(a->scale(a->cross(a,b),c)))/6;
    

    2. Variante:

    float Vec::spat(Vec *a,Vec *b,Vec *c){
    	float d;
    
    	d = a->x*(b->y*c->z-b->z*c->y)
    	   +a->y*(b->z*c->x-b->x*c->z)
    	   +a->z*(b->x*c->y-b->y*c->x);
    
    	return d;
    	}
    

    Volumenberechnung sieht dann so aus:
    Für jedes Teraeder kommt dieser Ausdruck einmal vor

    Volumen+=(fabs(a->spat(a,b,c)))/6;
    

    Bekomme dennoch selsame Werte raus....

    Muss ich vielleicht vorher irgendwas mit den Vektoren machen ?
    Ich meine nicht die vorherige Bildung der drei Verbindungsvektoren aus den vier Punkten...
    Ist es vielleicht wichtig welchen Punkt ich als Stützpunkt zur Bildung der Verbindungsvektoren nehme ?
    Ist möglicherweise sogar ausschlaggebend, dass manche Punkte negativ sind ?

    Könnte es sein, dass "Tetgen"(Die Triangulierungslibrary) zuviele Tetraeder generiert ? Wie gesagt, Ich bekomme für die Punkte, die alle im Einheitskubus liegen, Werte größer 1 !?

    Aber danke trotzdem für die bisherige Hilfe 🙂



  • negative volumina sind nicht schlimm das kann passieren...und kommt auf die orientierung an...in den fällen nimmst du einfach den betrag des wertes als volumen.

    kannst du mal "debuggen" für welchen tetraeder du ein volumen größer 1 bekommst? die berechnung sieht richtig aus.



  • Ist zwar nicht zu deiner Frage aber mich interessiert das Tetgen Triangulierungs-Tool .Ich habe mir das runtergeladen und kompiliert. Wie benutzt man das jetzt um mal die Delaunay-Triangulierung auszuprobieren?



  • @billg

    Hier findest du eine Beispielanwendung:

    http://tetgen.berlios.de/files/tetcall.cxx

    Zuerst erzeugst du zwei Tegenio-Objekte "in" und "out". Das "in"-Objekt musst du dann mit deiner Datenmenge, in meinem Fall die pointlist[] mit Punkten, füllen.

    Dann rufst du tetrahedralize("", &in, &out) auf...
    Der erste Parameter der Methode ist der Command-Line-Switches-Ausdruck.
    Man braucht da anscheinend nichts anzugeben wenn man nur eine "tetrahedralization" haben will. Bei mir hats so geklappt... 😃

    Das ist nur eine Beschreibung der gröbsten Schritte. Eigentlich ist der von mir erklärte Sachverhalt und alles andere aus der Beispieldatei ersichtlich.

    @analytiker
    Das mit dem Debuggen werde ich aus Zeitmangel jetzt erst mal nicht machen.
    Aber ich hab es mal mit 3 Kubi unterschiedlicher Seitenlänge und der o.g. 2. Variante der Volumenberechnung(spat-Methode) ausprobiert.
    Hier die Ergebnisse:

    Seitenlänge 1 : V = 0,8333 statt 1
    Seitenlänge 2 : V = 6,6667 statt 8
    Seitenlänge 3 : V = 22,5 statt 27

    Wie ihr seht fehlt da immer 1/6 des korrekten Ergebnisses. Seht ihr was ich falsch berechne ?

    Danke....



  • Habe das Problem gelöst...
    Es waren nicht die Art und Weise wie ich das Volumen berechnet habe. Alle Varianten waren richtig.
    Ich hatte die Vektoren einfach nur falsch aus den Tetgen-listen ausgelesen und diese waren dadurch einfach nur verfälscht....
    Also Leute:
    Falls ihr mal Tetgen nutzen solltet, denkt daran, dass die Indizes der Eckpunkte
    der Tetraeder in der tetrahedronlist[] um 1 zu hoch sind... Ihr müsst sie also um 1 dekrementieren um sie aus der pointlist[] auszulesen....

    Dummer Fehler.... Sorry das ich das Mathematik-Forum dafür mehr oder weniger vollgespamt habe...

    Obwohl... Diese Dinge die ich hier über Volumenberechnung und Tetrahedrization gepostet habe, musste ich mir vorher mühsam zusammenkratzen...
    Vielleicht stoßen Leute die ähnliche Sachverhalte behandeln, dann ja auf diesen Thread und ich hätte damit etwas gutes für die Internetcommunity getan !?

    Ich bin stolz auf mich 🤡

    Also, bis zu meinem nächsten Problem..... 😃


Anmelden zum Antworten