24 #include <Eigen/Eigenvalues>
33 unsigned sz = M.
size();
35 Eigen::MatrixXd A(sz, sz);
36 for (
unsigned c = 0; c < sz; ++c) {
37 for (
unsigned r = 0; r < sz; ++r) {
47 : m_quadricEquationDirections(0, 1, 2),
48 m_structuresValidity(FLAG_DEPRECATED),
49 m_associatedCloud(associatedCloud) {
132 for (
unsigned i = 0; i <
count; ++i) {
134 Psum.
x +=
static_cast<double>(P->
x);
135 Psum.
y +=
static_cast<double>(P->
y);
136 Psum.
z +=
static_cast<double>(P->
z);
161 for (
unsigned i = 0; i <
count; ++i) {
164 mXX +=
static_cast<double>(P.
x) *
static_cast<double>(P.
x);
165 mYY +=
static_cast<double>(P.
y) *
static_cast<double>(P.
y);
166 mZZ +=
static_cast<double>(P.
z) *
static_cast<double>(P.
z);
167 mXY +=
static_cast<double>(P.
x) *
static_cast<double>(P.
y);
168 mXZ +=
static_cast<double>(P.
x) *
static_cast<double>(P.
z);
169 mYZ +=
static_cast<double>(P.
y) *
static_cast<double>(P.
z);
187 if (pointCount < 2)
return 0;
196 double maxSquareDist = 0;
197 for (
unsigned i = 0; i < pointCount; ++i) {
199 const double d2 =
static_cast<double>((*P - *G).norm2());
200 if (d2 > maxSquareDist) maxSquareDist = d2;
215 "Invalid CV_LOCAL_MODEL_MIN_SIZE size");
222 if (pointCount > 3) {
228 std::vector<double> eigValues;
238 double minEigValue = 0;
249 double maxEigValue = 0;
315 if (!lsPlane)
return false;
346 std::vector<float> A, b;
348 A.resize(6 *
count, 0);
350 }
catch (
const std::bad_alloc&) {
359 float* _A = A.data();
360 float* _b = b.data();
361 for (
unsigned i = 0; i <
count; ++i) {
364 float lX =
static_cast<float>(P.
u[idx.
x]);
365 float lY =
static_cast<float>(P.
u[idx.
y]);
366 float lZ =
static_cast<float>(P.
u[idx.
z]);
373 if (*_A > lmax2) lmax2 = *_A;
378 if (*_A > lmax2) lmax2 = *_A;
384 if (lZ > lmax2) lmax2 = lZ;
392 double* tAb = cg.
b();
396 for (
unsigned i = 0; i < 6; ++i) {
398 for (
unsigned j = i; j < 6; ++j) {
400 float* _Ai = &(A[i]);
401 float* _Aj = &(A[j]);
402 for (
unsigned k = 0; k <
count; ++k, _Ai += 6, _Aj += 6) {
404 tmp +=
static_cast<double>(*_Ai) *
405 static_cast<double>(*_Aj);
413 float* _Ai = &(A[i]);
414 for (
unsigned k = 0; k <
count; ++k, _Ai += 6) {
416 tmp +=
static_cast<double>(*_Ai) *
417 static_cast<double>(b[k]);
426 fopen_s(&f,
"CG_trace.txt",
"wt");
429 fprintf_s(f,
"lmax2 = %3.12f\n", lmax2);
432 float Amin = 0, Amax = 0;
434 for (
unsigned i = 1; i < 6 *
count; ++i)
439 fprintf_s(f,
"A in [%3.12f ; %3.12f]\n", Amin, Amax);
442 float bmin = 0, bmax = 0;
444 for (
unsigned i = 1; i <
count; ++i)
449 fprintf_s(f,
"b in [%3.12f ; %3.12f]\n", bmin, bmax);
452 fprintf_s(f,
"tA.A\n");
453 for (
unsigned i = 0; i < 6; ++i)
455 for (
unsigned j = 0; j < 6; ++j)
457 fprintf_s(f,
"%3.12f ", tAA.
m_values[i][j]);
463 fprintf_s(f,
"tA.b\n");
464 for (
unsigned i = 0; i < 6; ++i)
466 fprintf_s(f,
"%3.12f ", tAb[i]);
484 static_cast<double>(-lsPlane[idx.
x] / lsPlane[idx.
z]),
485 static_cast<double>(-lsPlane[idx.
y] / lsPlane[idx.
z]), 0, 0, 0};
488 if (X0[1] == 0 && X0[2] == 0) {
497 const double convergenceThreshold =
498 static_cast<double>(lmax2) *
501 for (
unsigned i = 0; i < 1500; ++i) {
503 if (lastError < convergenceThreshold)
513 for (
unsigned i = 0; i < 6; ++i) {
547 std::vector<PointCoordinateType> M;
550 M.resize(
count * 10);
551 }
catch (
const std::bad_alloc&) {
556 for (
unsigned i = 0; i <
count; ++i) {
575 for (
unsigned l = 0; l < 10; ++l) {
576 for (
unsigned c = 0; c < 10; ++c) {
579 for (
unsigned i = 0; i <
count; ++i, _M += 10)
580 sum +=
static_cast<double>(_M[l] * _M[c]);
591 Eigen::MatrixXd A = ToEigen(D);
592 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> es;
597 const auto& minEigenVec = es.eigenvectors().col(0);
599 for (
unsigned i = 0; i < D.
size(); ++i) {
600 quadricEquation[i] = minEigenVec[i];
604 std::vector<double> eigValues;
612 double minEigValue = 0;
614 minEigValue, quadricEquation);
621 bool duplicateVertices,
623 std::string& outputErrorStr) {
626 outputErrorStr =
"Not enough points";
637 std::vector<CCVector2> points2D;
639 if (projectPointsOn2DPlane<CCVector2>(points2D)) {
650 if (duplicateVertices) {
654 outputErrorStr =
"Not enough memory";
659 for (
unsigned i = 0; i <
count; ++i)
667 if (maxEdgeLength > 0) {
669 if (dm->
size() == 0) {
671 outputErrorStr =
"Not triangle left after pruning";
684 if (nStepX < 2 || nStepY < 2)
return nullptr;
689 if (!Q)
return nullptr;
718 if (!vertices->
reserve(nStepX * nStepY)) {
724 if (!quadMesh->
reserve((nStepX - 1) * (nStepY - 1) * 2)) {
729 for (
unsigned x = 0; x < nStepX; ++x) {
731 P.
x = bbMin[
X] + stepX * x - G->
u[
X];
732 for (
unsigned y = 0; y < nStepY; ++y) {
733 P.
y = bbMin[Y] + stepY * y - G->
u[Y];
734 P.
z = a + b * P.
x + c * P.
y + d * P.
x * P.
x + e * P.
x * P.
y +
745 if (x > 0 && y > 0) {
746 const unsigned iA = (x - 1) * nStepY + y - 1;
747 const unsigned iB = iA + 1;
748 const unsigned iC = iA + nStepY;
749 const unsigned iD = iB + nStepY;
767 std::vector<double> eigValues;
775 eigVectors, eigValues);
778 double m1 = 0.0, m2 = 0.0;
787 m2 += dotProd * dotProd;
791 return (m2 < std::numeric_limits<double>::epsilon()
793 :
static_cast<ScalarType
>((m1 * m1) / m2));
799 return std::numeric_limits<double>::quiet_NaN();
803 std::vector<double> eigValues;
807 return std::numeric_limits<double>::quiet_NaN();
811 eigVectors, eigValues);
815 const double& l1 = eigValues[0];
816 const double& l2 = eigValues[1];
817 const double& l3 = eigValues[2];
819 double value = std::numeric_limits<double>::quiet_NaN();
823 value = l1 + l2 + l3;
826 value = pow(l1 * l2 * l3, 1.0 / 3.0);
829 value = -(l1 * log(l1) + l2 * log(l2) + l3 * log(l3));
832 if (
std::abs(l1) > std::numeric_limits<double>::epsilon())
833 value = (l1 - l3) / l1;
836 if (
std::abs(l1) > std::numeric_limits<double>::epsilon())
837 value = (l2 - l3) / l1;
840 if (
std::abs(l1) > std::numeric_limits<double>::epsilon())
841 value = (l1 - l2) / l1;
844 double sum = l1 + l2 + l3;
845 if (
std::abs(sum) > std::numeric_limits<double>::epsilon())
849 double sum = l1 + l2 + l3;
850 if (
std::abs(sum) > std::numeric_limits<double>::epsilon())
854 double sum = l1 + l2 + l3;
855 if (
std::abs(sum) > std::numeric_limits<double>::epsilon())
859 if (
std::abs(l1) > std::numeric_limits<double>::epsilon())
890 ScalarType distToPlane =
893 if (roughnessUpDir) {
895 distToPlane = -distToPlane;
898 distToPlane =
std::abs(distToPlane);
936 b + (d * 2) * Q.
u[
X] + (e)*Q.
u[Y];
938 c + (e)*Q.
u[
X] + (f * 2) * Q.
u[Y];
951 std::abs(fxx * fyy - fxy * fxy) / (q * q);
952 return static_cast<ScalarType
>(K);
958 std::abs(((1 + fx2) * fyy - 2 * fx * fy * fxy +
961 return static_cast<ScalarType
>(H2);
972 unsigned pointCount =
976 if (pointCount < 4) {
987 std::vector<double> eigValues;
989 covMat, eigVectors, eigValues,
true)) {
999 const double sum = e.
x + e.
y + e.
z;
1005 return static_cast<ScalarType
>(eMin / sum);
constexpr unsigned CV_LOCAL_MODEL_MIN_SIZE[]
Min number of points to compute local models (see CV_LOCAL_MODEL_TYPES)
constexpr ScalarType NAN_VALUE
NaN as a ScalarType value.
constexpr PointCoordinateType PC_NAN
'NaN' as a PointCoordinateType value
float PointCoordinateType
Type of the coordinates of a (N-D) point.
Jacobi eigen vectors/values decomposition.
static bool GetEigenVector(const SquareMatrix &eigenVectors, unsigned index, Scalar eigenVector[])
Returns the given eigenvector.
static bool GetMinEigenValueAndVector(const SquareMatrix &eigenVectors, const EigenValues &eigenValues, Scalar &minEigenValue, Scalar minEigenVector[])
Returns the smallest eigenvalue and its associated eigenvector.
static bool SortEigenValuesAndVectors(SquareMatrix &eigenVectors, EigenValues &eigenValues)
static bool GetMaxEigenValueAndVector(const SquareMatrix &eigenVectors, const EigenValues &eigenValues, Scalar &maxEigenValue, Scalar maxEigenVector[])
Returns the biggest eigenvalue and its associated eigenvector.
void normalize()
Sets vector norm to unity.
Type dot(const Vector3Tpl &v) const
Dot product.
Vector3Tpl cross(const Vector3Tpl &v) const
Cross product.
static Vector3Tpl fromArray(const int a[3])
Constructor from an int array.
static PointCoordinateType vdot(const PointCoordinateType p[], const PointCoordinateType q[])
A class to perform a conjugate gradient optimization.
Scalar iterConjugateGradient(Scalar *Xn)
Iterates the conjugate gradient.
cloudViewer::SquareMatrixTpl< Scalar > & A()
Returns A matrix.
void initConjugateGradient(const Scalar *X0)
Initializes the conjugate gradient.
Scalar * b()
Returns b vector.
A class to compute and handle a Delaunay 2D mesh on a subset of points.
virtual unsigned size() const override
Returns the number of triangles.
bool removeTrianglesWithEdgesLongerThan(PointCoordinateType maxEdgeLength)
Filters out the triangles based on their edge length.
virtual bool buildMesh(const std::vector< CCVector2 > &points2D, std::size_t pointCountToUse, std::string &outputErrorStr)
Build the Delaunay mesh on top a set of 2D points.
virtual void linkMeshWith(GenericIndexedCloud *aCloud, bool passOwnership=false)
Associate this mesh to a point cloud.
static constexpr int USE_ALL_POINTS
virtual void getBoundingBox(CCVector3 &bbMin, CCVector3 &bbMax)=0
Returns the cloud bounding box.
virtual unsigned size() const =0
Returns the number of points.
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.
A generic mesh with index-based vertex access.
ScalarType computeCurvature(const CCVector3 &P, CurvatureType cType)
Computes the curvature of a set of point (by fitting a 2.5D quadric)
cloudViewer::SquareMatrixd computeCovarianceMatrix()
Computes the covariance matrix.
PointCoordinateType computeLargestRadius()
const PointCoordinateType * getQuadric(Tuple3ub *dims=nullptr)
Returns the best interpolating 2.5D quadric.
GenericIndexedMesh * triangulateFromQuadric(unsigned stepsX, unsigned stepsY)
const CCVector3 * getLSPlaneY()
Returns best interpolating plane (Least-square) 'Y' base vector.
const PointCoordinateType * getLSPlane()
Returns best interpolating plane equation (Least-square)
ScalarType computeRoughness(const CCVector3 &P, const CCVector3 *roughnessUpDir=nullptr)
CCVector3 m_lsPlaneVectors[3]
Least-square best fitting plane base vectors.
const CCVector3 * getGravityCenter()
Returns gravity center.
PointCoordinateType m_quadricEquation[6]
2.5D Quadric equation
void setLSPlane(const PointCoordinateType eq[4], const CCVector3 &X, const CCVector3 &Y, const CCVector3 &N)
Sets the best interpolating plane equation (Least-square)
bool computeQuadric()
Computes best fitting 2.5D quadric.
virtual void reset()
Resets structure (depreactes all associated geometrical fetaures)
Neighbourhood(GenericIndexedCloudPersist *associatedCloud)
Default constructor.
GeomFeature
Geometric feature computed from eigen values/vectors.
bool compute3DQuadric(double quadricEquation[10])
Computes the best interpolating quadric (Least-square)
CCVector3 m_gravityCenter
Gravity center.
const CCVector3 * getLSPlaneX()
Returns best interpolating plane (Least-square) 'X' base vector.
void computeGravityCenter()
Computes the gravity center.
void setGravityCenter(const CCVector3 &G)
Sets gravity center.
GenericIndexedMesh * triangulateOnPlane(bool duplicateVertices, PointCoordinateType maxEdgeLength, std::string &outputErrorStr)
Applies 2D Delaunay triangulation.
CurvatureType
Curvature type.
GenericIndexedCloudPersist * m_associatedCloud
Associated cloud.
unsigned char m_structuresValidity
Geometrical elements validity (flags)
const CCVector3 * getLSPlaneNormal()
Returns best interpolating plane (Least-square) normal vector.
Tuple3ub m_quadricEquationDirections
2.5D Quadric equation dimensions
double computeFeature(GeomFeature feature)
Computes the given feature on a set of point.
ScalarType computeMomentOrder1(const CCVector3 &P)
PointCoordinateType m_lsPlaneEquation[4]
Least-square best fitting plane parameters.
bool computeLeastSquareBestFittingPlane()
Computes the least-square best fitting plane.
virtual bool reserve(unsigned newCapacity)
Reserves memory for the point database.
void addPoint(const CCVector3 &P)
Adds a 3D point to the database.
A simple mesh structure, with index-based vertex access.
virtual void addTriangle(unsigned i1, unsigned i2, unsigned i3)
Adds a triangle to the mesh.
virtual bool reserve(unsigned n)
Reserves the memory to store the triangles (as 3 indexes each)
Scalar ** m_values
The matrix rows.
unsigned size() const
Returns matrix size.
Scalar getValue(unsigned row, unsigned column) const
Returns a particular matrix value.
__host__ __device__ int2 abs(int2 v)
::ccPointCloud PointCloud
Generic file read and write utility for python interface.
SquareMatrixTpl< double > SquareMatrixd
Double square matrix type.
bool LessThanEpsilon(float x)
Test a floating point number against our epsilon (a very small number).