42 unsigned numberOfPoints = cloud->
size();
49 label =
"Feature computation";
54 label =
"Curvature computation";
59 label =
"Density computation";
66 static_cast<Density>(subOption),
67 progressCb, inputOctree);
70 label =
"Roughness computation";
74 label =
"1st order moment computation";
100 void* additionalParameters[] = {
101 static_cast<void*
>(&c),
static_cast<void*
>(&subOption),
102 static_cast<void*
>(&kernelRadius),
103 static_cast<void*
>(
const_cast<CCVector3*
>(roughnessUpDir))};
109 true, progressCb, label.c_str()) == 0) {
114 if (
octree && !inputOctree) {
124 ScalarType dimensionalCoef = 1.0f;
125 switch (
static_cast<Density>(subOption)) {
128 dimensionalCoef = 1.0f;
132 static_cast<ScalarType
>(
M_PI * pow(kernelRadius, 2.0));
135 dimensionalCoef =
static_cast<ScalarType
>(
144 for (
unsigned i = 0; i < numberOfPoints; ++i) {
146 s /= dimensionalCoef;
156 void** additionalParameters,
162 additionalParameters[1]);
166 static_cast<const CCVector3*
>(additionalParameters[3]);
183 }
catch (
const std::bad_alloc&) {
188 DgmOctree::NeighboursSet::iterator it =
190 for (
unsigned i = 0; i < n; ++i, ++it) {
198 for (
unsigned i = 0; i < n; ++i) {
205 unsigned neighborCount =
207 nNSS, radius,
false);
213 if (neighborCount > 3) {
224 if (neighborCount > 5) {
236 value =
static_cast<ScalarType
>(neighborCount);
240 if (neighborCount > 3) {
243 const unsigned globalIndex =
245 unsigned localIndex = 0;
246 while (localIndex < neighborCount &&
252 assert(localIndex < neighborCount);
302 double minDistanceBetweenPoints ,
307 unsigned numberOfPoints = cloud->
size();
313 if (theOctree->
build(progressCb) < 1) {
323 unsigned char level =
328 void* additionalParameters[1] = {
329 static_cast<void*
>(&minDistanceBetweenPoints)};
336 progressCb,
"Flag duplicate points") == 0) {
355 void** additionalParameters,
358 double minDistBetweenPoints =
359 *
static_cast<double*
>(additionalParameters[0]);
374 for (
unsigned i = 0; i < n; ++i) {
383 unsigned neighborCount =
385 nNSS, minDistBetweenPoints,
false);
386 if (neighborCount > 1)
389 for (
unsigned j = 0; j < neighborCount; ++j) {
394 static_cast<ScalarType
>(1));
416 unsigned numberOfPoints = cloud->
size();
422 if (theOctree->
build(progressCb) < 1) {
434 void* additionalParameters[] = {
static_cast<void*
>(&densityType)};
440 additionalParameters,
true, progressCb,
441 "Approximate Local Density Computation") == 0) {
458 void** additionalParameters,
461 Density densityType = *
static_cast<Density*
>(additionalParameters[0]);
473 for (
unsigned i = 0; i < n; ++i) {
482 switch (densityType) {
486 density =
static_cast<ScalarType
>(1.0 / sqrt(R2));
490 double circleArea =
M_PI * R2;
491 density =
static_cast<ScalarType
>(1.0 / circleArea);
494 double sphereVolume =
496 density =
static_cast<ScalarType
>(1.0 / sphereVolume);
527 points->placeIteratorAtBeginning();
529 while ((P =
points->getNextPoint())) {
533 sum /=
static_cast<double>(
count);
539 assert(cloud && weights);
549 for (
unsigned i = 0; i <
count; ++i) {
551 ScalarType w = weights->
getValue(i);
557 if (wSum != 0) sum /= wSum;
565 unsigned n = (cloud ? cloud->
size() : 0);
584 points->placeIteratorAtBeginning();
585 for (
unsigned i = 0; i < n; ++i) {
589 mXX +=
static_cast<double>(P.
x * P.
x);
590 mYY +=
static_cast<double>(P.
y * P.
y);
591 mZZ +=
static_cast<double>(P.
z * P.
z);
592 mXY +=
static_cast<double>(P.
x * P.
y);
593 mXZ +=
static_cast<double>(P.
x * P.
z);
594 mYZ +=
static_cast<double>(P.
y * P.
z);
597 covMat.
m_values[0][0] = mXX /
static_cast<double>(n);
598 covMat.
m_values[1][1] = mYY /
static_cast<double>(n);
599 covMat.
m_values[2][2] = mZZ /
static_cast<double>(n);
601 mXY /
static_cast<double>(n);
603 mXZ /
static_cast<double>(n);
605 mYZ /
static_cast<double>(n);
620 double* l1 = covMat.
row(0);
621 double* l2 = covMat.
row(1);
622 double* l3 = covMat.
row(2);
629 for (
unsigned i = 0; i <
count; i++) {
633 l1[0] += Pt.
x * Qt.
x;
634 l1[1] += Pt.
x * Qt.
y;
635 l1[2] += Pt.
x * Qt.
z;
636 l2[0] += Pt.
y * Qt.
x;
637 l2[1] += Pt.
y * Qt.
y;
638 l2[2] += Pt.
y * Qt.
z;
639 l3[0] += Pt.
z * Qt.
x;
640 l3[1] += Pt.
z * Qt.
y;
641 l3[2] += Pt.
z * Qt.
z;
644 covMat.
scale(1.0 /
static_cast<double>(
count));
658 assert(coupleWeights);
663 double* r1 = covMat.
row(0);
664 double* r2 = covMat.
row(1);
665 double* r3 = covMat.
row(2);
673 for (
unsigned i = 0; i <
count; i++) {
681 ScalarType w = coupleWeights->
getValue(i);
692 r1[0] += Pt.
x * Qt.
x;
693 r1[1] += Pt.
x * Qt.
y;
694 r1[2] += Pt.
x * Qt.
z;
696 r2[0] += Pt.
y * Qt.
x;
697 r2[1] += Pt.
y * Qt.
y;
698 r2[2] += Pt.
y * Qt.
z;
700 r3[0] += Pt.
z * Qt.
x;
701 r3[1] += Pt.
z * Qt.
y;
702 r3[2] += Pt.
z * Qt.
z;
705 if (wSum != 0.0) covMat.
scale(1.0 / wSum);
714 double minRelativeCenterShift ) {
715 if (!cloud || cloud->
size() < 5) {
727 for (
unsigned i = 0; i <
count; ++i) {
734 static const unsigned MAX_ITERATIONS = 100;
735 for (
unsigned it = 0; it < MAX_ITERATIONS; ++it) {
737 double meanNorm = 0.0;
739 unsigned realCount = 0;
740 for (
unsigned i = 0; i <
count; ++i) {
743 double norm = Di.
norm();
747 derivatives += Di / norm;
752 derivatives /=
count;
757 c = G - derivatives * meanNorm;
760 double shift = (c - c0).norm();
761 double relativeShift = shift / radius;
762 if (relativeShift < minRelativeCenterShift)
break;
771 double outliersRatio,
780 unsigned n = cloud->
size();
783 assert(confidence < 1.0);
784 confidence =
std::min(confidence, 1.0 - FLT_EPSILON);
786 const unsigned p = 4;
789 std::vector<PointCoordinateType> values;
792 }
catch (
const std::bad_alloc&) {
800 m =
static_cast<unsigned>(
801 log(1.0 - confidence) /
802 log(1.0 - pow(1.0 - outliersRatio,
static_cast<double>(p))));
810 sprintf(buffer,
"Least Median of Squares samples: %u", m);
821 std::random_device randomGenerator;
822 seed = randomGenerator();
824 std::mt19937 gen(seed);
825 std::uniform_int_distribution<unsigned>
dist(0, n - 1);
826 unsigned sampleCount = 0;
827 unsigned attempts = 0;
828 double minError = -1.0;
829 while (sampleCount < m && attempts < 2 * m) {
831 unsigned indexes[4] = {0, 0, 0, 0};
832 for (
unsigned j = 0; j < 4; ++j) {
835 indexes[j] =
dist(gen);
837 for (
unsigned k = 0; k < j && isOK; ++k)
838 if (indexes[j] == indexes[k]) isOK =
false;
855 for (
unsigned i = 0; i < n; ++i) {
857 (*cloud->
getPoint(i) - thisCenter).norm() - thisRadius;
861 const unsigned int medianIndex = n / 2;
863 std::nth_element(values.begin(), values.begin() + medianIndex,
867 double error =
static_cast<double>(values[medianIndex]);
870 if (
error < minError || minError < 0.0) {
885 if (sampleCount < m) {
893 double sigma = 1.4826 * (1.0 + 5.0 / (n - p)) * sqrt(minError);
897 double maxResidual = 2.5 * sigma;
900 for (
unsigned i = 0; i < n; ++i) {
902 (*cloud->
getPoint(i) - center).norm() - radius;
922 double residuals = 0;
923 for (
unsigned i = 0; i < n; ++i) {
925 double e = (*P - center).norm() - radius;
928 rms = sqrt(residuals / n);
937 size_t N = xy.size();
943 double p1 = 0.0, p2 = 0.0, p3 = 0.0, p4 = 0.0, p5 = 0.0, p6 = 0.0, p7 = 0.0,
946 for (
size_t i = 0; i < N; ++i) {
948 p2 += xy[i].x * xy[i].x;
949 p3 += xy[i].x * xy[i].y;
951 p5 += xy[i].y * xy[i].y;
952 p6 += xy[i].x * xy[i].x * xy[i].x;
953 p7 += xy[i].x * xy[i].y * xy[i].y;
954 p8 += xy[i].y * xy[i].y * xy[i].y;
955 p9 += xy[i].x * xy[i].x * xy[i].y;
958 double a1 = 2 * (p1 * p1 - N * p2);
959 double b1 = 2 * (p1 * p4 - N * p3);
961 double b2 = 2 * (p4 * p4 - N * p5);
962 double c1 = p2 * p1 - N * p6 + p1 * p5 - N * p7;
963 double c2 = p2 * p4 - N * p8 + p4 * p5 - N * p9;
965 center.
x = (c1 * b2 - c2 * b1) / (a1 * b2 - a2 * b1);
966 center.
y = (a1 * c2 - a2 * c1) / (a1 * b2 - a2 * b1);
968 sqrt(((p2 + p5) - (2 * p1 * center.
x) + (N * center.
x * center.
x) -
969 (2 * p4 * center.
y) + (N * center.
y * center.
y)) /
984 radius = std::numeric_limits<PointCoordinateType>::quiet_NaN();
985 rms = std::numeric_limits<double>::quiet_NaN();
992 unsigned n = cloud->
size();
1002 "Detect circle using Landau Smith algorithm");
1005 progressCb->
start();
1028 std::vector<CCVector2d> pointsOnPlane;
1030 pointsOnPlane.resize(cloud->
size());
1031 }
catch (
const std::bad_alloc&) {
1040 FILE* fp = fopen(
"C:\\Temp\\circle_fit.txt",
"wt");
1043 for (
unsigned dim = 0; dim < 2; ++dim) {
1044 const CCVector3* eigenVector = eigenvectors[dim];
1045 assert(eigenVector);
1052 fprintf(fp,
"Dim %i\n", dim);
1053 fprintf(fp,
"X = %f %f %f\n", x.
x, x.
y, x.
z);
1054 fprintf(fp,
"Y = %f %f %f\n", y.
x, y.
y, y.
z);
1055 fprintf(fp,
"Z = %f %f %f\n", eigenVector->
x, eigenVector->
y,
1061 for (
unsigned i = 0; i < n; ++i) {
1063 pointsOnPlane[i] = {Plocal.
dot(x), Plocal.
dot(y)};
1073 FILE* fpc =
nullptr;
1076 fpc = fopen(
"C:\\Temp\\circle_dim0.asc",
"wt");
1079 fpc = fopen(
"C:\\Temp\\circle_dim1.asc",
"wt");
1082 fpc = fopen(
"C:\\Temp\\circle_dim2.asc",
"wt");
1086 for (
const CCVector2d& P2D : pointsOnPlane) {
1087 fprintf(fpc,
"%f %f 0\n", P2D.x, P2D.y);
1097 if (!
Landau_Smith(pointsOnPlane, thisCenter2D, thisRadius)) {
1103 fprintf(fp,
"Center (%f, %f) - radius = %f\n", thisCenter2D.
x,
1104 thisCenter2D.
y, thisRadius);
1109 double thisRMS = 0.0;
1110 for (
const CCVector2d& P2D : pointsOnPlane) {
1111 double r = (P2D - thisCenter2D).norm();
1112 double error = thisRadius - r;
1116 thisRMS = sqrt(thisRMS / n);
1119 fprintf(fp,
"RMS = %f\n", thisRMS);
1120 fprintf(fp,
"=================\n");
1123 if (dim == 0 || thisRMS < rms) {
1129 radius = thisRadius;
1185 for (
int j = 0; j < n; j++) {
1188 double apivot = a[j + j * n];
1190 for (
int i = j; i < n; i++) {
1192 apivot = a[i + j * n];
1197 if (apivot == 0.0) {
1202 for (
int i = 0; i < n + rhs_num; i++) {
1203 std::swap(a[ipivot + i * n], a[j + i * n]);
1208 for (
int k = j; k < n + rhs_num; k++) {
1209 a[j + k * n] = a[j + k * n] / apivot;
1213 for (
int i = 0; i < n; i++) {
1215 double factor = a[i + j * n];
1217 for (
int k = j; k < n + rhs_num; k++) {
1218 a[i + k * n] = a[i + k * n] - factor * a[j + k * n];
constexpr PointCoordinateType PC_ONE
'1' as a PointCoordinateType value
constexpr ScalarType NAN_VALUE
NaN as a ScalarType value.
constexpr double ZERO_TOLERANCE_D
Vector3Tpl< PointCoordinateType > CCVector3
Default 3D Vector.
float PointCoordinateType
Type of the coordinates of a (N-D) point.
Type dot(const Vector3Tpl &v) const
Dot product.
double norm2d() const
Returns vector square norm (forces double precision output)
Vector3Tpl orthogonal() const
Returns a normalized vector which is orthogonal to this one.
Type norm() const
Returns vector norm.
Vector3Tpl cross(const Vector3Tpl &v) const
Cross product.
static Vector3Tpl fromArray(const int a[3])
Constructor from an int array.
A kind of ReferenceCloud based on the DgmOctree::NeighboursSet structure.
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
unsigned char findBestLevelForAGivenNeighbourhoodSizeExtraction(PointCoordinateType radius) const
int findNeighborsInASphereStartingFromCell(NearestNeighboursSearchStruct &nNSS, double radius, bool sortValues=true) const
Advanced form of the nearest neighbours search algorithm (in a sphere)
const PointCoordinateType & getCellSize(unsigned char level) const
Returns the octree cells length for a given level of subdivision.
void computeCellCenter(CellCode code, unsigned char level, CCVector3 ¢er, bool isCodeTruncated=false) const
unsigned executeFunctionForAllCellsAtLevel(unsigned char level, octreeCellFunc func, void **additionalParameters, bool multiThread=false, GenericProgressCallback *progressCb=nullptr, const char *functionTitle=nullptr, int maxThreadCount=0)
int build(GenericProgressCallback *progressCb=nullptr)
Builds the structure.
unsigned char findBestLevelForAGivenPopulationPerCell(unsigned indicativeNumberOfPointsPerCell) const
virtual bool enableScalarField()=0
Enables the scalar field associated to the cloud.
virtual void forEach(genericPointAction action)=0
Fast iteration mechanism.
virtual void placeIteratorAtBeginning()=0
Sets the cloud iterator at the beginning.
virtual const CCVector3 * getNextPoint()=0
Returns the next point (relatively to the global iterator position)
virtual unsigned size() const =0
Returns the number of points.
virtual ScalarType getPointScalarValue(unsigned pointIndex) const =0
Returns the ith point associated scalar value.
virtual void setPointScalarValue(unsigned pointIndex, ScalarType value)=0
Sets the ith point associated scalar value.
A generic 3D point cloud with index-based and presistent access to points.
virtual const CCVector3 * getPoint(unsigned index) const =0
Returns the ith point.
virtual void setInfo(const char *infoStr)=0
Notifies some information about the ongoing process.
virtual void setMethodTitle(const char *methodTitle)=0
Notifies the algorithm title.
virtual bool textCanBeEdited() const
Returns whether the dialog title and info can be updated or not.
virtual void update(float percent)=0
Notifies the algorithm progress.
ScalarType computeCurvature(const CCVector3 &P, CurvatureType cType)
Computes the curvature of a set of point (by fitting a 2.5D quadric)
const PointCoordinateType * getLSPlane()
Returns best interpolating plane equation (Least-square)
ScalarType computeRoughness(const CCVector3 &P, const CCVector3 *roughnessUpDir=nullptr)
const CCVector3 * getGravityCenter()
Returns gravity center.
GeomFeature
Geometric feature computed from eigen values/vectors.
const CCVector3 * getLSPlaneX()
Returns best interpolating plane (Least-square) 'X' base vector.
CurvatureType
Curvature type.
const CCVector3 * getLSPlaneNormal()
Returns best interpolating plane (Least-square) normal vector.
double computeFeature(GeomFeature feature)
Computes the given feature on a set of point.
ScalarType computeMomentOrder1(const CCVector3 &P)
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 bool resize(unsigned n)
Presets the size of the vector used to store point references.
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.
A simple scalar field (to be associated to a point cloud)
ScalarType & getValue(std::size_t index)
static bool ValidValue(ScalarType value)
Returns whether a scalar value is valid or not.
unsigned currentSize() const
Scalar ** m_values
The matrix rows.
void clear()
Sets all elements to 0.
void scale(Scalar coef)
Scales matrix (all elements are multiplied by the same coef.)
Scalar * row(unsigned index)
Returns pointer to matrix row.
__host__ __device__ int2 abs(int2 v)
static double dist(double x1, double y1, double x2, double y2)
static void error(char *msg)
Generic file read and write utility for python interface.
SquareMatrixTpl< double > SquareMatrixd
Double square matrix type.
bool GreaterThanEpsilon(float x)
Test a floating point number against our epsilon (a very small number).
void swap(cloudViewer::core::SmallVectorImpl< T > &LHS, cloudViewer::core::SmallVectorImpl< T > &RHS)
Implement std::swap in terms of SmallVector swap.
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.