ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
qCSFCommands.h
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 #pragma once
9 
10 // CloudViewer
12 
13 // Local
14 #include "CSF.h"
15 #include "ccCSFDlg.h"
16 
17 static const char COMMAND_CSF[] = "CSF";
18 static const char COMMAND_CSF_SCENE[] = "SCENES";
19 static const char COMMAND_CSF_SCENE_SLOPE[] = "SLOPE";
20 static const char COMMAND_CSF_SCENE_RELIEF[] = "RELIEF";
21 static const char COMMAND_CSF_SCENE_FLAT[] = "FLAT";
22 static const char COMMAND_CSF_PROC_SLOPE[] = "PROC_SLOPE";
23 static const char COMMAND_CSF_CLOTH_RESOLUTION[] = "CLOTH_RESOLUTION";
24 static const char COMMAND_CSF_MAX_ITERATION[] = "MAX_ITERATION";
25 static const char COMMAND_CSF_CLASS_THRESHOLD[] = "CLASS_THRESHOLD";
26 static const char COMMAND_CSF_EXPORT_GROUND[] = "EXPORT_GROUND";
27 static const char COMMAND_CSF_EXPORT_OFFGROUND[] = "EXPORT_OFFGROUND";
28 
31 
32  virtual bool process(ccCommandLineInterface& cmd) override {
33  cmd.print("[CSF]");
34 
35  if (cmd.clouds().size() < 1) {
36  cmd.error("No cloud loaded (1 is expected)");
37  return false;
38  }
39 
40  ccPointCloud* pc = cmd.clouds()[0].pc;
41 
42  // Convert CC point cloud to CSF type
43  unsigned count = pc->size();
44  wl::PointCloud csfPC;
45  try {
46  csfPC.reserve(count);
47  } catch (const std::bad_alloc&) {
48  return cmd.error("Not enough memory!");
49  }
50 
51  for (unsigned i = 0; i < count; i++) {
52  const CCVector3* P = pc->getPoint(i);
53  wl::Point tmpPoint;
54  tmpPoint.x = P->x;
55  tmpPoint.y = -P->z;
56  tmpPoint.z = P->y;
57  csfPC.push_back(tmpPoint);
58  }
59 
60  // initial parameters
61  bool csfPostprocessing = false;
62  double clothResolution = 2;
63  double classThreshold = 0.5;
64  int csfRigidness = 2;
65  int maxIteration = 500;
66  bool exportGround = false;
67  bool exportOffground = false;
68 
69  while (!cmd.arguments().empty()) {
70  const QString& ARGUMENT = cmd.arguments().front();
73  cmd.arguments().pop_front();
74  bool conv = false;
75  QString scene = cmd.arguments().takeFirst();
76  if (scene == COMMAND_CSF_SCENE_SLOPE) {
77  cmd.print("Set scene to steep slope");
78  csfRigidness = 1;
79  } else if (scene == COMMAND_CSF_SCENE_RELIEF) {
80  cmd.print("Set scene to relief");
81  csfRigidness = 2;
82  } else if (scene == COMMAND_CSF_SCENE_FLAT) {
83  cmd.print("Set scene to flat");
84  csfRigidness = 3;
85  } else {
86  cmd.error("Unknown scene parameter. Defaulting to relief");
87  csfRigidness = 2;
88  }
90  ARGUMENT, COMMAND_CSF_PROC_SLOPE)) {
91  cmd.arguments().pop_front();
92  cmd.print("Slope processing turned on");
93  csfPostprocessing = true;
95  ARGUMENT, COMMAND_CSF_CLOTH_RESOLUTION)) {
96  cmd.arguments().pop_front();
97  bool conv = false;
98  clothResolution = cmd.arguments().takeFirst().toDouble(&conv);
99  if (!conv) {
100  return cmd.error(
101  QObject::tr(
102  "Invalid parameter: value after \"-%1\"")
104  }
105  cmd.print(QString("Custom cloth resulution set: %1")
106  .arg(clothResolution));
108  ARGUMENT, COMMAND_CSF_MAX_ITERATION)) {
109  cmd.arguments().pop_front();
110  bool conv = false;
111  maxIteration = cmd.arguments().takeFirst().toInt(&conv);
112  if (!conv) {
113  return cmd.error(
114  QObject::tr(
115  "Invalid parameter: value after \"-%1\"")
117  }
118  cmd.print(QString("Custom max iteration set: %")
119  .arg(maxIteration));
121  ARGUMENT, COMMAND_CSF_CLASS_THRESHOLD)) {
122  cmd.arguments().pop_front();
123  bool conv = false;
124  classThreshold = cmd.arguments().takeFirst().toDouble(&conv);
125  if (!conv) {
126  return cmd.error(
127  QObject::tr(
128  "Invalid parameter: value after \"-%1\"")
130  }
131  cmd.print(QString("Custom class threshold set: %1")
132  .arg(classThreshold));
134  ARGUMENT, COMMAND_CSF_EXPORT_GROUND)) {
135  cmd.arguments().pop_front();
136  cmd.print("Ground will be exported");
137  exportGround = true;
139  ARGUMENT, COMMAND_CSF_EXPORT_OFFGROUND)) {
140  cmd.arguments().pop_front();
141  cmd.print("Off-ground will be exported");
142  exportOffground = true;
143  } else {
144  cmd.print("Set all parameters");
145  break;
146  }
147  }
148 
149  // instantiation a CSF class
150  CSF csf(csfPC);
151 
152  // setup paramter
153  csf.params.k_nearest_points = 1;
154  csf.params.bSloopSmooth = csfPostprocessing;
155  csf.params.time_step = 0.65;
156  csf.params.class_threshold = classThreshold;
157  csf.params.cloth_resolution = clothResolution;
158  csf.params.rigidness = csfRigidness;
159  csf.params.iterations = maxIteration;
160 
161  std::vector<int> groundIndexes;
162  std::vector<int> offGroundIndexes;
163  ccMesh* clothMesh = nullptr;
164  if (!csf.do_filtering(groundIndexes, offGroundIndexes, false, clothMesh,
165  nullptr, cmd.widgetParent())) {
166  return cmd.error("Process failed");
167  }
168 
169  cmd.print(QString("[CSF] %1% of points classified as ground points")
170  .arg((groundIndexes.size() * 100.0) / count, 0, 'f',
171  2));
172 
173  // extract ground subset
174  ccPointCloud* groundpoint = nullptr;
175  {
176  cloudViewer::ReferenceCloud groundpc(pc);
177  if (groundpc.reserve(static_cast<unsigned>(groundIndexes.size()))) {
178  for (unsigned j = 0; j < groundIndexes.size(); ++j) {
179  groundpc.addPointIndex(groundIndexes[j]);
180  }
181  groundpoint = pc->partialClone(&groundpc);
182  }
183  }
184  if (!groundpoint) {
185  cmd.print(
186  "Failed to extract the ground subset (not enough memory)");
187  }
188 
189  ccPointCloud* offgroundpoint = nullptr;
190  {
191  cloudViewer::ReferenceCloud offgroundpc(pc);
192  if (offgroundpc.reserve(
193  static_cast<unsigned>(offGroundIndexes.size()))) {
194  for (unsigned k = 0; k < offGroundIndexes.size(); ++k) {
195  offgroundpc.addPointIndex(offGroundIndexes[k]);
196  }
197  offgroundpoint = pc->partialClone(&offgroundpc);
198  }
199  }
200  if (!offgroundpoint) {
201  cmd.print(
202  "Failed to extract the off-ground subset (not enough "
203  "memory)");
204  if (!groundpoint) {
205  return false;
206  }
207  }
208 
209  QString baseName = cmd.clouds()[0].basename;
210 
211  cmd.removeClouds();
212 
213  if (groundpoint) {
214  CLCloudDesc groundDesc(groundpoint,
215  baseName + QObject::tr("_ground_points"),
216  -1); // add cloud to the current pool
217  cmd.clouds().push_back(groundDesc);
218  if (exportGround) {
219  QString errorStr = cmd.exportEntity(
220  groundDesc, QString(), nullptr,
222  if (!errorStr.isEmpty()) {
223  cmd.error(errorStr);
224  }
225  }
226  }
227 
228  if (offgroundpoint) {
229  CLCloudDesc offgroundDesc(
230  offgroundpoint, baseName + QObject::tr("_offground_points"),
231  -1);
232  cmd.clouds().push_back(offgroundDesc);
233  if (exportOffground) {
234  QString errorStr = cmd.exportEntity(
235  offgroundDesc, QString(), nullptr,
237  if (!errorStr.isEmpty()) {
238  cmd.error(errorStr);
239  }
240  }
241  }
242 
243  return true;
244  }
245 };
int count
Definition: CSF.h:21
bool do_filtering(std::vector< int > &groundIndexes, std::vector< int > &offGroundIndexes, bool exportClothMesh, ccMesh *&clothMesh, ecvMainAppInterface *app=0, QWidget *parent=0)
Definition: CSF.cpp:73
Parameters params
Definition: CSF.h:63
Type y
Definition: CVGeom.h:137
Type x
Definition: CVGeom.h:137
Type z
Definition: CVGeom.h:137
Command line interface.
virtual QStringList & arguments()=0
Returns the list of arguments.
virtual void print(const QString &message) const =0
virtual bool error(const QString &message) const =0
static bool IsCommand(const QString &token, const char *command)
Test whether a command line token is a valid command keyword or not.
virtual QString exportEntity(CLEntityDesc &entityDesc, const QString &suffix=QString(), QString *outputFilename=nullptr, ccCommandLineInterface::ExportOptions options=ExportOption::NoOptions)=0
Exports a cloud or a mesh.
virtual void removeClouds(bool onlyLast=false)=0
Removes all clouds (or only the last one ;)
virtual QDialog * widgetParent()
Returns a (widget) parent (if any is available)
virtual std::vector< CLCloudDesc > & clouds()
Currently opened point clouds and their filename.
Triangular mesh.
Definition: ecvMesh.h:35
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
ccPointCloud * partialClone(const cloudViewer::ReferenceCloud *selection, int *warnings=nullptr, bool withChildEntities=true) const
Creates a new point cloud object from a ReferenceCloud (selection)
unsigned size() const override
Definition: PointCloudTpl.h:38
const CCVector3 * getPoint(unsigned index) const override
A very simple point cloud (no point duplication)
virtual bool addPointIndex(unsigned globalIndex)
Point global index insertion mechanism.
virtual bool reserve(unsigned n)
Reserves some memory for hosting the point references.
static const char COMMAND_CSF_EXPORT_OFFGROUND[]
Definition: qCSFCommands.h:27
static const char COMMAND_CSF_SCENE[]
Definition: qCSFCommands.h:18
static const char COMMAND_CSF_MAX_ITERATION[]
Definition: qCSFCommands.h:24
static const char COMMAND_CSF[]
Definition: qCSFCommands.h:17
static const char COMMAND_CSF_SCENE_SLOPE[]
Definition: qCSFCommands.h:19
static const char COMMAND_CSF_CLOTH_RESOLUTION[]
Definition: qCSFCommands.h:23
static const char COMMAND_CSF_SCENE_RELIEF[]
Definition: qCSFCommands.h:20
static const char COMMAND_CSF_SCENE_FLAT[]
Definition: qCSFCommands.h:21
static const char COMMAND_CSF_EXPORT_GROUND[]
Definition: qCSFCommands.h:26
static const char COMMAND_CSF_PROC_SLOPE[]
Definition: qCSFCommands.h:22
static const char COMMAND_CSF_CLASS_THRESHOLD[]
Definition: qCSFCommands.h:25
Loaded cloud description.
double time_step
Definition: CSF.h:52
int iterations
Definition: CSF.h:60
double class_threshold
Definition: CSF.h:54
int k_nearest_points
Definition: CSF.h:48
bool bSloopSmooth
Definition: CSF.h:50
double cloth_resolution
Definition: CSF.h:56
int rigidness
Definition: CSF.h:58
virtual bool process(ccCommandLineInterface &cmd) override
Main process.
Definition: qCSFCommands.h:32
Command(const QString &name, const QString &keyword)
Default constructor.
Point type.
Definition: wlPointCloud.h:15