/**************************************************************************** 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 "opencv2/imgproc/imgproc.hpp" #include "opencv2/core/core.hpp" ONF_StepSegmentCrownsFromStemClusters::ONF_StepSegmentCrownsFromStemClusters() : SuperClass() { _distMax = 1.0; } QString ONF_StepSegmentCrownsFromStemClusters::description() const { return tr("Segmenter des houppiers à partir de Clusters tiges"); } QString ONF_StepSegmentCrownsFromStemClusters::detailledDescription() const { return tr(""); } QString ONF_StepSegmentCrownsFromStemClusters::inputDescription() const { return SuperClass::inputDescription() + tr("

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

"); } QString ONF_StepSegmentCrownsFromStemClusters::detailsDescription() const { return tr(""); } QString ONF_StepSegmentCrownsFromStemClusters::URL() const { //return tr("STEP URL HERE"); return SuperClass::URL(); //by default URL of the plugin } CT_VirtualAbstractStep* ONF_StepSegmentCrownsFromStemClusters::createNewInstance() const { return new ONF_StepSegmentCrownsFromStemClusters(); } //////////////////// PROTECTED METHODS ////////////////// void ONF_StepSegmentCrownsFromStemClusters::declareInputModels(CT_StepInModelStructureManager& manager) { manager.addResult(_inResult, tr("Tiges détéctées")); manager.setZeroOrMoreRootGroup(_inResult, _inZeroOrMoreRootGroup); manager.addGroup(_inZeroOrMoreRootGroup, _inGroup); manager.addItem(_inGroup, _inScene, tr("Scène complète")); manager.addGroup(_inGroup, _inGroupStem); manager.addItem(_inGroupStem, _inStem, tr("Tige")); } void ONF_StepSegmentCrownsFromStemClusters::declareOutputModels(CT_StepOutModelStructureManager& manager) { manager.addResultCopy(_inResult); manager.addItem(_inGroupStem, _outCluster, tr("Cluster segmenté")); manager.addItemAttribute(_outCluster, _outAtt, PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_Z), tr("Zmax")); } void ONF_StepSegmentCrownsFromStemClusters::fillPostInputConfigurationDialog(CT_StepConfigurableDialog* postInputConfigDialog) { postInputConfigDialog->addDouble(tr("Distance Max"), "m", 0.01, 9999, 2, _distMax); } void ONF_StepSegmentCrownsFromStemClusters::compute() { setProgress(1); for (CT_StandardItemGroup* group : _inGroup.iterateOutputs(_inResult)) { if (isStopped()) {return;} const CT_AbstractItemDrawableWithPointCloud* inScene = group->singularItem(_inScene); if (inScene != nullptr) { // List of stems QList stems; for (const CT_StandardItemGroup* grpPos : group->groups(_inGroupStem)) { const CT_PointCluster *cluster = group->singularItem(_inStem); if (cluster != nullptr) { StemData* stem = new StemData(const_cast(grpPos), _distMax); CT_PointIterator itP(cluster->pointCloudIndex()); 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 = inScene->pointCloudIndex(); size_t n_points = pointCloudIndex->size(); size_t cpt = 0; QList points; CT_PointIterator itScene(inScene->pointCloudIndex()); 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.0f*cpt++/n_points + 10.0f); } setProgress(40.0); std::sort(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 = nullptr; 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 == nullptr) { delete ptData; } else { closestStem->addPoint(ptData); } setProgress(30.0f*cpt++/n_points + 50.0f); } 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(); for (int j = 0 ; j < stem->size() ; j++) { outCluster->addPoint(stem->_points.at(j)->_index); } stem->_group->addSingularItem(_outCluster, outCluster); // creation et ajout de la scene outCluster->addItemAttribute(_outAtt, new CT_StdItemAttributeT(CT_AbstractCategory::DATA_Z, stem->maxZ())); } delete stem; } setProgress(99); } } setProgress(100); }