Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Sa Jul 19, 2025 06:15

Foren-Übersicht » Programmierung » Einsteiger-Fragen
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 10 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Di Jan 19, 2010 12:46 
Offline
DGL Member

Registriert: Do Mär 05, 2009 20:17
Beiträge: 284
Wohnort: Kaiserslautern
Hallo,

Nachdem ich die Volumenberechnung hinbekommen habe und auch die Oberfläche eines beliebigen Mesh aus Dreiecksflächen hinbekommen habe, fehlt mir eigentlich noch der Schritt davor, denn zuerst müsste ich meine Meshs auf Geschlossenheit prüfen.

Ich habe jetzt nach viel googeln und lesen gelernt das ein Mesh aus Dreiecken dann als geschlossen gilt, wenn alle Kanten genau zu zwei Flächen existieren.
Existiert eine Kante nur zu einer Fläche, dann ist das eine "offene" Kante.

Soweit die Theorie...

Jetzt die Frage:

Hat zufällig jemand mal irgendwo einen Algorythmus oder Codefetzen gesehen wie man ein Mesh am besten danach durchsucht? Ich hab (mal wieder) mehrere Stunden gegoogelt und gelesen aber nix finden können...
Bei mir liegen die Vertices des Mesh in einem Array of TVertex vor.

Gruß und Danke schonmal.

Wölfchen


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Jan 19, 2010 12:59 
Offline
DGL Member
Benutzeravatar

Registriert: Di Sep 20, 2005 13:18
Beiträge: 1054
Wohnort: Dresden
Programmiersprache: C, C++, Pascal, OPL
Also ein Algo mit einer schlechten durchschnittlichen Dauer (weil Aufwand=n²) wäre doch einfach
Code:
  1. var kanten:integer;
  2.     geschlossen : boolean;
  3. ...
  4. geschlossen:=true;
  5. for i:=1 to Anzahl_der_Meshes do
  6. begin
  7.   kanten:=1;
  8.   for k:=i+1 to Anzahl_der_Meshes do
  9.     if eine_Kante_gleich(i,k) then
  10.       inc(kanten);
  11.   if kanten<>2 then
  12.   begin
  13.     geschlossen:=False;
  14.     break;
  15.   end;
  16. end;


Wobei die Beschreibung von dir und mein Code aber MEHRERE geschlossene Meshes zulässt. ;-)

LG Ziz

PS: Der neue Highlighterstil ist total depri - scheiß Demokratie -_-

_________________
Denn wer nur schweigt, weil er Konflikte scheut, der macht Sachen, die er hinterher bereut.
Und das ist verkehrt, denn es ist nicht so schwer, jeden Tag zu tun als ob's der letzte wär’.
Und du schaust mich an und fragst ob ich das kann.
Und ich denk, ich werd' mich ändern irgendwann.

_________________Farin Urlaub - Bewegungslos


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Jan 19, 2010 13:07 
Offline
DGL Member

Registriert: Do Mär 05, 2009 20:17
Beiträge: 284
Wohnort: Kaiserslautern
Ziz hat geschrieben:
Also ein Algo mit einer schlechten durchschnittlichen Dauer (weil Aufwand=n²) wäre doch einfach
Code:
  1. var kanten:integer;
  2.     geschlossen : boolean;
  3. ...
  4. geschlossen:=true;
  5. for i:=1 to Anzahl_der_Meshes do
  6. begin
  7.   kanten:=1;
  8.   for k:=i+1 to Anzahl_der_Meshes do
  9.     if eine_Kante_gleich(i,k) then
  10.       inc(kanten);
  11.   if kanten<>2 then
  12.   begin
  13.     geschlossen:=False;
  14.     break;
  15.   end;
  16. end;


Wobei die Beschreibung von dir und mein Code aber MEHRERE geschlossene Meshes zulässt. ;-)

LG Ziz

PS: Der neue Highlighterstil ist total depri - scheiß Demokratie -_-



hmm ja danke erstmal :)

aber ich hab hier teilweise meshs mit paarhunderttausend triangles... wär schon schön wenns da was schnelleres geben würde...

