/**************************************************************************** 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_stepselectsceneforeachposition.h" #include "documentinterface.h" #include ONF_StepSelectSceneForEachPosition::ONF_StepSelectSceneForEachPosition() : SuperClass() { _distThrehold = 3.0; _interactiveCorrection = true; _dataContainer = nullptr; setManual(true); _m_doc = nullptr; } ONF_StepSelectSceneForEachPosition::~ONF_StepSelectSceneForEachPosition() { } QString ONF_StepSelectSceneForEachPosition::description() const { return tr("Apparier scènes et positions terrain"); } QString ONF_StepSelectSceneForEachPosition::detailledDescription() const { return tr(""); } QString ONF_StepSelectSceneForEachPosition::inputDescription() const { return SuperClass::inputDescription() + tr("

"); } QString ONF_StepSelectSceneForEachPosition::outputDescription() const { return SuperClass::outputDescription() + tr("

"); } QString ONF_StepSelectSceneForEachPosition::detailsDescription() const { return tr(""); } CT_VirtualAbstractStep* ONF_StepSelectSceneForEachPosition::createNewInstance() const { return new ONF_StepSelectSceneForEachPosition(); } //////////////////// PROTECTED METHODS ////////////////// void ONF_StepSelectSceneForEachPosition::declareInputModels(CT_StepInModelStructureManager& manager) { manager.addResult(_inResPlot, tr("Placette"), "", true); manager.setZeroOrMoreRootGroup(_inResPlot, _inZeroOrMoreRootGroup); manager.addGroup(_inZeroOrMoreRootGroup, _inGroup); manager.addItem(_inGroup, _inRef, tr("Arbre")); manager.addItemAttribute(_inRef, _inRefDbh, CT_AbstractCategory::DATA_VALUE, tr("DBH")); manager.addItemAttribute(_inRef, _inRefHeight, CT_AbstractCategory::DATA_VALUE, tr("Height")); manager.addItemAttribute(_inRef, _inRefID, CT_AbstractCategory::DATA_ID, tr("IDtree")); manager.addItemAttribute(_inRef, _inRefIDplot, CT_AbstractCategory::DATA_ID, tr("IDplot")); manager.addItemAttribute(_inRef, _inSpecies, CT_AbstractCategory::DATA_VALUE, tr("Species")); manager.addResult(_inResScene, tr("Scene"), "", true); manager.setZeroOrMoreRootGroup(_inResScene, _inZeroOrMoreRootGroupSc); manager.addGroup(_inZeroOrMoreRootGroupSc, _inGroupSc); manager.addItem(_inGroupSc, _inScene, tr("Scene")); manager.addResult(_inResDTM, tr("MNT"), "", true); manager.setZeroOrMoreRootGroup(_inResDTM, _inZeroOrMoreRootGroupDTM); manager.addGroup(_inZeroOrMoreRootGroupDTM, _inGroupDTM); manager.addItem(_inGroupDTM, _inDTM, tr("MNT")); } void ONF_StepSelectSceneForEachPosition::declareOutputModels(CT_StepOutModelStructureManager& manager) { manager.addResultCopy(_inResPlot); manager.addItem(_inGroup, _outScene, tr("Scene arbre")); manager.addItemAttribute(_outScene, _outAttSceneIDCluster, CT_AbstractCategory::DATA_ID, tr("IDCluster")); } void ONF_StepSelectSceneForEachPosition::fillPostInputConfigurationDialog(CT_StepConfigurableDialog* postInputConfigDialog) { postInputConfigDialog->addDouble(tr("Distance d'appariement maximale :"), "m", 0, std::numeric_limits::max(), 2, _distThrehold); postInputConfigDialog->addBool(tr("Correction interactive"), "", "", _interactiveCorrection); } void ONF_StepSelectSceneForEachPosition::compute() { setManual(_interactiveCorrection); _dataContainer = new ONF_ActionSelectSceneForEachPosition_dataContainer(); const CT_Image2D* dtm = _inDTM.firstInput(_inResDTM); for(const CT_AbstractItemDrawableWithPointCloud* sc : _inScene.iterateInputs(_inResScene)) { if(isStopped()) break; const CT_AbstractPointCloudIndex *pointCloudIndex = sc->pointCloudIndex(); if (pointCloudIndex->size() > 0) { Eigen::Vector3d apex; apex(2) = -std::numeric_limits::max(); CT_PointIterator itP(pointCloudIndex); while(itP.hasNext()) { const CT_Point &point = itP.next().currentPoint(); if (point(2) > apex(2)) {apex = point;} } _dataContainer->_scenes.append(const_cast(sc)); _dataContainer->_scenesApex.append(apex); } } for(CT_StandardItemGroup* grp : _inGroup.iterateOutputs(_inResPlot)) { if(isStopped()) break; const CT_Circle2D* circle = grp->singularItem(_inRef); if (circle != nullptr) { ONF_ActionSelectSceneForEachPosition_treePosition* treePos = new ONF_ActionSelectSceneForEachPosition_treePosition(); treePos->_base(0) = circle->centerX(); treePos->_base(1) = circle->centerY(); treePos->_base(2) = 0; if (dtm != nullptr) { treePos->_base(2) = double(dtm->valueAtCoords(treePos->_base(0), treePos->_base(1))); if (qFuzzyCompare(treePos->_base(2), double(dtm->NA()))) {treePos->_base(2) = 0;} } treePos->_apex(0) = circle->centerX(); treePos->_apex(1) = circle->centerY(); treePos->_apex(2) = treePos->_base(2); treePos->_hasApex = false; const CT_AbstractItemAttribute* att = circle->itemAttribute(_inRefDbh); if (att != nullptr) {treePos->_dbh = att->toFloat(circle, nullptr);} if (treePos->_dbh <= 0) {treePos->_dbh = 7.5;} att = circle->itemAttribute(_inRefHeight); if (att != nullptr) {treePos->_height = att->toFloat(circle, nullptr);} if (treePos->_height <= 0) {treePos->_height = -1;} att = circle->itemAttribute(_inRefID); if (att != nullptr) {treePos->_idTree = att->toString(circle, nullptr);} att = circle->itemAttribute(_inRefIDplot); if (att != nullptr) {treePos->_idPlot = att->toString(circle, nullptr);} att = circle->itemAttribute(_inSpecies); if (att != nullptr) {treePos->_species = att->toString(circle, nullptr);} _dataContainer->_positions.append(treePos); treePos->_grp = grp; } } // Tri par ordre décroissant de diamètre std::sort(_dataContainer->_positions.begin(), _dataContainer->_positions.end(), ONF_StepSelectSceneForEachPosition::lessThan); positionMatching(_dataContainer); if (_interactiveCorrection && !isStopped()) { requestManualMode(); } for (int i = 0 ; i < _dataContainer->_positions.size() ; i++) { if(isStopped()) break; ONF_ActionSelectSceneForEachPosition_treePosition* treePos = _dataContainer->_positions.at(i); if (treePos != nullptr && treePos->_grp != nullptr) { CT_PointCloudIndexVector *resPointCloudIndex = new CT_PointCloudIndexVector(); resPointCloudIndex->setSortType(CT_PointCloudIndexVector::NotSorted); // Fusion des scènes associées for (int i = 0 ; i < treePos->_scenesIds.size() ; i++) { int id = treePos->_scenesIds.at(i); CT_AbstractItemDrawableWithPointCloud* sc = static_cast(_dataContainer->_scenes.at(id)); if (sc != nullptr) { const CT_AbstractPointCloudIndex *pointCloudIndex = sc->pointCloudIndex(); if (pointCloudIndex != nullptr) { CT_PointIterator itP(pointCloudIndex); while(itP.hasNext()) { size_t index = itP.next().currentGlobalIndex(); resPointCloudIndex->addIndex(index); } } } } if (resPointCloudIndex->size() > 0) { resPointCloudIndex->setSortType(CT_PointCloudIndexVector::SortedInAscendingOrder); // creation et ajout de la scene CT_Scene *outScene = _outScene.createInstance(PS_REPOSITORY->registerPointCloudIndex(resPointCloudIndex)); treePos->_grp->addSingularItem(_outScene, outScene); const QString sceneName = QString("%1_%2").arg(treePos->_idPlot).arg(treePos->_idTree); outScene->addItemAttribute(_outAttSceneIDCluster, _outAttSceneIDCluster.createInstance(CT_AbstractCategory::DATA_ID, sceneName)); } else { delete resPointCloudIndex; } } delete treePos; } delete _dataContainer; if (_interactiveCorrection && !isStopped()) { _m_doc = nullptr; } } void ONF_StepSelectSceneForEachPosition::positionMatching(ONF_ActionSelectSceneForEachPosition_dataContainer* dataContainer) { dataContainer->_matched.resize(dataContainer->_scenesApex.size()); dataContainer->_matched.fill(false); for (int pos = 0 ; pos < dataContainer->_positions.size() ; pos++) { if(isStopped()) break; ONF_ActionSelectSceneForEachPosition_treePosition* treePos = dataContainer->_positions.at(pos); // if (treePos->_height > 0) // { // for (int ap = 0 ; ap < dataContainer->_scenesApex.size() ; ap++) // { // if (!affected[ap]) // { // const Eigen::Vector3d &apex = dataContainer->_scenesApex.at(ap); // double dist = sqrt(pow(treePos->_base(0) - apex(0), 2) + pow(treePos->_base(1) - apex(1), 2)); // if (dist < _distThrehold) // { // double apexHeight = apex(2) - treePos->_base(2); // double deltaH = std::abs(treePos->_height - apexHeight); // double hd = treePos->_height / (treePos->_dbh / 100.0); // } // } // } // } else { // on garde le plus haut double maxApexHeight = -std::numeric_limits::max(); int bestApex = -1; for (int ap = 0 ; ap < dataContainer->_scenesApex.size() ; ap++) { if (!dataContainer->_matched[ap]) { const Eigen::Vector3d &apex = dataContainer->_scenesApex.at(ap); double dist = sqrt(pow(treePos->_base(0) - apex(0), 2) + pow(treePos->_base(1) - apex(1), 2)); if (dist < _distThrehold) { double apexHeight = apex(2) - treePos->_base(2); if (apexHeight > maxApexHeight) { maxApexHeight = apexHeight; bestApex = ap; } } } } if (bestApex >= 0) { treePos->addScene(bestApex, dataContainer->_scenesApex.at(bestApex)); dataContainer->_matched[bestApex] = true; } // } } } void ONF_StepSelectSceneForEachPosition::initManualMode() { if(_m_doc == nullptr) { // create a new 3D document QColor col = Qt::black; _m_doc = guiContext()->documentManager()->new3DDocument(2.0, false, &col); ONF_ActionSelectSceneForEachPosition* action = new ONF_ActionSelectSceneForEachPosition(_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_StepSelectSceneForEachPosition::useManualMode(bool quit) { Q_UNUSED(quit) }