#include "tk_stepextractpointsinverticalcylinders.h" #include "ct_view/ct_asciifilechoicebutton.h" #include "ct_view/ct_combobox.h" #include "ct_log/ct_logmanager.h" #include #include #include TK_StepExtractPointsInVerticalCylinders::TK_StepExtractPointsInVerticalCylinders() : SuperClass() { _neededFields.append(CT_TextFileConfigurationFields("ID_Plot", QRegExp("([iI][dD]|[nN][uU][mM]|[pP][lL][oO][tT]|[pP][lL][aA][cC][eE][tT][tT][eE])"), true)); _neededFields.append(CT_TextFileConfigurationFields("ID_Tree", QRegExp("([tT][rR][eE][eE]|[aA][rR][bB][rR][eE])"), false)); _neededFields.append(CT_TextFileConfigurationFields("X", QRegExp("[xX]"), false)); _neededFields.append(CT_TextFileConfigurationFields("Y", QRegExp("[yY]"), false)); _neededFields.append(CT_TextFileConfigurationFields("Z", QRegExp("[yZ]"), false)); _neededFields.append(CT_TextFileConfigurationFields("Zmin", QRegExp("([Zz][Mm][Ii][Nn]|[Hh][Mm][Ii][Nn])"), false)); _neededFields.append(CT_TextFileConfigurationFields("Zmax", QRegExp("([Zz][Mm][Aa][Xx]|[Hh][Mm][Aa][Xx])"), false)); _neededFields.append(CT_TextFileConfigurationFields(tr("Rayon"), QRegExp("([Rr][Aa][Dd][Ii][Uu][Ss]|[Rr][Aa][Yy][Oo][Nn]|[Rr])"), false)); _refFileName = ""; _refHeader = true; _refSeparator = "\t"; _refDecimal = "."; _refLocale = QLocale(QLocale::English, QLocale::UnitedKingdom).name(); _refSkip = 0; _translate = false; } QString TK_StepExtractPointsInVerticalCylinders::description() const { return tr("Extraire points dans des cylindres verticaux (par placette)"); } QString TK_StepExtractPointsInVerticalCylinders::detailledDescription() const { return tr("Cette étape permet d'extraire des sous-parties cylindriques de scènes de points.
" "Un fichier ASCII passé en paramètre permet de définir les cylindres pour chaque placette (une ligne par cylindre).
" "Ce fichier doit contenir les champs suivants :
" "- ID_Plot : Identifiant placette
" "- ID_Tree : Identifiant du cylindre à extraire
" "- X : Coordonnée X du centre du cylindre
" "- Y : Coordonnée Y du centre du cylindre
" "- Z : Coordonnée Z du centre du cylindre
" "- Zmin : Z minium de la tranche à conserver dans le cylindre
" "- Zmax : Z maximum de la tranche à conserver dans le cylindre
" "- Rayon : Rayon (XY) du cylindre à conserver
" "Le champs ID_Plot est mis en correspondance avec le nom de la placette (cf. choix des résultats d'entrée).
" "Si le champs ID_Plot est absent (NODATA), tous les cylindres sont conservés.
" "Il est également possible pour chaque cylindre de réaliser une translation de son centre (X,Y,Z) aux coordonnées (0,0,0)."); } QString TK_StepExtractPointsInVerticalCylinders::URL() const { return SuperClass::URL(); //by default URL of the plugin } CT_VirtualAbstractStep* TK_StepExtractPointsInVerticalCylinders::createNewInstance() const { return new TK_StepExtractPointsInVerticalCylinders(); } //////////////////// PROTECTED METHODS ////////////////// void TK_StepExtractPointsInVerticalCylinders::declareInputModels(CT_StepInModelStructureManager& manager) { manager.addResult(_inResult, tr("Scène(s)")); manager.setZeroOrMoreRootGroup(_inResult, _inZeroOrMoreRootGroup); manager.addGroup(_inZeroOrMoreRootGroup, _inGroup); manager.addItem(_inGroup, _inScene, tr("Scène")); manager.addItem(_inGroup, _inFileNameItem, tr("Item avec nom de fichier")); manager.addItemAttribute(_inFileNameItem, _inAttFileName, CT_AbstractCategory::DATA_VALUE, tr("Nom de fichier")); } void TK_StepExtractPointsInVerticalCylinders::declareOutputModels(CT_StepOutModelStructureManager& manager) { manager.addResultCopy(_inResult); manager.addGroup(_inGroup, _outGroup, tr("Scene extraite")); manager.addItem(_outGroup, _outScene, tr("Scène extraite")); manager.addItemAttribute(_outScene, _outAttIDModelName, CT_AbstractCategory::DATA_VALUE, tr("PlotID")); } void TK_StepExtractPointsInVerticalCylinders::fillPostInputConfigurationDialog(CT_StepConfigurableDialog* postInputConfigDialog) { postInputConfigDialog->addAsciiFileChoice(tr("Fichier des cylindres par placette"), tr("Fichier ASCII (*.txt ; *.asc)"), true, _neededFields, _refFileName, _refHeader, _refSeparator, _refDecimal, _refLocale, _refSkip, _refColumns); postInputConfigDialog->addBool(tr("Appliquer translation"), "", "", _translate); } void TK_StepExtractPointsInVerticalCylinders::compute() { int colIDplot_ref = _refColumns.value("ID_Plot", -1); bool plotColExist = (colIDplot_ref >= 0); QList plotIds; if (plotColExist) { // Listing available plots scenes for (CT_StandardItemGroup* group : _inGroup.iterateOutputs(_inResult)) { for (const CT_AbstractSingularItemDrawable* in_item : group->singularItems(_inFileNameItem)) { if (isStopped()) {return;} // TODOV6 - Plantage à l'exécution de la ligne suivante const CT_AbstractItemAttribute* att = in_item->itemAttribute(_inAttFileName); QString attributeValue = att->toString(in_item, nullptr); QFileInfo fileInfo(attributeValue); plotIds.append(fileInfo.baseName()); } } } QMultiMap cylinders; QFile fRef(_refFileName); if (fRef.exists() && fRef.open(QIODevice::ReadOnly | QIODevice::Text)) { QTextStream stream(&fRef); stream.setLocale(_refLocale); int colID = _refColumns.value("ID_Tree", -1); int colX = _refColumns.value("X", -1); int colY = _refColumns.value("Y", -1); int colZ = _refColumns.value("Z", -1); int colZmin = _refColumns.value("Zmin", -1); int colZmax = _refColumns.value("Zmax", -1); int colRadius = _refColumns.value(tr("Rayon"), -1); if (!plotColExist) {PS_LOG->addMessage(LogInterface::info, LogInterface::step, QString(tr("Champ IDplot non défini (non bloquant)")));} if (colID < 0) {PS_LOG->addMessage(LogInterface::error, LogInterface::step, QString(tr("Champ IDtree non défini")));} if (colX < 0) {PS_LOG->addMessage(LogInterface::error, LogInterface::step, QString(tr("Champ X non défini")));} if (colY < 0) {PS_LOG->addMessage(LogInterface::error, LogInterface::step, QString(tr("Champ Y non défini")));} if (colZ < 0) {PS_LOG->addMessage(LogInterface::error, LogInterface::step, QString(tr("Champ Z non défini")));} if (colZmin < 0) {PS_LOG->addMessage(LogInterface::error, LogInterface::step, QString(tr("Champ Zmin non défini")));} if (colZmax < 0) {PS_LOG->addMessage(LogInterface::error, LogInterface::step, QString(tr("Champ Zmax non défini")));} if (colRadius < 0) {PS_LOG->addMessage(LogInterface::error, LogInterface::step, QString(tr("Champ Rayon non défini")));} if (colID >=0 && colX >= 0 && colY >= 0 && colZ >= 0 && colZmin >= 0 && colZmax >= 0 && colRadius >= 0) { int colMax = colID; if (colX > colMax) {colMax = colX;} if (colY > colMax) {colMax = colY;} if (colZ > colMax) {colMax = colZ;} if (colZmin > colMax) {colMax = colZmin;} if (colZmax > colMax) {colMax = colZmax;} if (colRadius > colMax) {colMax = colRadius;} if (colIDplot_ref > colMax) {colMax = colIDplot_ref;} for (int i = 0 ; i < _refSkip ; i++) {stream.readLine();} if (_refHeader) {stream.readLine();} size_t cpt = 1; while (!stream.atEnd()) { QString line = stream.readLine(); cpt++; if (!line.isEmpty()) { QStringList values = line.split(_refSeparator); if (values.size() >= colMax) { QString plot = ""; if (plotColExist) { plot = values.at(colIDplot_ref); } else { plot = "NOPLOT"; } if (!plotColExist || plotIds.contains(plot)) { bool okX, okY, okZ, okZmin, okZmax, okRadius; double x = _refLocale.toDouble(values.at(colX), &okX); double y = _refLocale.toDouble(values.at(colY), &okY); double z = _refLocale.toDouble(values.at(colZ), &okZ); double zmin = _refLocale.toDouble(values.at(colZmin), &okZmin); double zmax = _refLocale.toDouble(values.at(colZmax), &okZmax); double radius = _refLocale.toDouble(values.at(colRadius), &okRadius); QString id = values.at(colID); if (okX && okY && okZ && okZmin && okZmax && okRadius) { cylinders.insert(plot, new CylData(id, x, y, z, zmin, zmax, radius)); } else { PS_LOG->addMessage(LogInterface::info, LogInterface::step, QString(tr("Ligne %1 du fichier REF non valide")).arg(cpt)); } } } } } } fRef.close(); } for (CT_StandardItemGroup* group : _inGroup.iterateOutputs(_inResult)) { for (const CT_AbstractItemDrawableWithPointCloud* inScene : group->singularItems(_inScene)) { if (isStopped()) {return;} const CT_AbstractSingularItemDrawable* in_item = group->singularItem(_inFileNameItem); if (in_item != nullptr) { const CT_AbstractItemAttribute* att = in_item->itemAttribute(_inAttFileName); QString attributeValue = att->toString(in_item, nullptr); QFileInfo fileInfo(attributeValue); QString plotName = fileInfo.baseName(); if (!plotColExist) {plotName = "NOPLOT";} if (_translate) { extractCylindersWithTranslation(group, cylinders, inScene, plotName); } else { extractCylindersWithoutTranslation(group, cylinders, inScene, plotName); } } } } } void TK_StepExtractPointsInVerticalCylinders::extractCylindersWithoutTranslation(CT_StandardItemGroup* group, QMultiMap cylinders, const CT_AbstractItemDrawableWithPointCloud *in_scene, QString plotName) { QMap cloudIndexVectors; QList cylindersForActivePlot = cylinders.values(plotName); for (int i = 0 ; i < cylindersForActivePlot.size() ; i++) { cloudIndexVectors.insert(cylindersForActivePlot.at(i), new CT_PointCloudIndexVector()); } if (cylindersForActivePlot.size() > 0) { QMapIterator itCl(cloudIndexVectors); const CT_AbstractPointCloudIndex *pointCloudIndex = in_scene->pointCloudIndex(); CT_PointIterator itP(pointCloudIndex); while(itP.hasNext()) { const CT_Point &point = itP.next().currentPoint(); size_t index = itP.currentGlobalIndex(); itCl.toFront(); while (itCl.hasNext()) { itCl.next(); if (itCl.key()->contains(point(0), point(1), point(2))) { itCl.value()->addIndex(index);; } } } itCl.toFront(); while (itCl.hasNext()) { itCl.next(); CylData* dataCyl = itCl.key(); QString idTree = dataCyl->_id; // creation du groupe CT_StandardItemGroup *outGroup = new CT_StandardItemGroup(); group->addGroup(_outGroup, outGroup); // creation et ajout de la scene CT_Scene *outScene = new CT_Scene(PS_REPOSITORY->registerPointCloudIndex(itCl.value())); outScene->updateBoundingBox(); outScene->setDisplayableName(idTree); outGroup->addSingularItem(_outScene, outScene); outScene->addItemAttribute(_outAttIDModelName, new CT_StdItemAttributeT(PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_VALUE), plotName)); } } } void TK_StepExtractPointsInVerticalCylinders::extractCylindersWithTranslation(CT_StandardItemGroup* group, QMultiMap cylinders, const CT_AbstractItemDrawableWithPointCloud *in_scene, QString plotName) { QList cylindersForActivePlot = cylinders.values(plotName); for (int i = 0 ; i < cylindersForActivePlot.size() ; i++) { CylData* cyl = cylindersForActivePlot.at(i); CT_AbstractUndefinedSizePointCloud *cloud = PS_REPOSITORY->createNewUndefinedSizePointCloud(); const CT_AbstractPointCloudIndex *pointCloudIndex = in_scene->pointCloudIndex(); CT_PointIterator itP(pointCloudIndex); while(itP.hasNext()) { const CT_Point &point = itP.next().currentPoint(); if (cyl->contains(point(0), point(1), point(2))) { cloud->addPoint(Eigen::Vector3d(point(0) - cyl->_x, point(1) - cyl->_y, point(2) - cyl->_z)); } } // creation du groupe CT_StandardItemGroup *outGroup = new CT_StandardItemGroup(); group->addGroup(_outGroup, outGroup); // creation et ajout de la scene CT_Scene *outScene = new CT_Scene(PS_REPOSITORY->registerUndefinedSizePointCloud(cloud)); outScene->updateBoundingBox(); outGroup->addSingularItem(_outScene, outScene); outScene->addItemAttribute(_outAttIDModelName, new CT_StdItemAttributeT(PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_VALUE), plotName)); } }