12 #include <QMessageBox>
63 QString(
"Unknwon projection type: %1 (defaulting to 'average')")
81 cmd.
warning(QString(
"Unknwon empty cell filling strategy: %1 "
82 "(defaulting to 'leave empty')")
92 cmd.
print(
"[RASTERIZE]");
96 bool outputCloud =
false;
97 bool outputRasterZ =
false;
98 bool outputRasterRGB =
false;
99 bool outputMesh =
false;
100 bool resample =
false;
101 double customHeight = std::numeric_limits<double>::quiet_NaN();
111 QString argument = cmd.
arguments().front();
119 "Can't output the grid as a mesh AND a cloud at the "
131 "Can't output the grid as a mesh AND a cloud at the "
141 outputRasterZ =
true;
147 outputRasterRGB =
true;
154 gridStep = cmd.
arguments().takeFirst().toDouble(&ok);
155 if (!ok || gridStep <= 0) {
156 return cmd.
error(QString(
"Invalid grid step value! (after %1)")
165 customHeight = cmd.
arguments().takeFirst().toDouble(&ok);
168 QString(
"Invalid custom height value! (after %1)")
177 vertDir = cmd.
arguments().takeFirst().toInt(&ok);
178 if (!ok || vertDir < 0 || vertDir > 2) {
179 return cmd.
error(QString(
"Invalid vert. direction! (after %1)")
188 cmd.
arguments().takeFirst().toUpper(), cmd);
195 cmd.
arguments().takeFirst().toUpper(), cmd);
202 cmd.
arguments().takeFirst().toUpper(), cmd);
215 return cmd.
error(QString(
"Grid step value not defined (use %1)")
220 std::isnan(customHeight)) {
222 "[Rasterize] The filling stragety is set to 'fill with custom "
223 "height' but no custom height was defined...");
227 if (!outputCloud && !outputMesh && !outputRasterZ && !outputRasterRGB) {
231 assert(outputCloud || outputMesh);
233 if (resample && !outputCloud && !outputMesh) {
235 "[Rasterize] The 'resample' option is set while the raster "
236 "won't be exported as a cloud nor as a mesh");
248 unsigned gridWidth = 0;
249 unsigned gridHeight = 0;
251 gridWidth, gridHeight)) {
253 "Failed to compute the grid dimensions (check input "
254 "cloud(s) bounding-box)");
257 cmd.
print(QString(
"Grid size: %1 x %2").arg(gridWidth).arg(gridHeight));
259 if (gridWidth * gridHeight > (1 << 26))
264 static bool s_firstTime =
true;
266 QMessageBox::warning(
268 "Grid size is huge. Are you sure you want to "
269 "proceed?\n(you can avoid this message by running "
272 QMessageBox::No) == QMessageBox::No) {
284 if (!grid.
init(gridWidth, gridHeight, gridStep, minCorner)) {
286 return cmd.
error(
"Not enough memory");
290 QScopedPointer<ecvProgressDialog> pDlg(
nullptr);
295 if (grid.
fillWith(cloudDesc.pc, vertDir, projectionType,
296 emptyCellFillStrategy ==
298 sfProjectionType, pDlg.data())) {
300 cmd.
print(QString(
"[Rasterize] Raster grid: size: %1 x %2 / "
301 "heights: [%3 ; %4]")
307 return cmd.
error(
"Rasterize process failed");
312 if (outputCloud || outputMesh) {
313 std::vector<ccRasterGrid::ExportableFields> exportedFields;
317 }
catch (
const std::bad_alloc&) {
318 return cmd.
error(
"Not enough memory");
322 exportedFields,
true,
true, resample, resample,
323 cloudDesc.pc, vertDir, gridBBox,
328 return cmd.
error(
"Failed to output the raster grid as a cloud");
331 rasterCloud->
showColors(cloudDesc.pc->hasColors());
333 rasterCloud->
showSF(!cloudDesc.pc->hasColors());
344 cloudDesc.pc = rasterCloud;
345 cloudDesc.basename += QString(
"_RASTER");
347 rasterCloud =
nullptr;
351 if (!errorStr.isEmpty()) {
352 return cmd.
error(errorStr);
355 }
else if (outputMesh) {
356 std::string errorStr;
362 IGNORE_MAX_EDGE_LENGTH,
377 rasterCloud =
nullptr;
379 cmd.
print(QString(
"[Rasterize] Mesh '%1' successfully "
384 meshDesc.
mesh = rasterMesh;
386 cloudDesc.basename + QString(
"_RASTER_MESH");
387 meshDesc.
path = cloudDesc.path;
390 if (!errorStr.isEmpty()) {
392 return cmd.
error(errorStr);
396 cmd.
meshes().push_back(meshDesc);
400 cmd.
warning(QString(
"[Rasterize] Failed to create output "
402 .arg(QString::fromStdString(errorStr)));
408 rasterCloud =
nullptr;
421 cloudDesc,
"tif",
"RASTER_Z",
nullptr, !cmd.
addTimestamp());
422 if (exportFilename.isEmpty()) {
423 exportFilename =
"rasterZ.tif";
427 exportFilename, bands, emptyCellFillStrategy, grid,
428 gridBBox, vertDir, customHeight, cloudDesc.pc);
431 if (outputRasterRGB) {
439 QString exportFilename =
442 if (exportFilename.isEmpty()) {
443 exportFilename =
"rasterRGB.tif";
447 exportFilename, bands, emptyCellFillStrategy, grid,
448 gridBBox, vertDir, customHeight, cloudDesc.pc);
460 cmd.
print(
"[2.5D VOLUME]");
463 bool groundIsFirst =
false;
465 double constHeight = std::numeric_limits<double>::quiet_NaN();
466 bool outputMesh =
false;
470 QString argument = cmd.
arguments().front();
476 groundIsFirst =
true;
489 gridStep = cmd.
arguments().takeFirst().toDouble(&ok);
490 if (!ok || gridStep <= 0) {
491 return cmd.
error(QString(
"Invalid grid step value! (after %1)")
500 constHeight = cmd.
arguments().takeFirst().toDouble(&ok);
503 QString(
"Invalid const. height value! (after %1)")
512 vertDir = cmd.
arguments().takeFirst().toInt(&ok);
513 if (!ok || vertDir < 0 || vertDir > 2) {
514 return cmd.
error(QString(
"Invalid vert. direction! (after %1)")
524 return cmd.
error(QString(
"Grid step value not defined (use %1)")
534 if (!cmd.
clouds().empty()) {
535 clouds[index++] = &cmd.
clouds()[0];
536 if (std::isnan(constHeight) && cmd.
clouds().size() > 1) {
537 clouds[index++] = &cmd.
clouds()[1];
541 int expectedCount = std::isnan(constHeight) ? 2 : 1;
542 if (index != expectedCount) {
543 return cmd.
error(QString(
"Not enough loaded entities (%1 found, %2 "
546 .arg(expectedCount));
549 if (index == 2 && groundIsFirst) {
564 unsigned gridWidth = 0;
565 unsigned gridHeight = 0;
569 "Failed to compute the grid dimensions (check input cloud(s) "
573 cmd.
print(QString(
"Grid size: %1 x %2").arg(gridWidth).arg(gridHeight));
575 if (gridWidth * gridHeight > (1 << 26))
580 static bool s_firstTime =
true;
583 "Grid size is huge. Are you sure you want "
584 "to proceed?\n(you can avoid this message "
585 "by running in SILENT mode)",
587 QMessageBox::No) == QMessageBox::No) {
597 grid, ground ? ground->
pc :
nullptr,
ceil ?
ceil->pc :
nullptr,
598 gridBBox, vertDir, gridStep, gridWidth, gridHeight,
607 QString txtFilename =
608 QString(
"%1/VolumeCalculationReport").arg(desc->
path);
610 txtFilename += QString(
"_%1").arg(
611 QDateTime::currentDateTime().
toString(
612 "yyyy-MM-dd_hh'h'mm"));
613 txtFilename += QString(
".txt");
615 QFile txtFile(txtFilename);
616 txtFile.open(QIODevice::WriteOnly | QIODevice::Text);
617 QTextStream txtStream(&txtFile);
625 grid, gridBBox, vertDir,
true);
627 return cmd.
error(
"Failed to output the volume grid");
636 ccMesh* rasterMesh =
nullptr;
638 std::string errorStr;
644 IGNORE_MAX_EDGE_LENGTH,
648 rasterMesh =
new ccMesh(baseMesh, rasterCloud);
658 rasterCloud->
setName(
"vertices");
663 QString(
"[Volume] Mesh '%1' successfully generated")
668 QString(
"[Voume] Failed to create output "
670 .arg(QString::fromStdString(errorStr)));
677 meshDesc.
mesh = rasterMesh;
680 cmd.
meshes().push_back(meshDesc);
681 outputDesc = &cmd.
meshes().back();
684 cloudDesc.
pc = rasterCloud;
687 cmd.
clouds().push_back(cloudDesc);
688 outputDesc = &cmd.
clouds().back();
693 QString outputFilename;
695 *outputDesc,
"HEIGHT_DIFFERENCE", &outputFilename);
696 if (!errorStr.isEmpty()) cmd.
warning(errorStr);
700 return cmd.
error(
"Failed to compte the volume");
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
static Vector3Tpl fromArray(const int a[3])
Constructor from an int array.
virtual ccBBox getOwnBB(bool withGLFeatures=false) override
Returns the entity's own bounding-box.
bool autoSaveMode() const
bool addTimestamp() 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 QString getExportFilename(const CLEntityDesc &entityDesc, QString extension=QString(), QString suffix=QString(), QString *baseOutputFilename=nullptr, bool forceNoTimestamp=false) const =0
Returns the name of a to-be-exported entity.
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.
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 QDialog * widgetParent()
Returns a (widget) parent (if any is available)
virtual std::vector< CLCloudDesc > & clouds()
Currently opened point clouds and their filename.
virtual bool colorsShown() const
Returns whether colors are shown or not.
virtual void setVisible(bool state)
Sets entity visibility.
virtual bool sfShown() const
Returns whether active scalar field is visible.
virtual void showColors(bool state)
Sets colors visibility.
virtual void showSF(bool state)
Sets active scalarfield visibility.
ccBBox getOwnBB(bool withGLFeatures=false) override
Returns the entity's own bounding-box.
virtual bool addChild(ccHObject *child, int dependencyFlags=DP_PARENT_OF_OTHER, int insertIndex=-1)
Adds a child.
virtual QString getName() const
Returns object name.
virtual void setName(const QString &name)
Sets object name.
virtual void setEnabled(bool state)
Sets the "enabled" property.
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void setCurrentDisplayedScalarField(int index)
Sets the currently displayed scalar field.
bool convertCurrentScalarFieldToColors(bool mixWithExistingColor=false)
bool hasScalarFields() const override
Returns whether one or more scalar fields are instantiated.
virtual void setGlobalScale(double scale)
virtual void setGlobalShift(double x, double y, double z)
Sets shift applied to original coordinates (information storage only)
const Vector3Tpl< T > & minCorner() const
Returns min corner (const)
A generic mesh with index-based vertex access.
Graphical progress indicator (thread-safe)
constexpr char COMMAND_RASTERIZE[]
constexpr char COMMAND_RASTER_PROJ_MIN[]
static ccRasterGrid::EmptyCellFillOption GetEmptyCellFillingStrategy(QString option, ccCommandLineInterface &cmd)
constexpr char COMMAND_GRID_VERT_DIR[]
constexpr char COMMAND_RASTER_FILL_MAX_HEIGHT[]
constexpr char COMMAND_RASTER_FILL_INTERPOLATE[]
constexpr char COMMAND_RASTER_CUSTOM_HEIGHT[]
constexpr char COMMAND_RASTER_FILL_MIN_HEIGHT[]
constexpr char COMMAND_VOLUME[]
constexpr char COMMAND_RASTER_PROJ_MAX[]
constexpr char COMMAND_GRID_OUTPUT_RASTER_Z[]
constexpr char COMMAND_RASTER_PROJ_TYPE[]
constexpr char COMMAND_RASTER_RESAMPLE[]
constexpr char COMMAND_GRID_OUTPUT_RASTER_RGB[]
constexpr char COMMAND_VOLUME_GROUND_IS_FIRST[]
constexpr char COMMAND_RASTER_FILL_EMPTY_CELLS[]
static ccRasterGrid::ProjectionType GetProjectionType(QString option, ccCommandLineInterface &cmd)
constexpr char COMMAND_GRID_STEP[]
constexpr char COMMAND_RASTER_PROJ_AVG[]
constexpr char COMMAND_RASTER_FILL_CUSTOM_HEIGHT[]
constexpr char COMMAND_GRID_OUTPUT_CLOUD[]
constexpr char COMMAND_VOLUME_CONST_HEIGHT[]
constexpr char COMMAND_GRID_OUTPUT_MESH[]
constexpr char COMMAND_RASTER_SF_PROJ_TYPE[]
QTextStream & endl(QTextStream &stream)
MiniVec< float, N > ceil(const MiniVec< float, N > &a)
@ DELAUNAY_2D_AXIS_ALIGNED
std::string toString(T x)
void swap(cloudViewer::core::SmallVectorImpl< T > &LHS, cloudViewer::core::SmallVectorImpl< T > &RHS)
Implement std::swap in terms of SmallVector swap.
Loaded cloud description.
Loaded entity description.
bool process(ccCommandLineInterface &cmd) override
Main process.
bool process(ccCommandLineInterface &cmd) override
Main process.
ProjectionType
Types of projection.
unsigned height
Number of rows.
bool init(unsigned w, unsigned h, double gridStep, const CCVector3d &minCorner)
Initializes / resets the grid.
bool fillWith(ccGenericPointCloud *cloud, unsigned char projectionDimension, ProjectionType projectionType, bool interpolateEmptyCells, ProjectionType sfInterpolation=INVALID_PROJECTION_TYPE, ecvProgressDialog *progressDialog=nullptr)
Fills the grid with a point cloud.
static bool ComputeGridSize(unsigned char Z, const ccBBox &box, double gridStep, unsigned &width, unsigned &height)
Computes the raster size for a given bounding-box.
double maxHeight
Max height (computed on the NON-EMPTY or INTERPOLATED cells)
ccPointCloud * convertToCloud(const std::vector< ExportableFields > &exportedFields, bool interpolateSF, bool interpolateColors, bool resampleInputCloudXY, bool resampleInputCloudZ, ccGenericPointCloud *inputCloud, unsigned char Z, const ccBBox &box, bool fillEmptyCells, double emptyCellsHeight, bool exportToOriginalCS) const
Converts the grid to a cloud with scalar field(s)
unsigned width
Number of columns.
EmptyCellFillOption
Option for handling empty cells.
double minHeight
Min height (computed on the NON-EMPTY or INTERPOLATED cells)
void fillEmptyCells(EmptyCellFillOption fillEmptyCellsStrategy, double customCellHeight=0)
Fills the empty cell (for all strategies but 'INTERPOLATE_DELAUNAY')