I factorized some functions to assemble the covariance matrix and fitting plane or line (those are internal functions)

This commit is contained in:
Pierre Alliez 2006-03-01 16:16:13 +00:00
parent 92531eb001
commit f6f35c423e
1 changed files with 199 additions and 141 deletions

View File

@ -29,54 +29,22 @@ CGAL_BEGIN_NAMESPACE
namespace CGALi {
// fits a plane to a 3D point set
// returns a fitting quality (1 - lambda_min/lambda_max):
// 1 is best (zero variance orthogonally to the fitting line)
// 0 is worst (isotropic case, returns a plane with default direction)
template < typename InputIterator,
typename K >
typename K::FT
linear_least_squares_fitting_3(InputIterator first,
InputIterator beyond,
typename K::Plane_3& plane, // best fit plane
typename K::Point_3& c, // centroid
const K& k, // kernel
const typename K::Point_3*)
// compute the eigen values and vectors of the covariance
// matrix and deduces the best linear fitting plane
// (this is an internal function)
// returns fitting quality
template < typename K >
typename K::FT
fitting_plane_3(const typename K::FT covariance[6], // covariance matrix
const typename K::Point_3& c, // centroid
typename K::Plane_3& plane, // best fit plane
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Point_3 Point;
typedef typename K::Plane_3 Plane;
typedef typename K::Vector_3 Vector;
// precondition: at least one element in the container.
CGAL_precondition(first != beyond);
// compute centroid
c = centroid(first,beyond,K());
// assemble covariance matrix as a
// semi-definite matrix.
// Matrix numbering:
// 0
// 1 2
// 3 4 5
FT covariance[6] = {0.0,
0.0, 0.0,
0.0, 0.0, 0.0};
for(InputIterator it = first;
it != beyond;
it++)
{
const Point& p = *it;
Vector d = p - c;
covariance[0] += d.x() * d.x();
covariance[1] += d.x() * d.y();
covariance[2] += d.y() * d.y();
covariance[3] += d.x() * d.z();
covariance[4] += d.y() * d.z();
covariance[5] += d.z() * d.z();
}
// solve for eigenvalues and eigenvectors.
// eigen values are sorted in descending order,
// eigen vectors are sorted in accordance.
@ -106,56 +74,24 @@ linear_least_squares_fitting_3(InputIterator first,
plane = Plane(c,Vector(0.0,0.0,1.0));
return (FT)0.0;
}
} // end fit plane to point set
}
// fits a line to a 3D point set
// returns a fitting quality (1 - lambda_min/lambda_max):
// 1 is best (zero variance orthogonally to the fitting line)
// 0 is worst (isotropic case, returns a line along x axis)
template < typename InputIterator,
typename K >
typename K::FT
linear_least_squares_fitting_3(InputIterator first,
InputIterator beyond,
typename K::Line_3& line, // best fit line
typename K::Point_3& c, // centroid
const K& k, // kernel
const typename K::Point_3*)
// compute the eigen values and vectors of the covariance
// matrix and deduces the best linear fitting line
// (this is an internal function)
// returns fitting quality
template < typename K >
typename K::FT
fitting_line_3(const typename K::FT covariance[6], // covariance matrix
const typename K::Point_3& c, // centroid
typename K::Line_3& line, // best fit line
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Point_3 Point;
typedef typename K::Line_3 Line;
typedef typename K::Vector_3 Vector;
// precondition: at least one element in the container.
CGAL_precondition(first != beyond);
// compute centroid
c = centroid(first,beyond,K());
// assemble covariance matrix as a
// semi-definite matrix.
// Matrix numbering:
// 0
// 1 2
// 3 4 5
FT covariance[6] = {0.0,
0.0, 0.0,
0.0, 0.0, 0.0};
for(InputIterator it = first;
it != beyond;
it++)
{
const Point& p = *it;
Vector d = p - c;
covariance[0] += d.x() * d.x();
covariance[1] += d.x() * d.y();
covariance[2] += d.y() * d.y();
covariance[3] += d.x() * d.z();
covariance[4] += d.y() * d.z();
covariance[5] += d.z() * d.z();
}
// solve for eigenvalues and eigenvectors.
// eigen values are sorted in descending order,
// eigen vectors are sorted in accordance.
@ -182,40 +118,65 @@ linear_least_squares_fitting_3(InputIterator first,
line = Line(c,Vector(1.0,0.0,0.0));
return (FT)0.0;
}
} // end fit line to point set
}
// fits a plane to a 3D triangle set
template < typename InputIterator,
// assemble covariance matrix from a point set
// (internal function)
template < typename InputIterator,
typename K >
typename K::FT
linear_least_squares_fitting_3(InputIterator first,
InputIterator beyond,
typename K::Plane_3& plane, // best fit plane
typename K::Point_3& c, // centroid
const K& k, // kernel
const typename K::Triangle_3*)
void
assemble_covariance_matrix_3(InputIterator first,
InputIterator beyond,
typename K::FT covariance[6], // covariance matrix
const typename K::Point_3& c, // centroid
const K& k,
const typename K::Point_3*)
{
typedef typename K::FT FT;
typedef typename K::Point_3 Point;
typedef typename K::Vector_3 Vector;
typedef typename K::Triangle_3 Triangle;
typedef typename K::FT FT;
typedef typename K::Point_3 Point;
typedef typename K::Vector_3 Vector;
// precondition: at least one element in the container.
CGAL_precondition(first != beyond);
// compute centroid
c = centroid(first,beyond,K());
// assemble covariance matrix as a
// semi-definite matrix.
// Matrix numbering:
// 0
// 1 2
// 3 4 5
FT covariance[6] = {0.0,
0.0, 0.0,
0.0, 0.0, 0.0};
for(InputIterator it = first;
it != beyond;
it++)
{
const Point& p = *it;
Vector d = p - c;
covariance[0] += d.x() * d.x();
covariance[1] += d.x() * d.y();
covariance[2] += d.y() * d.y();
covariance[3] += d.x() * d.z();
covariance[4] += d.y() * d.z();
covariance[5] += d.z() * d.z();
}
}
// assemble covariance matrix from a triangle set
// (internal function)
template < typename InputIterator,
typename K >
void
assemble_covariance_matrix_3(InputIterator first,
InputIterator beyond,
typename K::FT covariance[6], // covariance matrix
const typename K::Point_3& c, // centroid
const K& k,
const typename K::Triangle_3*)
{
typedef typename K::FT FT;
typedef typename K::Point_3 Point;
typedef typename K::Vector_3 Vector;
typedef typename K::Triangle_3 Triangle;
// Matrix numbering:
// 0
// 1 2
// 3 4 5
FT sum_areas = 0.0;
for(InputIterator it = first;
it != beyond;
@ -256,41 +217,138 @@ linear_least_squares_fitting_3(InputIterator first,
covariance[3] -= sum_areas * c.z() * c.x();
covariance[4] -= sum_areas * c.z() * c.y();
covariance[5] -= sum_areas * c.z() * c.z();
// solve for eigenvalues and eigenvectors.
// eigen values are sorted in descending order,
// eigen vectors are sorted in accordance.
FT eigen_values[3];
FT eigen_vectors[9];
eigen_symmetric<FT>(covariance,3,eigen_vectors,eigen_values);
CGAL_assertion(eigen_values[0] >= 0.0 &&
eigen_values[1] >= 0.0 &&
eigen_values[2] >= 0.0);
}
// check unicity and build fitting plane accordingly
if(eigen_values[0] != eigen_values[2])
{
// regular case
Vector normal(eigen_vectors[6],
eigen_vectors[7],
eigen_vectors[8]);
plane = Plane(c,normal);
return (FT)1.0 - eigen_values[2] / eigen_values[0];
} // end regular case
else
{
// isotropic case (infinite number of directions)
// by default: assemble a horizontal plane that goes
// through the centroid.
plane = Plane(c,Vector(0.0,0.0,1.0));
return (FT)0.0;
} // end isotropic case
// fits a plane to a 3D point set
// returns a fitting quality (1 - lambda_min/lambda_max):
// 1 is best (zero variance orthogonally to the fitting line)
// 0 is worst (isotropic case, returns a plane with default direction)
template < typename InputIterator,
typename K >
typename K::FT
linear_least_squares_fitting_3(InputIterator first,
InputIterator beyond,
typename K::Plane_3& plane, // best fit plane
typename K::Point_3& c, // centroid
const K& k, // kernel
const typename K::Point_3*)
{
typedef typename K::FT FT;
typedef typename K::Point_3 Point;
typedef typename K::Plane_3 Plane;
typedef typename K::Vector_3 Vector;
// precondition: at least one element in the container.
CGAL_precondition(first != beyond);
// compute centroid
c = centroid(first,beyond,K());
// assemble covariance matrix
FT covariance[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
assemble_covariance_matrix_3(first,beyond,covariance,c,k,(Point*) NULL);
// compute fitting plane
return fitting_plane_3(covariance,c,plane,k);
} // end fit plane to point set
// fits a line to a 3D point set
// returns a fitting quality (1 - lambda_min/lambda_max):
// 1 is best (zero variance orthogonally to the fitting line)
// 0 is worst (isotropic case, returns a line along x axis)
template < typename InputIterator,
typename K >
typename K::FT
linear_least_squares_fitting_3(InputIterator first,
InputIterator beyond,
typename K::Line_3& line, // best fit line
typename K::Point_3& c, // centroid
const K& k, // kernel
const typename K::Point_3*)
{
typedef typename K::FT FT;
typedef typename K::Point_3 Point;
typedef typename K::Line_3 Line;
typedef typename K::Vector_3 Vector;
// precondition: at least one element in the container.
CGAL_precondition(first != beyond);
// compute centroid
c = centroid(first,beyond,K());
// assemble covariance matrix
FT covariance[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
assemble_covariance_matrix_3(first,beyond,covariance,c,k,(Point*) NULL);
// compute fitting line
return fitting_line_3(covariance,c,line,k);
} // end fit line to point set
// fits a plane to a 3D triangle set
template < typename InputIterator,
typename K >
typename K::FT
linear_least_squares_fitting_3(InputIterator first,
InputIterator beyond,
typename K::Plane_3& plane, // best fit plane
typename K::Point_3& c, // centroid
const K& k, // kernel
const typename K::Triangle_3*)
{
typedef typename K::FT FT;
typedef typename K::Point_3 Point;
typedef typename K::Vector_3 Vector;
typedef typename K::Triangle_3 Triangle;
// precondition: at least one element in the container.
CGAL_precondition(first != beyond);
// compute centroid
c = centroid(first,beyond,K());
// assemble covariance matrix
FT covariance[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
assemble_covariance_matrix_3(first,beyond,covariance,c,k,(Triangle*) NULL);
// compute fitting plane
return fitting_plane_3(covariance,c,plane,k);
} // end linear_least_squares_fitting_3
// fits a line to a 3D triangle set
template < typename InputIterator,
typename K >
typename K::FT
linear_least_squares_fitting_3(InputIterator first,
InputIterator beyond,
typename K::Line_3& line, // best fit line
typename K::Point_3& c, // centroid
const K& k, // kernel
const typename K::Triangle_3*)
{
typedef typename K::FT FT;
typedef typename K::Point_3 Point;
typedef typename K::Vector_3 Vector;
typedef typename K::Triangle_3 Triangle;
typedef typename K::Line_3 Line;
// precondition: at least one element in the container.
CGAL_precondition(first != beyond);
// compute centroid
c = centroid(first,beyond,K());
// assemble covariance matrix
FT covariance[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
assemble_covariance_matrix_3(first,beyond,covariance,c,k,(Triangle*) NULL);
// compute fitting plane
return fitting_line_3(covariance,c,line,k);
} // end linear_least_squares_fitting_3
} // end namespace CGALi
template < typename InputIterator,
typename K >
inline