/**************************************************************************** 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_stepsegmentcrownsfromstemclusters.h" #include "ct_itemdrawable/tools/iterator/ct_groupiterator.h" #include "ct_itemdrawable/ct_pointcluster.h" #include "ct_result/ct_resultgroup.h" #include "ct_result/model/inModel/ct_inresultmodelgrouptocopy.h" #include "ct_result/model/outModel/tools/ct_outresultmodelgrouptocopypossibilities.h" #include "ct_view/ct_stepconfigurabledialog.h" #include "ct_pointcloudindex/ct_pointcloudindexvector.h" #include "ct_iterator/ct_pointiterator.h" #include #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/core/core.hpp" // Alias for indexing models #define DEFin_res "res" #define DEFin_grp "grp" #define DEFin_scene "scene" #define DEFin_grpPos "grpPos" #define DEFin_position "pos" // Constructor : initialization of parameters ONF_StepSegmentCrownsFromStemClusters::ONF_StepSegmentCrownsFromStemClusters(CT_StepInitializeData &dataInit) : CT_AbstractStep(dataInit) { _distMax = 1.0; } // Step description (tooltip of contextual menu) QString ONF_StepSegmentCrownsFromStemClusters::getStepDescription() const { return tr("Segmenter des houppiers à partir de Clusters tiges"); } // Step detailled description QString ONF_StepSegmentCrownsFromStemClusters::getStepDetailledDescription() const { return tr("No detailled description for this step"); } // Step URL QString ONF_StepSegmentCrownsFromStemClusters::getStepURL() const { //return tr("STEP URL HERE"); return CT_AbstractStep::getStepURL(); //by default URL of the plugin } // Step copy method CT_VirtualAbstractStep* ONF_StepSegmentCrownsFromStemClusters::createNewInstance(CT_StepInitializeData &dataInit) { return new ONF_StepSegmentCrownsFromStemClusters(dataInit); } //////////////////// PROTECTED METHODS ////////////////// // Creation and affiliation of IN models void ONF_StepSegmentCrownsFromStemClusters::createInResultModelListProtected() { CT_InResultModelGroupToCopy *resIn_res = createNewInResultModelForCopy(DEFin_res, tr("Tiges détéctées")); resIn_res->setZeroOrMoreRootGroup(); resIn_res->addGroupModel("", DEFin_grp, CT_AbstractItemGroup::staticGetType(), tr("Groupe")); resIn_res->addItemModel(DEFin_grp, DEFin_scene, CT_AbstractItemDrawableWithPointCloud::staticGetType(), tr("Scène complète")); resIn_res->addGroupModel(DEFin_grp, DEFin_grpPos, CT_AbstractItemGroup::staticGetType(), tr("Groupe")); resIn_res->addItemModel(DEFin_grpPos, DEFin_position, CT_PointCluster::staticGetType(), tr("Tige")); } // Creation and affiliation of OUT models void ONF_StepSegmentCrownsFromStemClusters::createOutResultModelListProtected() { CT_OutResultModelGroupToCopyPossibilities *resCpy_res = createNewOutResultModelToCopy(DEFin_res); if(resCpy_res != NULL) { resCpy_res->addItemModel(DEFin_grpPos, _outScene_ModelName, new CT_PointCluster(), tr("Cluster segmenté")); resCpy_res->addItemAttributeModel(_outScene_ModelName, _outAttZmax_ModelName, new CT_StdItemAttributeT(CT_AbstractCategory::DATA_Z), tr("Zmax")); } } // Semi-automatic creation of step parameters DialogBox void ONF_StepSegmentCrownsFromStemClusters::createPostConfigurationDialog() { CT_StepConfigurableDialog *configDialog = newStandardPostConfigurationDialog(); configDialog->addDouble(tr("Distance Max"), "m", 0.01, 9999, 2, _distMax); } void ONF_StepSegmentCrownsFromStemClusters::compute() { QList outResultList = getOutResultList(); CT_ResultGroup* res = outResultList.at(0); CT_ResultGroupIterator itCpy_grp(res, this, DEFin_grp); while (itCpy_grp.hasNext() && !isStopped()) { setProgress(1); CT_StandardItemGroup* grp = (CT_StandardItemGroup*) itCpy_grp.next(); CT_AbstractItemDrawableWithPointCloud* in_scene = (CT_AbstractItemDrawableWithPointCloud*)grp->firstItemByINModelName(this, DEFin_scene); if (in_scene != NULL) { // List of stems QList stems; CT_GroupIterator itCpy_grpPos(grp, this, DEFin_grpPos); while (itCpy_grpPos.hasNext() && !isStopped()) { CT_StandardItemGroup* grpPos = (CT_StandardItemGroup*) itCpy_grpPos.next(); CT_PointCluster* cluster = (CT_PointCluster*) grpPos->firstItemByINModelName(this, DEFin_position); if (cluster != NULL) { StemData* stem = new StemData(grpPos, _distMax); CT_PointIterator itP(cluster->getPointCloudIndex()); while(itP.hasNext() && (!isStopped())) { const CT_Point &point = itP.next().currentPoint(); size_t index = itP.currentGlobalIndex(); stem->addPoint(new PointData(index, point(0), point(1), point(2))); } stems.append(stem); } } setProgress(10); const CT_AbstractPointCloudIndex *pointCloudIndex = in_scene->getPointCloudIndex(); size_t n_points = pointCloudIndex->size(); size_t cpt = 0; QList points; CT_PointIterator itScene(in_scene->getPointCloudIndex()); while(itScene.hasNext() && (!isStopped())) { const CT_Point &point = itScene.next().currentPoint(); size_t index = itScene.currentGlobalIndex(); points.append(new PointData(index, point(0), point(1), point(2))); setProgress(40.0*cpt++/n_points + 10.0); } setProgress(40.0); qSort(points.begin(), points.end(), ONF_StepSegmentCrownsFromStemClusters::lessThan); setProgress(50.0); cpt = 0; for (int pi = 0 ; pi < points.size() ; pi++) { PointData* ptData = points.at(pi); bool alreadyExist = false; StemData* closestStem = NULL; double smallestDist = std::numeric_limits::max(); for (int i = 0 ; i < stems.size() && !alreadyExist; i++) { StemData* stem = stems.at(i); if (ptData->_z >= stem->maxZ()) { double dist = stem->getDistance(ptData , alreadyExist); if (dist < smallestDist && dist < _distMax) { smallestDist = dist; closestStem = stem; } } } if (closestStem == NULL) { delete ptData; } else { closestStem->addPoint(ptData); } setProgress(30.0*cpt++/n_points + 50.0); } points.clear(); for (int i = 0 ; i < stems.size() ; i++) { StemData* stem = stems.at(i); if (stem->size() > 0) { CT_PointCluster *outCluster = new CT_PointCluster(_outScene_ModelName.completeName(), res); for (int j = 0 ; j < stem->size() ; j++) { outCluster->addPoint(stem->_points.at(j)->_index); } // creation et ajout de la scene outCluster->addItemAttribute(new CT_StdItemAttributeT(_outAttZmax_ModelName.completeName(), CT_AbstractCategory::DATA_Z, res, stem->maxZ())); stem->_group->addItemDrawable(outCluster); } delete stem; } setProgress(99); } } setProgress(100); }