26 "BITMAP_EPSILON_PERCENTAGE_OF_SCALE";
40 "OUTPUT_INDIVIDUAL_PAIRED_CLOUD_PRIMITIVE";
55 if (cmd.
clouds().empty()) {
56 return cmd.
error(QObject::tr(
"No point cloud to attempt RANSAC on "
57 "(be sure to open one with \"-O "
58 "[cloud filename]\" before \"-%2\")")
61 qRansacSD::RansacParams
params;
62 QStringList paramNames =
74 QString outputCloudsDir;
75 QString outputMeshesDir;
76 QString outputPairDir;
77 QString outputGroupDir;
78 bool outputIndividualClouds =
false;
79 bool outputIndividualPrimitives =
false;
80 bool outputIndividualPairs =
false;
81 bool outputGrouped =
false;
83 float epsilonABS = -1.0f;
84 float epsilonPercentage = -1.0f;
85 float bitmapEpsilonABS = -1.0f;
86 float bitmapEpsilonPercentage = -1.0f;
88 params.bitmapEpsilon = -1.0f;
89 params.randomColor =
false;
91 for (
unsigned char k = 0; k < 5; ++k) {
92 params.primEnabled[k] =
false;
96 QString param = cmd.
arguments().takeFirst().toUpper();
97 while (paramNames.contains(param)) {
102 QObject::tr(
"Missing parameter: number after "
107 float val = cmd.
arguments().takeFirst().toFloat(&ok);
109 return cmd.
error(
"Invalid number for epsilon!");
111 cmd.
print(QObject::tr(
"\tEpsilon : %1").arg(val));
116 QObject::tr(
"Missing parameter: number after "
122 float val = cmd.
arguments().takeFirst().toFloat(&ok);
123 if (!ok || (val <= 0.0f || val >= 1.0f)) {
125 "Invalid number for epsilon percentage must be "
126 "a float greater than 0.0 and less than 1.0!");
128 cmd.
print(QObject::tr(
"\tEpsilon : %1").arg(val));
129 epsilonPercentage = val;
132 return cmd.
error(QObject::tr(
"Missing parameter: "
133 "number after \"-%1 %2\"")
138 float val = cmd.
arguments().takeFirst().toFloat(&ok);
140 return cmd.
error(
"Invalid number for Bitmap epsilon!");
142 cmd.
print(QObject::tr(
"\tBitmap Epsilon : %1").arg(val));
143 bitmapEpsilonABS = val;
147 QObject::tr(
"Missing parameter: number after "
153 float val = cmd.
arguments().takeFirst().toFloat(&ok);
154 if (!ok || (val <= 0.0f || val >= 1.0f)) {
156 "Invalid number for Bitmap epsilon must be a "
157 "float greater than 0.0 and less than 1.0!!");
159 cmd.
print(QObject::tr(
"\tBitmap Epsilon : %1").arg(val));
160 bitmapEpsilonPercentage = val;
164 QObject::tr(
"Missing parameter: number after "
172 "Invalid number of for support points!");
174 cmd.
print(QObject::tr(
"\tsupport points: %1").arg(
count));
179 QObject::tr(
"Missing parameter: number after "
184 float val = cmd.
arguments().takeFirst().toFloat(&ok);
187 "Invalid number for Max Normal Deviation!");
189 cmd.
print(QObject::tr(
"\tMax Normal Deviation : %1")
191 params.maxNormalDev_deg = val;
195 QObject::tr(
"Missing parameter: number after "
200 float val = cmd.
arguments().takeFirst().toFloat(&ok);
202 return cmd.
error(
"Invalid number for Probability!");
204 cmd.
print(QObject::tr(
"\tProbability : %1").arg(val));
207 params.randomColor =
true;
210 &outputIndividualClouds)) {
215 &outputIndividualPrimitives)) {
225 &outputIndividualPairs)) {
229 outputIndividualClouds =
true;
231 outputIndividualPrimitives =
true;
233 outputIndividualPairs =
true;
235 outputGrouped =
true;
239 QObject::tr(
"Missing parameter: primitive type "
243 QString prim = cmd.
arguments().takeFirst().toUpper();
244 unsigned primCount = 0;
245 while (primitiveNames.contains(prim)) {
247 params.primEnabled[qRansacSD::RPT_PLANE] =
true;
250 params.primEnabled[qRansacSD::RPT_SPHERE] =
true;
253 params.primEnabled[qRansacSD::RPT_CYLINDER] =
true;
256 params.primEnabled[qRansacSD::RPT_CONE] =
true;
259 params.primEnabled[qRansacSD::RPT_TORUS] =
true;
265 prim = cmd.
arguments().takeFirst().toUpper();
268 if (!primitiveNames.contains(prim)) {
273 QObject::tr(
"No valid parameter: primitive "
274 "type after \"-%1 %2\"")
281 param = cmd.
arguments().takeFirst().toUpper();
283 if (!paramNames.contains(param)) {
287 unsigned char primCount = 0;
288 for (
unsigned char k = 0; k < 5; ++k) {
289 primCount +=
static_cast<unsigned>(
params.primEnabled[k]);
291 if (primCount == 0) {
292 cmd.
print(QObject::tr(
"\tDefault Shape Search == %1")
294 params.primEnabled[qRansacSD::RPT_PLANE] =
true;
296 if (!outputIndividualClouds && !outputIndividualPrimitives &&
297 !outputGrouped && !outputIndividualPairs) {
300 outputGrouped =
true;
305 clCloud.pc->getBoundingBox(bbMin, bbMax);
308 if (epsilonPercentage > 0.0f) {
309 params.epsilon = (epsilonPercentage * scale);
311 if (bitmapEpsilonPercentage > 0.0f) {
312 params.bitmapEpsilon = (bitmapEpsilonPercentage * scale);
314 if (epsilonABS > 0.0f) {
315 params.epsilon = epsilonABS;
317 if (bitmapEpsilonABS > 0.0f) {
318 params.bitmapEpsilon = bitmapEpsilonABS;
320 if (
params.epsilon < 0.0f) {
321 params.epsilon = (0.005f * scale);
323 if (
params.bitmapEpsilon < 0.0f) {
324 params.bitmapEpsilon = (0.01f * scale);
333 clCloud.basename +
"_" +
335 "_RANSAC_DETECTED_SHAPES",
336 outputGroupDir !=
"" ? outputGroupDir
339 clGroup, QString(),
nullptr,
342 if (!errorStr.isEmpty()) {
346 if (outputIndividualPrimitives || outputIndividualClouds ||
347 outputIndividualPairs) {
351 unsigned planeCount = 1;
352 unsigned sphereCount = 1;
353 unsigned cylinderCount = 1;
354 unsigned coneCount = 1;
355 unsigned torusCount = 1;
357 for (
auto meshObj : meshGroup) {
362 suffix = QString(
"_PLANE_%1")
363 .arg(planeCount, 4, 10,
367 suffix = QString(
"_SPHERE_%1")
368 .arg(sphereCount, 4, 10,
372 suffix = QString(
"_CYLINDER_%1")
373 .arg(cylinderCount, 4, 10,
377 suffix = QString(
"_CONE_%1")
378 .arg(coneCount, 4, 10,
382 suffix = QString(
"_TORUS_%1")
383 .arg(torusCount, 4, 10,
389 if (outputIndividualPairs) {
392 clCloud.basename +
"_" +
393 clCloud.pc->getName() + suffix +
395 outputPairDir !=
"" ? outputPairDir
398 clPair, QString(),
nullptr,
401 if (!errorStr.isEmpty()) {
406 cld->detachChild(mesh);
410 clCloud.basename +
"_" +
411 clCloud.pc->getName() + suffix +
413 outputCloudsDir !=
"" ? outputCloudsDir
415 cmd.
clouds().push_back(clCloudp);
418 clCloud.basename +
"_" +
419 clCloud.pc->getName() + suffix,
420 outputMeshesDir !=
"" ? outputMeshesDir
422 cmd.
meshes().push_back(clMesh);
423 if (outputIndividualClouds) {
425 if (!errorStr.isEmpty()) {
429 if (outputIndividualPrimitives) {
431 if (!errorStr.isEmpty()) {
443 if (!errorStr.isEmpty()) {
453 const QString& param,
455 bool* performOutput) {
459 "\nMissing parameter: Directory after \"-%1 %2\"")
462 QString arg = cmd.
arguments().takeFirst();
464 bool pathExists = dir.exists();
467 QObject::tr(
"\n%1 Does not exist\tcreating path").arg(arg));
468 pathExists = dir.mkpath(arg);
471 *outputPath = dir.cleanPath(arg);
472 cmd.
print(QObject::tr(
"\t%1 : %2").arg(param, *outputPath));
473 *performOutput =
true;
475 cmd.
print(QObject::tr(
"\n%1 path could not be created, skipping %2")
cmdLineReadable * params[]
bool autoSaveMode() const
virtual QStringList & arguments()=0
Returns the list of arguments.
virtual void warning(const QString &message) const =0
virtual void print(const QString &message) const =0
virtual bool error(const QString &message) const =0
bool silentMode() const
Returns the silent mode.
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 std::vector< CLMeshDesc > & meshes()
Currently opened meshes and their filename.
virtual std::vector< CLCloudDesc > & clouds()
Currently opened point clouds and their filename.
static ccMesh * ToMesh(ccHObject *obj)
Converts current object to ccMesh (if possible)
static ccPointCloud * ToPointCloud(ccHObject *obj, bool *isLockedVertices=nullptr)
Converts current object to 'equivalent' ccPointCloud.
Hierarchical CLOUDVIEWER Object.
unsigned filterChildren(Container &filteredChildren, bool recursive=false, CV_CLASS_ENUM filter=CV_TYPES::OBJECT, bool strict=false) const
Collects the children corresponding to a certain pattern.
std::vector< ccHObject * > Container
Standard instances container (for children, etc.)
virtual QString getName() const
Returns object name.
constexpr char BITMAP_EPSILON_PERCENTAGE_OF_SCALE[]
constexpr char OUT_RANDOM_COLOR[]
constexpr char OUT_GROUP_DIR[]
constexpr char PRIM_CYLINDER[]
constexpr char PRIM_PLANE[]
constexpr char PRIM_TORUS[]
constexpr char COMMAND_RANSAC[]
constexpr char OUTPUT_INDIVIDUAL_PRIMITIVES[]
constexpr char OUT_PAIR_DIR[]
constexpr char ENABLE_PRIMITIVE[]
constexpr char OUTPUT_GROUPED[]
constexpr char EPSILON_PERCENTAGE_OF_SCALE[]
constexpr char PRIM_SPHERE[]
constexpr char PRIM_CONE[]
constexpr char EPSILON_ABSOLUTE[]
constexpr char SUPPORT_POINTS[]
constexpr char OUT_CLOUD_DIR[]
constexpr char OUTPUT_INDIVIDUAL_PAIRED_CLOUD_PRIMITIVE[]
constexpr char PROBABILITY[]
constexpr char BITMAP_EPSILON_ABSOLUTE[]
constexpr char OUTPUT_INDIVIDUAL_SUBCLOUDS[]
constexpr char OUT_MESH_DIR[]
constexpr char MAX_NORMAL_DEV[]
Loaded cloud description.
Loaded group description.
virtual bool process(ccCommandLineInterface &cmd) override
Main process.
bool makePathIfPossible(ccCommandLineInterface &cmd, const QString ¶m, QString *outputPath, bool *performOutput)
Generic command interface.
Command(const QString &name, const QString &keyword)
Default constructor.