/**************************************************************************** Copyright (C) 2010-2021 the Office National des Forêts (ONF), France All rights reserved. Contact : alexandre.piboule@onf.fr Developers : Michael Krebbs (Independant) Alexandre PIBOULE (ONF) This file is part of PluginGenerate library. PluginGenerate 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. PluginGenerate 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 PluginGenerate. If not, see . *****************************************************************************/ #include "gen_stepgeneratespherecloud.h" #include #include #include "ct_math/ct_mathpoint.h" #define DEG_TO_RAD 0.01745329251 GEN_StepGenerateSphereCloud::GEN_StepGenerateSphereCloud() : SuperClass() { _botX = 0; _botY = 0; _botZ = 0; _radius = 1; _thetaMin = 0; _thetaMax = 360; _phiMin = 0; _phiMax = 360; _resTheta = 5; _resPhi = 5; _noiseTheta = 0; _noisePhi = 0; _noiseRadius = 0; } QString GEN_StepGenerateSphereCloud::description() const { return tr("Créer une Sphère de points"); } CT_VirtualAbstractStep* GEN_StepGenerateSphereCloud::createNewInstance() const { return new GEN_StepGenerateSphereCloud(); } //////////////////// PROTECTED METHODS ////////////////// void GEN_StepGenerateSphereCloud::declareInputModels(CT_StepInModelStructureManager& manager) { manager.setNotNeedInputResult(); } void GEN_StepGenerateSphereCloud::declareOutputModels(CT_StepOutModelStructureManager& manager) { manager.addResult(m_hOutResult, tr("Generated Point Cloud")); manager.setRootGroup(m_hOutResult, m_hOutRootGroup); manager.addItem(m_hOutRootGroup, m_hOutScene, tr("Generated Sphere Cloud")); } void GEN_StepGenerateSphereCloud::fillPostInputConfigurationDialog(CT_StepConfigurableDialog* postInputConfigDialog) { postInputConfigDialog->addDouble(tr("Radius"), "", -std::numeric_limits::max(), std::numeric_limits::max(), 4, _radius); postInputConfigDialog->addText(tr("Sphere center"), "", ""); postInputConfigDialog->addDouble("X", "", -std::numeric_limits::max(), std::numeric_limits::max(), 4, _botX); postInputConfigDialog->addDouble("Y", "", -std::numeric_limits::max(), std::numeric_limits::max(), 4, _botY); postInputConfigDialog->addDouble("Z", "", -std::numeric_limits::max(), std::numeric_limits::max(), 4, _botZ); postInputConfigDialog->addText(tr("Limits"), "", ""); postInputConfigDialog->addDouble(tr("Minimum theta"), "°", 0, 359.9999, 4, _thetaMin, DEG_TO_RAD); postInputConfigDialog->addDouble(tr("Maximum theta"), "°", 0, 360, 4, _thetaMax, DEG_TO_RAD); postInputConfigDialog->addDouble(tr("Minimum phi"), "°", 0, 179.9999, 4, _phiMin, DEG_TO_RAD); postInputConfigDialog->addDouble(tr("Maximum phi"), "°", 0, 180, 4, _phiMax, DEG_TO_RAD); postInputConfigDialog->addText(tr("Resolution"), "", ""); postInputConfigDialog->addDouble(tr("Theta"), "°", 0.0001, std::numeric_limits::max(), 4, _resTheta, DEG_TO_RAD); postInputConfigDialog->addDouble(tr("Phi"), "°", 0.0001, std::numeric_limits::max(), 4, _resPhi, DEG_TO_RAD); postInputConfigDialog->addText(tr("Add noise"), "", ""); postInputConfigDialog->addDouble(tr("Theta"), "°", 0, std::numeric_limits::max(), 4, _noiseTheta, DEG_TO_RAD); postInputConfigDialog->addDouble(tr("Phi"), "°", 0, std::numeric_limits::max(), 4, _noisePhi, DEG_TO_RAD); postInputConfigDialog->addDouble(tr("Radius"), "", 0, std::numeric_limits::max(), 4, _noiseRadius); } void GEN_StepGenerateSphereCloud::compute() { assert(_thetaMin < _thetaMax); if (_thetaMin >= _thetaMax) {qDebug() << "GEN_StepGenerateSphereCloud::compute" << ", " << "_thetaMin >= _thetaMax";} assert(_phiMin < _phiMax); if (_phiMin >= _phiMax) {qDebug() << "GEN_StepGenerateSphereCloud::compute" << ", " << "_phiMin >= _phiMax";} for(CT_ResultGroup* result : m_hOutResult.iterateOutputs()) { CT_StandardItemGroup* rootGroup = m_hOutRootGroup.createInstance(); result->addRootGroup(m_hOutRootGroup, rootGroup); // On initialise l'aleatoire pour le bruit par la suite srand(uint(time(nullptr))); int nbPts = 0; int nbPtsTheta = int(ceil((_thetaMax - _thetaMin) / _resTheta)); int nbPtsPhi = int(ceil((_phiMax - _phiMin) / _resPhi)); int nbPtsTotal = nbPtsPhi * nbPtsTheta; CT_AbstractUndefinedSizePointCloud *undepositPointCloud = PS_REPOSITORY->createNewUndefinedSizePointCloud(); // Construction du cote du cylindre double valTheta, valPhi, valRadius; for (double i = _thetaMin ; (i < _thetaMax) && !isStopped() ; i += _resTheta) { for (double j = _phiMin ; (j <= _phiMax) && !isStopped() ; j += _resPhi) { // On ajoute un point en tenant compte de la variabilité en epsilone valTheta = i - _noiseTheta + ((double(rand())/RAND_MAX) * 2 * _noiseTheta); valPhi = j - _noisePhi + ((double(rand())/RAND_MAX) * 2 * _noisePhi); valRadius = _radius - _noiseRadius + ((double(rand())/RAND_MAX) * 2 * _noiseRadius); undepositPointCloud->addPoint(Eigen::Vector3d(_botX + (valRadius * sin(valPhi) * cos(valTheta)), _botY + (valRadius * sin(valPhi) * sin(valTheta)), _botZ + (valRadius * cos(valPhi)))); nbPts++; // Barre de progression (multiplie par 100/6 parce qu'on a huit face et qu'on est a la premiere setProgress(float(nbPts) * 100.0f / float(nbPtsTotal)); // On regarde si on est en debug mode waitForAckIfInDebugMode(); } } // On enregistre le nuage de points cree dans le depot CT_NMPCIR depositPointCloud = PS_REPOSITORY->registerUndefinedSizePointCloud(undepositPointCloud); if(!isStopped()) { CT_Scene* itemOut_scene = new CT_Scene(depositPointCloud); itemOut_scene->updateBoundingBox(); rootGroup->addSingularItem(m_hOutScene, itemOut_scene); } } }