dann nochwas...
*hust*
also ne Kante AB mit A= (Ax,Ay,Az) und B = (Bx,By,Bz) ist doch (dachte ich) Ax-Bx, Ay-By, Az-Bz...
das würde aber für nen doofen würfel mit Kantenlänge 1 ja ergeben das da ziemlich viele Kanten gleich wären...
:?:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Jan 19, 2010 16:10 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Wie ist denn dein Modell gebaut. Können 2 Vertices an der selben stelle existieren, oder gibts an einer Stelle immer nur ein Vertex.
Letzteres wäre einfacher zu händeln.
Dann könntest du mit Idices/Pointer arbeiten und eine Datenstruktur aufbauen wo du leicht nachschauen kannst, welche Kanten existieren und aus welchen Vertices sie bestehen, und in welchen Tris die wiederum benutzt werden.

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Jan 19, 2010 20:09 
Offline
DGL Member

Registriert: Do Mär 05, 2009 20:17
Beiträge: 284
Wohnort: Kaiserslautern
Flash hat geschrieben:
Wie ist denn dein Modell gebaut. Können 2 Vertices an der selben stelle existieren, oder gibts an einer Stelle immer nur ein Vertex.
Letzteres wäre einfacher zu händeln.
Dann könntest du mit Idices/Pointer arbeiten und eine Datenstruktur aufbauen wo du leicht nachschauen kannst, welche Kanten existieren und aus welchen Vertices sie bestehen, und in welchen Tris die wiederum benutzt werden.


Die Modelle sind in CAD erstellt und somit ist mit allem zu rechnen... Modelle mit nur einer Haut (offene shells) genauso wie doppelte flächen und was man sonst noch anstellen kann wenn man den 3D malpinsel schwingt.

Allerdings liegen auch "saubere" daten - also darunter verstehe ich hier geschlossene volumen - so vor, das jeder vertice mehrfach vorkommt meine versuche das nachträglich zu reduzieren scheiterten an der normalendarstellung.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Jan 19, 2010 20:59 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Wieso kannst du das nicht reduzieren? Ich meine, wenn du einfach das Modell beim laden in einen Quadtree lädst, und dann Vertices vergleichst die in einem Knoten liegen (und den direkten Nachbarn) dann kannst du alle Vertices die näher als X sind zusammenlegen.

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Jan 20, 2010 00:48 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Also Geschlossenheit ist nicht so leicht zu prüfen wenn du 2 Mannigfaltigkeit nicht voraussetzen kannst. Denn es gilt zwar für ein 2-mannigfaltiges und geschlossenes Mesh, dass jede Kante zu genau zwei Faces adjazent ist, aber diese Aussage gilt nicht umgekehrt.

Siehe auch:
http://wiki.delphigl.com/index.php/Mesh#Eigenschaften

Du solltest dir wirklich überlegen ob du das wirklich testen musst oder ob du dem Nutzer deiner Methode/Funktion lieber im Kommentar mitteilst, dass dies nur für geschlossene 2-mannigfaltige Meshes funktioniert.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Jan 20, 2010 13:26 
Offline
DGL Member

Registriert: Do Mär 05, 2009 20:17
Beiträge: 284
Wohnort: Kaiserslautern
Coolcat hat geschrieben:
Also Geschlossenheit ist nicht so leicht zu prüfen wenn du 2 Mannigfaltigkeit nicht voraussetzen kannst. Denn es gilt zwar für ein 2-mannigfaltiges und geschlossenes Mesh, dass jede Kante zu genau zwei Faces adjazent ist, aber diese Aussage gilt nicht umgekehrt.

Siehe auch:
http://wiki.delphigl.com/index.php/Mesh#Eigenschaften

Du solltest dir wirklich überlegen ob du das wirklich testen musst oder ob du dem Nutzer deiner Methode/Funktion lieber im Kommentar mitteilst, dass dies nur für geschlossene 2-mannigfaltige Meshes funktioniert.


hmm das ist mir jetzt irgendwie zu theoretisch.

