Στο πρόσφατο άρθρο του στο blog του ApeeScape, ειδικευμένος επιστήμονας δεδομένων Ο Τσαρλς Κουκ έγραψε για επιστημονικός υπολογισμός με εργαλεία ανοιχτού κώδικα . Το σεμινάριό του κάνει ένα σημαντικό σημείο σχετικά με τα εργαλεία ανοιχτού κώδικα και τον ρόλο που μπορούν να παίξουν στην εύκολη επεξεργασία δεδομένων και στην απόκτηση αποτελεσμάτων.
Αλλά μόλις λύσουμε όλες αυτές τις πολύπλοκες διαφορικές εξισώσεις, προκύπτουν άλλα προβλήματα. Πώς κατανοούμε και ερμηνεύουμε τις τεράστιες ποσότητες δεδομένων που προέρχονται από αυτές τις προσομοιώσεις; Πώς απεικονίζουμε πιθανά gigabyte δεδομένων, όπως δεδομένα με εκατομμύρια σημεία πλέγματος σε μια μεγάλη προσομοίωση;
Κατά τη διάρκεια της εργασίας μου για παρόμοια προβλήματα για το δικό μου Μεταπτυχιακή εργασία , Ήρθα σε επαφή με το Visualization Toolkit ή VTK - μια ισχυρή βιβλιοθήκη γραφικών που ειδικεύεται στην οπτικοποίηση δεδομένων.
Σε αυτό το σεμινάριο θα δώσω μια γρήγορη εισαγωγή στο VTK και στην αρχιτεκτονική του αγωγού και θα συνεχίσω να συζητώ ένα πραγματικό παράδειγμα απεικόνισης 3D χρησιμοποιώντας δεδομένα από ένα προσομοιωμένο ρευστό σε μια αντλία στροφείου. Τέλος, θα αναφέρω τα δυνατά σημεία της βιβλιοθήκης, καθώς και τα αδύνατα σημεία που αντιμετώπισα.
Η βιβλιοθήκη ανοιχτού κώδικα VTK περιέχει ένα σταθερό αγωγό επεξεργασίας και απόδοσης με πολλούς εξελιγμένους αλγόριθμους οπτικοποίησης. Οι δυνατότητες, ωστόσο, δεν σταματούν εκεί, καθώς με την πάροδο του χρόνου έχουν προστεθεί αλγόριθμοι επεξεργασίας εικόνας και πλέγματος. Στο τρέχον πρόγραμμά μου με μια εταιρεία οδοντιατρικής έρευνας, χρησιμοποιώ το VTK για εργασίες επεξεργασίας με βάση το πλέγμα μέσα σε ένα Qt - βασισμένη σε εφαρμογή CAD. ο Μελέτες περιπτώσεων VTK δείξτε το ευρύ φάσμα των κατάλληλων εφαρμογών.
Η αρχιτεκτονική του VTK περιστρέφεται γύρω από μια ισχυρή ιδέα αγωγού. Η βασική περιγραφή αυτής της έννοιας εμφανίζεται εδώ:
vtkConeSource
δημιουργεί έναν 3D κώνο και ένα vtkSTLReader
διαβάζει *.stl
Τρισδιάστατα αρχεία γεωμετρίας.vtkCutter
κόβει την έξοδο του προηγούμενου αντικειμένου στους αλγόριθμους χρησιμοποιώντας μια σιωπηρή συνάρτηση, π.χ. ένα επίπεδο. Όλοι οι αλγόριθμοι επεξεργασίας που συνοδεύουν το VTK εφαρμόζονται ως φίλτρα και μπορούν να συνδεθούν ελεύθερα μαζί.Ένας τυπικός αγωγός απόδοσης VTK ξεκινά με μία ή περισσότερες πηγές, τις επεξεργάζεται χρησιμοποιώντας διάφορα φίλτρα σε διάφορα αντικείμενα εξόδου, τα οποία στη συνέχεια αποδίδονται ξεχωριστά χρησιμοποιώντας χαρτογράφους και παράγοντες. Η δύναμη πίσω από αυτήν την ιδέα είναι ο μηχανισμός ενημέρωσης. Εάν αλλάξουν οι ρυθμίσεις φίλτρων ή πηγών, όλα τα εξαρτώμενα φίλτρα, οι χαρτογράφοι, οι ηθοποιοί και τα παράθυρα απόδοσης ενημερώνονται αυτόματα. Εάν, από την άλλη πλευρά, ένα αντικείμενο πιο κάτω από τον αγωγό χρειάζεται πληροφορίες για να εκτελέσει τις εργασίες του, μπορεί εύκολα να το αποκτήσει.
Επιπλέον, δεν χρειάζεται να ασχοληθείτε άμεσα με συστήματα απόδοσης όπως το OpenGL. Το VTK ενσωματώνει όλη την εργασία χαμηλού επιπέδου σε πλατφόρμα και (μερικώς) καθιστώντας ανεξάρτητο από το σύστημα τρόπο. ο προγραμματιστής λειτουργεί σε πολύ υψηλότερο επίπεδο.
Ας δούμε ένα παράδειγμα οπτικοποίησης δεδομένων χρησιμοποιώντας ένα σύνολο δεδομένων ροής ρευστού σε μια περιστρεφόμενη αντλία στροφείου από τον Διαγωνισμό Οπτικοποίησης IEEE 2011. Τα ίδια τα δεδομένα είναι το αποτέλεσμα μιας υπολογιστικής προσομοίωσης δυναμικής ρευστού, όπως αυτή που περιγράφεται στο άρθρο του Charles Cook.
Τα δεδομένα προσομοίωσης με φερμουάρ της επιλεγμένης αντλίας έχουν μέγεθος πάνω από 30 GB. Περιέχει πολλά μέρη και πολλαπλά βήματα χρόνου, εξ ου και το μεγάλο μέγεθος. Σε αυτόν τον οδηγό, θα παίξουμε με το ρότορα ενός από αυτά τα βήματα, το οποίο έχει συμπιεσμένο μέγεθος περίπου 150 MB.
Πώς θα επηρεάσει η ελληνική χρεοκοπία το ευρώ
Η γλώσσα επιλογής μου για τη χρήση του VTK είναι C ++, αλλά υπάρχουν αντιστοιχίσεις για πολλές άλλες γλώσσες, όπως Tcl / Tk, Java και Python. Εάν ο στόχος είναι απλώς η οπτικοποίηση ενός μεμονωμένου συνόλου δεδομένων, δεν χρειάζεται να γράψετε κώδικα και μπορεί να χρησιμοποιήσετε Paraview , ένα γραφικό front-end για το μεγαλύτερο μέρος της λειτουργικότητας του VTK.
Έχω εξαγάγει το σύνολο δεδομένων του ρότορα από το σύνολο δεδομένων 30 GB που παρέχεται παραπάνω, ανοίγοντας ένα χρονικό βήμα στο Paraview και εξάγοντας το τμήμα του ρότορα σε ένα ξεχωριστό αρχείο. Πρόκειται για ένα μη δομημένο αρχείο πλέγματος, δηλαδή έναν τόμο 3D που αποτελείται από σημεία και κελιά 3D, όπως εξάχδρα, τετράεδρα και ούτω καθεξής. Κάθε ένα από τα σημεία 3D έχει σχετικές τιμές. Μερικές φορές τα κελιά έχουν επίσης σχετικές τιμές, αλλά όχι σε αυτήν την περίπτωση. Αυτή η εκπαίδευση θα επικεντρωθεί στην πίεση και την ταχύτητα στα σημεία και θα προσπαθήσει να τα απεικονίσει στο τρισδιάστατο περιβάλλον τους.
Το μέγεθος του συμπιεσμένου αρχείου είναι περίπου 150 MB και το μέγεθος της μνήμης είναι περίπου 280 MB όταν φορτώνεται με VTK. Ωστόσο, με την επεξεργασία του σε VTK, το σύνολο δεδομένων αποθηκεύεται προσωρινά σε αποθήκευση εντός του αγωγού VTK και φτάνουμε γρήγορα στο όριο μνήμης των 2 GB για προγράμματα 32bit. Υπάρχουν τρόποι εξοικονόμησης μνήμης κατά τη χρήση του VTK, αλλά για να το διατηρήσουμε απλό, θα συντάξουμε και θα εκτελέσουμε το παράδειγμα σε 64bit.
Ευχαριστίες : Το σύνολο δεδομένων διατίθεται με ευγένεια από το Ινστιτούτο Εφαρμοσμένης Μηχανικής, Πανεπιστήμιο Clausthal, Γερμανία (Διπλ. Wirtsch.-Ing. Andreas Lucius).
Αυτό που θα επιτύχουμε χρησιμοποιώντας το VTK ως εργαλείο είναι η οπτικοποίηση που φαίνεται στην παρακάτω εικόνα. Ως τρισδιάστατο πλαίσιο, το περίγραμμα του συνόλου δεδομένων εμφανίζεται χρησιμοποιώντας μια μερικώς διαφανή απόδοση wireframe. Το αριστερό μέρος του συνόλου δεδομένων χρησιμοποιείται στη συνέχεια για την εμφάνιση της πίεσης χρησιμοποιώντας απλή χρωματική κωδικοποίηση των επιφανειών. (Θα παραλείψουμε την πιο περίπλοκη απόδοση έντασης για αυτό το παράδειγμα). Για να απεικονιστεί το πεδίο ταχύτητας, συμπληρώνεται το δεξί μέρος του συνόλου δεδομένων απλουστεύει , τα οποία κωδικοποιούνται με το χρώμα από το μέγεθος της ταχύτητάς τους. Αυτή η επιλογή οπτικοποίησης δεν είναι τεχνικά ιδανική, αλλά ήθελα να διατηρήσω τον κώδικα VTK όσο το δυνατόν πιο απλός. Επιπλέον, υπάρχει ένας λόγος για αυτό το παράδειγμα να είναι μέρος μιας πρόκλησης οπτικοποίησης, δηλαδή, πολλές αναταράξεις στη ροή.
Θα συζητήσω τον κώδικα VTK βήμα προς βήμα, δείχνοντας πώς θα φαίνεται η έξοδος απόδοσης σε κάθε στάδιο. Μπορείτε να κατεβάσετε τον πλήρη πηγαίο κώδικα στο τέλος της εκπαίδευσης.
Ας ξεκινήσουμε συμπεριλαμβάνοντας ό, τι χρειαζόμαστε από το VTK και ανοίξτε την κύρια λειτουργία.
τι είναι το θέμα bootstrap css
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int main(int argc, char** argv) {
Στη συνέχεια, ρυθμίζουμε το πρόγραμμα απόδοσης και το παράθυρο απόδοσης για να εμφανίσουμε τα αποτελέσματά μας. Ορίζουμε το χρώμα του φόντου και το μέγεθος του παραθύρου απόδοσης.
// Setup the renderer vtkNew renderer; renderer->SetBackground(0.9, 0.9, 0.9); // Setup the render window vtkNew renWin; renWin->AddRenderer(renderer.Get()); renWin->SetSize(500, 500);
Με αυτόν τον κωδικό θα μπορούσαμε ήδη να εμφανίσουμε ένα στατικό παράθυρο απόδοσης. Αντ 'αυτού, επιλέγουμε να προσθέσουμε ένα vtkRenderWindowInteractor
για να περιστρέφετε διαδραστικά, να κάνετε ζουμ και να μετακινείτε τη σκηνή.
// Setup the render window interactor vtkNew interact; vtkNew style; interact->SetRenderWindow(renWin.Get()); interact->SetInteractorStyle(style.Get());
Τώρα έχουμε ένα τρέχον παράδειγμα που δείχνει ένα γκρι, κενό παράθυρο απόδοσης.
Στη συνέχεια, φορτώνουμε το σύνολο δεδομένων χρησιμοποιώντας έναν από τους πολλούς αναγνώστες που συνοδεύουν το VTK.
// Read the file vtkSmartPointer pumpReader = vtkSmartPointer::New(); pumpReader->SetFileName('rotor.vtu');
Σύντομη εκδρομή στη διαχείριση μνήμης VTK : Το VTK χρησιμοποιεί μια βολική έννοια αυτόματης διαχείρισης μνήμης που περιστρέφεται γύρω από την καταμέτρηση αναφοράς. Διαφορετικά από τις περισσότερες άλλες εφαρμογές, ωστόσο, ο αριθμός αναφοράς διατηρείται στα ίδια τα αντικείμενα VTK, αντί της κλάσης έξυπνου δείκτη. Αυτό έχει το πλεονέκτημα ότι ο αριθμός αναφοράς μπορεί να αυξηθεί, ακόμη και αν το αντικείμενο VTK περνάει ως ακατέργαστος δείκτης. Υπάρχουν δύο βασικοί τρόποι δημιουργίας διαχειριζόμενων αντικειμένων VTK. vtkNew
και vtkSmartPointer::New()
, με την κύρια διαφορά να είναι ότι vtkSmartPointer
είναι σιωπηρή δυνατότητα μετάδοσης στον ακατέργαστο δείκτη T*
και μπορεί να επιστραφεί από μια συνάρτηση. Για περιπτώσεις vtkNew
θα πρέπει να καλέσουμε .Get()
για να αποκτήσουμε έναν ακατέργαστο δείκτη και μπορούμε να τον επιστρέψουμε μόνο τυλίγοντας τον σε ένα vtkSmartPointer
. Στο παράδειγμά μας, δεν επιστρέφουμε ποτέ από συναρτήσεις και όλα τα αντικείμενα ζουν όλη την ώρα, επομένως θα χρησιμοποιήσουμε το σύντομο vtkNew
, μόνο με την παραπάνω εξαίρεση για σκοπούς επίδειξης.
Σε αυτό το σημείο, δεν έχει διαβαστεί ακόμη τίποτα από το αρχείο. Εμείς ή ένα φίλτρο πιο μακριά θα πρέπει να καλέσουμε Update()
για την πραγματική ανάγνωση του αρχείου. Συνήθως είναι η καλύτερη προσέγγιση για να επιτρέψετε στις τάξεις VTK να χειρίζονται οι ίδιοι τις ενημερώσεις. Ωστόσο, μερικές φορές θέλουμε να έχουμε άμεση πρόσβαση στο αποτέλεσμα ενός φίλτρου, για παράδειγμα για να λάβουμε το εύρος των πιέσεων σε αυτό το σύνολο δεδομένων. Τότε πρέπει να καλέσουμε Update()
χειροκίνητα. (Δεν χάνουμε την απόδοση κάνοντας κλήση Update()
πολλές φορές, καθώς τα αποτελέσματα αποθηκεύονται προσωρινά.)
// Get the pressure range pumpReader->Update(); double pressureRange[2]; pumpReader->GetOutput()->GetPointData()->GetArray('Pressure')->GetRange(pressureRange);
Στη συνέχεια, πρέπει να εξαγάγουμε το αριστερό μισό του συνόλου δεδομένων, χρησιμοποιώντας vtkClipDataSet
. Για να το επιτύχουμε αυτό ορίζουμε πρώτα ένα vtkPlane
που καθορίζει τη διαίρεση. Στη συνέχεια, θα δούμε για πρώτη φορά πώς συνδέεται ο αγωγός VTK: successor->SetInputConnection(predecessor->GetOutputPort())
. Όποτε ζητάμε μια ενημέρωση από clipperLeft
Αυτή η σύνδεση θα διασφαλίσει τώρα ότι όλα τα προηγούμενα φίλτρα είναι επίσης ενημερωμένα.
// Clip the left part from the input vtkNew planeLeft; planeLeft->SetOrigin(0.0, 0.0, 0.0); planeLeft->SetNormal(-1.0, 0.0, 0.0); vtkNew clipperLeft; clipperLeft->SetInputConnection(pumpReader->GetOutputPort()); clipperLeft->SetClipFunction(planeLeft.Get());
Τέλος, δημιουργούμε τους πρώτους ηθοποιούς και χαρτογράφους μας για να εμφανίσουμε την απόδοση του wireframe του αριστερού μισού. Σημειώστε ότι ο χαρτογράφος είναι συνδεδεμένος στο φίλτρο του με τον ίδιο ακριβώς τρόπο όπως τα φίλτρα μεταξύ τους. Τις περισσότερες φορές, ο ίδιος ο δημιουργός ενεργοποιεί τις ενημερώσεις όλων των ηθοποιών, χαρτογράφων και των αλυσίδων φίλτρων!
Η μόνη γραμμή που δεν είναι αυτονόητη είναι πιθανώς leftWireMapper->ScalarVisibilityOff();
- απαγορεύει το χρωματισμό του καλωδίου από τιμές πίεσης, οι οποίες ορίζονται ως η τρέχουσα ενεργή συστοιχία.
// Create the wireframe representation for the left part vtkNew leftWireMapper; leftWireMapper->SetInputConnection(clipperLeft->GetOutputPort()); leftWireMapper->ScalarVisibilityOff(); vtkNew leftWireActor; leftWireActor->SetMapper(leftWireMapper.Get()); leftWireActor->GetProperty()->SetRepresentationToWireframe(); leftWireActor->GetProperty()->SetColor(0.8, 0.8, 0.8); leftWireActor->GetProperty()->SetLineWidth(0.5); leftWireActor->GetProperty()->SetOpacity(0.8); renderer->AddActor(leftWireActor.Get());
Σε αυτό το σημείο, το παράθυρο απόδοσης δείχνει επιτέλους κάτι, δηλαδή, το wireframe για το αριστερό μέρος.
Η απόδοση του wireframe για το σωστό μέρος δημιουργείται με παρόμοιο τρόπο, αλλάζοντας το επίπεδο κανονικό του (πρόσφατα δημιουργημένου) vtkClipDataSet
στην αντίθετη κατεύθυνση και ελαφρώς αλλάζοντας το χρώμα και την αδιαφάνεια του (νεοδημιουργηθέντος) χαρτογράφου και του ηθοποιού. Σημειώστε ότι εδώ ο αγωγός VTK χωρίζεται σε δύο κατευθύνσεις (δεξιά και αριστερά) από το ίδιο σύνολο δεδομένων εισόδου.
// Clip the right part from the input vtkNew planeRight; planeRight->SetOrigin(0.0, 0.0, 0.0); planeRight->SetNormal(1.0, 0.0, 0.0); vtkNew clipperRight; clipperRight->SetInputConnection(pumpReader->GetOutputPort()); clipperRight->SetClipFunction(planeRight.Get()); // Create the wireframe representation for the right part vtkNew rightWireMapper; rightWireMapper->SetInputConnection(clipperRight->GetOutputPort()); rightWireMapper->ScalarVisibilityOff(); vtkNew rightWireActor; rightWireActor->SetMapper(rightWireMapper.Get()); rightWireActor->GetProperty()->SetRepresentationToWireframe(); rightWireActor->GetProperty()->SetColor(0.2, 0.2, 0.2); rightWireActor->GetProperty()->SetLineWidth(0.5); rightWireActor->GetProperty()->SetOpacity(0.1); renderer->AddActor(rightWireActor.Get());
Το παράθυρο εξόδου δείχνει τώρα και τα δύο μέρη του wireframe, όπως αναμενόταν.
Τώρα είμαστε έτοιμοι να απεικονίσουμε κάποια χρήσιμα δεδομένα! Για την προσθήκη της οπτικοποίησης πίεσης στο αριστερό μέρος, δεν χρειάζεται να κάνουμε πολλά. Δημιουργούμε έναν νέο χαρτογράφο και τον συνδέουμε στο clipperLeft
επίσης, αλλά αυτή τη φορά χρωματίζουμε από τον πίνακα πίεσης. Είναι επίσης εδώ, που τελικά χρησιμοποιούμε το pressureRange
έχουμε προκύψει παραπάνω.
ποιος είναι ο ρόλος ενός οικονομικού διευθυντή
// Create the pressure representation for the left part vtkNew pressureColorMapper; pressureColorMapper->SetInputConnection(clipperLeft->GetOutputPort()); pressureColorMapper->SelectColorArray('Pressure'); pressureColorMapper->SetScalarRange(pressureRange); vtkNew pressureColorActor; pressureColorActor->SetMapper(pressureColorMapper.Get()); pressureColorActor->GetProperty()->SetOpacity(0.5); renderer->AddActor(pressureColorActor.Get());
Η έξοδος μοιάζει τώρα με την παρακάτω εικόνα. Η πίεση στη μέση είναι πολύ χαμηλή, απορροφώντας υλικό στην αντλία. Στη συνέχεια, αυτό το υλικό μεταφέρεται προς τα έξω, κερδίζοντας γρήγορα πίεση. (Φυσικά πρέπει να υπάρχει ένας θρύλος έγχρωμου χάρτη με τις πραγματικές τιμές, αλλά το άφησα για να διατηρήσω το παράδειγμα μικρότερο.)
Τώρα ξεκινά το πιο δύσκολο μέρος. Θέλουμε να σχεδιάσουμε βελτιώσεις ταχύτητας στο σωστό μέρος. Οι εξορθολογισμοί δημιουργούνται με ενσωμάτωση σε ένα διανυσματικό πεδίο από τα σημεία πηγής. Το διανυσματικό πεδίο είναι ήδη μέρος του συνόλου δεδομένων με τη μορφή του διανυσματικού πίνακα 'Velocities'. Επομένως, χρειάζεται μόνο να δημιουργήσουμε τα σημεία προέλευσης. vtkPointSource
δημιουργεί μια σφαίρα τυχαίων σημείων. Θα δημιουργήσουμε 1500 σημεία πηγής, επειδή τα περισσότερα από αυτά δεν θα βρίσκονται στο σύνολο δεδομένων ούτως ή άλλως και θα αγνοηθούν από τον ιχνηλάτη ροής.
// Create the source points for the streamlines vtkNew pointSource; pointSource->SetCenter(0.0, 0.0, 0.015); pointSource->SetRadius(0.2); pointSource->SetDistributionToUniform(); pointSource->SetNumberOfPoints(1500);
Στη συνέχεια δημιουργούμε το streamtracer και ορίζουμε τις συνδέσεις εισόδου του. 'Περίμενε, πολλαπλούς συνδέσεις; », θα μπορούσατε να πείτε. Ναι - αυτό είναι το πρώτο φίλτρο VTK με πολλές εισόδους που συναντάμε. Η κανονική σύνδεση εισόδου χρησιμοποιείται για το διανυσματικό πεδίο και η πηγή πηγής χρησιμοποιείται για τα σημεία σποράς. Δεδομένου ότι το 'Velocities' είναι ο 'ενεργός' διανυσματικός πίνακας στο clipperRight
, δεν χρειάζεται να τον προσδιορίσουμε εδώ ρητά. Τέλος, καθορίζουμε ότι η ολοκλήρωση πρέπει να πραγματοποιηθεί και στις δύο κατευθύνσεις από τα σημεία σπόρου και να ορίσουμε τη μέθοδο ολοκλήρωσης σε Runge-Kutta-4.5 .
vtkNew tracer; tracer->SetInputConnection(clipperRight->GetOutputPort()); tracer->SetSourceConnection(pointSource->GetOutputPort()); tracer->SetIntegrationDirectionToBoth(); tracer->SetIntegratorTypeToRungeKutta45();
Το επόμενο πρόβλημά μας είναι ο χρωματισμός των απλουστεύσεων με μέγεθος ταχύτητας. Δεδομένου ότι δεν υπάρχει πίνακας για τα μεγέθη των διανυσμάτων, θα υπολογίσουμε απλώς τα μεγέθη σε μια νέα συστοιχία. Όπως μαντέψατε, υπάρχει και ένα φίλτρο VTK για αυτήν την εργασία: vtkArrayCalculator
. Παίρνει ένα σύνολο δεδομένων και το εξάγει αμετάβλητο, αλλά προσθέτει ακριβώς έναν πίνακα που υπολογίζεται από έναν ή περισσότερους από τους υπάρχοντες. Διαμορφώνουμε αυτήν την αριθμομηχανή πίνακα ώστε να λαμβάνει το μέγεθος του διανύσματος 'Velocity' και να το εξάγει ως 'MagVelocity'. Τέλος, καλούμε Update()
χειροκίνητα και πάλι, για να αντλήσουμε το εύρος του νέου πίνακα.
// Compute the velocity magnitudes and create the ribbons vtkNew magCalc; magCalc->SetInputConnection(tracer->GetOutputPort()); magCalc->AddVectorArrayName('Velocity'); magCalc->SetResultArrayName('MagVelocity'); magCalc->SetFunction('mag(Velocity)'); magCalc->Update(); double magVelocityRange[2]; magCalc->GetOutput()->GetPointData()->GetArray('MagVelocity')->GetRange(magVelocityRange);
vtkStreamTracer
εξάγει απευθείας πολυλίνες και vtkArrayCalculator
τα μεταφέρει σε αμετάβλητα. Επομένως θα μπορούσαμε απλώς να εμφανίσουμε την έξοδο του magCalc
χρησιμοποιώντας απευθείας έναν νέο χαρτογράφο και ηθοποιό.
Αντ 'αυτού, σε αυτήν την προπόνηση επιλέγουμε να κάνουμε την έξοδο λίγο καλύτερη, προβάλλοντας αντ' αυτού κορδέλες. vtkRibbonFilter
δημιουργεί 2D κελιά για να εμφανίζει κορδέλες για όλες τις πολυλίνες της εισόδου του.
// Create and render the ribbons vtkNew ribbonFilter; ribbonFilter->SetInputConnection(magCalc->GetOutputPort()); ribbonFilter->SetWidth(0.0005); vtkNew streamlineMapper; streamlineMapper->SetInputConnection(ribbonFilter->GetOutputPort()); streamlineMapper->SelectColorArray('MagVelocity'); streamlineMapper->SetScalarRange(magVelocityRange); vtkNew streamlineActor; streamlineActor->SetMapper(streamlineMapper.Get()); renderer->AddActor(streamlineActor.Get());
Αυτό που εξακολουθεί να λείπει, και είναι πραγματικά απαραίτητο για την παραγωγή των ενδιάμεσων αποδόσεων επίσης, είναι οι τελευταίες πέντε γραμμές για την πραγματική απόδοση της σκηνής και την προετοιμασία του αλληλεπιδραστή.
// Render and show interactive window renWin->Render(); interact->Initialize(); interact->Start(); return 0; }
Τέλος, φτάνουμε στην τελική απεικόνιση, την οποία θα παρουσιάσω για άλλη μια φορά εδώ:
Μπορείτε να βρείτε τον πλήρη πηγαίο κώδικα για την παραπάνω οπτικοποίηση εδώ .
Θα κλείσω αυτό το άρθρο με μια λίστα με τα προσωπικά μου πλεονεκτήματα και μειονεκτήματα του πλαισίου VTK.
Για : Ενεργή ανάπτυξη : Το VTK βρίσκεται υπό ενεργή ανάπτυξη από διάφορους συντελεστές, κυρίως από την ερευνητική κοινότητα. Αυτό σημαίνει ότι υπάρχουν διαθέσιμοι αλγόριθμοι αιχμής, πολλές μορφές 3D μπορούν να εισαχθούν και να εξαχθούν, τα σφάλματα διορθώνονται ενεργά και τα προβλήματα έχουν συνήθως μια έτοιμη λύση στους πίνακες συζητήσεων.
Με : Αξιοπιστία : Η σύνδεση πολλών αλγορίθμων από διαφορετικούς συντελεστές με τον ανοιχτό σχεδιασμό αγωγών του VTK ωστόσο, μπορεί να οδηγήσει σε προβλήματα με ασυνήθιστους συνδυασμούς φίλτρων. Έπρεπε να πάω στον πηγαίο κώδικα VTK μερικές φορές για να καταλάβω γιατί η περίπλοκη αλυσίδα φίλτρων μου δεν παράγει τα επιθυμητά αποτελέσματα. Θα συνιστούσα ανεπιφύλακτα τη ρύθμιση του VTK με τρόπο που να επιτρέπει τον εντοπισμό σφαλμάτων.
Για : Αρχιτεκτονική λογισμικού : Ο σχεδιασμός του αγωγού και η γενική αρχιτεκτονική του VTK φαίνεται καλά μελετημένος και είναι ευχάριστο να συνεργαστείτε. Μερικές γραμμές κώδικα μπορούν να παράγουν εκπληκτικά αποτελέσματα. Οι ενσωματωμένες δομές δεδομένων είναι εύκολο να κατανοηθούν και να χρησιμοποιηθούν.
Με : Μικρο αρχιτεκτονική : Ορισμένες μικρο-αρχιτεκτονικές αποφάσεις σχεδιασμού ξεφεύγουν από την κατανόησή μου. Το Const-correctness είναι σχεδόν ανύπαρκτο, οι πίνακες μεταφέρονται ως είσοδοι και έξοδοι χωρίς σαφή διάκριση. Το έκανα αυτό για τους δικούς μου αλγόριθμους, παραιτώντας κάποια απόδοση και χρησιμοποιώντας το δικό μου περιτύλιγμα για vtkMath
που χρησιμοποιεί προσαρμοσμένους τύπους 3D όπως typedef std::array Pnt3d;
.
Για : Μικρή τεκμηρίωση : Η τεκμηρίωση Doxygen όλων των τάξεων και των φίλτρων είναι εκτεταμένη και χρησιμοποιήσιμη, τα παραδείγματα και οι δοκιμαστικές περιπτώσεις στο wiki είναι επίσης μια μεγάλη βοήθεια για να κατανοήσουμε πώς χρησιμοποιούνται τα φίλτρα.
Με : Μακροεντολή τεκμηρίωση : Υπάρχουν πολλά καλά μαθήματα και εισαγωγές στο VTK στον Ιστό. Ωστόσο, όσο γνωρίζω, δεν υπάρχει μεγάλη τεκμηρίωση αναφοράς που να εξηγεί πώς γίνονται συγκεκριμένα πράγματα. Εάν θέλετε να κάνετε κάτι νέο, περιμένετε να αναζητήσετε πώς να το κάνετε για κάποιο χρονικό διάστημα. Επιπλέον, είναι δύσκολο να βρείτε το συγκεκριμένο φίλτρο για μια εργασία. Μόλις το βρείτε, η τεκμηρίωση Doxygen συνήθως αρκεί. Ένας καλός τρόπος για να εξερευνήσετε το πλαίσιο VTK είναι να κατεβάσετε και να πειραματιστείτε με το Paraview.
Για : Υπονοούμενη υποστήριξη παραλληλισμού : Εάν οι πηγές σας μπορούν να χωριστούν σε διάφορα μέρη που μπορούν να υποβληθούν σε επεξεργασία ανεξάρτητα, η παραλληλοποίηση είναι τόσο απλή όσο η δημιουργία μιας ξεχωριστής αλυσίδας φίλτρου σε κάθε νήμα που επεξεργάζεται ένα μόνο μέρος. Τα περισσότερα μεγάλα προβλήματα οπτικοποίησης συνήθως εμπίπτουν σε αυτήν την κατηγορία.
διαφορά σε s corp και c corp
Με : Χωρίς ρητή υποστήριξη παραλληλισμού : Εάν δεν είστε ευλογημένοι με μεγάλα, διαιρετά προβλήματα, αλλά θέλετε να χρησιμοποιήσετε πολλούς πυρήνες, είστε μόνοι σας. Θα πρέπει να καταλάβετε ποια μαθήματα είναι ασφαλή για νήματα ή ακόμα και να εισαχθούν εκ νέου με δοκιμή και σφάλμα ή διαβάζοντας την πηγή. Κάποτε βρήκα ένα πρόβλημα παραλληλισμού σε ένα φίλτρο VTK που χρησιμοποίησε μια στατική καθολική μεταβλητή για να καλέσω κάποια βιβλιοθήκη Γ.
Για : Buildsystem CMake : Το μετα-build-multi-platform σύστημα CMake αναπτύσσεται επίσης από το Kitware (οι κατασκευαστές του VTK) και χρησιμοποιείται σε πολλά έργα εκτός του Kitware. Ενσωματώνεται πολύ ωραία με το VTK και κάνει τη δημιουργία ενός συστήματος κατασκευής για πολλές πλατφόρμες πολύ λιγότερο επώδυνη.
Για : Ανεξαρτησία, άδεια και μακροζωία πλατφόρμας : Το VTK είναι ανεξάρτητο από την πλατφόρμα και δεν διαθέτει άδεια χρήσης υπό πολύ ανεκτική άδεια τύπου BSD . Επιπλέον, διατίθεται επαγγελματική υποστήριξη για εκείνα τα σημαντικά έργα που το απαιτούν. Το Kitware υποστηρίζεται από πολλές ερευνητικές οντότητες και άλλες εταιρείες και θα είναι εδώ και αρκετό καιρό.
Συνολικά, το VTK είναι το καλύτερο εργαλείο οπτικοποίησης δεδομένων για τα είδη προβλημάτων που μου αρέσουν. Εάν συναντήσετε ποτέ ένα έργο που απαιτεί οπτικοποίηση, επεξεργασία πλέγματος, επεξεργασία εικόνας ή παρόμοιες εργασίες, δοκιμάστε να ενεργοποιήσετε το Paraview με ένα παράδειγμα εισαγωγής και να αξιολογήσετε εάν το VTK θα μπορούσε να είναι το εργαλείο για εσάς.