ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ProjectionFilter.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 "ProjectionFilter.h"
9 
10 // LOCAL
11 #include <Utils/cc2sm.h>
12 #include <Utils/sm2cc.h>
13 
14 #include "PclUtils/PCLModules.h"
16 
17 // ECV_PLUGINS
18 #include <ecvMainAppInterface.h>
19 
20 // CV_DB_LIB
21 #include <ecvPointCloud.h>
22 
23 // QT
24 #include <QMainWindow>
25 
28  tr("Projection Filter"),
29  tr("Projection Filter"),
30  tr("Projection Filter for the selected entity"),
31  ":/toolbar/PclAlgorithms/icons/filter_projection.png")),
32  m_dialog(nullptr),
33  m_projectionMode(true),
34  m_coefficientA(0.0f),
35  m_coefficientB(0.0f),
36  m_coefficientC(1.0f),
37  m_coefficientD(0.0f),
38  m_useVoxelGrid(false),
39  m_leafSize(0.01f),
40  m_useKnn(true),
41  m_knn_radius(20),
42  m_normalSearchRadius(0.01f),
43  m_boundarySearchRadius(0.05f),
44  m_boundaryAngleThreshold(90.0f) {}
45 
47  // we must delete parent-less dialogs ourselves!
48  if (m_dialog && m_dialog->parent() == nullptr) delete m_dialog;
49 }
50 
52  if (!m_dialog) {
53  m_dialog =
55  }
56 
57  return m_dialog->exec() ? 1 : 0;
58 }
59 
61  assert(m_dialog);
62  if (!m_dialog) return;
63 
64  switch (m_dialog->tab->currentIndex()) {
65  // Cloud Projection Filter
66  case 0: {
67  // fill in parameters from dialog
68  m_coefficientA = static_cast<float>(m_dialog->aSpinBox->value());
69  m_coefficientB = static_cast<float>(m_dialog->bSpinBox->value());
70  m_coefficientC = static_cast<float>(m_dialog->cSpinBox->value());
71  m_coefficientD = static_cast<float>(m_dialog->dSpinBox->value());
72  m_projectionMode = true;
73  } break;
74  // Cloud Boundary Filter
75  case 1: {
76  m_useVoxelGrid = m_dialog->useVoxelGridCheckBox->isChecked();
77  m_leafSize = static_cast<float>(m_dialog->leafSizeSpinBox->value());
78  m_useKnn = m_dialog->useKnnBoundaryCheckBox->isChecked();
79  m_knn_radius = m_dialog->knnrBoundarySpinBox->value();
81  static_cast<float>(m_dialog->normalSearchRadius->value());
82 
83  m_boundaryAngleThreshold = static_cast<float>(
84  m_dialog->boundaryAngleThresholdSpinBox->value());
85  m_projectionMode = false;
86 
87  } break;
88  }
89 }
90 
92 
94  // pointer to selected cloud
96  if (!cloud) return -1;
97 
98  PointCloudT::Ptr xyzCloud = cc2smReader(cloud).getXYZ2();
99  if (!xyzCloud) return -1;
100 
101  // initialize all possible clouds
102  PCLCloud::Ptr out_cloud_sm(new PCLCloud);
103  PointCloudT::Ptr outCloudxyz(new PointCloudT);
104 
105  QString name;
106  if (m_projectionMode) // Projection mode
107  {
108  // originCloud: cloud before projection
109  pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
110  coefficients->values.resize(4);
111  coefficients->values[0] = m_coefficientA;
112  coefficients->values[1] = m_coefficientB;
113  coefficients->values[2] = m_coefficientC;
114  coefficients->values[3] = m_coefficientD;
115 
116  if (!PCLModules::GetProjection(xyzCloud, outCloudxyz, coefficients, 0))
117  return -1;
118  name = tr("%1-projection").arg(cloud->getName());
119  } else // boundary mode
120  {
121  // voxel grid filter
122  if (m_useVoxelGrid) {
123  PointCloudT::Ptr tempCloud(new PointCloudT);
124  if (!PCLModules::VoxelGridFilter<PointT>(xyzCloud, tempCloud,
126  m_leafSize)) {
127  return -1;
128  }
129  xyzCloud = tempCloud;
130  }
131 
132  // create storage for normals
133  pcl::PointCloud<NormalT>::Ptr normals(new pcl::PointCloud<NormalT>);
134  {
135  if (!cloud->hasNormals()) {
136  // now compute normals
137  int result = PCLModules::ComputeNormals<PointT, NormalT>(
138  xyzCloud, normals,
140  m_useKnn);
141  if (result < 0) return -1;
142  } else {
143  PCLCloud::Ptr sm_cloud = cc2smReader(cloud).getNormals();
144  FROM_PCL_CLOUD(*sm_cloud, *normals);
145  }
146  }
147 
148  if (!m_useKnn) {
149  float resolution = static_cast<float>(
150  PCLModules::ComputeCloudResolution<PointT>(xyzCloud));
151  if (resolution > 0) {
152  m_boundarySearchRadius = 10 * resolution;
153  }
154  }
155 
156  if (!PCLModules::GetBoundaryCloud<PointT, NormalT>(
157  xyzCloud, normals, outCloudxyz, m_boundaryAngleThreshold,
159  return -1;
160 
161  name = tr("%1-boundary").arg(cloud->getName());
162  }
163 
164  if (outCloudxyz->width * outCloudxyz->height == 0) {
165  return -53;
166  }
167 
168  TO_PCL_CLOUD(*outCloudxyz, *out_cloud_sm);
169  ccPointCloud* out_cloud_cc = pcl2cc::Convert(*out_cloud_sm);
170  {
171  if (!out_cloud_cc) {
172  // conversion failed (not enough memory?)
173  return -1;
174  }
175  out_cloud_cc->setName(name);
177  out_cloud_cc->setRGBColor(col);
178  out_cloud_cc->showColors(true);
179  out_cloud_cc->showSF(false);
180 
181  // copy global shift & scale
182  out_cloud_cc->setGlobalScale(cloud->getGlobalScale());
183  out_cloud_cc->setGlobalShift(cloud->getGlobalShift());
184  }
185 
186  if (cloud->getParent()) cloud->getParent()->addChild(out_cloud_cc);
187 
188  emit newEntity(out_cloud_cc);
189 
190  return 1;
191 }
192 
193 QString ProjectionFilter::getErrorMessage(int errorCode) {
194  switch (errorCode) {
195  // THESE CASES CAN BE USED TO OVERRIDE OR ADD FILTER-SPECIFIC ERRORS
196  // CODES ALSO IN DERIVED CLASSES DEFULAT MUST BE ""
197 
198  case -51:
199  return tr(
200  "Selected entity does not have any suitable scalar field "
201  "or RGB. Intensity scalar field or RGB are needed for "
202  "computing SIFT");
203  case -52:
204  return tr(
205  "Wrong Parameters. One or more parameters cannot be "
206  "accepted");
207  case -53:
208  return tr(
209  "Projection extraction does not returned any point. Try "
210  "relaxing your parameters");
211  }
212 
213  return BasePclModule::getErrorMessage(errorCode);
214 }
std::string name
core::Tensor result
Definition: VtkUtils.cpp:76
Base abstract class for each implemented PCL filter.
Definition: BasePclModule.h:53
void newEntity(ccHObject *)
Signal emitted when a new entity is created by the filter.
ecvMainAppInterface * m_app
Associated application interface.
virtual QString getErrorMessage(int errorCode)
Returns the error message corresponding to a given error code.
ccPointCloud * getSelectedEntityAsCCPointCloud() const
Returns the first selected entity as a ccPointCloud.
virtual int openInputDialog()
virtual int checkParameters()
virtual QString getErrorMessage(int errorCode)
Returns the error message corresponding to a given error code.
float m_boundaryAngleThreshold
virtual void getParametersFromDialog()
Collects parameters from the filter dialog (if openDialog is successful)
virtual int compute()
Performs the actual filter job.
ProjectionFilterDlg * m_dialog
virtual ~ProjectionFilter()
virtual void showColors(bool state)
Sets colors visibility.
virtual void showSF(bool state)
Sets active scalarfield visibility.
virtual bool addChild(ccHObject *child, int dependencyFlags=DP_PARENT_OF_OTHER, int insertIndex=-1)
Adds a child.
ccHObject * getParent() const
Returns parent object.
Definition: ecvHObject.h:245
virtual QString getName() const
Returns object name.
Definition: ecvObject.h:72
virtual void setName(const QString &name)
Sets object name.
Definition: ecvObject.h:75
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
bool hasNormals() const override
Returns whether normals are enabled or not.
bool setRGBColor(ColorCompType r, ColorCompType g, ColorCompType b)
Set a unique color for the whole cloud (shortcut)
virtual void setGlobalScale(double scale)
virtual void setGlobalShift(double x, double y, double z)
Sets shift applied to original coordinates (information storage only)
virtual const CCVector3d & getGlobalShift() const
Returns the shift applied to original coordinates.
virtual double getGlobalScale() const
Returns the scale applied to original coordinates.
static Rgb Random(bool lightOnly=true)
Generates a random color.
RGB color structure.
Definition: ecvColorTypes.h:49
virtual QWidget * getActiveWindow()=0
double normals[3]
PCL filter description.
Definition: BasePclModule.h:26