// Inclusion du fichier d'entête #include "tufr_steptutorial03.h" // Inclure ensuite les éventuelles classes de définitions nécessaires à votre étape #include "ct_itemdrawable/ct_scene.h" #include "ct_itemdrawable/ct_pointcluster.h" // Pour les vecteurs en 3D #include // Pour afficher des messages à la console #include // Pour inclure certaines fonctions mathématiques #include // Constructeur : appel du constructeur de la classe mère // et initialisation des paramètres (valeurs par défaut) TUFR_StepTutorial03::TUFR_StepTutorial03() : SuperClass() { _nx = 3; _ny = 3; _nz = 3; } // Destructeur TUFR_StepTutorial03::~TUFR_StepTutorial03() { } // Description de l'étape (tooltip du menu contextuel) QString TUFR_StepTutorial03::description() const { return QString(tr("Découpe une scène de points")); } // Description détaillée de l'étape (dans le menu de description) QString TUFR_StepTutorial03::detailledDescription() const { return QString(tr("Découpe une scène de points en groupes paralellepipediques")); } // Méthode de recopie de l'étape CT_VirtualAbstractStep* TUFR_StepTutorial03::createNewInstance() const { // cree une copie de cette étape return new TUFR_StepTutorial03(); } // Création et affiliation des modèles IN void TUFR_StepTutorial03::declareInputModels(CT_StepInModelStructureManager& manager) { // On se base sur les résultats entrants manager.addResult(_inResult, tr("Scène(s)")); // Déclaration et création du modèle de groupe de référence manager.setZeroOrMoreRootGroup(_inResult, _inZeroOrMoreRootGroup); // Déclaration et création du modèle de groupe manager.addGroup(_inZeroOrMoreRootGroup, _inGroup); // On ajoute le modèle d'item au modèle du groupe racine (le type d'item sera automatiquement déduit) manager.addItem(_inGroup, _inScene, tr("Scène source")); } // Création et affiliation des modèles OUT void TUFR_StepTutorial03::declareOutputModels(CT_StepOutModelStructureManager& manager) { // On se base sur les résultats entrants (copie) manager.addResultCopy(_inResult); // Déclaration et création du modèle de groupe manager.addGroup(_inGroup, _outGroup); // On ajoute le modèle d'item au modèle du groupe racine (le type d'item sera automatiquement déduit) manager.addItem(_outGroup, _outScene, tr("Scène extraite")); } // Création semi-automatique de la boite de dialogue de paramétrage de l'étape void TUFR_StepTutorial03::fillPostInputConfigurationDialog(CT_StepConfigurableDialog* postInputConfigDialog) { // Ajout de contrôles unitaires de paramètrages à la boite (un par paramètre en général) postInputConfigDialog->addInt("Nombre clusters selon x", "", 1, 100, _nx); postInputConfigDialog->addInt("Nombre clusters selon y", "", 1, 100, _ny); postInputConfigDialog->addInt("Nombre clusters selon z", "", 1, 100, _nz); } // Etape de calcul, créant les données des résultats de sortie void TUFR_StepTutorial03::compute() { // Ici on peut faire quelques initialisations et/ou calculs préliminaires // Récupération de la liste des groupes d'entrée et leurs items // L'ordre dans cette liste est celui des ajouts successifs for (CT_StandardItemGroup* group : _inGroup.iterateOutputs(_inResult)) { for (const CT_AbstractItemDrawableWithPointCloud* inScene : group->singularItems(_inScene)) { if (isStopped()) return; // Ici on peut faire d'autre calculs préliminaires pour l'item en cours // Récupération des limites min et max en (x,y,z) de la scène d'entrée Eigen::Vector3d min, max; inScene->boundingBox(min, max); // Calcul de la taille des clusters float xClusterSize = (max.x() - min.x())/_nx; float yClusterSize = (max.y() - min.y())/_ny; float zClusterSize = (max.z() - min.z())/_nz; // On Cree un nouveau tableau qui stockera les nuages QVector extractedCloud; extractedCloud.resize(_nx*_ny*_nz); const CT_AbstractPointCloudIndex *pointCloudIndex = inScene->pointCloudIndex(); CT_PointIterator itP(pointCloudIndex); size_t nbPoints = pointCloudIndex->size(); size_t i = 0; while (itP.hasNext()) { if (isStopped()) return; const CT_Point &point = itP.next().currentPoint(); size_t point_index = itP.currentGlobalIndex(); // Calcul des indices x, y et z du cluster où affecter le point int blockX = (int) floor((point.x() - min.x()) / xClusterSize); int blockY = (int) floor((point.y() - min.y()) / yClusterSize); int blockZ = (int) floor((point.z() - min.z()) / zClusterSize); // Indice dans le tableau de clusters int block = blockX + blockY*_nx + blockZ*_nx*_ny; // Si le cluster n'existe pas on le créée if (extractedCloud[block]==NULL) extractedCloud[block] = new CT_PointCluster(); // Ajout du point au cluster (son index en fait) extractedCloud[block]->addPoint(point_index, false); // On fait avancer le % de progression (ici par rapport au nombre de points traités sur le total) setProgress(float(100.0 * i++ / nbPoints)); } // On parcourt les clusters créés for (int k = 0 ; k < extractedCloud.size() ; k++) { // Création du cluster, qui est un morceau de la scène CT_PointCluster* cluster = extractedCloud[k]; if (cluster!=NULL) { // On ajuste les limites cluster->updateBoundingBox(); // Création du groupe contenant le(s) item(s) CT_StandardItemGroup* outGroup = new CT_StandardItemGroup(); // Ajout du groupe au résultat (AVANT d'ajouter l'item !) group->addGroup(_outGroup, outGroup); // Ajout de l'item au groupe outGroup->addSingularItem(_outScene, cluster); } } } } }