nehmen wir doch mal dieses beispiel:
Code:
  1.  
  2. {erste fläche}  
  3.       varray[1]  0  0  1
  4.       varray[2]  1  0  1
  5.       varray[3]  0  1  1
  6. {zweite fläche}
  7.       varray[4]  0  1  1
  8.       varray[5]  1  0  1
  9.       varray[6]  1  1  1    
  10. {dritte fläche}
  11.       varray[7]  1  1  1
  12.       varray[8]  0  1  0
  13.       varray[9]  0  1  1
  14.  


So, das sind nun 3 Dreiecksflächen, die aneinander grenzen.. von den insgesamt 9 Kanten sind 5 offen und 2 sind jeweils identisch.
Und nichts anderes will ich gerne mit einer effizienten Schleife prüfen, ob alle Kanten geschlossen sind und wenn nicht, welche offen sind (nur an eine Fläche grenzen).


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Jan 20, 2010 16:56 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Offtopic@Wölfchen: Bitte nicht immer komplette Posts zitieren. Es macht höchstens Sinn einzelne Passagen zu zitieren wenn du direkt darauf Bezug nimmst. Danke.

Zitat:
So, das sind nun 3 Dreiecksflächen, die aneinander grenzen.. von den insgesamt 9 Kanten sind 5 offen und 2 sind jeweils identisch. Und nichts anderes will ich gerne mit einer effizienten Schleife prüfen, ob alle Kanten geschlossen sind und wenn nicht, welche offen sind (nur an eine Fläche grenzen).

Ich weiß zwar nicht wozu das gut sein soll, aber gut...also:
Schritt 1: Vertices mergen
Du schreibst etwas von ein "paarhunderttausend triangles", du wirst also auch entsprechend viele Vertices haben. Sind das eher eine Million als Hundertausend Vertices? Wenn das dann noch wirklich effizient sein soll, du also weniger als quadratische Laufzeit (O(n^2)) für diesen Schritt haben möchtest brauchst du eine räumliche Datenstruktur. Damit ließe sich eine Laufzeit von O(n * log n) erreichen. Als Datenstruktur eignet sich beispielsweise ein Octree, ein Gridfile oder auch ein R-Baum. Der Octree ist vergleichsweise leicht und müsste auch im Wiki beschrieben sein. Die beiden anderen Methoden sind komplizierter zu implementieren.

Dies ist aber das Einsteiger-Forum daher empfehle ich dir die Variante ohne Datenstruktur.
Ich schreibe das mal als Pseudocode in C-Syntax, wenn was unklar ist einfach Fragen.

Code:
  1. // die Anzahl Vertices die du als Eingabe hast, sowie die Vertices
  2. int N;
  3. Vector3 inputVertices[N];
  4.  
  5. // Anzahl der Dreiecke und die Dreiecke selbst
  6. int T;
  7. int inputIndices[3*T];
  8.  
  9. // gibt an ab welcher Entfernung zwei Vertices identisch sind.
  10. // Gleitpunktzahlen sind immer ungenau, daher würde hier "0" nicht immer funktionieren!
  11. float epsilon = 0.0001f;
  12.  
  13. // ein uninitialisiertes Array aus Integern. Steht an Stelle i der Wert j bedeutet dies,
  14. // dass inputVertices[i] und inputVertices[j] identisch sind.
  15. // Dabei ist j der kleinst mögliche Wert für den dies gilt. Dies stellt sicher, dass es
  16. // keine Verkettungen gibt sondern immer direkt der korrekte Repräsentant angegeben ist.
  17. int index[N];
  18.  
  19. // die reale Anzahl der Vertices, also nach dem zusammenfassen.
  20. int M = N;
  21.  
  22. // Index-Array aufbauen
  23. float squaredEpsilon = epsilon * epsilon;
  24. for (int i=0; i<N; i=i+1) {
  25.     index[i] = i;
  26.     Vector3 current = inputVertices[i];
  27.  
  28.     // Suche nach einem identischen Vertex
  29.     // (dies würde durch eine Datenstruktur extrem beschleunigt,
  30.     //  hier gehen wir aber einfach alle Vertices durch)
  31.     for (int j=0; j<i; j=j+1) {
  32.         Vector3 vertex = inputVertices[index[j]];
  33.         // um die Wurzel zu sparen quadrieren wir einfach die andere Seite der Ungleichung.
  34.         if (squaredDistance(current, vertex) < squaredEpsilon) {
  35.             index[i] = j;
  36.             M = M - 1;
  37.             break; // innere Schleife abbrechen
  38.         }
  39.     }
  40. }
  41.  
  42. // Vertices zusammen kopieren
  43. Vector3 outputVertices[M];
  44. int j=0;
  45. for (int i=0; i<N; i=i+1) {
  46.     if (index[i] == i) { // wenn != i dann ist dieser Vertex schon kopiert worden
  47.         outputVertices[j] = inputVertices[i];
  48.         j = j + 1;
  49.     }
  50. }
  51.  
  52. //alle Dreiecke durchgehen und Indices korrigieren
  53. for (int i=0; i<3*T; i=i+1) {
  54.     inputIndices[i] = index[inputIndices[i]];
  55. }
  56.  
  57. // ====================== 
  58.  
  59. // diese Funktion berechnet einfach nur den Abstand zwischen zwei Punkten. Das ist einfach
  60. // nur der dreidimensionale Pythagoras, wobei ich die Wurzel weggelassen habe, daher "squared".
  61. float squaredDistance(Vector3 a, Vector3 b) {
  62.     Vector3 d = Vector3(a.x-b.x, a.y-b.y, a.z-b.z);
  63.     return d.x*d.x + d.y*d.y + d.z*d.z;
  64. }


