portaldacalheta.pt
  • Principal
  • Science Des Données Et Bases De Données
  • Conception Mobile
  • Design De Marque
  • Personnes Et Équipes Produit
Science Des Données Et Bases De Données

Visualisation de données 3D avec des outils Open Source: un didacticiel utilisant VTK



Dans son récent article sur le blog d'ApeeScape, spécialiste des données Charles Cook a écrit sur calcul scientifique avec des outils open source . Son tutoriel fait un point important sur les outils open source et le rôle qu'ils peuvent jouer dans le traitement facile des données et l'acquisition de résultats.

Mais dès que nous avons résolu toutes ces équations différentielles complexes, un autre problème se pose. Comment comprendre et interpréter les énormes quantités de données issues de ces simulations? Comment visualiser des gigaoctets potentiels de données, telles que des données avec des millions de points de grille dans une grande simulation?



Une formation en visualisation de données pour les data scientists intéressés par les outils de visualisation de données 3D.



Pendant mon travail sur des problèmes similaires pour mon La thèse de master , Je suis entré en contact avec le Visualization Toolkit, ou VTK - une puissante bibliothèque graphique spécialisée pour la visualisation de données.



Dans ce didacticiel, je donnerai une introduction rapide à VTK et à son architecture de pipeline, puis je discuterai d'un exemple de visualisation 3D réel utilisant des données provenant d'un fluide simulé dans une pompe à impulseur. Enfin, je vais énumérer les points forts de la bibliothèque, ainsi que les points faibles que j'ai rencontrés.

Visualisation des données et pipeline VTK

La bibliothèque open source VTK contient un pipeline de traitement et de rendu solide avec de nombreux algorithmes de visualisation sophistiqués. Cependant, ses capacités ne s'arrêtent pas là, car au fil du temps, des algorithmes de traitement d'images et de maillages ont également été ajoutés. Dans mon projet actuel avec une société de recherche dentaire, j'utilise VTK pour des tâches de traitement basées sur le maillage dans un Qt application de type CAO. La Études de cas VTK montrer le large éventail d'applications appropriées.



L'architecture de VTK s'articule autour d'un concept de pipeline puissant. Les grandes lignes de ce concept sont présentées ici:

