ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
GreedyTriangulation.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 "GreedyTriangulation.h"
9 
10 #include <Utils/cc2sm.h>
11 #include <Utils/sm2cc.h>
12 
13 #include "PclUtils/PCLModules.h"
15 
16 // CV_DB_LIB
17 #include <ecvMesh.h>
18 #include <ecvPointCloud.h>
19 
20 // ECV_PLUGINS
21 #include <ecvMainAppInterface.h>
22 
23 // QT
24 #include <QMainWindow>
25 
26 // SYSTEM
27 #include <iostream>
28 
31  tr("Greedy Triangulation"),
32  tr("Greedy Triangulation"),
33  tr("Greedy Triangulation from clouds"),
34  ":/toolbar/PclAlgorithms/icons/greedy_triangulation.png")),
35  m_dialog(nullptr),
36  m_normalSearchRadius(10),
37  m_knn_radius(10),
38  m_useKnn(false),
39  m_trigulationSearchRadius(25),
40  m_weightingFactor(2.5),
41  m_maxNearestNeighbors(100),
42  m_maxSurfaceAngle(45),
43  m_minAngle(10),
44  m_maxAngle(120),
45  m_normalConsistency(false) {}
46 
48  // we must delete parent-less dialogs ourselves!
49  if (m_dialog && m_dialog->parent() == nullptr) delete m_dialog;
50 }
51 
53  // do we have a selected cloud?
54  int have_cloud = isFirstSelectedCcPointCloud();
55  if (have_cloud != 1) return -11;
56 
57  return 1;
58 }
59 
61  // initialize the dialog object
62  if (!m_dialog)
64  : 0);
65 
67  if (cloud) {
68  ccBBox bBox = cloud->getOwnBB();
69  if (bBox.isValid())
70  m_dialog->normalSearchRadius->setValue(bBox.getDiagNorm() * 0.005);
71  }
72 
73  if (!m_dialog->exec()) return 0;
74 
75  return 1;
76 }
77 
79  if (!m_dialog) return;
80 
81  // get the parameters from the dialog
82  m_normalConsistency = m_dialog->normalConsistency->isChecked();
83  m_useKnn = m_dialog->useKnnCheckBoxForTriangulation->isChecked();
84  m_knn_radius = m_dialog->knnSpinBoxForTriangulation->value();
86  static_cast<float>(m_dialog->normalSearchRadius->value());
87 
88  m_trigulationSearchRadius = m_dialog->triangulationSearchRadius->value();
89  m_weightingFactor = static_cast<float>(m_dialog->weightingFactor->value());
90  m_maxNearestNeighbors = m_dialog->nearestThreshold->value();
91  m_maxSurfaceAngle = m_dialog->maxSurfaceAngle->value();
92  m_minAngle = m_dialog->minAngle->value();
93  m_maxAngle = m_dialog->maxAngle->value();
94 }
95 
97  if (m_maxAngle > m_minAngle) {
98  return 1;
99  } else {
100  return -52;
101  }
102 }
103 
106  if (!cloud) return -1;
107 
108  // create storage for normals
109  pcl::PointCloud<pcl::PointNormal>::Ptr cloudWithNormals(
110  new pcl::PointCloud<pcl::PointNormal>);
111 
112  if (!cloud->hasNormals()) {
113  // get xyz as pcl point cloud
114  pcl::PointCloud<pcl::PointXYZ>::Ptr xyzCloud =
115  cc2smReader(cloud).getXYZ2();
116  if (!xyzCloud) return -1;
117 
118  // now compute
119  pcl::PointCloud<NormalT>::Ptr normals(new pcl::PointCloud<NormalT>);
120  int result = PCLModules::ComputeNormals<pcl::PointXYZ, NormalT>(
121  xyzCloud, normals,
123  if (result < 0) return -1;
124 
125  // concat points and normals
126  pcl::concatenateFields(*xyzCloud, *normals, *cloudWithNormals);
127  CVLog::Print(tr("[GreedyTriangulation::compute] generate new normals"));
128  } else {
129  PCLCloud::Ptr sm_cloud = cc2smReader(cloud).getAsSM();
130  FROM_PCL_CLOUD(*sm_cloud, *cloudWithNormals);
131  CVLog::Print(
132  tr("[GreedyTriangulation::compute] find normals and use the "
133  "normals"));
134  }
135 
136  // reconstruction
137  PCLMesh mesh;
139  cloudWithNormals, mesh, m_trigulationSearchRadius,
142  if (result < 0) return -1;
143 
144  PCLCloud out_cloud_sm(mesh.cloud);
145  if (out_cloud_sm.height * out_cloud_sm.width == 0) {
146  // cloud is empty
147  return -53;
148  }
149 
150  ccMesh* out_mesh = pcl2cc::Convert(out_cloud_sm, mesh.polygons);
151  if (!out_mesh) {
152  // conversion failed (not enough memory?)
153  return -1;
154  }
155 
156  unsigned vertCount = out_mesh->getAssociatedCloud()->size();
157  unsigned faceCount = out_mesh->size();
158  CVLog::Print(
159  tr("[greedy-triangulation-Reconstruction] %1 points, %2 face(s)")
160  .arg(vertCount)
161  .arg(faceCount));
162 
163  out_mesh->setName(tr("greedy-triangulation searchRadius[%1]")
165  // copy global shift & scale
166  out_mesh->getAssociatedCloud()->setGlobalScale(cloud->getGlobalScale());
167  out_mesh->getAssociatedCloud()->setGlobalShift(cloud->getGlobalShift());
168 
169  if (cloud->getParent()) cloud->getParent()->addChild(out_mesh);
170 
171  emit newEntity(out_mesh);
172 
173  return 1;
174 }
175 
176 QString GreedyTriangulation::getErrorMessage(int errorCode) {
177  switch (errorCode) {
178  // THESE CASES CAN BE USED TO OVERRIDE OR ADD FILTER-SPECIFIC ERRORS
179  // CODES ALSO IN DERIVED CLASSES DEFULAT MUST BE ""
180 
181  case -51:
182  return tr(
183  "Selected entity does not have any suitable scalar field "
184  "or RGB.");
185  case -52:
186  return tr(
187  "Wrong Parameters. One or more parameters cannot be "
188  "accepted");
189  case -53:
190  return tr(
191  "Greedy Triangulation does not returned any point. Try "
192  "relaxing your parameters");
193  default:
194  break;
195  }
196 
197  return BasePclModule::getErrorMessage(errorCode);
198 }
pcl::PCLPointCloud2 PCLCloud
Definition: PCLCloud.h:34
pcl::PolygonMesh PCLMesh
Definition: PCLCloud.h:31
#define FROM_PCL_CLOUD
Definition: PCLConv.h:11
core::Tensor result
Definition: VtkUtils.cpp:76
Base abstract class for each implemented PCL filter.
Definition: BasePclModule.h:53
int isFirstSelectedCcPointCloud()
Returns 1 if the first selected object is a ccPointCloud.
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.
static bool Print(const char *format,...)
Prints out a formatted message in console.
Definition: CVLog.cpp:113
virtual QString getErrorMessage(int errorCode)
Returns the error message corresponding to a given error code.
virtual void getParametersFromDialog()
Collects parameters from the filter dialog (if openDialog is successful)
GreedyTriangulationDlg * m_dialog
virtual int compute()
Performs the actual filter job.
virtual int checkSelected()
Checks if current selection is compliant with the filter.
CC to PCL cloud converter.
Definition: cc2sm.h:43
PCLCloud::Ptr getAsSM(std::list< std::string > &requested_fields) const
Definition: cc2sm.cpp:607
pcl::PointCloud< pcl::PointXYZ >::Ptr getXYZ2() const
Definition: cc2sm.cpp:218
Bounding box structure.
Definition: ecvBBox.h:25
ccBBox getOwnBB(bool withGLFeatures=false) override
Returns the entity's own bounding-box.
ccHObject * getParent() const
Returns parent object.
Definition: ecvHObject.h:245
virtual bool addChild(ccHObject *child, int dependencyFlags=DP_PARENT_OF_OTHER, int insertIndex=-1)
Adds a child.
Definition: ecvHObject.cpp:534
Triangular mesh.
Definition: ecvMesh.h:35
virtual unsigned size() const override
Returns the number of triangles.
Definition: ecvMesh.cpp:2143
ccGenericPointCloud * getAssociatedCloud() const override
Returns the vertices cloud.
Definition: ecvMesh.h:143
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.
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 void setGlobalScale(double scale)
virtual double getGlobalScale() const
Returns the scale applied to original coordinates.
T getDiagNorm() const
Returns diagonal length.
Definition: BoundingBox.h:172
bool isValid() const
Returns whether bounding box is valid or not.
Definition: BoundingBox.h:203
virtual unsigned size() const =0
Returns the number of points.
virtual QWidget * getActiveWindow()=0
static ccMesh * Convert(PCLTextureMesh::ConstPtr textureMesh)
Converts a PCL point cloud to a ccPointCloud.
double normals[3]
int GetGreedyTriangulation(const PointCloudNormal::ConstPtr &cloudWithNormals, PCLMesh &outMesh, int trigulationSearchRadius, float weightingFactor, int maxNearestNeighbors, int maxSurfaceAngle, int minAngle, int maxAngle, bool normalConsistency)
Definition: PCLModules.cpp:270
PCL filter description.
Definition: BasePclModule.h:26