Schritt 2: identische Kanten zählen
Dies ist der aufwendigere Schritt, da es deutlich mehr Kanten als Vertices gibt (*). Habe gerade schon 30min am obigen Code gebastelt, ich bin da gerade zu faul zu. Hier darf sich jemand anderes austoben ;)
Auf keinen Fall sollte ein Array über alle möglichen Kanten angelegt werden, den das sind quadratisch viele. Die Idee wäre eine HashMap (TreeMap ginge genauso) zu benutzen um Kanten auf ein Bool zu mappen. Dabei steht "false" für offene Kante und "true" für geschlossen. Also man geht alle Kanten durch und fügt sie in die HashMap ein. Wenn die Kante schon drin ist und der Bool "false" ist wird auf "true" gesetzt. Ist der Wert schon "true" ist was faul, also eine Kante mit drei Dreiecken.
Am Ende gehst du nochmal die HashMap durch und guckst ob es noch Werte mit "false", also offene Kanten gibt.

(*) ungefähr dreimal so viele bei einem geschlossenen 2-mannigfaltigen Mesh mit vernachlässigbarem Genus, siehe Mesh.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Jan 21, 2010 02:04 
Offline
DGL Member

Registriert: Do Mär 05, 2009 20:17
Beiträge: 284
Wohnort: Kaiserslautern
huhu,

danke für die Zeit die du dir da genommen hast - ich habe mir jetzt eine krücke gebastelt die fürs erste ausreicht. Ich baller alle kanten in eine sortierte stringlist, laufe dann noch einmal durch diese durch und zähle ob es kanten gibt die weniger oder öfter als 2 mal vorkommen.

Das ist bei > 500 000 flächen dann zwar schon sehr zäh (zwischen 25 und 45 sekunden) aber 95% meiner teile haben max 100 000 flächen und da gehts noch mit 0-3 sekunden, erträglich zu. Zumal der pc hier an dem ich das gestoppt habe eh nicht der schnellste ist.

den punkt schau ich mir aber sicherlich bei gelegenheit (wenn ich auch noch bissi mehr C kenne und so) nochmal an.

*EDIT - 31.01.2010*

Ich habe das Verfahren zwar grundsätzlich beibehalten aber ich gehe nun nicht mehr den Umweg über eine Stringlist sondern habe alles in einem array, das ich sortiere und danach zähle wie oft was eine Kante vorkommt. Das hat die Rechenzeit selbst bei den größten Testmodellen in Bereiche unter 2 Sekunden gebracht (von ehemals 45 Sekunden) was absolut in Ordnung ist für meine Zwecke.


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 10 Beiträge ] 
Foren-Übersicht » Programmierung » Einsteiger-Fragen


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.009s | 15 Queries | GZIP : On ]