ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ecvPlaneEditDlg.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include "ecvPlaneEditDlg.h"
9 
10 // local
11 #include "MainWindow.h"
12 
13 // common
14 #include <ecvPickingHub.h>
15 
16 // CV_DB_LIB
17 #include <ecvNormalVectors.h>
18 #include <ecvPlane.h>
19 
20 // Qt
21 #include <QDoubleValidator>
22 
23 // semi-persistent parameters
24 static double s_dip = 0;
25 static double s_dipDir = 0;
26 static double s_width = 10.0;
27 static double s_height = 10.0;
28 static bool s_upward = true;
29 static CCVector3d s_center(0, 0, 0);
30 
31 ccPlaneEditDlg::ccPlaneEditDlg(ccPickingHub* pickingHub, QWidget* parent)
32  : QDialog(parent),
33  Ui::PlaneEditDlg(),
34  m_associatedPlane(nullptr),
35  m_pickingHub(pickingHub) {
36  assert(pickingHub);
37 
38  setModal(false);
39  setupUi(this);
40 
41  // restore semi-persistent parameters
42  dipDoubleSpinBox->setValue(s_dip);
43  dipDirDoubleSpinBox->setValue(s_dipDir);
44  upwardCheckBox->setChecked(s_upward);
45  onDipDirChanged(0); // 0 = fake argument
46  wDoubleSpinBox->setValue(s_width);
47  hDoubleSpinBox->setValue(s_height);
48  cxAxisDoubleSpinBox->setValue(s_center.x);
49  cyAxisDoubleSpinBox->setValue(s_center.y);
50  czAxisDoubleSpinBox->setValue(s_center.z);
51 
52  connect(pickCenterToolButton, &QCheckBox::toggled, this,
54  connect(upwardCheckBox, &QCheckBox::toggled, this,
56  connect(dipDoubleSpinBox,
57  static_cast<void (QDoubleSpinBox::*)(double)>(
58  &QDoubleSpinBox::valueChanged),
60  connect(dipDirDoubleSpinBox,
61  static_cast<void (QDoubleSpinBox::*)(double)>(
62  &QDoubleSpinBox::valueChanged),
64  connect(nxDoubleSpinBox,
65  static_cast<void (QDoubleSpinBox::*)(double)>(
66  &QDoubleSpinBox::valueChanged),
68  connect(nyDoubleSpinBox,
69  static_cast<void (QDoubleSpinBox::*)(double)>(
70  &QDoubleSpinBox::valueChanged),
72  connect(nzDoubleSpinBox,
73  static_cast<void (QDoubleSpinBox::*)(double)>(
74  &QDoubleSpinBox::valueChanged),
76 
77  connect(buttonBox, &QDialogButtonBox::accepted, this,
79  connect(buttonBox, &QDialogButtonBox::rejected, this,
80  &ccPlaneEditDlg::deleteLater);
81 
82  // auto disable picking mode on quit
83  connect(this, &QDialog::finished, [&]() {
84  if (pickCenterToolButton->isChecked())
85  pickCenterToolButton->setChecked(false);
86  });
87 }
88 
90  assert(!pickCenterToolButton->isChecked());
91 }
92 
94  // save semi-persistent parameters
95  if (!m_associatedPlane) {
96  s_dip = dipDoubleSpinBox->value();
97  s_dipDir = dipDirDoubleSpinBox->value();
98  s_upward = upwardCheckBox->isChecked();
99  s_width = wDoubleSpinBox->value();
100  s_height = hDoubleSpinBox->value();
101  s_center.x = cxAxisDoubleSpinBox->value();
102  s_center.y = cyAxisDoubleSpinBox->value();
103  s_center.z = czAxisDoubleSpinBox->value();
104  }
105 
106  // edition mode
107  if (m_associatedPlane) {
112  } else // creation
113  {
114  ccPlane* plane = new ccPlane();
115  updatePlane(plane);
116 
117  if (MainWindow::TheInstance()) {
119  } else {
120  delete plane;
121  plane = nullptr;
122  }
123  }
124 
125  accept();
126 
127  deleteLater();
128 }
129 
131  onDipDirChanged(0); // 0 = fake argument
132 }
133 
135  double dip = dipDoubleSpinBox->value();
136  double dipDir = dipDirDoubleSpinBox->value();
137  bool upward = upwardCheckBox->isChecked();
139  static_cast<PointCoordinateType>(dip),
140  static_cast<PointCoordinateType>(dipDir), upward);
141 
142  nxDoubleSpinBox->blockSignals(true);
143  nyDoubleSpinBox->blockSignals(true);
144  nzDoubleSpinBox->blockSignals(true);
145 
146  nxDoubleSpinBox->setValue(Nd.x);
147  nyDoubleSpinBox->setValue(Nd.y);
148  nzDoubleSpinBox->setValue(Nd.z);
149 
150  nxDoubleSpinBox->blockSignals(false);
151  nyDoubleSpinBox->blockSignals(false);
152  nzDoubleSpinBox->blockSignals(false);
153 }
154 
156  CCVector3 Nd;
157  Nd.x = nxDoubleSpinBox->value();
158  Nd.y = nyDoubleSpinBox->value();
159  Nd.z = nzDoubleSpinBox->value();
160  Nd.normalize();
161 
162  PointCoordinateType dip = 0, dipDir = 0;
164 
165  dipDoubleSpinBox->blockSignals(true);
166  dipDirDoubleSpinBox->blockSignals(true);
167  upwardCheckBox->blockSignals(true);
168 
169  dipDoubleSpinBox->setValue(dip);
170  dipDirDoubleSpinBox->setValue(dipDir);
171  upwardCheckBox->setChecked(Nd.z >= 0);
172 
173  dipDoubleSpinBox->blockSignals(false);
174  dipDirDoubleSpinBox->blockSignals(false);
175  upwardCheckBox->blockSignals(false);
176 }
177 
179  if (!m_pickingHub) {
180  return;
181  }
182  if (state) {
183  if (!m_pickingHub->addListener(this, true)) {
184  CVLog::Error(
185  "Can't start the picking process (another tool is using "
186  "it)");
187  state = false;
188  }
189  } else {
191  }
192 
193  pickCenterToolButton->blockSignals(true);
194  pickCenterToolButton->setChecked(state);
195  pickCenterToolButton->blockSignals(false);
196 }
197 
199  if (!pi.entity) {
200  return;
201  }
202 
203  cxAxisDoubleSpinBox->setValue(pi.P3D.x);
204  cyAxisDoubleSpinBox->setValue(pi.P3D.y);
205  czAxisDoubleSpinBox->setValue(pi.P3D.z);
206 
207  pickCenterToolButton->setChecked(false);
208 }
209 
211  m_associatedPlane = plane;
212  if (!plane) {
213  assert(false);
214  return;
215  }
216 
217  CCVector3 N = plane->getNormal();
218 
219  // init the dialog
220  nxDoubleSpinBox->blockSignals(true);
221  nyDoubleSpinBox->blockSignals(true);
222  nzDoubleSpinBox->blockSignals(true);
223 
224  nxDoubleSpinBox->setValue(N.x);
225  nyDoubleSpinBox->setValue(N.y);
226  nzDoubleSpinBox->setValue(N.z);
227 
228  nxDoubleSpinBox->blockSignals(false);
229  nyDoubleSpinBox->blockSignals(false);
230  nzDoubleSpinBox->blockSignals(false);
231 
232  onNormalChanged(0);
233  // PointCoordinateType dip = 0, dipDir = 0;
234  // ccNormalVectors::ConvertNormalToDipAndDipDir(N, dip, dipDir);
235 
236  // dipDoubleSpinBox->setValue(dip);
237  // dipDirDoubleSpinBox->setValue(dipDir);
238  // upwardCheckBox->setChecked(N.z >= 0);
239 
240  wDoubleSpinBox->setValue(plane->getXWidth());
241  hDoubleSpinBox->setValue(plane->getYWidth());
242 
243  CCVector3 C = plane->getCenter();
244  cxAxisDoubleSpinBox->setValue(C.x);
245  cyAxisDoubleSpinBox->setValue(C.y);
246  czAxisDoubleSpinBox->setValue(C.z);
247 }
248 
250  if (!plane) {
251  assert(false);
252  return;
253  }
254 
255  double dip = dipDoubleSpinBox->value();
256  double dipDir = dipDirDoubleSpinBox->value();
257  bool upward = upwardCheckBox->isChecked();
259  static_cast<PointCoordinateType>(wDoubleSpinBox->value());
261  static_cast<PointCoordinateType>(hDoubleSpinBox->value());
262  CCVector3 Nd =
264  CCVector3 Cd = {
265  static_cast<PointCoordinateType>(cxAxisDoubleSpinBox->value()),
266  static_cast<PointCoordinateType>(cyAxisDoubleSpinBox->value()),
267  static_cast<PointCoordinateType>(czAxisDoubleSpinBox->value())};
268 
269  CCVector3 N = plane->getNormal();
270  CCVector3 C = plane->getCenter();
271 
272  // shall we transform (translate and / or rotate) the plane?
273  ccGLMatrix trans;
274  bool needToApplyTrans = false;
275  bool needToApplyRot = false;
276 
277  needToApplyRot = (fabs(N.dot(Nd) - PC_ONE) >
278  std::numeric_limits<PointCoordinateType>::epsilon());
279  needToApplyTrans = needToApplyRot || ((C - Cd).norm2d() != 0);
280 
281  if (needToApplyTrans) {
282  trans.setTranslation(-C);
283  needToApplyTrans = true;
284  }
285  if (needToApplyRot) {
286  ccGLMatrix rotation;
287  // special case: plane parallel to XY
288  if (fabs(N.z) >
289  PC_ONE - std::numeric_limits<PointCoordinateType>::epsilon()) {
290  ccGLMatrix rotX;
292  CCVector3(1, 0, 0),
293  CCVector3(0, 0, 0)); // plunge
294  ccGLMatrix rotZ;
296  CCVector3(0, 0, -1), CCVector3(0, 0, 0));
297  rotation = rotZ * rotX;
298  } else // general case
299  {
300  rotation = ccGLMatrix::FromToRotation(N, Nd);
301  }
302  trans = rotation * trans;
303  }
304  if (needToApplyTrans) {
305  trans.setTranslation(trans.getTranslationAsVec3D() + Cd);
306  }
307  if (needToApplyRot || needToApplyTrans) {
308  plane->applyGLTransformation_recursive(&trans);
309 
310  CVLog::Print("[Plane edit] Applied transformation matrix:");
311  CVLog::Print(trans.toString(12, ' ')); // full precision
312  }
313 
314  if (plane->getXWidth() != width || plane->getYWidth() != height) {
315  plane->setXWidth(width, false);
316  plane->setYWidth(height, true);
317  }
318 }
constexpr PointCoordinateType PC_ONE
'1' as a PointCoordinateType value
Definition: CVConst.h:67
Vector3Tpl< PointCoordinateType > CCVector3
Default 3D Vector.
Definition: CVGeom.h:798
float PointCoordinateType
Type of the coordinates of a (N-D) point.
Definition: CVTypes.h:16
int width
int height
static bool Print(const char *format,...)
Prints out a formatted message in console.
Definition: CVLog.cpp:113
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Definition: CVLog.cpp:143
static MainWindow * TheInstance()
Returns the unique instance of this object.
void addToDB(const QStringList &filenames, QString fileFilter=QString(), bool displayDialog=true)
void updatePropertiesView()
Updates the 'Properties' view.
Type y
Definition: CVGeom.h:137
Type x
Definition: CVGeom.h:137
Type z
Definition: CVGeom.h:137
void normalize()
Sets vector norm to unity.
Definition: CVGeom.h:428
Type dot(const Vector3Tpl &v) const
Dot product.
Definition: CVGeom.h:408
QString toString(int precision=12, QChar separator=' ') const
Returns matrix as a string.
Vector3Tpl< T > getTranslationAsVec3D() const
Returns a copy of the translation as a CCVector3.
static ccGLMatrixTpl< float > FromToRotation(const Vector3Tpl< float > &from, const Vector3Tpl< float > &to)
Creates a transformation matrix that rotates a vector to another.
void setTranslation(const Vector3Tpl< float > &Tr)
Sets translation (float version)
void initFromParameters(T alpha_rad, const Vector3Tpl< T > &axis3D, const Vector3Tpl< T > &t3D)
Inits transformation from a rotation axis, an angle and a translation.
Float version of ccGLMatrixTpl.
Definition: ecvGLMatrix.h:19
void applyGLTransformation_recursive(const ccGLMatrix *trans=nullptr)
Applies the active OpenGL transformation to the entity (recursive)
virtual void redrawDisplay(bool forceRedraw=true, bool only2D=false)
Redraws associated display.
static CCVector3 ConvertDipAndDipDirToNormal(PointCoordinateType dip_deg, PointCoordinateType dipDir_deg, bool upward=true)
static void ConvertNormalToDipAndDipDir(const CCVector3 &N, PointCoordinateType &dip_deg, PointCoordinateType &dipDir_deg)
Converts a normal vector to geological 'dip direction & dip' parameters.
Point/triangle picking hub.
Definition: ecvPickingHub.h:29
void removeListener(ccPickingListener *listener, bool autoStopPickingIfLast=true)
Removes a listener.
bool addListener(ccPickingListener *listener, bool exclusive=false, bool autoStartPicking=true, ecvDisplayTools::PICKING_MODE mode=ecvDisplayTools::POINT_OR_TRIANGLE_PICKING)
Adds a listener.
virtual void onItemPicked(const PickedItem &pi)
Inherited from ccPickingListener.
ccPickingHub * m_pickingHub
Picking hub.
void initWithPlane(ccPlane *plane)
Links this dialog with an existing plane.
virtual ~ccPlaneEditDlg()
Destructor.
void saveParamsAndAccept()
void pickPointAsCenter(bool)
void updatePlane(ccPlane *plane)
Updates a plane with the current parameters.
ccPlane * m_associatedPlane
Associated plane (if any)
void onDipDirModified(bool)
void onNormalChanged(double)
void onDipDirChanged(double)
ccPlaneEditDlg(ccPickingHub *pickingHub, QWidget *parent)
Default constructor.
Plane (primitive)
Definition: ecvPlane.h:18
CCVector3 getCenter() const
Returns the center.
Definition: ecvPlane.h:56
CCVector3 getNormal() const override
Returns the entity normal.
Definition: ecvPlane.h:73
void setXWidth(PointCoordinateType w, bool autoUpdate=true)
Sets 'X' width.
Definition: ecvPlane.h:61
PointCoordinateType getXWidth() const
Returns 'X' width.
Definition: ecvPlane.h:50
PointCoordinateType getYWidth() const
Returns 'Y' width.
Definition: ecvPlane.h:53
void setYWidth(PointCoordinateType h, bool autoUpdate=true)
Sets 'Y' width.
Definition: ecvPlane.h:67
__host__ __device__ float2 fabs(float2 v)
Definition: cutil_math.h:1254
static double s_width
static bool s_upward
static double s_dip
static double s_dipDir
static CCVector3d s_center(0, 0, 0)
static double s_height
float DegreesToRadians(int degrees)
Convert degrees to radians.
Definition: CVMath.h:98