//########################################################################## //# # //# CLOUDCOMPARE # //# # //# This program is free software; you can redistribute it and/or modify # //# it under the terms of the GNU General Public License as published by # //# the Free Software Foundation; version 2 or later of the License. # //# # //# This program 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. # //# # //# COPYRIGHT: EDF R&D / TELECOM ParisTech (ENST-TSI) # //# # //########################################################################## #include "ccNormalComputationDlg.h" //qCC_db #include #include #include //Qt #include //system #include ccNormalComputationDlg::ccNormalComputationDlg(bool withScanGrid, bool withSensor, QWidget* parent/*=nullptr*/) : QDialog(parent, Qt::Tool) , Ui::NormalComputationDlg() , m_cloud(nullptr) { setupUi(this); //by default, the 'auto' button is hidden (as long as setCloud is not called) autoRadiusToolButton->setVisible(false); connect(localModelComboBox, qOverload(&QComboBox::currentIndexChanged), this, &ccNormalComputationDlg::localModelChanged); connect(autoRadiusToolButton, &QToolButton::clicked, this, &ccNormalComputationDlg::autoEstimateRadius); if (withScanGrid) { useScanGridCheckBox->setChecked(true); scanGridsOrientCheckBox->setChecked(true); } else { //disable 'scan grid' options useScanGridCheckBox->setChecked(false); useScanGridCheckBox->setEnabled(false); gridAngleFrame->setEnabled(false); scanGridsOrientCheckBox->setChecked(false); scanGridsOrientCheckBox->setEnabled(false); } if (withSensor) { sensorOrientCheckBox->setChecked(true); } else { //disable 'sensor' options sensorOrientCheckBox->setChecked(false); sensorOrientCheckBox->setEnabled(false); } } void ccNormalComputationDlg::setLocalModel(CCCoreLib::LOCAL_MODEL_TYPES model) { int index = -1; switch (model) { case CCCoreLib::LS: index = 0; break; case CCCoreLib::QUADRIC: index = 1; break; case CCCoreLib::TRI: index = 2; break; default: assert(false); break; } localModelComboBox->setCurrentIndex(index); } CCCoreLib::LOCAL_MODEL_TYPES ccNormalComputationDlg::getLocalModel() const { switch (localModelComboBox->currentIndex()) { case 0: return CCCoreLib::LS; case 1: return CCCoreLib::QUADRIC; case 2: return CCCoreLib::TRI; } assert(false); return CCCoreLib::LS; } void ccNormalComputationDlg::localModelChanged(int index) { //DGM: we don't disable the parent frame anymore as it is used by the octree/grid toggling radiusDoubleSpinBox->setEnabled(index != 2); autoRadiusToolButton->setEnabled(index != 2); } void ccNormalComputationDlg::setRadius(PointCoordinateType radius) { radiusDoubleSpinBox->setValue(static_cast(radius)); } void ccNormalComputationDlg::setCloud(ccPointCloud* cloud) { m_cloud = cloud; autoRadiusToolButton->setVisible(m_cloud != nullptr); } PointCoordinateType ccNormalComputationDlg::getRadius() const { return static_cast(radiusDoubleSpinBox->value()); } void ccNormalComputationDlg::setPreferredOrientation(ccNormalVectors::Orientation orientation) { if (orientation == ccNormalVectors::UNDEFINED) { preferredOrientRadioButton->setChecked(false); } else { preferredOrientRadioButton->setChecked(true); preferredOrientationComboBox->setCurrentIndex(orientation); } } bool ccNormalComputationDlg::useScanGridsForComputation() const { return useScanGridCheckBox->isChecked(); } double ccNormalComputationDlg::getMinGridAngle_deg() const { return gridAngleDoubleSpinBox->value(); } void ccNormalComputationDlg::setMinGridAngle_deg(double value) { gridAngleDoubleSpinBox->setValue(value); } bool ccNormalComputationDlg::orientNormals() const { return normalsOrientGroupBox->isChecked(); } void ccNormalComputationDlg::setOrientNormals(bool state) { normalsOrientGroupBox->setChecked(state); } bool ccNormalComputationDlg::useScanGridsForOrientation() const { return scanGridsOrientCheckBox->isChecked(); } bool ccNormalComputationDlg::useSensorsForOrientation() const { return sensorOrientCheckBox->isChecked(); } bool ccNormalComputationDlg::usePreferredOrientation() const { return preferredOrientRadioButton->isChecked(); } bool ccNormalComputationDlg::useMSTOrientation() const { return mstOrientRadioButton->isChecked(); } void ccNormalComputationDlg::setMSTNeighborCount(int n) { mstNeighborsSpinBox->setValue(n); } int ccNormalComputationDlg::getMSTNeighborCount() const { return mstNeighborsSpinBox->value(); } ccNormalVectors::Orientation ccNormalComputationDlg::getPreferredOrientation() const { int index = preferredOrientRadioButton->isChecked() ? preferredOrientationComboBox->currentIndex() : -1; return (index >= 0 && index <= ccNormalVectors::MINUS_SENSOR_ORIGIN ? static_cast(index) : ccNormalVectors::UNDEFINED); } void ccNormalComputationDlg::autoEstimateRadius() { ccOctree::BestRadiusParams params; { params.aimedPopulationPerCell = 16; params.aimedPopulationRange = 4; params.minCellPopulation = 6; params.minAboveMinRatio = 0.97; } PointCoordinateType radius = ccOctree::GuessBestRadiusAutoComputeOctree(m_cloud, params, this); if (radius > 0) { radiusDoubleSpinBox->setValue(radius); } else { ccLog::Error("Failed to estimate the radius"); } }