| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021 |
- #include "ccCommandLineParser.h"
- //Local
- #include "ccCommandCrossSection.h"
- #include "ccCommandLineCommands.h"
- #include "ccCommandRaster.h"
- #include "ccPluginInterface.h"
- //qCC_db
- #include <ccGenericMesh.h>
- #include <ccHObjectCaster.h>
- #include <ccProgressDialog.h>
- //qCC_io
- #include <AsciiFilter.h>
- #include <BinFilter.h>
- //qCC
- #include "ccConsole.h"
- #include <ui_commandLineDlg.h>
- //Qt
- #include <QDateTime>
- #include <QElapsedTimer>
- #include <QMessageBox>
- //system
- #include <unordered_set>
- //commands
- constexpr char COMMAND_HELP[] = "HELP";
- constexpr char COMMAND_SILENT_MODE[] = "SILENT";
- /*****************************************************/
- /*************** ccCommandLineParser *****************/
- /*****************************************************/
- void ccCommandLineParser::printVerbose(const QString& message) const
- {
- ccConsole::PrintVerbose(message);
- }
- void ccCommandLineParser::print(const QString& message) const
- {
- ccConsole::Print(message);
- }
- void ccCommandLineParser::printHigh(const QString& message) const
- {
- ccConsole::PrintHigh(message);
- }
- void ccCommandLineParser::printDebug(const QString& message) const
- {
- ccConsole::PrintDebug(message);
- }
- void ccCommandLineParser::warning(const QString& message) const
- {
- ccConsole::Warning(message);
- }
- void ccCommandLineParser::warningDebug(const QString& message) const
- {
- ccConsole::WarningDebug(message);
- }
- bool ccCommandLineParser::error(const QString& message) const
- {
- ccConsole::Error(message);
- return false;
- }
- bool ccCommandLineParser::errorDebug(const QString& message) const
- {
- ccConsole::ErrorDebug(message);
- return false;
- }
- int ccCommandLineParser::Parse(const QStringList& arguments, ccPluginInterfaceList& plugins)
- {
- if (arguments.size() < 2)
- {
- assert(false);
- return EXIT_SUCCESS;
- }
- //load arguments
- QScopedPointer<ccCommandLineParser> parser(new ccCommandLineParser);
-
- parser->registerBuiltInCommands();
- ccConsole::SetRefreshCycle(200);
- // 'massage' the arguments to properly handle single quotes
- {
- bool insideSingleQuoteSection = false;
- QString buffer;
- static const QChar SingleQuote{ '\'' };
- for (int currentArgIndex = 1; currentArgIndex < arguments.size(); ++currentArgIndex) // start from 1, as the first argument is always the executable file
- {
- QString arg = arguments[currentArgIndex];
- // argument starts with a single quote
- if (!insideSingleQuoteSection && arg.startsWith(SingleQuote))
- {
- if (arg.endsWith(SingleQuote))
- {
- // nothing to do, non-truncated argument
- }
- else
- {
- // we'll collect the next pieces to get the full argument
- insideSingleQuoteSection = true;
- buffer = arg.mid(1); // remove the single quote
- }
- }
- else if (insideSingleQuoteSection)
- {
- buffer += QChar(' ') + arg; // append the current argument to the previous one(s)
- if (arg.endsWith(SingleQuote))
- {
- insideSingleQuoteSection = false;
- arg = buffer.left(buffer.length() - 1); // remove the single quote
- }
- }
- if (!insideSingleQuoteSection)
- {
- parser->arguments().append(arg);
- }
- }
- if (insideSingleQuoteSection)
- {
- // the single quote section was not closed...
- parser->warning("Probably malformed command (missing closing simple quote)");
- // ...still, we'll try to proceed
- parser->arguments().append(buffer);
- }
- }
- //specific command: silent mode (will prevent the console dialog from appearing!
- if (ccCommandLineInterface::IsCommand(parser->arguments().front(), COMMAND_SILENT_MODE))
- {
- parser->arguments().pop_front();
- parser->toggleSilentMode(true);
- }
- QScopedPointer<QDialog> consoleDlg(nullptr);
- if (!parser->silentMode())
- {
- //show console
- consoleDlg.reset(new QDialog);
- Ui_commandLineDlg commandLineDlg;
- commandLineDlg.setupUi(consoleDlg.data());
- consoleDlg->show();
- ccConsole::Init(commandLineDlg.consoleWidget, consoleDlg.data());
- parser->fileLoadingParams().parentWidget = consoleDlg.data();
- QApplication::processEvents(); //Get rid of the spinner
- }
- else
- {
- //allows ccLog/ccConsole or ccCommandLineParser (print, warning, error) to output to the console
- ccConsole::Init(nullptr, nullptr, nullptr, true);
- }
- //load the plugins commands
- for ( ccPluginInterface *plugin : plugins )
- {
- if (!plugin)
- {
- assert(false);
- continue;
- }
- plugin->registerCommands(parser.data());
- }
- //parse input
- int result = parser->start(consoleDlg.data());
- if (!parser->silentMode())
- {
- if (result == EXIT_SUCCESS)
- QMessageBox::information(consoleDlg.data(), "Processed finished", "Job done");
- else
- QMessageBox::warning(consoleDlg.data(), "Processed finished", "An error occurred! Check console");
- }
- //release the parser before the console (as its dialogs may be chidren of the console)
- parser->cleanup();
- parser.reset();
- ccConsole::ReleaseInstance();
- return result;
- }
- ccCommandLineParser::ccCommandLineParser()
- : ccCommandLineInterface()
- , m_cloudExportFormat(BinFilter::GetFileFilter())
- , m_cloudExportExt(BinFilter::GetDefaultExtension())
- , m_meshExportFormat(BinFilter::GetFileFilter())
- , m_meshExportExt(BinFilter::GetDefaultExtension())
- , m_hierarchyExportFormat(BinFilter::GetFileFilter())
- , m_hierarchyExportExt(BinFilter::GetDefaultExtension())
- , m_orphans("orphans")
- , m_progressDialog(nullptr)
- , m_parentWidget(nullptr)
- {
- }
- ccCommandLineParser::~ccCommandLineParser()
- {
- if (m_progressDialog)
- {
- m_progressDialog->close();
- m_progressDialog->deleteLater();
- }
- }
- bool ccCommandLineParser::registerCommand(Command::Shared command)
- {
- if (!command)
- {
- assert(false);
- return false;
- }
- if (m_commands.contains(command->m_keyword))
- {
- assert(false);
- warning(QString("Internal error: keyword '%1' already registered (by command '%2')").arg(command->m_keyword, m_commands[command->m_keyword]->m_name));
- return false;
- }
- m_commands.insert(command->m_keyword, command);
- return true;
- }
- QString ccCommandLineParser::getExportFilename( const CLEntityDesc& entityDesc,
- QString extension/*=QString()*/,
- QString suffix/*=QString()*/,
- QString* baseOutputFilename/*=nullptr*/,
- bool forceNoTimestamp/*=false*/) const
- {
- //fetch the real entity
- const ccHObject* entity = entityDesc.getEntity();
- if (!entity)
- {
- assert(false);
- warning("[getExportFilename] Internal error: invalid input entity!");
- return QString();
- }
- //sub-item?
- if (entityDesc.indexInFile >= 0)
- {
- if (suffix.isEmpty())
- suffix = QString("%1").arg(entityDesc.indexInFile);
- else
- suffix.prepend(QString("%1_").arg(entityDesc.indexInFile));
- }
- QString baseName = entityDesc.basename;
- if (!suffix.isEmpty())
- {
- baseName += QString("_") + suffix;
- }
- QString outputFilename = baseName;
- if (m_addTimestamp && !forceNoTimestamp)
- {
- outputFilename += QString("_%1").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd_hh'h'mm_ss_zzz"));
- }
- if (!extension.isEmpty())
- {
- outputFilename += '.' + extension;
- }
- if (baseOutputFilename)
- {
- *baseOutputFilename = outputFilename;
- }
- if (!entityDesc.path.isEmpty())
- {
- outputFilename.prepend(entityDesc.path + '/');
- }
- return outputFilename;
- }
- QString ccCommandLineParser::exportEntity( CLEntityDesc& entityDesc,
- const QString& suffix/*=QString()*/,
- QString* baseOutputFilename/*=nullptr*/,
- ccCommandLineInterface::ExportOptions options/*ExportOptiopn::NoOption*/)
- {
- print("[SAVING]");
- //fetch the real entity
- ccHObject* entity = entityDesc.getEntity();
- if (!entity)
- {
- assert(false);
- return "[ExportEntity] Internal error: invalid input entity!";
- }
- bool anyForced = options.testFlag(ExportOption::ForceCloud) | options.testFlag(ExportOption::ForceHierarchy) | options.testFlag(ExportOption::ForceMesh);
- //specific case: clouds
- bool isCloud = entity->isA(CC_TYPES::POINT_CLOUD) || entityDesc.getCLEntityType() == CL_ENTITY_TYPE::CLOUD;
- //specific case: mesh
- bool isMesh = entity->isKindOf(CC_TYPES::MESH) || entityDesc.getCLEntityType() == CL_ENTITY_TYPE::MESH;
- QString extension = isCloud ? m_cloudExportExt : isMesh ? m_meshExportExt : m_hierarchyExportExt;
- QString format = isCloud ? m_cloudExportFormat : isMesh ? m_meshExportFormat : m_hierarchyExportFormat;
- if (anyForced)
- {
- if (options.testFlag(ExportOption::ForceCloud))
- {
- extension = m_cloudExportExt;
- format = m_cloudExportFormat;
- }
- if (options.testFlag(ExportOption::ForceMesh))
- {
- extension = m_meshExportExt;
- format = m_meshExportFormat;
- }
- if (options.testFlag(ExportOption::ForceHierarchy))
- {
- extension = m_hierarchyExportExt;
- format = m_hierarchyExportFormat;
- }
- }
- QString outputFilename = getExportFilename( entityDesc,
- extension,
- suffix,
- baseOutputFilename,
- options.testFlag(ExportOption::ForceNoTimestamp) );
- if (outputFilename.isEmpty())
- {
- return QString();
- }
- //update the entity name as well
- {
- QString entName = entity->getName();
- if (entName.isEmpty())
- {
- entName = entityDesc.basename;
- }
- if (!suffix.isEmpty())
- {
- entName += QString("_") + suffix;
- }
- entity->setName(entName);
- }
- bool tempDependencyCreated = false;
- ccGenericMesh* mesh = nullptr;
- if (entity->isKindOf(CC_TYPES::MESH) && m_meshExportFormat == BinFilter::GetFileFilter())
- {
- //in a BIN file we must save the vertices cloud as well if it's not a child of the mesh!
- mesh = static_cast<ccGenericMesh*>(entity);
- ccGenericPointCloud* vertices = mesh->getAssociatedCloud();
- if (vertices && !mesh->isAncestorOf(vertices))
- {
- //we save the cloud first!
- vertices->addChild(mesh, ccHObject::DP_NONE); //we simply add a fake dependency
- entity = vertices;
- tempDependencyCreated = true;
- }
- }
- //save file
- FileIOFilter::SaveParameters parameters;
- {
- //no dialog by default for command line mode!
- parameters.alwaysDisplaySaveDialog = false;
- if (!silentMode() && ccConsole::TheInstance())
- {
- parameters.parentWidget = ccConsole::TheInstance()->parentWidget();
- }
- }
- #ifdef _DEBUG
- print("Output filename: " + outputFilename);
- #endif
- CC_FILE_ERROR result = FileIOFilter::SaveToFile(entity,
- outputFilename,
- parameters,
- format);
- //restore input state!
- if (tempDependencyCreated)
- {
- if (mesh && entity)
- {
- entity->detachChild(mesh);
- }
- else
- {
- assert(false);
- }
- }
- return (result != CC_FERR_NO_ERROR ? QString("Failed to save result in file '%1'").arg(outputFilename) : QString());
- }
- template<class EntityDesc > bool SelectEntities(ccCommandLineInterface::SelectEntitiesOptions options,
- const ccCommandLineParser& cmd,
- std::vector<EntityDesc>& selectedEntities,
- std::vector<EntityDesc>& unselectedEntities,
- QString entityType)
- {
- //early abort if no cloud found
- if (selectedEntities.empty() && unselectedEntities.empty())
- {
- //do not stop execution, just warn the user and return
- cmd.warning(QObject::tr("\tNo %1 loaded. Load some with the -O command").arg(entityType));
- return true;
- }
- if (options.selectRegex && !options.regex.isValid())
- {
- return cmd.error(QObject::tr("Regex string invalid: %1").arg(options.regex.errorString()));
- }
- try
- {
- //store everthyng in the unselected vector
- unselectedEntities.insert(unselectedEntities.end(), selectedEntities.begin(), selectedEntities.end());
- selectedEntities.clear();
- //sort the unselected clouds by uniqueID (so as to restore the order in which they were loaded/created)
- std::sort(unselectedEntities.begin(), unselectedEntities.end(), [](const EntityDesc& a, const EntityDesc& b) { return (a.getEntity()->getUniqueID() < b.getEntity()->getUniqueID()); });
- //put elements to the front facing vector
- unsigned index = 0;
- assert(!unselectedEntities.empty()); // we have tested above that neither selectedEntities and unselectedEntities are both empty
- size_t lastIndex = unselectedEntities.size() - 1;
- for (typename std::vector<EntityDesc>::iterator it = unselectedEntities.begin(); it != unselectedEntities.end();)
- {
- QString nameToValidate = QObject::tr("%1/%2").arg(it->basename).arg(it->getEntity()->getName());
- bool toBeSelected = false;
- if (!options.reverse)
- {
- //first {n}
- if (options.selectFirst && index < options.firstNr)
- {
- toBeSelected = true;
- }
- //last {n}
- if (options.selectLast && index > lastIndex - options.lastNr)
- {
- toBeSelected = true;
- }
- }
- else
- {
- //not first {n}
- if (options.selectFirst && index >= options.firstNr && !options.selectLast)
- {
- toBeSelected = true;
- }
- //not last {n}
- if (options.selectLast && index <= lastIndex - options.lastNr && !options.selectFirst)
- {
- toBeSelected = true;
- }
- //not first and not last
- if (options.selectFirst && options.selectLast && index >= options.firstNr && index <= lastIndex - options.lastNr)
- {
- toBeSelected = true;
- }
- }
- //regex has higher priority than first/last overwrite
- if (options.selectRegex)
- {
- if (options.regex.indexIn(nameToValidate) > -1)
- {
- //regex matched
- toBeSelected = !options.reverse;
- }
- else
- {
- //regex not matched
- toBeSelected = options.reverse;
- }
- }
- //selectAll has higher priority than first/last/regex overwrite
- if (options.selectAll)
- {
- toBeSelected = !options.reverse;
- }
- if (toBeSelected)
- {
- cmd.print(QObject::tr("\t[*] UID: %2 name: %1").arg(nameToValidate).arg(it->getEntity()->getUniqueID()));
- selectedEntities.push_back(*it);
- it = unselectedEntities.erase(it);
- }
- else
- {
- cmd.print(QObject::tr("\t[ ] UID: %2 name: %1").arg(nameToValidate).arg(it->getEntity()->getUniqueID()));
- ++it;
- }
- index++;
- }
- }
- catch (const std::bad_alloc&)
- {
- return cmd.error(QObject::tr("Not enough memory"));
- }
- return true;
- }
- bool ccCommandLineParser::selectClouds(const SelectEntitiesOptions& options)
- {
- return SelectEntities(options, *this, m_clouds, m_unselectedClouds, "cloud");
- }
- bool ccCommandLineParser::selectMeshes(const SelectEntitiesOptions& options)
- {
- return SelectEntities(options, *this, m_meshes, m_unselectedMeshes, "mesh");
- }
- void ccCommandLineParser::removeClouds(bool onlyLast/*=false*/)
- {
- while (!m_clouds.empty())
- {
- delete m_clouds.back().pc;
- m_clouds.pop_back();
- if (onlyLast)
- break;
- }
- }
- void ccCommandLineParser::removeMeshes(bool onlyLast/*=false*/)
- {
- while (!m_meshes.empty())
- {
- delete m_meshes.back().mesh;
- m_meshes.pop_back();
- if (onlyLast)
- break;
- }
- }
- //! Whether Global (coordinate) shift has already been defined
- static bool s_firstCoordinatesShiftEnabled = false;
- //! Global shift (if defined)
- static CCVector3d s_firstGlobalShift;
- //! First time the global shift is set/defined
- static bool s_globalShiftFirstTime = true;
- void ccCommandLineParser::setGlobalShiftOptions(const GlobalShiftOptions& globalShiftOptions)
- {
- //default Global Shift handling parameters
- m_loadingParameters.shiftHandlingMode = ccGlobalShiftManager::NO_DIALOG;
- m_loadingParameters.coordinatesShiftEnabled = false;
- m_loadingParameters.coordinatesShift = CCVector3d(0, 0, 0);
- switch (globalShiftOptions.mode)
- {
- case GlobalShiftOptions::AUTO_GLOBAL_SHIFT:
- //let CC handle the global shift automatically
- m_loadingParameters.shiftHandlingMode = ccGlobalShiftManager::NO_DIALOG_AUTO_SHIFT;
- break;
- case GlobalShiftOptions::FIRST_GLOBAL_SHIFT:
- //use the first encountered global shift value (if any)
- if (s_globalShiftFirstTime)
- {
- ccLog::Warning("Can't reuse the first Global Shift (no global shift set yet)");
- m_loadingParameters.shiftHandlingMode = ccGlobalShiftManager::NO_DIALOG_AUTO_SHIFT;
- }
- else
- {
- m_loadingParameters.coordinatesShiftEnabled = s_firstCoordinatesShiftEnabled;
- m_loadingParameters.coordinatesShift = s_firstGlobalShift;
- }
- break;
- case GlobalShiftOptions::CUSTOM_GLOBAL_SHIFT:
- //set the user defined shift vector as default shift information
- m_loadingParameters.coordinatesShiftEnabled = true;
- m_loadingParameters.coordinatesShift = globalShiftOptions.customGlobalShift;
- break;
- default:
- //nothing to do
- break;
- }
- }
- void ccCommandLineParser::updateInteralGlobalShift(const GlobalShiftOptions& globalShiftOptions)
- {
- if (globalShiftOptions.mode != GlobalShiftOptions::NO_GLOBAL_SHIFT)
- {
- if (s_globalShiftFirstTime)
- {
- // remember the first Global Shift parameters used
- s_firstCoordinatesShiftEnabled = m_loadingParameters.coordinatesShiftEnabled;
- s_firstGlobalShift = m_loadingParameters.coordinatesShift;
- s_globalShiftFirstTime = false;
- }
- }
- }
- bool ccCommandLineParser::importFile(QString filename, const GlobalShiftOptions& globalShiftOptions, FileIOFilter::Shared filter)
- {
- printHigh(QString("Opening file: '%1'").arg(filename));
- setGlobalShiftOptions(globalShiftOptions);
- CC_FILE_ERROR result = CC_FERR_NO_ERROR;
- ccHObject* db = nullptr;
- if (filter)
- {
- db = FileIOFilter::LoadFromFile(filename, m_loadingParameters, filter, result);
- }
- else
- {
- db = FileIOFilter::LoadFromFile(filename, m_loadingParameters, result, QString());
- }
- if (!db)
- {
- return false/*cmd.error(QString("Failed to open file '%1'").arg(filename))*/; //Error message already issued
- }
- updateInteralGlobalShift(globalShiftOptions);
- std::unordered_set<unsigned> verticesIDs;
- //first look for meshes inside loaded DB (so that we don't consider mesh vertices as clouds!)
- {
- ccHObject::Container meshes;
- size_t count = 0;
- //first look for all REAL meshes (so as to no consider sub-meshes)
- if (db->filterChildren(meshes, true, CC_TYPES::MESH, true) != 0)
- {
- count += meshes.size();
- for (size_t i = 0; i < meshes.size(); ++i)
- {
- ccGenericMesh* mesh = ccHObjectCaster::ToGenericMesh(meshes[i]);
- if (mesh->getParent())
- {
- mesh->getParent()->detachChild(mesh);
- }
- ccGenericPointCloud* vertices = mesh->getAssociatedCloud();
- if (vertices)
- {
- verticesIDs.insert(vertices->getUniqueID());
- print(QString("Found one mesh with %1 faces and %2 vertices: '%3'").arg(mesh->size()).arg(mesh->getAssociatedCloud()->size()).arg(mesh->getName()));
- m_meshes.emplace_back(mesh, filename, count == 1 ? -1 : static_cast<int>(i));
- }
- else
- {
- delete mesh;
- mesh = nullptr;
- assert(false);
- }
- }
- }
- //then look for the other meshes
- meshes.clear();
- if (db->filterChildren(meshes, true, CC_TYPES::MESH, false) != 0)
- {
- size_t countBefore = count;
- count += meshes.size();
- for (size_t i = 0; i < meshes.size(); ++i)
- {
- ccGenericMesh* mesh = ccHObjectCaster::ToGenericMesh(meshes[i]);
- if (mesh->getParent())
- mesh->getParent()->detachChild(mesh);
- ccGenericPointCloud* vertices = mesh->getAssociatedCloud();
- if (vertices)
- {
- verticesIDs.insert(vertices->getUniqueID());
- print(QString("Found one kind of mesh with %1 faces and %2 vertices: '%3'").arg(mesh->size()).arg(mesh->getAssociatedCloud()->size()).arg(mesh->getName()));
- m_meshes.emplace_back(mesh, filename, count == 1 ? -1 : static_cast<int>(countBefore + i));
- }
- else
- {
- delete mesh;
- mesh = nullptr;
- assert(false);
- }
- }
- }
- }
- //now look for the remaining clouds inside loaded DB
- {
- ccHObject::Container clouds;
- db->filterChildren(clouds, true, CC_TYPES::POINT_CLOUD);
- size_t count = clouds.size();
- for (size_t i = 0; i < count; ++i)
- {
- ccPointCloud* pc = static_cast<ccPointCloud*>(clouds[i]);
- if (pc->getParent())
- {
- pc->getParent()->detachChild(pc);
- }
- //if the cloud is a set of vertices, we ignore it!
- if (verticesIDs.find(pc->getUniqueID()) != verticesIDs.end())
- {
- m_orphans.addChild(pc);
- continue;
- }
- print(QString("Found one cloud with %1 points").arg(pc->size()));
- m_clouds.emplace_back(pc, filename, count == 1 ? -1 : static_cast<int>(i));
- }
- }
- delete db;
- db = nullptr;
- return true;
- }
- bool ccCommandLineParser::saveClouds(QString suffix/*=QString()*/, bool allAtOnce/*=false*/, const QString* allAtOnceFileName/*=nullptr*/)
- {
- //all-at-once: all clouds in a single file
- if (allAtOnce)
- {
- FileIOFilter::Shared filter = FileIOFilter::GetFilter(m_cloudExportFormat, false);
- bool multiple = false;
- if (filter)
- {
- bool exclusive = true;
- filter->canSave(CC_TYPES::POINT_CLOUD, multiple, exclusive);
- }
- if (multiple)
- {
- ccHObject tempContainer("Clouds");
- {
- for (CLCloudDesc& desc : m_clouds)
- {
- tempContainer.addChild(desc.getEntity(), ccHObject::DP_NONE);
- }
- }
- //save output
- CLGroupDesc desc(&tempContainer, "AllClouds", m_clouds.front().path);
- if (allAtOnceFileName)
- {
- CommandSave::SetFileDesc(desc, *allAtOnceFileName);
- }
- QString errorStr = exportEntity(desc, suffix, nullptr, ExportOption::ForceCloud);
- if (!errorStr.isEmpty())
- return error(errorStr);
- else
- return true;
- }
- else
- {
- error(QString("The currently selected output format for clouds (%1) doesn't handle multiple entities at once!").arg(m_cloudExportFormat));
- //will proceed with the standard way
- }
- }
- //standard way: one file per cloud
- {
- for (CLCloudDesc& desc : m_clouds)
- {
- //save output
- QString errorStr = exportEntity(desc, suffix);
- if (!errorStr.isEmpty())
- return error(errorStr);
- }
- }
- return true;
- }
- bool ccCommandLineParser::saveMeshes(QString suffix/*=QString()*/, bool allAtOnce/*=false*/, const QString* allAtOnceFileName/*=nullptr*/)
- {
- //all-at-once: all meshes in a single file
- if (allAtOnce)
- {
- FileIOFilter::Shared filter = FileIOFilter::GetFilter(m_meshExportFormat, false);
- bool multiple = false;
- if (filter)
- {
- bool exclusive = true;
- filter->canSave(CC_TYPES::MESH, multiple, exclusive);
- }
- if (multiple)
- {
- ccHObject tempContainer("Meshes");
- {
- for (auto &mesh : m_meshes)
- {
- tempContainer.addChild(mesh.getEntity(), ccHObject::DP_NONE);
- }
- }
- //save output
- CLGroupDesc desc(&tempContainer, "AllMeshes", m_meshes.front().path);
- if (allAtOnceFileName)
- {
- CommandSave::SetFileDesc(desc, *allAtOnceFileName);
- }
- QString errorStr = exportEntity(desc, suffix, nullptr, ExportOption::ForceMesh);
- if (!errorStr.isEmpty())
- return error(errorStr);
- else
- return true;
- }
- else
- {
- error(QString("The currently selected output format for meshes (%1) doesn't handle multiple entities at once!").arg(m_meshExportFormat));
- //will proceed with the standard way
- }
- }
- //standard way: one file per mesh
- for (auto &mesh : m_meshes)
- {
- //save output
- QString errorStr = exportEntity(mesh, suffix);
- if (!errorStr.isEmpty())
- return error(errorStr);
- }
- return true;
- }
- void ccCommandLineParser::registerBuiltInCommands()
- {
- registerCommand(Command::Shared(new CommandDebugCmdLine));
- registerCommand(Command::Shared(new CommandLoad));
- registerCommand(Command::Shared(new CommandLoadCommandFile));
- registerCommand(Command::Shared(new CommandSubsample));
- registerCommand(Command::Shared(new CommandExtractCCs));
- registerCommand(Command::Shared(new CommandCurvature));
- registerCommand(Command::Shared(new CommandApproxDensity));
- registerCommand(Command::Shared(new CommandDensity));
- registerCommand(Command::Shared(new CommandSFGradient));
- registerCommand(Command::Shared(new CommandRoughness));
- registerCommand(Command::Shared(new CommandApplyTransformation));
- registerCommand(Command::Shared(new CommandDropGlobalShift));
- registerCommand(Command::Shared(new CommandFilterBySFValue));
- registerCommand(Command::Shared(new CommandMergeClouds));
- registerCommand(Command::Shared(new CommandMergeMeshes));
- registerCommand(Command::Shared(new CommandSetActiveSF));
- registerCommand(Command::Shared(new CommandSetGlobalShift));
- registerCommand(Command::Shared(new CommandRemoveAllSFs));
- registerCommand(Command::Shared(new CommandRemoveSF));
- registerCommand(Command::Shared(new CommandRemoveRGB));
- registerCommand(Command::Shared(new CommandRemoveNormals));
- registerCommand(Command::Shared(new CommandRemoveScanGrids));
- registerCommand(Command::Shared(new CommandRemoveSensors));
- registerCommand(Command::Shared(new CommandMatchBBCenters));
- registerCommand(Command::Shared(new CommandMatchBestFitPlane));
- registerCommand(Command::Shared(new CommandOrientNormalsMST));
- registerCommand(Command::Shared(new CommandSORFilter));
- registerCommand(Command::Shared(new CommandNoiseFilter));
- registerCommand(Command::Shared(new CommandRemoveDuplicatePoints));
- registerCommand(Command::Shared(new CommandSampleMesh));
- registerCommand(Command::Shared(new CommandCompressFWF));
- registerCommand(Command::Shared(new CommandExtractVertices));
- registerCommand(Command::Shared(new CommandCrossSection));
- registerCommand(Command::Shared(new CommandCrop));
- registerCommand(Command::Shared(new CommandCrop2D));
- registerCommand(Command::Shared(new CommandCoordToSF));
- registerCommand(Command::Shared(new CommandSFToCoord));
- registerCommand(Command::Shared(new CommandColorBanding));
- registerCommand(Command::Shared(new CommandColorLevels));
- registerCommand(Command::Shared(new CommandC2MDist));
- registerCommand(Command::Shared(new CommandC2CDist));
- registerCommand(Command::Shared(new CommandCPS));
- registerCommand(Command::Shared(new CommandStatTest));
- registerCommand(Command::Shared(new CommandDelaunayTri));
- registerCommand(Command::Shared(new CommandSFArithmetic));
- registerCommand(Command::Shared(new CommandSFOperation));
- registerCommand(Command::Shared(new CommandSFOperationSF));
- registerCommand(Command::Shared(new CommandSFInterpolation));
- registerCommand(Command::Shared(new CommandColorInterpolation));
- registerCommand(Command::Shared(new CommandFilter));
- registerCommand(Command::Shared(new CommandRenameEntities));
- registerCommand(Command::Shared(new CommandSFRename));
- registerCommand(Command::Shared(new CommandSFAddConst));
- registerCommand(Command::Shared(new CommandSFAddId));
- registerCommand(Command::Shared(new CommandICP));
- registerCommand(Command::Shared(new CommandChangeCloudOutputFormat));
- registerCommand(Command::Shared(new CommandChangeMeshOutputFormat));
- registerCommand(Command::Shared(new CommandChangeHierarchyOutputFormat));
- registerCommand(Command::Shared(new CommandChangePLYExportFormat));
- registerCommand(Command::Shared(new CommandForceNormalsComputation));
- registerCommand(Command::Shared(new CommandSaveClouds));
- registerCommand(Command::Shared(new CommandSaveMeshes));
- registerCommand(Command::Shared(new CommandAutoSave));
- registerCommand(Command::Shared(new CommandLogFile));
- registerCommand(Command::Shared(new CommandSelectEntities));
- registerCommand(Command::Shared(new CommandClear));
- registerCommand(Command::Shared(new CommandClearClouds));
- registerCommand(Command::Shared(new CommandPopClouds));
- registerCommand(Command::Shared(new CommandClearMeshes));
- registerCommand(Command::Shared(new CommandPopMeshes));
- registerCommand(Command::Shared(new CommandSetNoTimestamp));
- registerCommand(Command::Shared(new CommandVolume25D));
- registerCommand(Command::Shared(new CommandRasterize));
- registerCommand(Command::Shared(new CommandOctreeNormal));
- registerCommand(Command::Shared(new CommandConvertNormalsToDipAndDipDir));
- registerCommand(Command::Shared(new CommandConvertNormalsToSFs));
- registerCommand(Command::Shared(new CommandConvertNormalsToHSV));
- registerCommand(Command::Shared(new CommandClearNormals));
- registerCommand(Command::Shared(new CommandInvertNormal));
- registerCommand(Command::Shared(new CommandComputeMeshVolume));
- registerCommand(Command::Shared(new CommandSFColorScale));
- registerCommand(Command::Shared(new CommandSFConvertToRGB));
- registerCommand(Command::Shared(new CommandMoment));
- registerCommand(Command::Shared(new CommandFeature));
- registerCommand(Command::Shared(new CommandRGBConvertToSF));
- registerCommand(Command::Shared(new CommandFlipTriangles));
- registerCommand(Command::Shared(new CommandSetVerbosity));
- }
- void ccCommandLineParser::cleanup()
- {
- removeClouds();
- removeMeshes();
- }
- int ccCommandLineParser::start(QDialog* parent/*=nullptr*/)
- {
- if (m_arguments.empty())
- {
- assert(false);
- return EXIT_FAILURE;
- }
- m_parentWidget = parent;
- //if (!m_silentMode)
- //{
- // m_progressDialog = new ccProgressDialog(false, parent);
- // //m_progressDialog->setAttribute(Qt::WA_DeleteOnClose);
- // m_progressDialog->setAutoClose(false);
- // m_progressDialog->hide();
- //}
- QElapsedTimer eTimer;
- eTimer.start();
- bool success = true;
- while (success && !m_arguments.empty())
- {
- QApplication::processEvents(); //Without this the console is just a spinner until the end of all processing
- QString argument = m_arguments.takeFirst();
- if (!argument.startsWith("-"))
- {
- error(QString("Command expected (commands start with '-'). Found '%1'").arg(argument));
- success = false;
- break;
- }
- QString keyword = argument.mid(1).toUpper();
- if (m_commands.contains(keyword))
- {
- assert(m_commands[keyword]);
- QElapsedTimer eTimerSubProcess;
- eTimerSubProcess.start();
- QString processName = m_commands[keyword]->m_name.toUpper();
- printHigh(QString("[%1]").arg(processName));
- success = m_commands[keyword]->process(*this);
- printHigh(QString("[%2] finished in %1 s.").arg(eTimerSubProcess.elapsed() / 1.0e3, 0, 'f', 2).arg(processName));
- }
- //silent mode (i.e. no console)
- else if (keyword == COMMAND_SILENT_MODE)
- {
- warning(QString("Misplaced command: '%1' (must be first)").arg(COMMAND_SILENT_MODE));
- }
- else if (keyword == COMMAND_HELP)
- {
- print("Available commands:");
- for (auto it = m_commands.constBegin(); it != m_commands.constEnd(); ++it)
- {
- print(QString("-%1: %2").arg(it.key().toUpper(), it.value()->m_name));
- }
- }
- else
- {
- error(QString("Unknown or misplaced command: '%1'").arg(argument));
- success = false;
- break;
- }
- }
- print(QString("Processed finished in %1 s.").arg(eTimer.elapsed() / 1.0e3, 0, 'f', 2));
- return success ? EXIT_SUCCESS : EXIT_FAILURE;
- }
|