ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ccCompassImport.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 "ccCompassImport.h"
9 
10 #include <QComboBox>
11 #include <QDialog>
12 #include <QDialogButtonBox>
13 #include <QLabel>
14 #include <QLineEdit>
15 #include <QMainWindow>
16 #include <QVBoxLayout>
17 
18 #include "CVMath.h"
19 #include "ccLineation.h"
20 #include "ecvMainAppInterface.h"
21 #include "ecvPlane.h"
22 #include "ecvPointCloud.h"
23 
24 namespace {
25 class ImportDialog : public QDialog {
26 public:
27  ImportDialog(const ccPointCloud* cloud, QWidget* parent)
28  : QDialog(parent),
29  m_dipLabel(new QLabel),
30  m_dipDirLabel(new QLabel),
31  m_sizeLabel(new QLabel),
32  m_dipDirCombo(new QComboBox),
33  m_dipCombo(new QComboBox) {
34  QVBoxLayout* vbox = new QVBoxLayout;
35 
36  for (unsigned int i = 0; i < cloud->getNumberOfScalarFields(); ++i) {
37  m_dipDirCombo->addItem(cloud->getScalarFieldName(i), i);
38  m_dipCombo->addItem(cloud->getScalarFieldName(i), i);
39  }
40 
41  m_planeSize = new QLineEdit("2.0");
42  m_planeSize->setValidator(new QDoubleValidator(
44 
45  QDialogButtonBox* buttonBox = new QDialogButtonBox(
46  QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
47  QObject::connect(buttonBox, &QDialogButtonBox::accepted, this,
48  &QDialog::accept);
49  QObject::connect(buttonBox, &QDialogButtonBox::rejected, this,
50  &QDialog::reject);
51 
52  vbox->addWidget(m_dipLabel);
53  vbox->addWidget(m_dipCombo);
54  vbox->addWidget(m_dipDirLabel);
55  vbox->addWidget(m_dipDirCombo);
56  vbox->addWidget(m_sizeLabel);
57  vbox->addWidget(m_planeSize);
58  vbox->addWidget(buttonBox);
59 
60  setLayout(vbox);
61  }
62 
63  void setLabels(const QStringList& labels) {
64  Q_ASSERT(labels.count() == 3);
65 
66  m_dipLabel->setText(labels.at(0));
67  m_dipDirLabel->setText(labels.at(1));
68  m_sizeLabel->setText(labels.at(2));
69  }
70 
71  int dipDirComboScalarFieldIndex() {
72  return m_dipDirCombo->currentData().toInt();
73  }
74 
75  int dipComboScalarFieldIndex() { return m_dipCombo->currentData().toInt(); }
76 
77  double planeSize() { return m_planeSize->text().toDouble(); }
78 
79 private:
80  QLabel* m_dipLabel;
81  QLabel* m_dipDirLabel;
82  QLabel* m_sizeLabel;
83 
84  QComboBox* m_dipDirCombo;
85  QComboBox* m_dipCombo;
86 
87  QLineEdit* m_planeSize;
88 };
89 } // namespace
90 
91 namespace ccCompassImport {
92 
93 // convert a point cloud containing field points (x,y,z) and dip+dip-direction
94 // scalar fields to planes for visualisation.
96  // get selected point cloud
97  std::vector<ccHObject*> sel = app->getSelectedEntities();
98  if (sel.empty()) {
99  app->dispToConsole(
100  "Please select a point cloud containing your field data (this "
101  "can be loaded from a text file)",
103  return;
104  }
105 
106  if (!sel[0]->isA(CV_TYPES::POINT_CLOUD)) {
107  app->dispToConsole(
108  "Please select a point cloud containing your field data (this "
109  "can be loaded from a text file)",
111  return;
112  }
113 
114  // get point cloud object
115  ccPointCloud* cld = static_cast<ccPointCloud*>(sel[0]);
116 
117  ImportDialog foliationDialog(cld, app->getMainWindow());
118 
119  foliationDialog.setLabels(
120  {QObject::tr("Dip Field:", "ccCompassImport"),
121  QObject::tr("Dip-Direction Field:", "ccCompassImport"),
122  QObject::tr("Plane Size", "ccCompassImport")});
123 
124  int result = foliationDialog.exec();
125 
126  if (result == QDialog::Rejected) {
127  return; // bail!
128  }
129 
130  // get values
131  const int dipSF = foliationDialog.dipComboScalarFieldIndex();
132  const int dipDirSF = foliationDialog.dipDirComboScalarFieldIndex();
133  const double size = foliationDialog.planeSize();
134 
135  if (dipSF == dipDirSF) {
136  app->dispToConsole(
137  "Error: Dip and Dip-Direction scalar fields must be different!",
139  return;
140  }
141 
142  // loop through points
143  for (unsigned p = 0; p < cld->size(); p++) {
144  float dip = cld->getScalarField(dipSF)->at(p);
145  float dipdir = cld->getScalarField(dipDirSF)->at(p);
146  CCVector3 Cd = *cld->getPoint(p);
147 
148  // build plane and get its orientation
149  ccPlane* plane = new ccPlane(
150  QString("%1/%2")
151  .arg(static_cast<int>(dip), 2, 10, QChar('0'))
152  .arg(static_cast<int>(dipdir), 3, 10, QChar('0')));
153  plane->showNameIn3D(true);
154  cld->addChild(plane);
155  app->addToDB(plane, false, true, false, false);
156  CCVector3 N = plane->getNormal();
157  CCVector3 C = plane->getCenter();
158 
159  // figure out transform (blatantly stolen from
160  // ccPlaneEditDlg::updatePlane())
161  CCVector3 Nd =
163  ccGLMatrix trans;
164  bool needToApplyTrans = false;
165  bool needToApplyRot = false;
166 
167  needToApplyRot = (std::abs(N.dot(Nd) - PC_ONE) >
168  std::numeric_limits<PointCoordinateType>::epsilon());
169  needToApplyTrans = needToApplyRot || ((C - Cd).norm2d() != 0);
170 
171  if (needToApplyTrans) {
172  trans.setTranslation(-C);
173  needToApplyTrans = true;
174  }
175  if (needToApplyRot) {
176  ccGLMatrix rotation;
177  // special case: plane parallel to XY
178  if (std::abs(N.z) >
179  PC_ONE - std::numeric_limits<PointCoordinateType>::epsilon()) {
180  ccGLMatrix rotX;
182  CCVector3(1, 0, 0),
183  CCVector3(0, 0, 0)); // plunge
184 
185  ccGLMatrix rotZ;
187  CCVector3(0, 0, -1),
188  CCVector3(0, 0, 0));
189  rotation = rotZ * rotX;
190  } else // general case
191  {
192  rotation = ccGLMatrix::FromToRotation(N, Nd);
193  }
194  trans = rotation * trans;
195  }
196  if (needToApplyTrans) {
197  trans.setTranslation(trans.getTranslationAsVec3D() + Cd);
198  }
199  if (needToApplyRot || needToApplyTrans) {
200  plane->applyGLTransformation_recursive(&trans);
201  }
202  plane->setXWidth(size, false);
203  plane->setYWidth(size, true);
204  }
205 }
206 
207 // convert a point cloud containing field points (x,y,z) and trend + plunge
208 // scalar fields to lineation vectors for visualisation.
210  // get selected point cloud
211  std::vector<ccHObject*> sel = app->getSelectedEntities();
212  if (sel.empty()) {
213  app->dispToConsole(
214  "Please select a point cloud containing your field data (this "
215  "can be loaded from a text file)",
217  return;
218  }
219 
220  if (!sel[0]->isA(CV_TYPES::POINT_CLOUD)) {
221  app->dispToConsole(
222  "Please select a point cloud containing your field data (this "
223  "can be loaded from a text file)",
225  return;
226  }
227 
228  // get point cloud object
229  ccPointCloud* cld = static_cast<ccPointCloud*>(sel[0]);
230 
231  ImportDialog lineationDialog(cld, app->getMainWindow());
232 
233  lineationDialog.setLabels(
234  {QObject::tr("Trend Field:", "ccCompassImport"),
235  QObject::tr("Plunge Field:", "ccCompassImport"),
236  QObject::tr("Display Length", "ccCompassImport")});
237 
238  int result = lineationDialog.exec();
239 
240  if (result == QDialog::Rejected) {
241  return; // bail!
242  }
243 
244  // get values
245  const int dipSF = lineationDialog.dipComboScalarFieldIndex();
246  const int dipDirSF = lineationDialog.dipDirComboScalarFieldIndex();
247  const double size = lineationDialog.planeSize();
248 
249  if (dipSF == dipDirSF) {
250  app->dispToConsole(
251  "Error: Trend and plunge scalar fields must be different!",
253  return;
254  }
255 
256  // loop through points
257  for (unsigned p = 0; p < cld->size(); p++) {
258  float trend = cld->getScalarField(dipSF)->at(p);
259  float plunge = cld->getScalarField(dipDirSF)->at(p);
260  CCVector3 Cd = *cld->getPoint(p);
261 
262  // build lineation vector
264  cos(cloudViewer::DegreesToRadians(plunge)),
265  cos(cloudViewer::DegreesToRadians(trend)) *
266  cos(cloudViewer::DegreesToRadians(plunge)),
267  -sin(cloudViewer::DegreesToRadians(plunge)));
268 
269  // create new point cloud to associate with lineation graphic
271  points->setGlobalScale(
272  cld->getGlobalScale()); // copy global shift & scale onto new
273  // point cloud
274  points->setGlobalShift(cld->getGlobalShift());
275  points->reserve(2);
276  points->addPoint(Cd);
277  points->addPoint(Cd + l * size);
278  points->setName("verts");
279 
280  // create lineation graphic
281  ccLineation* lineation = new ccLineation(points);
282  lineation->addChild(points);
283  lineation->addPointIndex(0);
284  lineation->addPointIndex(1);
285  lineation->updateMetadata();
286  lineation->setName(QStringLiteral("%1->%2")
287  .arg(qRound(plunge))
288  .arg(qRound(trend)));
289  cld->addChild(lineation);
290  app->addToDB(lineation, false, true, false, false);
291  }
292 }
293 
294 } // namespace ccCompassImport
constexpr PointCoordinateType PC_ONE
'1' as a PointCoordinateType value
Definition: CVConst.h:67
Vector3Tpl< PointCoordinateType > CCVector3
Default 3D Vector.
Definition: CVGeom.h:798
int size
int points
core::Tensor result
Definition: VtkUtils.cpp:76
Type z
Definition: CVGeom.h:137
Type dot(const Vector3Tpl &v) const
Dot product.
Definition: CVGeom.h:408
virtual void showNameIn3D(bool state)
Sets whether name should be displayed in 3D.
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 bool addChild(ccHObject *child, int dependencyFlags=DP_PARENT_OF_OTHER, int insertIndex=-1)
Adds a child.
void updateMetadata() override
Definition: ccLineation.cpp:20
static CCVector3 ConvertDipAndDipDirToNormal(PointCoordinateType dip_deg, PointCoordinateType dipDir_deg, bool upward=true)
virtual void setName(const QString &name)
Sets object name.
Definition: ecvObject.h:75
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
void setYWidth(PointCoordinateType h, bool autoUpdate=true)
Sets 'Y' width.
Definition: ecvPlane.h:67
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
virtual const CCVector3d & getGlobalShift() const
Returns the shift applied to original coordinates.
virtual double getGlobalScale() const
Returns the scale applied to original coordinates.
ScalarField * getScalarField(int index) const
Returns a pointer to a specific scalar field.
unsigned getNumberOfScalarFields() const
Returns the number of associated (and active) scalar fields.
unsigned size() const override
Definition: PointCloudTpl.h:38
const char * getScalarFieldName(int index) const
Returns the name of a specific scalar field.
const CCVector3 * getPoint(unsigned index) const override
virtual bool addPointIndex(unsigned globalIndex)
Point global index insertion mechanism.
Main application interface (for plugins)
virtual QMainWindow * getMainWindow()=0
Returns main window.
virtual const ccHObject::Container & getSelectedEntities() const =0
Returns currently selected entities ("read only")
virtual void addToDB(ccHObject *obj, bool updateZoom=false, bool autoExpandDBTree=true, bool checkDimensions=false, bool autoRedraw=true)=0
virtual void dispToConsole(QString message, ConsoleMessageLevel level=STD_CONSOLE_MESSAGE)=0
__host__ __device__ int2 abs(int2 v)
Definition: cutil_math.h:1267
int max(int a, int b)
Definition: cutil_math.h:48
@ POINT_CLOUD
Definition: CVTypes.h:104
void importFoliations(ecvMainAppInterface *app)
void importLineations(ecvMainAppInterface *app)
float DegreesToRadians(int degrees)
Convert degrees to radians.
Definition: CVMath.h:98