/**************************************************************************** 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 "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 // Alias for indexing models #define DEFin_resScene "resScene" #define DEFin_grpSc "grpSc" #define DEFin_scene "scene" #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" // Constructor : initialization of parameters ONF_StepSelectSceneForEachPosition::ONF_StepSelectSceneForEachPosition(CT_StepInitializeData &dataInit) : CT_AbstractStep(dataInit) { _distThrehold = 3.0; _interactiveCorrection = true; _dataContainer = NULL; setManual(true); _m_doc = NULL; } ONF_StepSelectSceneForEachPosition::~ONF_StepSelectSceneForEachPosition() { } // Step description (tooltip of contextual menu) QString ONF_StepSelectSceneForEachPosition::getStepDescription() const { return tr("Apparier scènes et positions terrain"); } // Step detailled description QString ONF_StepSelectSceneForEachPosition::getStepDetailledDescription() const { return tr("To Do"); } // Step copy method CT_VirtualAbstractStep* ONF_StepSelectSceneForEachPosition::createNewInstance(CT_StepInitializeData &dataInit) { return new ONF_StepSelectSceneForEachPosition(dataInit); } //////////////////// PROTECTED METHODS ////////////////// // Creation and affiliation of IN models void ONF_StepSelectSceneForEachPosition::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); 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")); 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_StepSelectSceneForEachPosition::createOutResultModelListProtected() { CT_OutResultModelGroupToCopyPossibilities *res = createNewOutResultModelToCopy(DEFin_resPlot); if(res != NULL) { res->addItemModel(DEFin_grp, _outSceneModelName, new CT_Scene(), tr("Scene arbre")); res->addItemAttributeModel(_outSceneModelName, _outSceneIDClusterAttModelName, new CT_StdItemAttributeT(CT_AbstractCategory::DATA_ID), tr("IDCluster")); } } // Semi-automatic creation of step parameters DialogBox void ONF_StepSelectSceneForEachPosition::createPostConfigurationDialog() { CT_StepConfigurableDialog *configDialog = newStandardPostConfigurationDialog(); configDialog->addDouble(tr("Distance d'appariement maximale :"), "m", 0, 1e+10, 2, _distThrehold); configDialog->addBool(tr("Correction interactive"), "", "", _interactiveCorrection); } void ONF_StepSelectSceneForEachPosition::compute() { setManual(_interactiveCorrection); _dataContainer = new ONF_ActionSelectSceneForEachPosition_dataContainer(); CT_Image2D* dtm = NULL; if (getInputResults().size() > 2) { CT_ResultGroup* resin_DTM = getInputResults().at(2); CT_ResultItemIterator it(resin_DTM, this, DEFin_DTM); if (it.hasNext()) { dtm = (CT_Image2D*) it.next(); } } 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 != NULL) { const CT_AbstractPointCloudIndex *pointCloudIndex = sc->getPointCloudIndex(); 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(sc); _dataContainer->_scenesApex.append(apex); } } } 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 != NULL) { ONF_ActionSelectSceneForEachPosition_treePosition* treePos = new ONF_ActionSelectSceneForEachPosition_treePosition(); treePos->_base(0) = circle->getCenterX(); treePos->_base(1) = circle->getCenterY(); treePos->_base(2) = 0; if (dtm != NULL) { treePos->_base(2) = dtm->valueAtCoords(treePos->_base(0), treePos->_base(1)); if (treePos->_base(2) == dtm->NA()) {treePos->_base(2) = 0;} } treePos->_apex(0) = circle->getCenterX(); treePos->_apex(1) = circle->getCenterY(); treePos->_apex(2) = treePos->_base(2); treePos->_hasApex = false; CT_AbstractItemAttribute* att = circle->firstItemAttributeByINModelName(resOut_positions, this, DEFin_refDbh); if (att != NULL) {treePos->_dbh = att->toFloat(circle, NULL);} if (treePos->_dbh <= 0) {treePos->_dbh = 7.5;} att = circle->firstItemAttributeByINModelName(resOut_positions, this, DEFin_refHeight); if (att != NULL) {treePos->_height = att->toFloat(circle, NULL);} if (treePos->_height <= 0) {treePos->_height = -1;} att = circle->firstItemAttributeByINModelName(resOut_positions, this, DEFin_refID); if (att != NULL) {treePos->_idTree = att->toString(circle, NULL);} att = circle->firstItemAttributeByINModelName(resOut_positions, this, DEFin_refIDplot); if (att != NULL) {treePos->_idPlot = att->toString(circle, NULL);} att = circle->firstItemAttributeByINModelName(resOut_positions, this, DEFin_species); if (att != NULL) {treePos->_species = att->toString(circle, NULL);} _dataContainer->_positions.append(treePos); treePos->_grp = grp; } } // Tri par ordre décroissant de diamètre qSort(_dataContainer->_positions.begin(), _dataContainer->_positions.end(), ONF_StepSelectSceneForEachPosition::lessThan); positionMatching(_dataContainer); if (_interactiveCorrection) { requestManualMode(); } for (int i = 0 ; i < _dataContainer->_positions.size() ; i++) { ONF_ActionSelectSceneForEachPosition_treePosition* treePos = _dataContainer->_positions.at(i); if (treePos != NULL && treePos->_grp != NULL) { 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 = (CT_AbstractItemDrawableWithPointCloud*) _dataContainer->_scenes.at(id); if (sc != NULL) { const CT_AbstractPointCloudIndex *pointCloudIndex = sc->getPointCloudIndex(); if (pointCloudIndex != NULL) { 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 = new CT_Scene(_outSceneModelName.completeName(), resOut_positions, PS_REPOSITORY->registerPointCloudIndex(resPointCloudIndex)); QString sceneName = QString("%1_%2").arg(treePos->_idPlot).arg(treePos->_idTree); outScene->addItemAttribute(new CT_StdItemAttributeT(_outSceneIDClusterAttModelName.completeName(), CT_AbstractCategory::DATA_ID, resOut_positions, sceneName)); treePos->_grp->addItemDrawable(outScene); } else { delete resPointCloudIndex; } } delete treePos; } delete _dataContainer; if (_interactiveCorrection) { _m_doc = NULL; } } 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++) { 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 == NULL) { // create a new 3D document QColor col = Qt::black; _m_doc = getGuiContext()->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(NULL, // tr("Mode manuel"), // tr("Bienvenue dans le mode manuel de cette étape.\n"), // QMessageBox::Ok); } void ONF_StepSelectSceneForEachPosition::useManualMode(bool quit) { }