ccUnrollDlg.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. //##########################################################################
  2. //# #
  3. //# CLOUDCOMPARE #
  4. //# #
  5. //# This program is free software; you can redistribute it and/or modify #
  6. //# it under the terms of the GNU General Public License as published by #
  7. //# the Free Software Foundation; version 2 or later of the License. #
  8. //# #
  9. //# This program is distributed in the hope that it will be useful, #
  10. //# but WITHOUT ANY WARRANTY; without even the implied warranty of #
  11. //# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
  12. //# GNU General Public License for more details. #
  13. //# #
  14. //# COPYRIGHT: EDF R&D / TELECOM ParisTech (ENST-TSI) #
  15. //# #
  16. //##########################################################################
  17. #include "ccUnrollDlg.h"
  18. #include "ui_unrollDlg.h"
  19. #include "ccEntitySelectionDlg.h"
  20. #include "ccUtils.h"
  21. //qCC_db
  22. #include <ccCylinder.h>
  23. //Qt
  24. #include <QSettings>
  25. //semi-persistent settings
  26. static double s_startAngle_deg = 0.0;
  27. static double s_stopAngle_deg = 360.0;
  28. static bool s_arbitraryOutputCS = false;
  29. ccUnrollDlg::ccUnrollDlg(ccHObject* dbRootEntity, QWidget* parent/*=nullptr*/)
  30. : QDialog(parent)
  31. , m_ui( new Ui::UnrollDialog )
  32. , m_dbRootEntity(dbRootEntity)
  33. {
  34. m_ui->setupUi(this);
  35. connect(m_ui->checkBoxAuto, &QCheckBox::stateChanged, this, &ccUnrollDlg::axisAutoStateChanged);
  36. connect(m_ui->comboBoxUnrollShapeType, qOverload<int>(&QComboBox::currentIndexChanged), this, &ccUnrollDlg::shapeTypeChanged);
  37. connect(m_ui->comboBoxProjectionType, qOverload<int>(&QComboBox::currentIndexChanged), this, &ccUnrollDlg::projectionTypeChanged);
  38. connect(m_ui->comboBoxAxisDimension, qOverload<int>(&QComboBox::currentIndexChanged), this, &ccUnrollDlg::axisDimensionChanged);
  39. connect(m_ui->flipxAxisToolButton, &QToolButton::clicked, [this] { m_ui->axisXDoubleSpinBox->setValue(-m_ui->axisXDoubleSpinBox->value());
  40. m_ui->axisYDoubleSpinBox->setValue(-m_ui->axisYDoubleSpinBox->value());
  41. m_ui->axisZDoubleSpinBox->setValue(-m_ui->axisZDoubleSpinBox->value());
  42. });
  43. connect(m_ui->fromEntityToolButton, &QToolButton::clicked, this, &ccUnrollDlg::loadParametersFromEntity);
  44. connect(m_ui->pasteAxisToolButton, &QToolButton::clicked, this, &ccUnrollDlg::axisFromClipboard);
  45. connect(m_ui->pasteCenterToolButton, &QToolButton::clicked, this, &ccUnrollDlg::centerFromClipboard);
  46. m_ui->checkBoxAuto->setChecked(true);
  47. shapeTypeChanged(m_ui->comboBoxUnrollShapeType->currentIndex());
  48. axisDimensionChanged(m_ui->comboBoxAxisDimension->currentIndex());
  49. if (!m_dbRootEntity)
  50. {
  51. assert(false);
  52. m_ui->fromEntityToolButton->setVisible(false);
  53. }
  54. }
  55. ccUnrollDlg::~ccUnrollDlg()
  56. {
  57. delete m_ui;
  58. }
  59. ccPointCloud::UnrollMode ccUnrollDlg::getType() const
  60. {
  61. switch (m_ui->comboBoxUnrollShapeType->currentIndex())
  62. {
  63. case 0:
  64. return ccPointCloud::CYLINDER;
  65. case 1:
  66. switch (m_ui->comboBoxProjectionType->currentIndex())
  67. {
  68. case 0:
  69. return ccPointCloud::CONE_CONICAL;
  70. case 1:
  71. return ccPointCloud::CONE_CYLINDRICAL_FIXED_RADIUS;
  72. case 2:
  73. return ccPointCloud::CONE_CYLINDRICAL_ADAPTIVE_RADIUS;
  74. default:
  75. assert(false);
  76. break;
  77. }
  78. break;
  79. default:
  80. assert(false);
  81. break;
  82. }
  83. assert(false);
  84. return ccPointCloud::CYLINDER;
  85. }
  86. CCVector3d ccUnrollDlg::getAxis() const
  87. {
  88. int axisDim = m_ui->comboBoxAxisDimension->currentIndex();
  89. switch (axisDim)
  90. {
  91. case 0:
  92. return CCVector3d(1.0, 0.0, 0.0);
  93. break;
  94. case 1:
  95. return CCVector3d(0.0, 1.0, 0.0);
  96. break;
  97. case 2:
  98. return CCVector3d(0.0, 0.0, 1.0);
  99. break;
  100. case 3:
  101. default:
  102. return CCVector3d(m_ui->axisXDoubleSpinBox->value(), m_ui->axisYDoubleSpinBox->value(), m_ui->axisZDoubleSpinBox->value());
  103. }
  104. return {};
  105. }
  106. bool ccUnrollDlg::isAxisPositionAuto() const
  107. {
  108. return m_ui->checkBoxAuto->isChecked();
  109. }
  110. bool ccUnrollDlg::useArbitraryOutputCS() const
  111. {
  112. return m_ui->arbitraryCSCheckBox->isChecked();
  113. }
  114. void ccUnrollDlg::getAngleRange(double& start_deg, double& stop_deg) const
  115. {
  116. start_deg = m_ui->startAngleDoubleSpinBox->value();
  117. stop_deg = m_ui->stopAngleDoubleSpinBox->value();
  118. }
  119. CCVector3 ccUnrollDlg::getAxisPosition() const
  120. {
  121. return CCVector3( static_cast<PointCoordinateType>(m_ui->axisCenterXDoubleSpinBox->value()),
  122. static_cast<PointCoordinateType>(m_ui->axisCenterYDoubleSpinBox->value()),
  123. static_cast<PointCoordinateType>(m_ui->axisCenterZDoubleSpinBox->value()));
  124. }
  125. double ccUnrollDlg::getRadius() const
  126. {
  127. return m_ui->radiusDoubleSpinBox->value();
  128. }
  129. double ccUnrollDlg::getConeHalfAngle() const
  130. {
  131. return m_ui->halfAngleDoubleSpinBox->value();
  132. }
  133. double ccUnrollDlg::getConicalProjSpanRatio() const
  134. {
  135. return m_ui->conicalProjSpanRatioDoubleSpinBox->value();
  136. }
  137. bool ccUnrollDlg::exportDeviationSF() const
  138. {
  139. return m_ui->exportDeviationSFCheckBox->isChecked();
  140. }
  141. void ccUnrollDlg::shapeTypeChanged(int index)
  142. {
  143. switch (index)
  144. {
  145. case 0: //cylinder
  146. {
  147. m_ui->conicalProjectionFrame->setVisible(false);
  148. m_ui->angleFrame->setVisible(false);
  149. m_ui->autoCenterFrame->setVisible(true);
  150. m_ui->radiusFrame->setVisible(true);
  151. m_ui->axisPositionGroupBox->setTitle("Axis position");
  152. m_ui->radiusLabel->setText("Radius");
  153. axisAutoStateChanged(m_ui->checkBoxAuto->checkState());
  154. }
  155. break;
  156. case 1: //cone
  157. {
  158. m_ui->conicalProjectionFrame->setVisible(true);
  159. m_ui->angleFrame->setVisible(true);
  160. m_ui->autoCenterFrame->setVisible(false);
  161. //m_ui->radiusFrame->setVisible(false); // will depend on the projection type
  162. m_ui->radiusLabel->setText("Fixed radius");
  163. m_ui->axisPositionGroupBox->setTitle("Cone apex");
  164. axisAutoStateChanged(Qt::Unchecked);
  165. //may be disabled if we were in cylinder mode previously
  166. m_ui->axisCenterXDoubleSpinBox->setDisabled(false);
  167. m_ui->axisCenterYDoubleSpinBox->setDisabled(false);
  168. m_ui->axisCenterZDoubleSpinBox->setDisabled(false);
  169. projectionTypeChanged(m_ui->comboBoxProjectionType->currentIndex());
  170. }
  171. break;
  172. default:
  173. {
  174. assert(false);
  175. }
  176. break;
  177. };
  178. }
  179. void ccUnrollDlg::projectionTypeChanged(int index)
  180. {
  181. switch (index)
  182. {
  183. case 0: //conical
  184. {
  185. m_ui->spanRatioFrame->setVisible(true);
  186. m_ui->radiusFrame->setVisible(false);
  187. }
  188. break;
  189. case 1: //cylindrical (fixed radius)
  190. {
  191. m_ui->spanRatioFrame->setVisible(false);
  192. m_ui->radiusFrame->setVisible(true); // for fixed radius only
  193. m_ui->radiusLabel->setText("Fixed radius");
  194. }
  195. break;
  196. case 2: //cylindrical (adaptive radius)
  197. {
  198. m_ui->spanRatioFrame->setVisible(false);
  199. m_ui->radiusFrame->setVisible(false);
  200. }
  201. break;
  202. };
  203. }
  204. void ccUnrollDlg::axisAutoStateChanged(int checkState)
  205. {
  206. if (checkState == Qt::Unchecked)
  207. {
  208. m_ui->axisCenterFrame->setEnabled(true);
  209. axisDimensionChanged(m_ui->comboBoxAxisDimension->currentIndex());
  210. }
  211. else
  212. {
  213. m_ui->axisCenterFrame->setEnabled(false);
  214. }
  215. }
  216. void ccUnrollDlg::axisDimensionChanged(int index)
  217. {
  218. m_ui->axisFrame->setEnabled(index == 3);
  219. if ( (m_ui->comboBoxUnrollShapeType->currentIndex() == 0)
  220. && (m_ui->checkBoxAuto->checkState() != Qt::Checked) )
  221. {
  222. //in 'cylinder' mode, we hide the axis coordinate that is not needed
  223. m_ui->axisCenterXDoubleSpinBox->setDisabled(index == 0);
  224. m_ui->axisCenterYDoubleSpinBox->setDisabled(index == 1);
  225. m_ui->axisCenterZDoubleSpinBox->setDisabled(index == 2);
  226. }
  227. }
  228. void ccUnrollDlg::toPersistentSettings() const
  229. {
  230. QSettings settings;
  231. settings.beginGroup("Unroll");
  232. {
  233. settings.setValue("shapeType", m_ui->comboBoxUnrollShapeType->currentIndex());
  234. settings.setValue("projectionType", m_ui->comboBoxProjectionType->currentIndex());
  235. settings.setValue("spanRatio", m_ui->conicalProjSpanRatioDoubleSpinBox->value());
  236. settings.setValue("axisDimension", m_ui->comboBoxAxisDimension->currentIndex());
  237. settings.setValue("angle", m_ui->halfAngleDoubleSpinBox->value());
  238. settings.setValue("radius", m_ui->radiusDoubleSpinBox->value());
  239. settings.setValue("autoCenter", m_ui->checkBoxAuto->isChecked());
  240. settings.setValue("exportDeviationSF", m_ui->exportDeviationSFCheckBox->isChecked());
  241. settings.setValue("axis.x", m_ui->axisXDoubleSpinBox->value());
  242. settings.setValue("axis.y", m_ui->axisYDoubleSpinBox->value());
  243. settings.setValue("axis.z", m_ui->axisZDoubleSpinBox->value());
  244. settings.setValue("axisCenter.x", m_ui->axisCenterXDoubleSpinBox->value());
  245. settings.setValue("axisCenter.y", m_ui->axisCenterYDoubleSpinBox->value());
  246. settings.setValue("axisCenter.z", m_ui->axisCenterZDoubleSpinBox->value());
  247. getAngleRange(s_startAngle_deg, s_stopAngle_deg);
  248. s_arbitraryOutputCS = useArbitraryOutputCS();
  249. }
  250. settings.endGroup();
  251. }
  252. void ccUnrollDlg::fromPersistentSettings()
  253. {
  254. QSettings settings;
  255. settings.beginGroup("Unroll");
  256. {
  257. int shapeType = settings.value("shapeType", m_ui->comboBoxUnrollShapeType->currentIndex()).toInt();
  258. int projectionType = settings.value("projectionType", -1).toInt();
  259. int axisDim = settings.value("axisDimension", m_ui->comboBoxAxisDimension->currentIndex()).toInt();
  260. double angle = settings.value("angle", m_ui->halfAngleDoubleSpinBox->value()).toDouble();
  261. double radius = settings.value("radius", m_ui->radiusDoubleSpinBox->value()).toDouble();
  262. bool autoCenter = settings.value("autoCenter", m_ui->checkBoxAuto->isChecked()).toBool();
  263. bool exportDeviationSF = settings.value("exportDeviationSF", m_ui->exportDeviationSFCheckBox->isChecked()).toBool();
  264. bool spanRatio = settings.value("spanRatio", m_ui->conicalProjSpanRatioDoubleSpinBox->value()).toDouble();
  265. // compatibility with older versions
  266. if (projectionType < 0 || shapeType > 1)
  267. {
  268. if (shapeType == ccPointCloud::CONE_CONICAL)
  269. {
  270. shapeType = 1;
  271. projectionType = 0;
  272. }
  273. else if (shapeType == ccPointCloud::CONE_CYLINDRICAL_FIXED_RADIUS)
  274. {
  275. shapeType = 1;
  276. projectionType = 1;
  277. }
  278. else if (shapeType == ccPointCloud::CONE_CYLINDRICAL_ADAPTIVE_RADIUS)
  279. {
  280. shapeType = 1;
  281. projectionType = 2;
  282. }
  283. }
  284. CCVector3d axis;
  285. axis.x = settings.value("axis.x", m_ui->axisXDoubleSpinBox->value()).toDouble();
  286. axis.y = settings.value("axis.y", m_ui->axisYDoubleSpinBox->value()).toDouble();
  287. axis.z = settings.value("axis.z", m_ui->axisZDoubleSpinBox->value()).toDouble();
  288. CCVector3d axisCenter;
  289. axisCenter.x = settings.value("axisCenter.x", m_ui->axisCenterXDoubleSpinBox->value()).toDouble();
  290. axisCenter.y = settings.value("axisCenter.y", m_ui->axisCenterYDoubleSpinBox->value()).toDouble();
  291. axisCenter.z = settings.value("axisCenter.z", m_ui->axisCenterZDoubleSpinBox->value()).toDouble();
  292. m_ui->comboBoxUnrollShapeType->setCurrentIndex(shapeType);
  293. m_ui->comboBoxProjectionType->setCurrentIndex(projectionType);
  294. m_ui->conicalProjSpanRatioDoubleSpinBox->setValue(spanRatio);
  295. m_ui->comboBoxAxisDimension->setCurrentIndex(axisDim);
  296. m_ui->halfAngleDoubleSpinBox->setValue(angle);
  297. m_ui->radiusDoubleSpinBox->setValue(radius);
  298. m_ui->checkBoxAuto->setChecked(autoCenter);
  299. m_ui->exportDeviationSFCheckBox->setChecked(exportDeviationSF);
  300. m_ui->axisXDoubleSpinBox->setValue(axis.x);
  301. m_ui->axisYDoubleSpinBox->setValue(axis.y);
  302. m_ui->axisZDoubleSpinBox->setValue(axis.z);
  303. m_ui->axisCenterXDoubleSpinBox->setValue(axisCenter.x);
  304. m_ui->axisCenterYDoubleSpinBox->setValue(axisCenter.y);
  305. m_ui->axisCenterZDoubleSpinBox->setValue(axisCenter.z);
  306. m_ui->startAngleDoubleSpinBox->setValue(s_startAngle_deg);
  307. m_ui->stopAngleDoubleSpinBox ->setValue(s_stopAngle_deg);
  308. m_ui->arbitraryCSCheckBox->setChecked(s_arbitraryOutputCS);
  309. }
  310. settings.endGroup();
  311. }
  312. void ccUnrollDlg::loadParametersFromEntity()
  313. {
  314. if (!m_dbRootEntity)
  315. {
  316. assert(false);
  317. return;
  318. }
  319. if (m_ui->comboBoxUnrollShapeType->currentIndex() == 0) // Cylinder
  320. {
  321. ccHObject::Container cylinders;
  322. m_dbRootEntity->filterChildren(cylinders, true, CC_TYPES::CYLINDER, false);
  323. if (cylinders.empty())
  324. {
  325. ccLog::Error("No cylinder in DB");
  326. return;
  327. }
  328. int selectedIndex = ccEntitySelectionDialog::SelectEntity(cylinders, -1, this, tr("Select a cylinder entity"));
  329. if (selectedIndex < 0)
  330. {
  331. //process cancelled by the user
  332. return;
  333. }
  334. const ccCylinder* cylinder = static_cast<const ccCylinder*>(cylinders[selectedIndex]);
  335. CCVector3 axis = cylinder->getTransformation().getColumnAsVec3D(2); // Z axis is the cylinder axis
  336. CCVector3 origin = cylinder->getTransformation().getTranslationAsVec3D();
  337. PointCoordinateType radius = cylinder->getBottomRadius();
  338. m_ui->comboBoxAxisDimension->setCurrentIndex(3); // custom
  339. m_ui->axisXDoubleSpinBox->setValue(axis.x);
  340. m_ui->axisYDoubleSpinBox->setValue(axis.y);
  341. m_ui->axisZDoubleSpinBox->setValue(axis.z);
  342. m_ui->axisCenterXDoubleSpinBox->setValue(origin.x);
  343. m_ui->axisCenterYDoubleSpinBox->setValue(origin.y);
  344. m_ui->axisCenterZDoubleSpinBox->setValue(origin.z);
  345. m_ui->radiusDoubleSpinBox->setValue(radius);
  346. m_ui->checkBoxAuto->setChecked(false);
  347. }
  348. else if (m_ui->comboBoxUnrollShapeType->currentIndex() == 1) // Cone
  349. {
  350. ccHObject::Container cones;
  351. m_dbRootEntity->filterChildren(cones, true, CC_TYPES::CONE, false);
  352. if (cones.empty())
  353. {
  354. ccLog::Error("No cone in DB");
  355. return;
  356. }
  357. int selectedIndex = ccEntitySelectionDialog::SelectEntity(cones, -1, this, tr("Select a cone entity"));
  358. if (selectedIndex < 0)
  359. {
  360. //process cancelled by the user
  361. return;
  362. }
  363. const ccCone* cone = static_cast<const ccCone*>(cones[selectedIndex]);
  364. CCVector3 axis = cone->getTransformation().getColumnAsVec3D(2); // Z axis is the cylinder axis
  365. CCVector3 apex = cone->computeApex();
  366. double angle_deg = cone->computeHalfAngle_deg();
  367. PointCoordinateType radius = cone->getLargeRadius();
  368. m_ui->comboBoxAxisDimension->setCurrentIndex(3); // custom
  369. m_ui->axisXDoubleSpinBox->setValue(axis.x);
  370. m_ui->axisYDoubleSpinBox->setValue(axis.y);
  371. m_ui->axisZDoubleSpinBox->setValue(axis.z);
  372. m_ui->axisCenterXDoubleSpinBox->setValue(apex.x);
  373. m_ui->axisCenterYDoubleSpinBox->setValue(apex.y);
  374. m_ui->axisCenterZDoubleSpinBox->setValue(apex.z);
  375. m_ui->radiusDoubleSpinBox->setValue(radius);
  376. m_ui->halfAngleDoubleSpinBox->setValue(angle_deg);
  377. m_ui->checkBoxAuto->setChecked(false);
  378. }
  379. else
  380. {
  381. assert(false);
  382. }
  383. }
  384. void ccUnrollDlg::axisFromClipboard()
  385. {
  386. CCVector3d vector;
  387. if (ccUtils::GetVectorFromClipboard(vector))
  388. {
  389. m_ui->axisXDoubleSpinBox->setValue(vector.x);
  390. m_ui->axisYDoubleSpinBox->setValue(vector.y);
  391. m_ui->axisZDoubleSpinBox->setValue(vector.z);
  392. }
  393. }
  394. void ccUnrollDlg::centerFromClipboard()
  395. {
  396. CCVector3d vector;
  397. if (ccUtils::GetVectorFromClipboard(vector))
  398. {
  399. m_ui->axisCenterXDoubleSpinBox->setValue(vector.x);
  400. m_ui->axisCenterYDoubleSpinBox->setValue(vector.y);
  401. m_ui->axisCenterZDoubleSpinBox->setValue(vector.z);
  402. }
  403. }