/**************************************************************************** Copyright (C) 2010-2012 the Office National des Forêts (ONF), France All rights reserved. Contact : alexandre.piboule@onf.fr Developers : Alexandre PIBOULE (ONF) This file is part of PluginONF library. PluginONF is free library: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. PluginONF is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with PluginONF. If not, see . *****************************************************************************/ #include "onf_stepadjustplotposition02.h" #include "ct_itemdrawable/ct_scene.h" #include "ct_itemdrawable/ct_circle2d.h" #include "ctliblas/itemdrawable/las/ct_stdlaspointsattributescontainer.h" #include "ct_itemdrawable/ct_pointsattributesscalartemplated.h" #include "ct_result/ct_resultgroup.h" #include "ct_result/model/inModel/ct_inresultmodelgroup.h" #include "ct_result/model/inModel/ct_inresultmodelgrouptocopy.h" #include "ct_result/model/outModel/ct_outresultmodelgroupcopy.h" #include "ct_result/model/outModel/tools/ct_outresultmodelgrouptocopypossibilities.h" #include "ct_view/ct_stepconfigurabledialog.h" #include "ct_pointcloudindex/ct_pointcloudindexvector.h" #include "ct_itemdrawable/tools/iterator/ct_groupiterator.h" #include "ct_iterator/ct_pointiterator.h" #include "ct_itemdrawable/ct_image2d.h" #include #include #include #include #include #include // Alias for indexing models #define DEFin_resScene "resScene" #define DEFin_grpSc "grpSc" #define DEFin_scene "scene" #define DEFin_lasAtt "lasAtt" #define DEFin_maxima "maximaraster" #define DEFin_mns "mns" #define DEFin_area "area" #define DEFin_heightAtt "heightAtt" #define DEFin_resDTM "resdtm" #define DEFin_DTMGrp "dtmgrp" #define DEFin_DTM "dtm" #define DEFin_resPlot "resPlot" #define DEFin_grp "grp" #define DEFin_ref "ref" #define DEFin_refDbh "refDbh" #define DEFin_refHeight "refHeight" #define DEFin_refID "refID" #define DEFin_refIDplot "refIDplot" #define DEFin_species "species" #define DEFin_comment "comment" // Constructor : initialization of parameters ONF_StepAdjustPlotPosition02::ONF_StepAdjustPlotPosition02(CT_StepInitializeData &dataInit) : CT_AbstractStep(dataInit) { _dataContainer = nullptr; setManual(true); _m_status = 0; _m_doc = nullptr; } ONF_StepAdjustPlotPosition02::~ONF_StepAdjustPlotPosition02() { } // Step description (tooltip of contextual menu) QString ONF_StepAdjustPlotPosition02::getStepDescription() const { return tr("Recaler une placette terrain (v02)"); } // Step detailled description QString ONF_StepAdjustPlotPosition02::getStepDetailledDescription() const { return tr("To Do"); } // Step copy method CT_VirtualAbstractStep* ONF_StepAdjustPlotPosition02::createNewInstance(CT_StepInitializeData &dataInit) { return new ONF_StepAdjustPlotPosition02(dataInit); } //////////////////// PROTECTED METHODS ////////////////// // Creation and affiliation of IN models void ONF_StepAdjustPlotPosition02::createInResultModelListProtected() { CT_InResultModelGroupToCopy *resIn_Plot = createNewInResultModelForCopy(DEFin_resPlot, tr("Placette"), "", true); resIn_Plot->setZeroOrMoreRootGroup(); resIn_Plot->addGroupModel("", DEFin_grp, CT_AbstractItemGroup::staticGetType(), tr("Groupe")); resIn_Plot->addItemModel(DEFin_grp, DEFin_ref, CT_Circle2D::staticGetType(), tr("Arbre")); resIn_Plot->addItemAttributeModel(DEFin_ref, DEFin_refDbh, QList() << CT_AbstractCategory::DATA_VALUE, CT_AbstractCategory::NUMBER, tr("DBH")); resIn_Plot->addItemAttributeModel(DEFin_ref, DEFin_refHeight, QList() << CT_AbstractCategory::DATA_VALUE, CT_AbstractCategory::NUMBER, tr("Height")); resIn_Plot->addItemAttributeModel(DEFin_ref, DEFin_refID, QList() << CT_AbstractCategory::DATA_ID, CT_AbstractCategory::STRING, tr("IDtree")); resIn_Plot->addItemAttributeModel(DEFin_ref, DEFin_refIDplot, QList() << CT_AbstractCategory::DATA_ID, CT_AbstractCategory::STRING, tr("IDplot")); resIn_Plot->addItemAttributeModel(DEFin_ref, DEFin_species, QList() << CT_AbstractCategory::DATA_VALUE, CT_AbstractCategory::STRING, tr("Species"), "", CT_InAbstractModel::C_ChooseOneIfMultiple, CT_InAbstractModel::F_IsOptional); resIn_Plot->addItemAttributeModel(DEFin_ref, DEFin_comment, QList() << CT_AbstractCategory::DATA_VALUE, CT_AbstractCategory::STRING, tr("Comment"), "", CT_InAbstractModel::C_ChooseOneIfMultiple, CT_InAbstractModel::F_IsOptional); CT_InResultModelGroup *resIn_Scene = createNewInResultModel(DEFin_resScene, tr("Scène"), "", true); resIn_Scene->setZeroOrMoreRootGroup(); resIn_Scene->addGroupModel("", DEFin_grpSc, CT_AbstractItemGroup::staticGetType(), tr("Groupe")); resIn_Scene->addItemModel(DEFin_grpSc, DEFin_scene, CT_AbstractItemDrawableWithPointCloud::staticGetType(), tr("Scène")); resIn_Scene->addItemModel(DEFin_grpSc, DEFin_lasAtt, CT_StdLASPointsAttributesContainer::staticGetType(), tr("Attributs LAS"), "", CT_InAbstractItemModel::C_ChooseOneIfMultiple, CT_InAbstractItemModel::F_IsOptional); resIn_Scene->addItemModel(DEFin_grpSc, DEFin_maxima, CT_Image2D::staticGetType(), tr("Maxima")); resIn_Scene->addItemModel(DEFin_grpSc, DEFin_mns, CT_Image2D::staticGetType(), tr("MNS")); resIn_Scene->addItemModel(DEFin_grpSc, DEFin_area, CT_Circle2D::staticGetType(), tr("Emprise")); resIn_Scene->addItemModel(DEFin_grpSc, DEFin_heightAtt, CT_PointsAttributesScalarTemplated::staticGetType(), tr("Attribut Hauteur"), "", CT_InAbstractItemModel::C_ChooseOneIfMultiple, CT_InAbstractItemModel::F_IsOptional); CT_InResultModelGroup *resultDTM = createNewInResultModel(DEFin_resDTM, tr("MNT"), "", true); resultDTM->setZeroOrMoreRootGroup(); resultDTM->addGroupModel("", DEFin_DTMGrp, CT_AbstractItemGroup::staticGetType(), tr("Group")); resultDTM->addItemModel(DEFin_DTMGrp, DEFin_DTM, CT_Image2D::staticGetType(), tr("MNT")); resultDTM->setMinimumNumberOfPossibilityThatMustBeSelectedForOneTurn(0); } // Creation and affiliation of OUT models void ONF_StepAdjustPlotPosition02::createOutResultModelListProtected() { CT_OutResultModelGroupToCopyPossibilities *res = createNewOutResultModelToCopy(DEFin_resPlot); if(res != nullptr) { res->addItemModel(DEFin_grp, _outCircleModelName, new CT_Circle2D(), tr("Arbre déplacé")); res->addItemAttributeModel(_outCircleModelName, _outDBHAttModelName, new CT_StdItemAttributeT(CT_AbstractCategory::DATA_NUMBER), tr("DBH")); res->addItemAttributeModel(_outCircleModelName, _outHeightAttModelName, new CT_StdItemAttributeT(CT_AbstractCategory::DATA_NUMBER), tr("Height")); res->addItemAttributeModel(_outCircleModelName, _outPlotIDAttModelName, new CT_StdItemAttributeT(CT_AbstractCategory::DATA_ID), tr("IDplot")); res->addItemAttributeModel(_outCircleModelName, _outTreeIDAttModelName, new CT_StdItemAttributeT(CT_AbstractCategory::DATA_ID), tr("IDtree")); res->addItemAttributeModel(_outCircleModelName, _outSpeciesAttModelName, new CT_StdItemAttributeT(CT_AbstractCategory::DATA_VALUE), tr("Species")); res->addItemAttributeModel(_outCircleModelName, _outTransXAttModelName, new CT_StdItemAttributeT(CT_AbstractCategory::DATA_NUMBER), tr("TransX")); res->addItemAttributeModel(_outCircleModelName, _outTransYAttModelName, new CT_StdItemAttributeT(CT_AbstractCategory::DATA_NUMBER), tr("TransY")); res->addItemAttributeModel(_outCircleModelName, _outMovedAttModelName, new CT_StdItemAttributeT(CT_AbstractCategory::DATA_VALUE), tr("Moved")); res->addItemAttributeModel(_outCircleModelName, _outZPointAttModelName, new CT_StdItemAttributeT(CT_AbstractCategory::DATA_NUMBER), tr("zPointClicked")); } } // Semi-automatic creation of step parameters DialogBox void ONF_StepAdjustPlotPosition02::createPostConfigurationDialog() { CT_StepConfigurableDialog *configDialog = newStandardPostConfigurationDialog(); configDialog->addFileChoice(tr("Fichier d'export des placettes recalées"), CT_FileChoiceButton::OneNewFile, tr("Fichier Texte (*.txt)"), _exportFile); configDialog->addFileChoice(tr("Fichier de couleurs pour les espèces"), CT_FileChoiceButton::OneExistingFile, tr("Fichier CSV (*.csv)"), _paramFile, tr("Fichier contenant sur chaque ligne : CodeEspèce,composanteRouge,compostanteBleue,composanteVerte")); } void ONF_StepAdjustPlotPosition02::compute() { _dataContainer = new ONF_ActionAdjustPlotPosition02_dataContainer(); if (getInputResults().size() > 2) { CT_ResultGroup* resin_DTM = getInputResults().at(2); CT_ResultItemIterator it(resin_DTM, this, DEFin_DTM); if (it.hasNext()) { _dataContainer->_dtm = (CT_Image2D*) it.next(); } } if (!_paramFile.isEmpty() && QFile::exists(_paramFile.first())) { QFile fSpecies(_paramFile.first()); if (fSpecies.open(QIODevice::ReadOnly | QIODevice::Text)) { QTextStream stream(&fSpecies); while (!stream.atEnd()) { QString line = stream.readLine(); if (!line.isNull()) { QStringList values = line.split(QRegExp("[;,]")); if (values.size() >= 4) { QString spCode = values.at(0).toUpper(); bool okR, okG, okB; int colR = values.at(1).toInt(&okR); int colG = values.at(2).toInt(&okG); int colB = values.at(3).toInt(&okB); if (!spCode.isEmpty() && okR && okG && okB && colR >= 0 && colG >= 0 && colB >= 0 && colR <= 255 && colG <= 255 && colB <= 255) { _dataContainer->_spColors.insert(spCode, QColor(colR, colG, colB)); } } } } } } _m_status = 0; QList inResultList = getInputResults(); CT_ResultGroup* resIn_scene = inResultList.at(1); CT_ResultGroupIterator itGrpSc(resIn_scene, this, DEFin_grpSc); while (itGrpSc.hasNext()) { const CT_AbstractItemGroup* grp = itGrpSc.next(); CT_AbstractItemDrawableWithPointCloud* sc = (CT_AbstractItemDrawableWithPointCloud*) grp->firstItemByINModelName(this, DEFin_scene); if (sc != nullptr) { CT_StdLASPointsAttributesContainer* lasAtt = (CT_StdLASPointsAttributesContainer*)grp->firstItemByINModelName(this, DEFin_lasAtt); CT_PointsAttributesScalarTemplated* heightAtt = (CT_PointsAttributesScalarTemplated*)grp->firstItemByINModelName(this, DEFin_heightAtt); CT_Image2D* maximaRaster = (CT_Image2D*)grp->firstItemByINModelName(this, DEFin_maxima); CT_Image2D* mns = (CT_Image2D*)grp->firstItemByINModelName(this, DEFin_mns); CT_Circle2D* area = (CT_Circle2D*)grp->firstItemByINModelName(this, DEFin_area); _dataContainer->_scenes.append(sc); _dataContainer->_LASattributes.append(lasAtt); _dataContainer->_heightAttributes.append(heightAtt); _dataContainer->_dsm = mns; if (area != nullptr) { _dataContainer->_idPlot = area->displayableName(); _dataContainer->_xPlot = area->getCenterX(); _dataContainer->_yPlot = area->getCenterY(); _dataContainer->_radiusPlot = area->getRadius(); } _dataContainer->_quality = 0; const CT_AbstractPointCloudIndex *pointCloudIndex = sc->getPointCloudIndex(); CT_PointIterator itP(pointCloudIndex); while(itP.hasNext() && (!isStopped())) { const CT_Point &point = itP.next().currentPoint(); quint32 maxRasterIndex = maximaRaster->valueAtCoords(point(0), point(1)); if (maxRasterIndex > 0) { Eigen::Vector3d previous = _dataContainer->_maximaPoints.value(maxRasterIndex, Eigen::Vector3d(0,0,-std::numeric_limits::max())); if (point(2) > previous(2)) { _dataContainer->_maximaPoints.insert(maxRasterIndex, point); } } } } } QList outResultList = getOutResultList(); CT_ResultGroup* resOut_positions = outResultList.at(0); CT_ResultGroupIterator itGrp(resOut_positions, this, DEFin_grp); while (itGrp.hasNext()) { CT_StandardItemGroup* grp = (CT_StandardItemGroup*) itGrp.next(); CT_Circle2D* circle = (CT_Circle2D*) grp->firstItemByINModelName(this, DEFin_ref); if (circle != nullptr) { ONF_CoRegistration_TreePosition* treePos = new ONF_CoRegistration_TreePosition(); treePos->_x = circle->getCenterX(); treePos->_y = circle->getCenterY(); treePos->_originalX = circle->getCenterX(); treePos->_originalY = circle->getCenterY(); CT_AbstractItemAttribute* att = circle->firstItemAttributeByINModelName(resOut_positions, this, DEFin_refDbh); if (att != nullptr) {treePos->_dbh = att->toFloat(circle, nullptr);} if (treePos->_dbh <= 0) {treePos->_dbh = 7.5;} att = circle->firstItemAttributeByINModelName(resOut_positions, this, DEFin_refHeight); if (att != nullptr) {treePos->_height = att->toFloat(circle, nullptr);} treePos->_trueheight = treePos->_height; if (treePos->_height <= 0) {treePos->_height = 5.0;} att = circle->firstItemAttributeByINModelName(resOut_positions, this, DEFin_refID); if (att != nullptr) {treePos->_idTree = att->toString(circle, nullptr);} att = circle->firstItemAttributeByINModelName(resOut_positions, this, DEFin_refIDplot); if (att != nullptr) {treePos->_idPlot = att->toString(circle, nullptr);} att = circle->firstItemAttributeByINModelName(resOut_positions, this, DEFin_species); if (att != nullptr) {treePos->_species = att->toString(circle, nullptr);} att = circle->firstItemAttributeByINModelName(resOut_positions, this, DEFin_comment); if (att != nullptr) {treePos->_comment = att->toString(circle, nullptr);} treePos->_color = _dataContainer->_spColors.value(treePos->_species.toUpper(), QColor(255,255,255)); _dataContainer->_positions.append(treePos); treePos->_grp = grp; } } requestManualMode(); _m_status = 1; double transX = _dataContainer->_transX; double transY = _dataContainer->_transY; if (_exportFile.size() > 0) { QFile file(_exportFile.first()); if (!file.exists()) { if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream stream(&file); stream << tr("Time\tPlot\tXbefore\tYbefore\tTransX\tTransY\tXafter\tYafter\tQuality\tComment\n"); file.close(); } } if (file.open(QIODevice::Append | QIODevice::Text)) { double xAfter = _dataContainer->_xPlot + transX; double yAfter = _dataContainer->_yPlot + transY; QTextStream stream(&file); stream << QDateTime::currentDateTime().toString() << "\t"; stream << _dataContainer->_idPlot << "\t"; stream << QString::number(_dataContainer->_xPlot, 'f',4) << "\t"; stream << QString::number(_dataContainer->_yPlot, 'f',4) << "\t"; stream << QString::number(transX, 'f',4) << "\t"; stream << QString::number(transY, 'f',4) << "\t"; stream << QString::number(xAfter, 'f',4) << "\t"; stream << QString::number(yAfter, 'f',4) << "\t"; stream << _dataContainer->_quality << "\t"; stream << _dataContainer->_comment << "\n"; file.close(); } } for (int i = 0 ; i < _dataContainer->_positions.size() ; i++) { ONF_CoRegistration_TreePosition* treePos = _dataContainer->_positions.at(i); if (treePos->_grp != nullptr) { CT_Circle2D* circle = new CT_Circle2D(_outCircleModelName.completeName(), resOut_positions, new CT_Circle2DData(Eigen::Vector2d(treePos->_x + transX, treePos->_y + transY), treePos->_dbh / 200.0)); circle->addItemAttribute(new CT_StdItemAttributeT(_outDBHAttModelName.completeName(), CT_AbstractCategory::DATA_NUMBER, resOut_positions, treePos->_dbh)); circle->addItemAttribute(new CT_StdItemAttributeT(_outHeightAttModelName.completeName(), CT_AbstractCategory::DATA_NUMBER, resOut_positions, treePos->_trueheight)); circle->addItemAttribute(new CT_StdItemAttributeT(_outPlotIDAttModelName.completeName(), CT_AbstractCategory::DATA_ID, resOut_positions, treePos->_idPlot)); circle->addItemAttribute(new CT_StdItemAttributeT(_outTreeIDAttModelName.completeName(), CT_AbstractCategory::DATA_ID, resOut_positions, treePos->_idTree)); circle->addItemAttribute(new CT_StdItemAttributeT(_outSpeciesAttModelName.completeName(), CT_AbstractCategory::DATA_VALUE, resOut_positions, treePos->_species)); circle->addItemAttribute(new CT_StdItemAttributeT(_outTransXAttModelName.completeName(), CT_AbstractCategory::DATA_NUMBER, resOut_positions, transX)); circle->addItemAttribute(new CT_StdItemAttributeT(_outTransYAttModelName.completeName(), CT_AbstractCategory::DATA_NUMBER, resOut_positions, transY)); circle->addItemAttribute(new CT_StdItemAttributeT(_outMovedAttModelName.completeName(), CT_AbstractCategory::DATA_VALUE, resOut_positions, treePos->_moved)); circle->addItemAttribute(new CT_StdItemAttributeT(_outZPointAttModelName.completeName(), CT_AbstractCategory::DATA_NUMBER, resOut_positions, treePos->_zPoint)); treePos->_grp->addItemDrawable(circle); } delete treePos; } _dataContainer->_dsm->setAlternativeDrawManager(nullptr); delete _dataContainer; requestManualMode(); } void ONF_StepAdjustPlotPosition02::initManualMode() { if(_m_doc == nullptr) { // create a new 3D document _m_doc = getGuiContext()->documentManager()->new3DDocument(); ONF_ActionAdjustPlotPosition02* action = new ONF_ActionAdjustPlotPosition02(_dataContainer); // set the action (a copy of the action is added at all graphics view, and the action passed in parameter is deleted) _m_doc->setCurrentAction(action, false); } // QMessageBox::information(nullptr, // tr("Mode manuel"), // tr("Bienvenue dans le mode manuel de cette étape.\n"), // QMessageBox::Ok); } void ONF_StepAdjustPlotPosition02::useManualMode(bool quit) { if(_m_status == 0) { if(quit) { } } else if(_m_status == 1) { if(!quit) { _m_doc = nullptr; quitManualMode(); } } }