ccPlaneEditDlg.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  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: SAGE INGENIERIE #
  15. //# #
  16. //##########################################################################
  17. #include "ccPlaneEditDlg.h"
  18. //local
  19. #include "mainwindow.h"
  20. //common
  21. #include <ccPickingHub.h>
  22. //qCC_db
  23. #include <ccPlane.h>
  24. #include <ccNormalVectors.h>
  25. //Qt
  26. #include <QDoubleValidator>
  27. //semi-persistent parameters
  28. static double s_dip = 0;
  29. static double s_dipDir = 0;
  30. static double s_width = 10.0;
  31. static double s_height = 10.0;
  32. static bool s_upward = true;
  33. static CCVector3d s_center(0, 0, 0);
  34. ccPlaneEditDlg::ccPlaneEditDlg(ccPickingHub* pickingHub, QWidget* parent)
  35. : QDialog(parent)
  36. , Ui::PlaneEditDlg()
  37. , m_pickingWin(nullptr)
  38. , m_associatedPlane(nullptr)
  39. , m_pickingHub(pickingHub)
  40. {
  41. assert(pickingHub);
  42. setModal(false);
  43. setupUi(this);
  44. //restore semi-persistent parameters
  45. dipDoubleSpinBox->setValue(s_dip);
  46. dipDirDoubleSpinBox->setValue(s_dipDir);
  47. upwardCheckBox->setChecked(s_upward);
  48. onDipDirChanged(0); //0 = fake argument
  49. wDoubleSpinBox->setValue(s_width);
  50. hDoubleSpinBox->setValue(s_height);
  51. cxAxisDoubleSpinBox->setValue(s_center.x);
  52. cyAxisDoubleSpinBox->setValue(s_center.y);
  53. czAxisDoubleSpinBox->setValue(s_center.z);
  54. connect(pickCenterToolButton, &QCheckBox::toggled, this, &ccPlaneEditDlg::pickPointAsCenter);
  55. connect(upwardCheckBox, &QCheckBox::toggled, this, &ccPlaneEditDlg::onDipDirModified);
  56. connect(dipDoubleSpinBox, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &ccPlaneEditDlg::onDipDirChanged);
  57. connect(dipDirDoubleSpinBox, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &ccPlaneEditDlg::onDipDirChanged);
  58. connect(nxDoubleSpinBox, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &ccPlaneEditDlg::onNormalChanged);
  59. connect(nyDoubleSpinBox, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &ccPlaneEditDlg::onNormalChanged);
  60. connect(nzDoubleSpinBox, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &ccPlaneEditDlg::onNormalChanged);
  61. connect(buttonBox, &QDialogButtonBox::accepted, this, &ccPlaneEditDlg::saveParamsAndAccept);
  62. connect(buttonBox, &QDialogButtonBox::rejected, this, &ccPlaneEditDlg::deleteLater);
  63. //auto disable picking mode on quit
  64. connect(this, &QDialog::finished, [&]()
  65. {
  66. if (pickCenterToolButton->isChecked()) pickCenterToolButton->setChecked(false); }
  67. );
  68. }
  69. ccPlaneEditDlg::~ccPlaneEditDlg()
  70. {
  71. assert(!pickCenterToolButton->isChecked());
  72. }
  73. void ccPlaneEditDlg::saveParamsAndAccept()
  74. {
  75. //save semi-persistent parameters
  76. if (!m_associatedPlane)
  77. {
  78. s_dip = dipDoubleSpinBox->value();
  79. s_dipDir = dipDirDoubleSpinBox->value();
  80. s_upward = upwardCheckBox->isChecked();
  81. s_width = wDoubleSpinBox->value();
  82. s_height = hDoubleSpinBox->value();
  83. s_center.x = cxAxisDoubleSpinBox->value();
  84. s_center.y = cyAxisDoubleSpinBox->value();
  85. s_center.z = czAxisDoubleSpinBox->value();
  86. }
  87. //edition mode
  88. if (m_associatedPlane)
  89. {
  90. updatePlane(m_associatedPlane);
  91. if (MainWindow::TheInstance())
  92. MainWindow::TheInstance()->updatePropertiesView();
  93. m_associatedPlane->redrawDisplay();
  94. }
  95. else //creation
  96. {
  97. PointCoordinateType width = static_cast<PointCoordinateType>(wDoubleSpinBox->value());
  98. PointCoordinateType height = static_cast<PointCoordinateType>(hDoubleSpinBox->value());
  99. ccPlane* plane = new ccPlane(width, height);
  100. updatePlane(plane);
  101. if (m_pickingWin)
  102. {
  103. plane->setDisplay(m_pickingWin);
  104. }
  105. if (MainWindow::TheInstance())
  106. {
  107. MainWindow::TheInstance()->addToDB(plane);
  108. }
  109. else
  110. {
  111. delete plane;
  112. plane = nullptr;
  113. }
  114. }
  115. accept();
  116. deleteLater();
  117. }
  118. void ccPlaneEditDlg::onDipDirModified(bool)
  119. {
  120. onDipDirChanged(0); //0 = fake argument
  121. }
  122. void ccPlaneEditDlg::onDipDirChanged(double)
  123. {
  124. double dip = dipDoubleSpinBox->value();
  125. double dipDir = dipDirDoubleSpinBox->value();
  126. bool upward = upwardCheckBox->isChecked();
  127. CCVector3 Nd = ccNormalVectors::ConvertDipAndDipDirToNormal(static_cast<PointCoordinateType>(dip), static_cast<PointCoordinateType>(dipDir), upward);
  128. nxDoubleSpinBox->blockSignals(true);
  129. nyDoubleSpinBox->blockSignals(true);
  130. nzDoubleSpinBox->blockSignals(true);
  131. nxDoubleSpinBox->setValue(Nd.x);
  132. nyDoubleSpinBox->setValue(Nd.y);
  133. nzDoubleSpinBox->setValue(Nd.z);
  134. nxDoubleSpinBox->blockSignals(false);
  135. nyDoubleSpinBox->blockSignals(false);
  136. nzDoubleSpinBox->blockSignals(false);
  137. }
  138. void ccPlaneEditDlg::onNormalChanged(double)
  139. {
  140. CCVector3 Nd;
  141. Nd.x = nxDoubleSpinBox->value();
  142. Nd.y = nyDoubleSpinBox->value();
  143. Nd.z = nzDoubleSpinBox->value();
  144. Nd.normalize();
  145. PointCoordinateType dip = 0;
  146. PointCoordinateType dipDir = 0;
  147. ccNormalVectors::ConvertNormalToDipAndDipDir(Nd, dip, dipDir);
  148. dipDoubleSpinBox->blockSignals(true);
  149. dipDirDoubleSpinBox->blockSignals(true);
  150. upwardCheckBox->blockSignals(true);
  151. dipDoubleSpinBox->setValue(dip);
  152. dipDirDoubleSpinBox->setValue(dipDir);
  153. upwardCheckBox->setChecked(Nd.z >= 0);
  154. dipDoubleSpinBox->blockSignals(false);
  155. dipDirDoubleSpinBox->blockSignals(false);
  156. upwardCheckBox->blockSignals(false);
  157. }
  158. void ccPlaneEditDlg::pickPointAsCenter(bool state)
  159. {
  160. if (!m_pickingHub)
  161. {
  162. return;
  163. }
  164. if (state)
  165. {
  166. if (!m_pickingHub->addListener(this, true))
  167. {
  168. ccLog::Error("Can't start the picking process (another tool is using it)");
  169. state = false;
  170. }
  171. }
  172. else
  173. {
  174. m_pickingHub->removeListener(this);
  175. }
  176. pickCenterToolButton->blockSignals(true);
  177. pickCenterToolButton->setChecked(state);
  178. pickCenterToolButton->blockSignals(false);
  179. }
  180. void ccPlaneEditDlg::onItemPicked(const PickedItem& pi)
  181. {
  182. if (!pi.entity)
  183. {
  184. return;
  185. }
  186. m_pickingWin = m_pickingHub->activeWindow();
  187. cxAxisDoubleSpinBox->setValue(pi.P3D.x);
  188. cyAxisDoubleSpinBox->setValue(pi.P3D.y);
  189. czAxisDoubleSpinBox->setValue(pi.P3D.z);
  190. pickCenterToolButton->setChecked(false);
  191. }
  192. void ccPlaneEditDlg::initWithPlane(ccPlane* plane)
  193. {
  194. m_associatedPlane = plane;
  195. if (!plane)
  196. {
  197. assert(false);
  198. return;
  199. }
  200. CCVector3 N = plane->getNormal();
  201. //init the dialog
  202. nxDoubleSpinBox->blockSignals(true);
  203. nyDoubleSpinBox->blockSignals(true);
  204. nzDoubleSpinBox->blockSignals(true);
  205. nxDoubleSpinBox->setValue(N.x);
  206. nyDoubleSpinBox->setValue(N.y);
  207. nzDoubleSpinBox->setValue(N.z);
  208. nxDoubleSpinBox->blockSignals(false);
  209. nyDoubleSpinBox->blockSignals(false);
  210. nzDoubleSpinBox->blockSignals(false);
  211. onNormalChanged(0);
  212. //PointCoordinateType dip = 0, dipDir = 0;
  213. //ccNormalVectors::ConvertNormalToDipAndDipDir(N, dip, dipDir);
  214. //dipDoubleSpinBox->setValue(dip);
  215. //dipDirDoubleSpinBox->setValue(dipDir);
  216. //upwardCheckBox->setChecked(N.z >= 0);
  217. wDoubleSpinBox->setValue(plane->getXWidth());
  218. hDoubleSpinBox->setValue(plane->getYWidth());
  219. CCVector3 C = plane->getCenter();
  220. cxAxisDoubleSpinBox->setValue(C.x);
  221. cyAxisDoubleSpinBox->setValue(C.y);
  222. czAxisDoubleSpinBox->setValue(C.z);
  223. }
  224. void ccPlaneEditDlg::updatePlane(ccPlane* plane)
  225. {
  226. if (!plane)
  227. {
  228. assert(false);
  229. return;
  230. }
  231. double dip = dipDoubleSpinBox->value();
  232. double dipDir = dipDirDoubleSpinBox->value();
  233. bool upward = upwardCheckBox->isChecked();
  234. PointCoordinateType width = static_cast<PointCoordinateType>(wDoubleSpinBox->value());
  235. PointCoordinateType height = static_cast<PointCoordinateType>(hDoubleSpinBox->value());
  236. CCVector3 Nd = ccNormalVectors::ConvertDipAndDipDirToNormal(static_cast<PointCoordinateType>(dip), static_cast<PointCoordinateType>(dipDir), upward);
  237. CCVector3 Cd { static_cast<PointCoordinateType>(cxAxisDoubleSpinBox->value()),
  238. static_cast<PointCoordinateType>(cyAxisDoubleSpinBox->value()),
  239. static_cast<PointCoordinateType>(czAxisDoubleSpinBox->value()) };
  240. CCVector3 N = plane->getNormal();
  241. CCVector3 C = plane->getCenter();
  242. //shall we transform (translate and / or rotate) the plane?
  243. ccGLMatrix trans;
  244. bool needToApplyRot = (std::abs(N.dot(Nd) - CCCoreLib::PC_ONE) > std::numeric_limits<PointCoordinateType>::epsilon());
  245. bool needToApplyTrans = (needToApplyRot || ((C - Cd).norm2d() != 0));
  246. if (needToApplyTrans)
  247. {
  248. trans.setTranslation(-C);
  249. }
  250. if (needToApplyRot)
  251. {
  252. ccGLMatrix rotation;
  253. //special case: plane parallel to XY
  254. if (std::abs(N.z) > CCCoreLib::PC_ONE - std::numeric_limits<PointCoordinateType>::epsilon())
  255. {
  256. ccGLMatrix rotX; rotX.initFromParameters( CCCoreLib::DegreesToRadians( -dip ), CCVector3(1, 0, 0), CCVector3(0, 0, 0) ); //plunge
  257. ccGLMatrix rotZ; rotZ.initFromParameters( CCCoreLib::DegreesToRadians( dipDir ), CCVector3(0, 0, -1), CCVector3(0, 0, 0) );
  258. rotation = rotZ * rotX;
  259. }
  260. else //general case
  261. {
  262. rotation = ccGLMatrix::FromToRotation(N, Nd);
  263. }
  264. trans = rotation * trans;
  265. }
  266. if (needToApplyTrans)
  267. {
  268. trans.setTranslation(trans.getTranslationAsVec3D() + Cd);
  269. }
  270. if (needToApplyRot || needToApplyTrans)
  271. {
  272. plane->applyGLTransformation_recursive(&trans);
  273. ccLog::Print("[Plane edit] Applied transformation matrix:");
  274. ccLog::Print(trans.toString(12, ' ')); //full precision
  275. }
  276. if ( plane->getXWidth() != width
  277. || plane->getYWidth() != height)
  278. {
  279. plane->setXWidth(width, false);
  280. plane->setYWidth(height, true);
  281. }
  282. }