/**************************************************************************** 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_stepcomputeboundaryv2.h" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/imgproc/types_c.h" #include "opencv2/core/core.hpp" #include #include ONF_StepComputeBoundaryV2::ONF_StepComputeBoundaryV2() : SuperClass() { _res = 10.0; _outRaster = nullptr; } QString ONF_StepComputeBoundaryV2::description() const { return tr("Calcul d'un raster d'emprise"); } QString ONF_StepComputeBoundaryV2::detailledDescription() const { return tr("Calcul d'un raster logique, avec une valeur 1 pour toute cellule contenant au moins un point." "L'étape peut fonctionner dans une boucle, en fournissant les emprises calculées pour toute la zone en entrée." "Un seul raster sur l'emprise totale sera créé. "); } QString ONF_StepComputeBoundaryV2::inputDescription() const { return SuperClass::inputDescription() + tr("

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

"); } QString ONF_StepComputeBoundaryV2::detailsDescription() const { return tr(""); } QString ONF_StepComputeBoundaryV2::URL() const { //return tr("STEP URL HERE"); return SuperClass::URL(); //by default URL of the plugin } CT_VirtualAbstractStep* ONF_StepComputeBoundaryV2::createNewInstance() const { return new ONF_StepComputeBoundaryV2(); } //////////////////// PROTECTED METHODS ////////////////// void ONF_StepComputeBoundaryV2::declareInputModels(CT_StepInModelStructureManager& manager) { manager.addResult(_inRfootprint, tr("Emprise totale (toutes les dalles)"), "", true); manager.setZeroOrMoreRootGroup(_inRfootprint, _inZeroOrMoreRootGroupFootprint); manager.addGroup(_inZeroOrMoreRootGroupFootprint, _inGrpfootprint); manager.addItem(_inGrpfootprint, _inFootprint, tr("Emprise")); manager.addResult(_inRscene, tr("Scène(s)")); manager.setZeroOrMoreRootGroup(_inRscene, _inZeroOrMoreRootGroupScene); manager.addGroup(_inZeroOrMoreRootGroupScene, _inGrpsc); manager.addItem(_inGrpsc, _inScene, tr("Scène(s)")); manager.addResult(_inResultCounter, tr("Résultat compteur"), "", true); manager.setZeroOrMoreRootGroup(_inResultCounter, _inZeroOrMoreRootGroupCounter); manager.addItem(_inZeroOrMoreRootGroupCounter, _inCounter, tr("Compteur")); } void ONF_StepComputeBoundaryV2::declareOutputModels(CT_StepOutModelStructureManager& manager) { manager.addResultCopy(_inRfootprint); manager.addResult(_outResult, tr("Emprise calculée")); manager.setRootGroup(_outResult, _outRootGroup); manager.addItem(_outRootGroup, _outFootprintRaster, tr("Raster d'emprise")); } void ONF_StepComputeBoundaryV2::fillPostInputConfigurationDialog(CT_StepConfigurableDialog* postInputConfigDialog) { postInputConfigDialog->addDouble(tr("Résolution"), "m", 0.1, 10000, 1, _res); } void ONF_StepComputeBoundaryV2::compute() { bool last_turn = true; bool first_turn = true; // use only first turn for (const CT_LoopCounter* counter : _inCounter.iterateInputs(_inResultCounter)) { if (counter->currentTurn() > 1) { first_turn = false; } if (counter->currentTurn() != counter->nTurns()) { last_turn = false; } if (counter != nullptr) {break;} } if (first_turn) { _outRaster = nullptr; // Compute cumulated Bounding Box double xmin = std::numeric_limits::max(); double xmax = -std::numeric_limits::max(); double ymin = std::numeric_limits::max(); double ymax = -std::numeric_limits::max(); for (const CT_AbstractGeometricalItem* item : _inFootprint.iterateInputs(_inRfootprint)) { if (isStopped()) {return;} if (item->hasBoundingBox()) { Eigen::Vector3d min, max; item->boundingBox(min, max); if (min(0) < xmin) {xmin = min(0);} if (min(1) < ymin) {ymin = min(1);} if (max(0) > xmax) {xmax = max(0);} if (max(1) > ymax) {ymax = max(1);} } } if (xmin < std::numeric_limits::max() && xmax > -std::numeric_limits::max() && ymin < std::numeric_limits::max() && ymax > -std::numeric_limits::max()) { // Obtain reguar coordinates (multiples of _res) double xmin2 = std::floor(xmin / _res) * _res - 2.0*_res; double ymin2 = std::floor(ymin / _res) * _res - 2.0*_res; double xmax2 = xmin2; double ymax2 = ymin2; while (xmax2 < xmax) {xmax2 += _res;} while (ymax2 < ymax) {ymax2 += _res;} xmax2 += 2.0*_res; ymax2 += 2.0*_res; _outRaster = CT_Image2D::createImage2DFromXYCoords(xmin2, ymin2, xmax2, ymax2, _res, 0, 0, 0); } } if (_outRaster != nullptr) { // parcours des scènes pour calculer l'enveloppe for (const CT_AbstractItemDrawableWithPointCloud* scene : _inScene.iterateInputs(_inRscene)) { if (isStopped()) {return;} // création de la liste complète des points CT_PointIterator itP(scene->pointCloudIndex()); while(itP.hasNext() && (!isStopped())) { const CT_Point &point = itP.next().currentPoint(); _outRaster->setValueAtCoords(point(0), point(1), 1); } } if (last_turn) { for(CT_ResultGroup* result : _outResult.iterateOutputs()) { CT_StandardItemGroup* outGrp = new CT_StandardItemGroup(); result->addRootGroup(_outRootGroup, outGrp); outGrp->addSingularItem(_outFootprintRaster, _outRaster); } } } }