18 #ifdef PLUGIN_IO_QPDAL
19 #include "../../../core/IO/qPDALIO/include/LASFields.h"
21 #include "../../../core/IO/qLASIO/include/LasDetails.h"
69 "[Classif] Synthetic flag",
70 "[Classif] Key-point flag",
71 "[Classif] Withheld flag",
72 "[Classif] Overlap flag",
87 #include <QCoreApplication>
106 error =
"invalid feature type";
112 if (!corePointRole.isEmpty() && !
scaled() &&
116 error =
"Scale-less features can only be computed on the core points / "
122 error =
"scaled point features need a STAT measure to be defined";
127 error =
"math operations require two clouds";
135 error = QString(
"Cloud %0 has no '%1' scalar field")
149 error = QString(
"Cloud %0 has no '%1' scalar field")
159 error = QString(
"Cloud %0 has no '%1' scalar field")
169 error = QString(
"Cloud %0 has no '%1' scalar field")
176 error = QString(
"Cloud %0 has no '%1' scalar field")
187 error = QString(
"Cloud %0 has no RGB color")
194 error = QString(
"Cloud %0 has no '%1' scalar field")
204 error = QString(
"Cloud %0 has no normals")
212 error = QString(
"Cloud %0 has no '%1' scalar field")
221 error = QString(
"Cloud %0 has no '%1' scalar field")
231 error = QString(
"Cloud %0 has no scalar field #%1")
256 error =
"Cloud has no 'intensity' scalar field";
274 error =
"Cloud has no 'number of returns' scalar field";
283 error =
"Cloud has no 'return number' scalar field";
292 if (!numberOfRetSF) {
293 error =
"Can't compute the 'echo ratio' field: no 'Number of "
294 "Return' SF available";
300 error =
"Can't compute the 'echo ratio' field: no 'Return "
301 "number' SF available";
304 if (retNumberSF->size() != numberOfRetSF->size() ||
305 retNumberSF->size() != cloud->
size()) {
306 error =
"Internal error (inconsistent scalar fields)";
310 retNumberSF, numberOfRetSF,
"EchoRat"));
325 error =
"Cloud has no 'NIR' scalar field";
334 error =
"Cloud has no normals: can't compute dip or dip dir. "
347 error =
"Cloud has no 'm3c2 distance' scalar field";
356 error =
"Cloud has no 'PCV/Illuminance' scalar field";
365 error = QString(
"Can't retrieve the specified SF: invalid "
376 error =
"Unhandled feature type";
393 error =
"invalid input parameters";
401 error =
"failed to compute octree on cloud " + cloud2.
getName();
413 QString(
"Extracting %1 core points nearest neighbors in cloud %2")
417 progressCb->setMethodTitle(
"Compute math operation");
418 progressCb->setInfo(qPrintable(logMessage));
423 double meanNeighborhoodSize = 0;
424 int tenth = pointCount / 10;
426 bool cancelled =
false;
429 #pragma omp parallel for num_threads(std::max(1, omp_get_max_threads() - 2))
432 for (
int i = 0; i < static_cast<int>(pointCount); ++i) {
436 double maxSquareDist = 0;
440 int neighborhoodSize = 0;
443 &neighborhoodSize) >= 1) {
451 if (i && (i % tenth) == 0) {
452 double density = meanNeighborhoodSize / tenth;
458 while (density > 2.9) {
464 "neighborhood size: %1 --> new level = %2")
465 .arg(meanNeighborhoodSize / tenth)
467 meanNeighborhoodSize = 0;
469 meanNeighborhoodSize += neighborhoodSize;
476 error =
"[Point feature] Process cancelled";
488 return error.isEmpty();
499 error =
"internal error (no input core points)";
523 error =
"Feature has a second cloud associated but no MATH "
524 "operation is defined";
532 QString resultSF1Name =
field1->getName();
542 error =
"Scaled features (SCx) must have an associated STAT "
551 error =
"Scale-less features (SC0) can only be defined on the core "
552 "points (origin) cloud";
568 resultSF1Name +=
"@" + QString::number(
scale);
587 error = QString(
"Failed to prepare scalar field for field '%1' @ "
599 QString resultSF2Name =
608 qPrintable(resultSF2Name));
611 generatedScalarFields,
615 generatedScalarFields,
618 error = QString(
"Failed to prepare scalar field for field '%1' "
632 int sfIdx =
corePoints.cloud->getScalarFieldIndexByName(
633 qPrintable(resultSF1Name));
638 resultSF =
corePoints.cloud->getScalarField(sfIdx);
643 error =
"Not enough memory";
658 error, progressCb)) {
659 error =
"Failed to perform the MATH operation (" +
error +
666 int newSFIdx =
corePoints.cloud->addScalarField(
668 if (generatedScalarFields) {
674 corePoints.cloud->setCurrentDisplayedScalarField(newSFIdx);
686 double& outputValue)
const {
687 outputValue = std::numeric_limits<double>::quiet_NaN();
695 size_t kNN = pointsInNeighbourhood.size();
706 for (
size_t k = 0; k < kNN; ++k) {
707 unsigned index = pointsInNeighbourhood[k].pointIndex;
708 double v = sourceField->pointValue(index);
714 else if (v > maxValue)
717 minValue = maxValue = v;
721 outputValue = maxValue - minValue;
734 }
catch (
const std::bad_alloc&) {
740 for (
unsigned k = 0; k < kNN; ++k) {
741 unsigned index = pointsInNeighbourhood[k].pointIndex;
742 double v = sourceField->pointValue(index);
751 values[k] =
static_cast<ScalarType
>(v);
757 outputValue = sum / kNN;
766 size_t medianIndex = values.size() / 2;
767 std::nth_element(values.begin(), values.begin() + medianIndex,
769 outputValue = values[medianIndex];
773 outputValue = sqrt(
std::abs(sum2 * kNN - sum * sum)) / kNN;
808 error =
"internal error (no input core points)";
820 int sfIndex1 =
corePoints.cloud->getScalarFieldIndexByName(
822 corePoints.cloud->setCurrentDisplayedScalarField(sfIndex1);
832 error =
"Failed to perform the MATH operation";
872 description +=
"_SC0";
constexpr ScalarType NAN_VALUE
NaN as a ScalarType value.
constexpr const char * LAS_FIELD_NAMES[22]
static const char * s_echoRatioSFName
static const char * s_normDipSFName
static const char * s_NIRSFName
static const char * s_PCVSFName
static const char * s_normDipDirSFName
static const char * s_M3C2SFName
static bool ComputeMathOpWithNearestNeighbor(const CorePoints &corePoints, const IScalarFieldWrapper &field1, cloudViewer::ScalarField *outSF, ccPointCloud &cloud2, const IScalarFieldWrapper &field2, masc::Feature::Operation op, QString &error, cloudViewer::GenericProgressCallback *progressCb=nullptr)
virtual void release()
Decrease counter and deletes object when 0.
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
static bool Print(const char *format,...)
Prints out a formatted message in console.
QSharedPointer< IScalarFieldWrapper > Shared
virtual double pointValue(unsigned index) const =0
void push(ccPointCloud *cloud, cloudViewer::ScalarField *sf, Behavior behavior)
bool setBehavior(cloudViewer::ScalarField *sf, Behavior behavior)
virtual ccOctree::Shared computeOctree(cloudViewer::GenericProgressCallback *progressCb=nullptr, bool autoAddChild=true)
Computes the cloud octree.
virtual ccOctree::Shared getOctree() const
Returns the associated octree (if any)
virtual QString getName() const
Returns object name.
QSharedPointer< ccOctree > Shared
Shared pointer.
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
bool hasNormals() const override
Returns whether normals are enabled or not.
bool hasColors() const override
Returns whether colors are enabled or not.
A scalar field associated to display-related parameters.
unsigned findPointNeighbourhood(const CCVector3 *_queryPoint, ReferenceCloud *Yk, unsigned maxNumberOfNeighbors, unsigned char level, double &maxSquareDist, double maxSearchDist=0, int *finalNeighbourhoodSize=nullptr) const
Finds the nearest neighbours around a query point.
static const int MAX_OCTREE_LEVEL
Max octree subdivision level.
std::vector< PointDescriptor > NeighboursSet
A set of neighbours.
unsigned char findBestLevelForAGivenPopulationPerCell(unsigned indicativeNumberOfPointsPerCell) const
virtual unsigned size() const =0
Returns the number of points.
std::vector< ScalarType > ScalarContainer
Scalar values container.
virtual const CCVector3 * getPoint(unsigned index) const =0
Returns the ith point.
bool oneStep()
Increments total progress value of a single unit.
int getScalarFieldIndexByName(const char *name) const
Returns the index of a scalar field represented by its name.
ScalarField * getScalarField(int index) const
Returns a pointer to a specific scalar field.
unsigned getNumberOfScalarFields() const
Returns the number of associated (and active) scalar fields.
unsigned size() const override
A very simple point cloud (no point duplication)
virtual unsigned getPointGlobalIndex(unsigned localIndex) const
A simple scalar field (to be associated to a point cloud)
virtual void computeMinAndMax()
Determines the min and max values.
void setValue(std::size_t index, ScalarType value)
const char * getName() const
Returns scalar field name.
bool resizeSafe(std::size_t count, bool initNewElements=false, ScalarType valueForNewElements=0)
Resizes memory (no exception thrown)
The Weibull statistical parametric distribution.
bool computeParameters(const ScalarContainer &values) override
Computes the distribution parameters from a set of values.
double computeSkewness() const
Returns the distribution 'skewness'.
double computeMode() const
Returns the distribution 'mode'.
__host__ __device__ int2 abs(int2 v)
static void error(char *msg)
constexpr const char * ScanDirectionFlag
constexpr const char * EdgeOfFlightLine
constexpr const char * NumberOfReturns
constexpr const char * UserData
constexpr const char * Classification
constexpr const char * ReturnNumber
constexpr const char * ScanAngleRank
constexpr const char * GpsTime
constexpr const char * Intensity
constexpr const char * PointSourceId
static bool CheckSFExistence(ccPointCloud *cloud, const char *resultSFName)
virtual bool checkValidity(QString corePointRole, QString &error) const
Checks the feature definition validity.
bool scaled() const
Returns whether the feature has an associated scale.
static QString StatToString(Stat stat)
bool sf2WasAlreadyExisting
static ScalarType PerformMathOp(double s1, double s2, Operation op)
Performs a mathematical operation between two scalars.
static QString OpToString(Operation op)
double scale
Scale (diameter)
static cloudViewer::ScalarField * PrepareSF(ccPointCloud *cloud, const char *resultSFName, SFCollector *generatedScalarFields, SFCollector::Behavior behavior)
bool sf1WasAlreadyExisting
bool computeStat(const cloudViewer::DgmOctree::NeighboursSet &pointsInNeighbourhood, const IScalarFieldWrapper::Shared &sourceField, double &outputValue) const
IScalarFieldWrapper::Shared field1
First cloud 'source' field.
virtual bool checkValidity(QString corePointRole, QString &error) const override
Checks the feature definition validity.
static QString ToString(PointFeatureType type)
PointFeatureType type
Point feature type.
cloudViewer::ScalarField * statSF1
For scaled features.
cloudViewer::ScalarField * statSF2
virtual bool finish(const CorePoints &corePoints, QString &error) override
Finishes the feature preparation (update the scalar field, etc.)
virtual QString toString() const override
Returns the formatted description.
virtual bool prepare(const CorePoints &corePoints, QString &error, cloudViewer::GenericProgressCallback *progressCb=nullptr, SFCollector *generatedScalarFields=nullptr) override
Prepares the feature (compute the scalar field, etc.)
IScalarFieldWrapper::Shared retrieveField(ccPointCloud *cloud, QString &error)
Returns the 'source' field from a given cloud.
IScalarFieldWrapper::Shared field2
Second cloud 'source' field (if any)
int sourceSFIndex
Source scalar field index (if the feature source is 'ScalarField')