ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ecvAnimationParamDlg.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 "ecvAnimationParamDlg.h"
9 
10 #include "ui_animationDlg.h"
11 
12 // Local
13 #include "MainWindow.h"
14 #include "ecvFileUtils.h"
15 #include "ecvPickingHub.h"
16 
17 // CV_CORE_LIB
18 #include <CVTools.h>
19 #include <ecvDisplayTools.h>
20 
21 // Qt
22 #include <QApplication>
23 #include <QCheckBox>
24 #include <QDialogButtonBox>
25 #include <QMdiSubWindow>
26 #include <QProgressDialog>
27 #include <QPushButton>
28 #include <QtConcurrentRun>
29 #include <QtMath>
30 
31 //=============================================================================
32 class AnimationDialogInternal : public Ui::AnimationParamDlg {
33 public:
34  AnimationDialogInternal() {}
35 
36  ~AnimationDialogInternal() {}
37 };
38 
40  MainWindow* app,
41  ccPickingHub* pickingHub)
42  : ccOverlayDialog(parent, Qt::Tool), m_app(app), m_pickingHub(pickingHub) {
43  this->Internal = new AnimationDialogInternal();
44  this->Internal->setupUi(this);
45 
46  this->Internal->EnablePickingAxis->setChecked(false);
47  this->Internal->SavingViewports->setChecked(false);
48  enablePickRotationAxis(false);
49 
50  connect(this->Internal->closeButtonBox, &QDialogButtonBox::clicked, this,
51  &ecvAnimationParamDlg::onClose);
52  QObject::connect(this->Internal->EnablePickingAxis, &QCheckBox::toggled,
53  this, &ecvAnimationParamDlg::enablePickRotationAxis);
54 
55  QObject::connect(this->Internal->angleButton, &QPushButton::clicked, this,
56  &ecvAnimationParamDlg::angleStep);
57 
58  QObject::connect(this->Internal->startAnimationButton,
59  &QPushButton::clicked, this,
61  QObject::connect(this->Internal->resetAnimationButton,
62  &QPushButton::clicked, this, &ecvAnimationParamDlg::reset);
63 
64  QObject::connect(this->Internal->pickingAxisStartToolButton,
65  &QToolButton::toggled, this,
67  QObject::connect(this->Internal->pickingAxisEndToolButton,
68  &QToolButton::toggled, this,
70 }
71 
72 ecvAnimationParamDlg::~ecvAnimationParamDlg() { delete this->Internal; }
73 
75  return this->Internal->rotationAngle->value();
76 }
77 
79  return this->Internal->SavingViewports->isChecked();
80 }
81 
83  // we'll take the rendering time into account!
84  QElapsedTimer timer;
85  timer.start();
86 
87  // show progress dialog
88  int viewport_num = 0;
89  QProgressDialog progressDialog(
90  QString("Saving Viewport number: %1").arg(viewport_num), "Cancel",
91  0, 0, this);
92  if (this->isSavingViewport()) {
93  progressDialog.setWindowTitle("Rendering");
94  } else {
95  progressDialog.setWindowTitle("Preview");
96  }
97 
98  progressDialog.show();
99  progressDialog.setModal(false);
100  progressDialog.setAutoClose(false);
101  QApplication::processEvents();
102 
103  int fps = this->Internal->fpsSpinBox->value();
104  // theoretical waiting time per frame
105  qint64 delay_ms = static_cast<int>(1000 / fps);
106 
107  double angle_step = this->getRotationAngle();
108  CCVector3d rotationAxis = this->getRotationAxis();
111 
112  while (true) {
113  // next frame
114  timer.restart();
115  ecvDisplayTools::RotateWithAxis(pos, rotationAxis, angle_step, 0);
116  if (this->isSavingViewport() && this->getMainWindow()) {
118  progressDialog.setLabelText(
119  QString("Saving Viewport number: %1").arg(++viewport_num));
120  } else {
121  progressDialog.setLabelText(QString("Render viewport to DB tree"));
122  }
123 
124  progressDialog.setValue(viewport_num);
125  progressDialog.update();
126  QApplication::processEvents();
127  if (progressDialog.wasCanceled()) {
128  break;
129  }
130 
131  qint64 dt_ms = timer.elapsed();
132 
133  // remaining time
134  if (dt_ms < delay_ms) {
135  int wait_ms = static_cast<int>(delay_ms - dt_ms);
137  }
138  }
139 }
140 
142  // with picking hub (CloudViewer)
143  if (!m_associatedWin || !m_pickingHub) {
144  assert(false);
145  return;
146  }
147 
148  AxisType axisType;
149  if (this->Internal->pickingAxisStartToolButton->isChecked()) {
150  axisType = AxisType::AXIS_START;
151  } else if (this->Internal->pickingAxisEndToolButton->isChecked()) {
152  axisType = AxisType::AXIS_END;
153  }
154 
156 
157  if (axisType == AxisType::AXIS_START) {
159  } else if (axisType == AxisType::AXIS_END) {
160  updateAxisEndToolState(false);
161  }
162 }
163 
165  ccHObject* entity, unsigned, int, int, const CCVector3& P) {
166  // without picking hub (ccViewer)
167  if (!m_associatedWin) {
168  assert(false);
169  return;
170  }
171 
172  if (!entity) {
173  return;
174  }
175 
176  AxisType axisType;
177  if (this->Internal->pickingAxisStartToolButton->isChecked()) {
178  axisType = AxisType::AXIS_START;
179  } else if (this->Internal->pickingAxisEndToolButton->isChecked()) {
180  axisType = AxisType::AXIS_END;
181  }
182 
184 
185  if (axisType == AxisType::AXIS_START) {
187  } else if (axisType == AxisType::AXIS_END) {
188  updateAxisEndToolState(false);
189  }
190 }
191 
194 
195  // no such concept for this dialog!
196  // (+ we want to allow dynamic change of associated window)
197  m_processing = false;
198 
199  // cache history viewport params
201 
202  return true;
203 }
204 
205 void ecvAnimationParamDlg::linkWith(QMdiSubWindow* qWin) {
206  QWidget* associatedWin =
207  (qWin ? static_cast<QWidget*>(qWin->widget()) : nullptr);
208 
209  linkWith(associatedWin);
210 }
211 
212 bool ecvAnimationParamDlg::linkWith(QWidget* win) {
213  QWidget* oldWin = m_associatedWin;
214 
215  if (!ccOverlayDialog::linkWith(win)) {
216  return false;
217  }
218 
219  if (oldWin != m_associatedWin) {
220  // automatically disable picking mode when changing th
221  if (this->Internal->pickingAxisStartToolButton->isChecked()) {
223  }
224 
225  if (this->Internal->pickingAxisEndToolButton->isChecked()) {
226  updateAxisEndToolState(false);
227  }
228  }
229 
230  if (oldWin) {
231  oldWin->disconnect(this);
232  }
233 
234  if (m_associatedWin) {
236  connect(ecvDisplayTools::TheInstance(), &ecvDisplayTools::destroyed,
237  this, &QWidget::hide);
238  }
239 
240  return true;
241 }
242 
243 void ecvAnimationParamDlg::initWith(QWidget* win) {
244  setEnabled(win != nullptr);
245  if (!win) return;
246 }
247 
249  if (this->Internal->EnablePickingAxis->isChecked()) {
250  CCVector3d axisStart(this->Internal->axisStartXDoubleSpinBox->value(),
251  this->Internal->axisStartYDoubleSpinBox->value(),
252  this->Internal->axisStartZDoubleSpinBox->value());
253  CCVector3d axisEnd(this->Internal->axisEndXDoubleSpinBox->value(),
254  this->Internal->axisEndYDoubleSpinBox->value(),
255  this->Internal->axisEndZDoubleSpinBox->value());
256  return axisEnd - axisStart;
257  }
258 
259  return CCVector3d(this->Internal->axisXDoubleSpinBox->value(),
260  this->Internal->axisYDoubleSpinBox->value(),
261  this->Internal->axisZDoubleSpinBox->value());
262 }
263 
265  const CCVector3d& P) {
266  if (AxisType::AXIS_START == axisType) {
267  this->Internal->axisStartXDoubleSpinBox->blockSignals(true);
268  this->Internal->axisStartYDoubleSpinBox->blockSignals(true);
269  this->Internal->axisStartZDoubleSpinBox->blockSignals(true);
270  this->Internal->axisStartXDoubleSpinBox->setValue(P.x);
271  this->Internal->axisStartYDoubleSpinBox->setValue(P.y);
272  this->Internal->axisStartZDoubleSpinBox->setValue(P.z);
273  this->Internal->axisStartXDoubleSpinBox->blockSignals(false);
274  this->Internal->axisStartYDoubleSpinBox->blockSignals(false);
275  this->Internal->axisStartZDoubleSpinBox->blockSignals(false);
276  } else if (AxisType::AXIS_END == axisType) {
277  this->Internal->axisEndXDoubleSpinBox->blockSignals(true);
278  this->Internal->axisEndYDoubleSpinBox->blockSignals(true);
279  this->Internal->axisEndZDoubleSpinBox->blockSignals(true);
280  this->Internal->axisEndXDoubleSpinBox->setValue(P.x);
281  this->Internal->axisEndYDoubleSpinBox->setValue(P.y);
282  this->Internal->axisEndZDoubleSpinBox->setValue(P.z);
283  this->Internal->axisEndXDoubleSpinBox->blockSignals(false);
284  this->Internal->axisEndYDoubleSpinBox->blockSignals(false);
285  this->Internal->axisEndZDoubleSpinBox->blockSignals(false);
286  }
287 }
288 
289 void ecvAnimationParamDlg::reset() {
292 }
293 
294 //-----------------------------------------------------------------------------
295 void ecvAnimationParamDlg::enablePickRotationAxis(bool state) {
296  auto& internal = (*this->Internal);
297  internal.pickingAxisStartToolButton->setEnabled(state);
298  internal.axisStartXDoubleSpinBox->setEnabled(state);
299  internal.axisStartYDoubleSpinBox->setEnabled(state);
300  internal.axisStartZDoubleSpinBox->setEnabled(state);
301  internal.pickingAxisEndToolButton->setEnabled(state);
302  internal.axisEndXDoubleSpinBox->setEnabled(state);
303  internal.axisEndYDoubleSpinBox->setEnabled(state);
304  internal.axisEndZDoubleSpinBox->setEnabled(state);
305  internal.axisXDoubleSpinBox->setEnabled(!state);
306  internal.axisYDoubleSpinBox->setEnabled(!state);
307  internal.axisZDoubleSpinBox->setEnabled(!state);
308 }
309 
310 //-----------------------------------------------------------------------------
311 void ecvAnimationParamDlg::angleStep() {
312  double angle_step = this->getRotationAngle();
315  CCVector3d rotationAxis = getRotationAxis();
316  ecvDisplayTools::RotateWithAxis(pos, rotationAxis, angle_step, 0);
317  if (this->isSavingViewport() && this->getMainWindow()) {
319  }
320 }
321 
323  if (m_pickingHub) {
324  if (state) {
325  if (!m_pickingHub->addListener(this, true)) {
326  CVLog::Error(
327  "Can't start the picking process (another tool is "
328  "using it)");
329  state = false;
330  }
331  } else {
333  }
334  } else if (m_associatedWin) {
335  if (state) {
341  } else {
343  disconnect(ecvDisplayTools::TheInstance(),
346  }
347  }
348 }
349 
351  enableListener(state);
352  this->Internal->pickingAxisStartToolButton->blockSignals(true);
353  this->Internal->pickingAxisStartToolButton->setChecked(state);
354  this->Internal->pickingAxisStartToolButton->blockSignals(false);
355 }
356 
358  enableListener(state);
359  this->Internal->pickingAxisEndToolButton->blockSignals(true);
360  this->Internal->pickingAxisEndToolButton->setChecked(state);
361  this->Internal->pickingAxisEndToolButton->blockSignals(false);
362 }
Vector3Tpl< double > CCVector3d
Double 3D Vector.
Definition: CVGeom.h:804
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Definition: CVLog.cpp:143
void doActionSaveViewportAsCamera()
Type y
Definition: CVGeom.h:137
Type u[3]
Definition: CVGeom.h:139
Type x
Definition: CVGeom.h:137
Type z
Definition: CVGeom.h:137
2D Vector
Definition: CVGeom.h:32
static Vector3Tpl fromArray(const int a[3])
Constructor from an int array.
Definition: CVGeom.h:268
Hierarchical CLOUDVIEWER Object.
Definition: ecvHObject.h:25
Generic overlay dialog interface.
virtual bool start()
Starts process.
bool m_processing
Running/processing state.
QWidget * m_associatedWin
Associated (MDI) window.
virtual bool linkWith(QWidget *win)
Links the overlay dialog with a MDI window.
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.
void updateRotationAxisPoint(AxisType axisType, const CCVector3d &P)
Updates dialog values with axis point.
bool start() override
Starts process.
MainWindow * getMainWindow()
CCVector3d getRotationAxis() const
ecvViewportParameters viewportParamsHistory
void startAnimation()
Start animation.
void initWith(QWidget *win)
Inits dialog values with specified window.
void onItemPicked(const PickedItem &pi) override
Method called whenever an item is picked.
ecvAnimationParamDlg(QWidget *parent, MainWindow *app, ccPickingHub *pickingHub)
Default constructor.
void updateAxisStartToolState(bool state)
void enableListener(bool state)
bool linkWith(QWidget *win) override
Links the overlay dialog with a MDI window.
void updateAxisEndToolState(bool state)
ccPickingHub * m_pickingHub
Picking hub.
void processPickedItem(ccHObject *, unsigned, int, int, const CCVector3 &)
~ecvAnimationParamDlg() override
Destructor.
static const ecvViewportParameters & GetViewportParameters()
static int GlWidth()
Returns the OpenGL context width.
static ecvDisplayTools * TheInstance()
void itemPicked(ccHObject *entity, unsigned subEntityID, int x, int y, const CCVector3 &P)
Signal emitted when a point (or a triangle) is picked.
static void SetViewportParameters(const ecvViewportParameters &params)
static int GlHeight()
Returns the OpenGL context height.
static void RotateWithAxis(const CCVector2i &pos, const CCVector3d &axis, double angle, int viewport=0)
static void SetPickingMode(PICKING_MODE mode=DEFAULT_PICKING)
static void UpdateScreen()
void Sleep(int milliseconds)
Definition: Helper.cpp:278
double timer
Definition: struct.h:215