2017-02-10 7 views
0

Ich habe eine STL Datei, die die Koordinaten (x,y,z) von 3 Punkten (p0, p1, p2) eines Dreiecks enthält. Diese Dreiecke repräsentieren eine 3D Oberfläche f(x,y,z). Die STL Datei kann über 1000 Dreiecke haben, um eine komplexe Geometrie darzustellen.Nachbar Suchalgorithmus

für meine Anwendung muss ich die benachbarten Dreiecke für jeden Dreieck Eintrag aus der STL-Datei kennen. was bedeutet, dass ich für jedes Dreieck 3 Paare von Punkten pair1=(p0,p1), pair2=(p0,p2), pair3= (p1,p2) nehmen und sie mit einem Paar von Punkten in anderen Dreiecken in der Menge vergleichen muss

was ist der beste und effizienteste Algorithmus, um diesen Zweck zu erreichen? Kann ich einen Hashtree verwenden, hashmap?

Antwort

1

Ändern Sie die Netzdarstellung zu Punkttabelle und Dreieck Gesichter Tabelle. STL verlangt, dass alle Dreiecke in ihren Scheitelpunkten verbunden sind, so dass keine Kanten abgeschnitten werden, was bedeutet, dass benachbarte Dreiecke immer eine vollständige Kante teilen.

double pnt[points][3]; 
int tri[triangles][3]; 

Die pnt sollte Liste aller verschiedenen Punkten sein (Index Art es Geschwindigkeit für hohe Punktzahl zu verbessern). Die tri sollte 3 Indizes von Punkten enthalten, die im Dreieck verwendet werden. Sortiere sie (asc oder desc), um die Spielgeschwindigkeit zu verbessern.

Nun, wenn ein Dreieck tri[i] teilt die gleiche Kante wie tri[j] dann sind diese beiden benachbarten Dreiecken.

if ((tri[i][0]==tri[j][0])&&(tri[i][1]==tri[j][1]) 
    ||(tri[i][0]==tri[j][1])&&(tri[i][1]==tri[j][2])) triangles i,j are neighbors 

alle Kombinationen hinzufügen ...

Wenn Sie nur benachbarte Punkte dann alle Dreiecke finden in diesen Dreiecke enthalten, dass die Punkte und alle anderen Punkte sind Nachbarn

STL laden auf eine solche Struktur wie folgt vorgehen:

  1. klar pnt[],tri[] Listen/Tabellen
  2. Prozess jedes Dreieck von STL
  3. für jeden Punkt des Dreiecks

    prüfen es in pnt[] ist, wenn ja seinen Index für neue triangle verwenden. wenn nicht, fügen Sie point zu hinzu und verwenden Sie seinen Index für neue triangle. Wenn alle 3 Punkte erledigt sind, fügen Sie triangle zu tri hinzu.

Verbesserung pnt[] Leistung

für pnt[] von jedem zum Beispiel Koordinaten sortiert Index sortieren hinzufügen x und verbessern die Leistung zu überprüfen, ob point in pnt bereits vorhanden ist.

So, während (xi,yi,zi) in pnt[] Fund Index von Punkt hinzufügen, der die größte x haben die xi>=pnt[i0][0] über binäre Suche ist und scannen Sie dann alle Punkte in pnt bis x Kreuze xi so xi<pnt[i1][0] diese Weise brauchen Sie nicht alle Punkte zu überprüfen .

Wenn dies zu langsam ist (in der Regel, wenn Anzahl der Punkte größer dann 40000 ist) Sie Leistung mehr nach Segmenten Sortier-Index verbessern können

Verbesserung (Index Art in das Segment Seiten endlicher Größe wie 8192 Punkte Dividieren) tri[] Leistung

Sie können auch die tri[] von tri[i][0] sortieren, so können Sie ähnlich wie pnt[] binäre Suche verwenden.

+0

Was denken Sie über meine Lösung? 1- Erstellen Sie eine Dreieck-Struktur, die drei Punkte mit x, y, z-Koordinaten enthält. 2- Erstellen Sie ein Array von Dreiecken und aktualisieren Sie sie durch Lesen von Einträgen aus der STL-Datei. 3. Verwenden Sie eine unordered_multimap und eine Hash-Funktion, um alle Punkte zu einer Tabelle zu hashen. 4- für jedes Dreieck, hash seine Punkte P0, P1 und P2 und finden Sie die ID der anderen Dreiecke, die auf die gleiche Stelle in den Tabellen gehashed sind. 5- Die benachbarten Dreiecke sind diejenigen, die zwei gemeinsame Punkte in der Tabelle haben. – Arash

+1

@Arash das ist fast das gleiche wie mein Ansatz, so sollte es funktionieren. – Spektre

0

Ich würde vorschlagen, mit hashmap gehen, wo Werte sind sets (basierend auf Baum) von Verweisen auf Tringles, Tasten jene Paare von Points sind (kann diese Paare einfach Sides nennen) und eine Hash-Funktion, die in nehmen würde achte darauf, dass der Hash von Side (a, b) gleich dem Hash von (b, a) sein soll.

Irgendeine Art von Algorithmus:

  1. 3 internationale Points und von ihnen 3 Sides und Triangle erstellen.
  2. hinzufügen, dass alle zu hashmap: map[side[i]].insert(tringle)
  3. Wiederholen Sie 1-2, bis Sie

nun alle Daten lesen Sie eine Karte mit gefüllten Daten haben. Über die Komplexität der Füllung: Einführen in hashmap ist konstante Zeit im Durchschnitt (es hängt auch von der Hash-Funktion) und Einsetzen Komplexität in ein set ist logarithmischen so die vollständige Komplexität der filleng Daten O(n*logm) wo n das ist Anzahl der Sides und m ist durchschnittliche Anzahl von Tringles mit der gleichen Side. 1 + 3 Seiten Nachbarn, so logm relativ klein ist (bis n Vergleich) und nicht berücksichtigt werden konnte (nehme an, es ist eine Konstante):

jeder set würde normalerweise rund 4 Triangles enthalten. Diese Vorschläge führen uns zu einer Art Fazit: Best-Case-Komplexität für Füllung ist O(n) (keine Kollisionen, keine Wiederkäuen, usw.) und das Schlimmste ist O(n*logn) (Worst-Case-Einfügen von nSides von 1 durchschnittlichen Fall in der Karte und durch logn Fall Einfügen in einen Satz, der alle Tringles teilt das gleiche Side).

nun alle Neben Nachbarn für einige Triangle bekommen:

  1. alle 3 sets davon für jeden Side Get Triangle (zB set[i] = map[triangle.sides[i]]
  2. Get Kreuzung von diesen 3 sets (triangle ausschließen nur zu bekommen. seine Neben Nachbarn).
  3. Fertig.

Über die Komplexität des Erhaltens von Seiten-Nachbarn: linear-dependent über die Größe der sets und relativ klein im Vergleich zu 'n' im Normalfall.

Hinweis: Um nicht Seite -neighbours zu bekommen, aber Punkt -neighbours einfach sets mit Points statt Sides füllen (vorausgesetzt Nachbarn sind alle 2 Triangles mit gemeinsamen Point nicht Side genannt). Die obigen Annahmen über Zeitkomplexitäten gelten für Konstanten.