46 unsigned numberOfClasses,
47 unsigned& finalNumberOfClasses,
48 bool noClassCompression ,
49 ScalarType* histoMin ,
50 ScalarType* histoMax ,
51 unsigned* histoValues ,
53 assert(distrib && cloud);
54 unsigned n = cloud->
size();
56 if (n == 0 || !distrib->
isValid())
return -1.0;
59 ScalarType minV = 0, maxV = 0;
60 unsigned numberOfValidValues = 0;
62 bool firstValidValue =
true;
63 for (
unsigned i = 0; i < n; ++i) {
66 if (firstValidValue) {
68 firstValidValue =
false;
75 ++numberOfValidValues;
80 if (numberOfValidValues == 0)
return -1.0;
82 if (histoMin) minV = *histoMin;
83 if (histoMax) maxV = *histoMax;
86 if (numberOfClasses == 0) {
87 numberOfClasses =
static_cast<unsigned>(
88 ceil(sqrt(
static_cast<double>(numberOfValidValues))));
90 if (numberOfClasses < 2) {
96 (histoValues ? histoValues :
new unsigned[numberOfClasses]);
101 memset(histo, 0,
sizeof(
unsigned) * numberOfClasses);
104 ScalarType dV = maxV - minV;
105 unsigned histoBefore = 0;
106 unsigned histoAfter = 0;
108 for (
unsigned i = 0; i < n; ++i) {
111 int bin =
static_cast<int>(
113 static_cast<ScalarType
>(numberOfClasses) / dV));
116 }
else if (bin >=
static_cast<int>(numberOfClasses)) {
120 histo[numberOfClasses - 1]++;
136 classes.emplace_back(1.0e-6,
static_cast<int>(histoBefore));
137 }
catch (
const std::bad_alloc&) {
143 for (
unsigned k = 1; k <= numberOfClasses; ++k) {
145 (k * dV) / numberOfClasses);
149 currentClass.
n = histo[k - 1];
150 currentClass.
pi = p2 - p1;
151 if (npis) npis[k - 1] = currentClass.
pi * numberOfValidValues;
154 classes.push_back(currentClass);
155 }
catch (
const std::bad_alloc&) {
164 classes.emplace_back(1.0e-6,
static_cast<int>(histoAfter));
165 }
catch (
const std::bad_alloc&) {
173 if (!noClassCompression) {
176 double minPi = 5.0 / numberOfValidValues;
178 while (classes.size() > 2) {
180 Chi2ClassList::iterator it = classes.begin();
181 Chi2ClassList::iterator minIt = it;
182 for (; it != classes.end(); ++it)
183 if (it->pi < minIt->pi) minIt = it;
191 Chi2ClassList::iterator smallestIt;
193 Chi2ClassList::iterator nextIt = minIt;
195 if (minIt == classes.begin()) {
198 Chi2ClassList::iterator predIt = minIt;
201 (nextIt != classes.end() && nextIt->pi < predIt->pi
207 smallestIt->pi += minIt->pi;
208 smallestIt->n += minIt->n;
211 classes.erase(minIt);
218 for (Chi2ClassList::iterator it = classes.begin(); it != classes.end();
220 double npi = it->pi * numberOfValidValues;
222 double temp =
static_cast<double>(it->n) - npi;
223 D2 += temp * (temp / npi);
235 if (!histoValues)
delete[] histo;
237 finalNumberOfClasses =
static_cast<unsigned>(classes.size());
254 unsigned numberOfNeighbours,
260 if (!distrib->
isValid())
return -1.0;
265 if (theOctree->
build(progressCb) < 1) {
277 unsigned numberOfChi2Classes =
static_cast<unsigned>(
278 ceil(sqrt(
static_cast<double>(numberOfNeighbours))));
281 unsigned* histoValues =
new unsigned[numberOfChi2Classes];
283 if (!inputOctree)
delete theOctree;
287 ScalarType *histoMin =
nullptr, customHistoMin = 0;
288 ScalarType *histoMax =
nullptr, customHistoMax = 0;
289 if (strcmp(distrib->
getName(),
"Gauss") == 0) {
292 ScalarType mu = 0, sigma2 = 0;
294 customHistoMin = mu -
static_cast<ScalarType
>(3.0) * sqrt(sigma2);
295 histoMin = &customHistoMin;
296 customHistoMax = mu +
static_cast<ScalarType
>(3.0) * sqrt(sigma2);
297 histoMax = &customHistoMax;
298 }
else if (strcmp(distrib->
getName(),
"Weibull") == 0) {
300 histoMin = &customHistoMin;
304 void* additionalParameters[] = {
306 reinterpret_cast<void*
>(&numberOfNeighbours),
307 reinterpret_cast<void*
>(&numberOfChi2Classes),
308 reinterpret_cast<void*
>(histoValues),
309 reinterpret_cast<void*
>(histoMin),
310 reinterpret_cast<void*
>(histoMax)};
312 double maxChi2 = -1.0;
317 numberOfNeighbours / 2, numberOfNeighbours * 3,
true,
319 "Statistical Test") != 0)
324 maxChi2 = sqrt(maxChi2);
329 delete[] histoValues;
330 histoValues =
nullptr;
332 if (!inputOctree)
delete theOctree;
339 void** additionalParameters,
344 unsigned numberOfNeighbours =
345 *
reinterpret_cast<unsigned*
>(additionalParameters[1]);
346 unsigned numberOfChi2Classes =
347 *
reinterpret_cast<unsigned*
>(additionalParameters[2]);
348 unsigned* histoValues =
349 reinterpret_cast<unsigned*
>(additionalParameters[3]);
350 ScalarType* histoMin =
351 reinterpret_cast<ScalarType*
>(additionalParameters[4]);
352 ScalarType* histoMax =
353 reinterpret_cast<ScalarType*
>(additionalParameters[5]);
371 }
catch (
const std::bad_alloc&)
376 DgmOctree::NeighboursSet::iterator it =
378 for (
unsigned j = 0; j < n; ++j, ++it) {
386 if (!neighboursCloud.
reserve(numberOfNeighbours)) {
391 for (
unsigned i = 0; i < n; ++i) {
401 if (k > numberOfNeighbours) k = numberOfNeighbours;
403 neighboursCloud.
clear();
404 for (
unsigned j = 0; j < k; ++j)
408 unsigned finalNumberOfChi2Classes = 0;
411 statModel, &neighboursCloud, numberOfChi2Classes,
412 finalNumberOfChi2Classes,
true, histoMin, histoMax,
420 D = (Chi2Dist >= 0.0 ?
static_cast<ScalarType
>(sqrt(Chi2Dist))
constexpr ScalarType NAN_VALUE
NaN as a ScalarType value.
static double pochisq(double x, int df)
Probability of chi-square value.
static double critchi(double p, int df)
Compute critical chi-square value toproduce given p.
The octree structure used throughout the library.
void getCellPos(CellCode code, unsigned char level, Tuple3i &cellPos, bool isCodeTruncated) const
unsigned findNearestNeighborsStartingFromCell(NearestNeighboursSearchStruct &nNSS, bool getOnlyPointsWithValidScalar=false) const
void computeCellCenter(CellCode code, unsigned char level, CCVector3 ¢er, bool isCodeTruncated=false) const
int build(GenericProgressCallback *progressCb=nullptr)
Builds the structure.
unsigned executeFunctionForAllCellsStartingAtLevel(unsigned char startingLevel, octreeCellFunc func, void **additionalParameters, unsigned minNumberOfPointsPerCell, unsigned maxNumberOfPointsPerCell, bool multiThread=true, GenericProgressCallback *progressCb=nullptr, const char *functionTitle=nullptr, int maxThreadCount=0)
unsigned char findBestLevelForAGivenPopulationPerCell(unsigned indicativeNumberOfPointsPerCell) const
virtual bool enableScalarField()=0
Enables the scalar field associated to the cloud.
virtual unsigned size() const =0
Returns the number of points.
virtual ScalarType getPointScalarValue(unsigned pointIndex) const =0
Returns the ith point associated scalar value.
A generic class to handle a probability distribution.
virtual const char * getName() const =0
Returns distribution name.
virtual bool isValid() const
Indicates if the distribution parameters are valid.
virtual double computePfromZero(ScalarType x) const =0
Computes the cumulative probability between 0 and x.
A generic 3D point cloud with index-based and presistent access to points.
virtual bool isCancelRequested()=0
Checks if the process should be canceled.
The Normal/Gaussian statistical distribution.
bool getParameters(ScalarType &_mu, ScalarType &_sigma2) const
Returns the distribution parameters.
bool oneStep()
Increments total progress value of a single unit.
A very simple point cloud (no point duplication)
void setPointScalarValue(unsigned pointIndex, ScalarType value) override
Sets the ith point associated scalar value.
virtual bool addPointIndex(unsigned globalIndex)
Point global index insertion mechanism.
virtual GenericIndexedCloudPersist * getAssociatedCloud()
Returns the associated (source) cloud.
unsigned size() const override
Returns the number of points.
virtual unsigned getPointGlobalIndex(unsigned localIndex) const
virtual void clear(bool releaseMemory=false)
Clears the cloud.
const CCVector3 * getPointPersistentPtr(unsigned index) override
Returns the ith point as a persistent pointer.
virtual bool reserve(unsigned n)
Reserves some memory for hosting the point references.
const CCVector3 * getPoint(unsigned index) const override
Returns the ith point.
ScalarType getPointScalarValue(unsigned pointIndex) const override
Returns the ith point associated scalar value.
static bool ValidValue(ScalarType value)
Returns whether a scalar value is valid or not.
MiniVec< float, N > floor(const MiniVec< float, N > &a)
MiniVec< float, N > ceil(const MiniVec< float, N > &a)
Generic file read and write utility for python interface.
bool GreaterThanEpsilon(float x)
Test a floating point number against our epsilon (a very small number).
Chi2Class(double _pi, int _n)
Constructor from parameters.
Chi2Class()
Default constructor.
ReferenceCloud * points
Set of points lying inside this cell.
const DgmOctree * parentOctree
Octree to which the cell belongs.
unsigned char level
Cell level of subdivision.
CellCode truncatedCode
Truncated cell code.