Voici à quoi ressemble le pipeline de visualisation de données VTK.



  • Sources sont au tout début du pipeline et créent «quelque chose à partir de rien». Par exemple, a vtkConeSource crée un cône 3D, et un vtkSTLReader lit *.stl Fichiers de géométrie 3D.
  • Filtres transformez la sortie de sources ou d'autres filtres en quelque chose de nouveau. Par exemple a vtkCutter coupe la sortie de l'objet précédent dans les algorithmes en utilisant une fonction implicite, par exemple, un plan. Tous les algorithmes de traitement fournis avec VTK sont implémentés sous forme de filtres et peuvent être enchaînés librement.
  • Mappeurs transformer les données en primitives graphiques. Par exemple, ils peuvent être utilisés pour spécifier une table de recherche pour colorer les données scientifiques. Ils sont une manière abstraite de spécifier ce qu'il faut afficher.
  • Acteurs représentent un objet (géométrie plus propriétés d'affichage) dans la scène. Des éléments tels que la couleur, l'opacité, l'ombrage ou l'orientation sont spécifiés ici.
  • Renderers et Windows décrivez enfin le rendu à l'écran d'une manière indépendante de la plateforme.

Un pipeline de rendu VTK typique commence avec une ou plusieurs sources, les traite à l'aide de divers filtres en plusieurs objets de sortie, qui sont ensuite rendus séparément à l'aide de mappeurs et d'acteurs. La puissance derrière ce concept est le mécanisme de mise à jour. Si les paramètres des filtres ou des sources sont modifiés, tous les filtres, mappeurs, acteurs et fenêtres de rendu dépendants sont automatiquement mis à jour. Si, en revanche, un objet plus bas dans le pipeline a besoin d'informations pour accomplir ses tâches, il peut facilement les obtenir.

De plus, il n'est pas nécessaire de traiter directement des systèmes de rendu comme OpenGL. VTK encapsule toutes les tâches de bas niveau d'une manière indépendante de la plate-forme et (partiellement) du système; le développeur travaille à un niveau beaucoup plus élevé.



Exemple de code avec un jeu de données de pompe à rotor

Examinons un exemple de visualisation de données utilisant un ensemble de données d'écoulement de fluide dans une pompe à impulseur rotatif du concours de visualisation IEEE 2011. Les données elles-mêmes sont le résultat d'une simulation de dynamique des fluides par ordinateur, un peu comme celle décrite dans l'article de Charles Cook.

Les données de simulation compressées de la pompe en vedette ont une taille supérieure à 30 Go. Il contient plusieurs parties et plusieurs pas de temps, d'où sa grande taille. Dans ce guide, nous allons jouer avec la partie rotor de l'un de ces pas temporels, qui a une taille compressée d'environ 150 Mo.



@media screen et (min-width 321px) et (max-width 480px)

Mon langage de choix pour utiliser VTK est le C ++, mais il existe des mappages pour plusieurs autres langages tels que Tcl / Tk, Java et Python. Si la cible n'est que la visualisation d'un seul ensemble de données, il n'est pas du tout nécessaire d'écrire du code et peut à la place utiliser Paraview , une interface graphique pour la plupart des fonctionnalités de VTK.

L'ensemble de données et pourquoi 64 bits est nécessaire

J'ai extrait l'ensemble de données du rotor de l'ensemble de données de 30 Go fourni ci-dessus, en ouvrant un pas de temps dans Paraview et en extrayant la partie rotor dans un fichier séparé. C'est un fichier de grille non structuré, c'est-à-dire un volume 3D composé de points et de cellules 3D, comme des hexaèdres, des tétraèdres, etc. Chacun des points 3D a des valeurs associées. Parfois, les cellules ont également des valeurs associées, mais pas dans ce cas. Cette formation se concentrera sur la pression et la vitesse aux points et tentera de les visualiser dans leur contexte 3D.



La taille du fichier compressé est d'environ 150 Mo et la taille de la mémoire est d'environ 280 Mo lorsqu'il est chargé avec VTK. Cependant, en le traitant dans VTK, l'ensemble de données est mis en cache plusieurs fois dans le pipeline VTK et nous atteignons rapidement la limite de 2 Go de mémoire pour les programmes 32 bits. Il existe des moyens d'économiser de la mémoire lors de l'utilisation de VTK, mais pour rester simple, nous allons simplement compiler et exécuter l'exemple en 64 bits.

Remerciements : L'ensemble de données est mis à disposition avec l'aimable autorisation de l'Institut de mécanique appliquée, Université Clausthal, Allemagne (Dipl. Wirtsch.-Ing. Andreas Lucius).

La cible

Ce que nous réaliserons en utilisant VTK comme outil est la visualisation montrée dans l'image ci-dessous. En tant que contexte 3D, le contour du jeu de données est affiché à l'aide d'un rendu filaire partiellement transparent. La partie gauche du jeu de données est ensuite utilisée pour afficher la pression en utilisant un simple codage couleur des surfaces. (Nous allons ignorer le rendu de volume plus complexe pour cet exemple). Afin de visualiser le champ de vitesse, la partie droite du jeu de données est remplie avec rationalise , qui sont codés en couleur par l'amplitude de leur vitesse. Ce choix de visualisation n'est techniquement pas idéal, mais je voulais garder le code VTK aussi simple que possible. De plus, il y a une raison pour que cet exemple fasse partie d'un défi de visualisation, c'est-à-dire beaucoup de turbulence dans l'écoulement.

Voici la visualisation de données 3D résultante de notre exemple de tutoriel VTK.

Pas à pas

Je discuterai du code VTK étape par étape, montrant à quoi ressemblerait la sortie de rendu à chaque étape. Le code source complet peut être téléchargé à la fin de la formation.

Commençons par inclure tout ce dont nous avons besoin de VTK et ouvrez la fonction principale.

#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) {

Ensuite, nous configurons le moteur de rendu et la fenêtre de rendu afin d'afficher nos résultats. Nous définissons la couleur d'arrière-plan et la taille de la fenêtre de rendu.

// 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);

Avec ce code, nous pourrions déjà afficher une fenêtre de rendu statique. Au lieu de cela, nous choisissons d'ajouter un vtkRenderWindowInteractor afin de faire pivoter, zoomer et faire un panoramique interactif sur la scène.

// Setup the render window interactor vtkNew interact; vtkNew style; interact->SetRenderWindow(renWin.Get()); interact->SetInteractorStyle(style.Get());

Nous avons maintenant un exemple en cours montrant une fenêtre de rendu grise et vide.

Ensuite, nous chargeons l'ensemble de données à l'aide de l'un des nombreux lecteurs fournis avec VTK.

// Read the file vtkSmartPointer pumpReader = vtkSmartPointer::New(); pumpReader->SetFileName('rotor.vtu');

Petite excursion dans la gestion de la mémoire VTK : VTK utilise un concept pratique de gestion automatique de la mémoire tournant autour du comptage de références. Cependant, différent de la plupart des autres implémentations, le nombre de références est conservé dans les objets VTK eux-mêmes, au lieu de la classe de pointeur intelligent. Cela présente l'avantage que le nombre de références peut être augmenté, même si l'objet VTK est transmis en tant que pointeur brut. Il existe deux méthodes principales pour créer des objets VTK gérés. vtkNew et vtkSmartPointer::New(), la principale différence étant que a vtkSmartPointer est implicitement castable vers le pointeur brut T*, et peut être retourné à partir d'une fonction. Pour les instances de vtkNew nous devrons appeler .Get() pour obtenir un pointeur brut et nous ne pouvons le retourner qu'en l'enveloppant dans un vtkSmartPointer. Dans notre exemple, nous ne revenons jamais des fonctions et tous les objets vivent tout le temps, nous utiliserons donc le raccourci vtkNew, à l'exception ci-dessus uniquement à des fins de démonstration.

À ce stade, rien n'a encore été lu dans le fichier. Nous ou un filtre plus bas dans la chaîne devrions appeler Update() pour que la lecture du fichier se produise réellement. C'est généralement la meilleure approche pour laisser les classes VTK gérer les mises à jour elles-mêmes. Cependant, nous souhaitons parfois accéder directement au résultat d'un filtre, par exemple pour obtenir la plage de pressions dans cet ensemble de données. Ensuite, nous devons appeler Update() manuellement. (Nous ne perdons pas de performances en appelant plusieurs fois Update(), car les résultats sont mis en cache.)

// Get the pressure range pumpReader->Update(); double pressureRange[2]; pumpReader->GetOutput()->GetPointData()->GetArray('Pressure')->GetRange(pressureRange);

Ensuite, nous devons extraire la moitié gauche de l'ensemble de données, en utilisant vtkClipDataSet. Pour y parvenir, nous définissons d'abord un vtkPlane qui définit la scission. Ensuite, nous verrons pour la première fois comment le pipeline VTK est connecté entre eux: successor->SetInputConnection(predecessor->GetOutputPort()). Chaque fois que nous demandons une mise à jour de clipperLeft cette connexion garantira maintenant que tous les filtres précédents sont également à jour.

quand a commencé la réalité augmentée
// 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());

Enfin, nous créons nos premiers acteurs et mappeurs pour afficher le rendu filaire de la moitié gauche. Notez que le mappeur est connecté à son filtre exactement de la même manière que les filtres les uns aux autres. La plupart du temps, le moteur de rendu déclenche lui-même les mises à jour de tous les acteurs, mappeurs et chaînes de filtres sous-jacentes!

La seule ligne qui ne s'explique pas d'elle-même est probablement leftWireMapper->ScalarVisibilityOff(); - il interdit la coloration du fil de fer par des valeurs de pression, qui sont définies comme le tableau actuellement actif.

// 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());

À ce stade, la fenêtre de rendu affiche enfin quelque chose, c'est-à-dire le filaire de la partie gauche.

Ceci est également un exemple résultant d

Le rendu filaire de la pièce droite est créé de la même manière, en changeant la normale plane d'un (nouvellement créé) vtkClipDataSet dans la direction opposée et en changeant légèrement la couleur et l'opacité du mappeur et de l'acteur (nouvellement créés). Notez qu'ici notre pipeline VTK se divise en deux directions (droite et gauche) à partir du même jeu de données d'entrée.

// 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());

La fenêtre de sortie affiche maintenant les deux parties filaires, comme prévu.

La fenêtre de sortie de visualisation des données affiche désormais les deux parties filaires, selon l

Nous sommes maintenant prêts à visualiser quelques données utiles! Pour ajouter la visualisation de la pression à la partie gauche, nous n'avons pas besoin de faire grand-chose. Nous créons un nouveau mappeur et le connectons à clipperLeft aussi, mais cette fois nous colorons par le tableau de pression. C'est aussi ici que nous utilisons enfin le pressureRange nous avons dérivé ci-dessus.

// 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());

La sortie ressemble maintenant à l'image ci-dessous. La pression au milieu est très basse, aspirant le matériau dans la pompe. Ensuite, ce matériau est transporté vers l'extérieur, prenant rapidement de la pression. (Bien sûr, il devrait y avoir une légende de carte de couleurs avec les valeurs réelles, mais je l'ai laissée de côté pour que l'exemple soit plus court.)

Lorsque la couleur est ajoutée à l

Maintenant, la partie la plus délicate commence. Nous voulons dessiner des lignes de vitesse dans la partie droite. Les rationalisations sont générées par intégration dans un champ vectoriel à partir de points source. Le champ vectoriel fait déjà partie du jeu de données sous la forme du tableau vectoriel «Vélocités». Il suffit donc de générer les points source. vtkPointSource génère une sphère de points aléatoires. Nous générerons 1 500 points source, car la plupart d'entre eux ne se trouveront de toute façon pas dans l'ensemble de données et seront ignorés par le traceur de flux.

// 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);

Ensuite, nous créons le streamtracer et définissons ses connexions d'entrée. 'Attendez, plusieurs connexions? », pourriez-vous dire. Oui - c'est le premier filtre VTK avec plusieurs entrées que nous rencontrons. La connexion d'entrée normale est utilisée pour le champ vectoriel et la connexion source est utilisée pour les points de départ. Puisque «Velocities» est le tableau vectoriel «actif» dans clipperRight, nous n'avons pas besoin de le spécifier ici explicitement. Enfin, nous spécifions que l'intégration doit être effectuée dans les deux sens à partir des points d'origine, et définissons la méthode d'intégration sur Runge-Kutta-4.5 .

vtkNew tracer; tracer->SetInputConnection(clipperRight->GetOutputPort()); tracer->SetSourceConnection(pointSource->GetOutputPort()); tracer->SetIntegrationDirectionToBoth(); tracer->SetIntegratorTypeToRungeKutta45();

Notre problème suivant est la coloration des lignes de courant par la magnitude de la vitesse. Puisqu'il n'y a pas de tableau pour les magnitudes des vecteurs, nous allons simplement calculer les magnitudes dans un nouveau tableau scalaire. Comme vous l'avez deviné, il existe également un filtre VTK pour cette tâche: vtkArrayCalculator. Il prend un ensemble de données et le sort inchangé, mais ajoute exactement un tableau qui est calculé à partir d'un ou plusieurs des tableaux existants. Nous configurons ce calculateur de tableau pour prendre la magnitude du vecteur «Velocity» et le sortir comme «MagVelocity». Enfin, nous appelons Update() manuellement à nouveau, afin de dériver la plage du nouveau tableau.

// 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 produit directement des polylignes et vtkArrayCalculator les transmet inchangés. Par conséquent, nous pourrions simplement afficher la sortie de magCalc en utilisant directement un nouveau mappeur et acteur.

Au lieu de cela, dans cette formation, nous choisissons de rendre la sortie un peu plus agréable, en affichant des rubans à la place. vtkRibbonFilter génère des cellules 2D pour afficher des rubans pour toutes les polylignes de son entrée.

php convertir la chaîne en utf 8
// 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());

Ce qui manque encore, et qui est réellement nécessaire pour produire les rendus intermédiaires également, ce sont les cinq dernières lignes pour rendre réellement la scène et initialiser l'interacteur.

// Render and show interactive window renWin->Render(); interact->Initialize(); interact->Start(); return 0; }

Enfin, nous arrivons à la visualisation terminée, que je présenterai à nouveau ici:

L

Le code source complet pour la visualisation ci-dessus peut être trouvé Ici .

Le bon le mauvais et le laid

Je terminerai cet article avec une liste de mes avantages et inconvénients personnels du framework VTK.

  • Pour : Développement actif : VTK est en cours de développement actif avec plusieurs contributeurs, principalement au sein de la communauté de recherche. Cela signifie que certains algorithmes de pointe sont disponibles, que de nombreux formats 3D peuvent être importés et exportés, les bogues sont activement corrigés et les problèmes ont généralement une solution toute faite dans les forums de discussion.

  • Avec : Fiabilité : Le couplage de nombreux algorithmes de différents contributeurs avec la conception de pipeline ouvert de VTK peut cependant conduire à des problèmes avec des combinaisons de filtres inhabituelles. J'ai dû entrer dans le code source de VTK à plusieurs reprises afin de comprendre pourquoi ma chaîne de filtres complexe ne produit pas les résultats souhaités. Je recommanderais fortement de configurer VTK de manière à permettre le débogage.

  • Pour : Architecture logicielle : La conception du pipeline et l'architecture générale de VTK semblent bien pensées et c'est un plaisir de travailler avec. Quelques lignes de code peuvent produire des résultats étonnants. Les structures de données intégrées sont faciles à comprendre et à utiliser.

  • Avec : Micro architecture : Certaines décisions de conception micro-architecturales échappent à ma compréhension. La correction des constantes est presque inexistante, les tableaux sont transmis en tant qu'entrées et sorties sans distinction claire. J'ai allégé cela pour mes propres algorithmes en abandonnant certaines performances et en utilisant mon propre wrapper pour vtkMath qui utilise des types 3D personnalisés comme typedef std::array Pnt3d;.

  • Pour : Micro documentation : La documentation Doxygen de toutes les classes et filtres est complète et utilisable, les exemples et cas de test sur le wiki sont également d'une grande aide pour comprendre comment les filtres sont utilisés.

  • Avec : Documentation des macros : Il existe plusieurs bons didacticiels et introductions à VTK sur le Web. Cependant, pour autant que je sache, il n'y a pas de grande documentation de référence qui explique comment des choses spécifiques sont faites. Si vous voulez faire quelque chose de nouveau, attendez-vous à chercher comment le faire pendant un certain temps. De plus, il est difficile de trouver le filtre spécifique pour une tâche. Une fois que vous l’avez trouvé, la documentation Doxygen suffit généralement. Un bon moyen d'explorer le framework VTK est de télécharger et d'expérimenter Paraview.

  • Pour : Prise en charge de la parallélisation implicite : Si vos sources peuvent être divisées en plusieurs parties qui peuvent être traitées indépendamment, la parallélisation est aussi simple que de créer une chaîne de filtres distincte dans chaque thread qui traite une seule partie. La plupart des problèmes de visualisation importants entrent généralement dans cette catégorie.

    conception de communication visuelle vs conception graphique
  • Avec : Pas de support de parallélisation explicite : Si vous n'avez pas la chance d'avoir des problèmes importants et divisibles, mais que vous souhaitez utiliser plusieurs cœurs, vous êtes seul. Vous devrez déterminer quelles classes sont thread-safe, ou même ré-entrantes par essais et erreurs ou en lisant la source. Une fois, j'ai retracé un problème de parallélisation vers un filtre VTK qui utilisait une variable globale statique afin d'appeler une bibliothèque C.

  • Pour : Buildsystem CMake : Le méta-système de construction multi-plateforme CMake est également développé par Kitware (le créateur de VTK) et utilisé dans de nombreux projets en dehors de Kitware. Il s'intègre très bien avec VTK et rend la configuration d'un système de construction pour plusieurs plates-formes beaucoup moins douloureuse.

  • Pour : Indépendance, licence et longévité de la plateforme : VTK est prêt à l'emploi indépendant de la plateforme et est licencié sous licence de type BSD très permissive . De plus, un soutien professionnel est disponible pour les projets importants qui en ont besoin. Kitware est soutenu par de nombreuses entités de recherche et d'autres sociétés et sera là pendant un certain temps.

Dernier mot

Dans l'ensemble, VTK est le meilleur outil de visualisation de données pour les types de problèmes que j'aime. Si jamais vous rencontrez un projet qui nécessite une visualisation, un traitement de maillage, un traitement d'image ou des tâches similaires, essayez de lancer Paraview avec un exemple d'entrée et évaluez si VTK pourrait être l'outil pour vous.

Toutes les tendances en valent-elles la peine? Les 5 erreurs UX les plus courantes commises par les concepteurs

Conception Ux

Toutes les tendances en valent-elles la peine? Les 5 erreurs UX les plus courantes commises par les concepteurs
Créer un jeu basé sur un canevas HTML5: un didacticiel utilisant AngularJS et CreateJS

Créer un jeu basé sur un canevas HTML5: un didacticiel utilisant AngularJS et CreateJS

Interface Web

Articles Populaires
Explorer la fonctionnalité Get & Transform d'Excel
Explorer la fonctionnalité Get & Transform d'Excel
Comment aborder les wrappers pour les propriétés Swift
Comment aborder les wrappers pour les propriétés Swift
ApeeScape s'associe à Guidant Global pour offrir un accès à la demande au réseau Elite de pigistes
ApeeScape s'associe à Guidant Global pour offrir un accès à la demande au réseau Elite de pigistes
Tutoriel Apache Spark Streaming: Identifier les hashtags Twitter tendances
Tutoriel Apache Spark Streaming: Identifier les hashtags Twitter tendances
Conception accessible vs conception inclusive (avec infographie)
Conception accessible vs conception inclusive (avec infographie)
 
L'intégration continue d'iOS avec le serveur Xcode expliquée
L'intégration continue d'iOS avec le serveur Xcode expliquée
Meilleurs éditeurs de programmation? Une bataille sans fin sans vainqueur clair
Meilleurs éditeurs de programmation? Une bataille sans fin sans vainqueur clair
Comment GWT déverrouille la réalité augmentée dans votre navigateur
Comment GWT déverrouille la réalité augmentée dans votre navigateur
Webpack ou Browserify & Gulp: quel est le meilleur?
Webpack ou Browserify & Gulp: quel est le meilleur?
Business Analyst - Stratégie & Analytics
Business Analyst - Stratégie & Analytics
Articles Populaires
  • comment trouver le numéro de carte de crédit
  • chartes et graphiques de conception graphique
  • comment créer un jeton ethereum
  • lequel d'entre eux est utilisé comme mesure du montant total des flux de trésorerie disponibles d'un projet
  • une application qui prend en charge un programme frontal est parfois appelée lequel des éléments suivants
  • lorsqu'il est effectué correctement, le processus de diligence raisonnable
  • principes de définition des modèles de conception
Catégories
  • Science Des Données Et Bases De Données
  • Conception Mobile
  • Design De Marque
  • Personnes Et Équipes Produit
  • © 2022 | Tous Les Droits Sont Réservés

    portaldacalheta.pt