This forum has been archived. All content is frozen. Please use KDE Discuss instead.

Porting Avogadro's hyperplane code

Tags: None
(comma "," separated)
ghutchis
Registered Member
Posts
3
Karma
0

Porting Avogadro's hyperplane code

Mon Jul 20, 2015 5:30 pm
Hi,

It's been ages, but I'm trying to finish porting Avogadro to Eigen3. Benoit wrote some nice code to rotate a molecule (basically a 3D point cloud) using the best-fit hyperplane:

Vector3d ** atomPositions = new Vector3d*[nAtoms];
// Calculate the center of the molecule too
foreach (Atom *atom, m_atomList) {
Vector3d *pos = &(*m_atomPos)[atom->id()];
d->center += *pos;
atomPositions[i++] = pos;
}
d->center /= static_cast<double>(nAtoms);
Eigen::Hyperplane<double, 3> planeCoeffs;
Eigen::fitHyperplane(numAtoms(), atomPositions, &planeCoeffs);
delete[] atomPositions;
d->normalVector = planeCoeffs.normal();

Is there already some easy migration path for this (i.e., fitting a Hyperplane from a set of points)?

Thanks,
-Geoff
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
The main problem of the deprecated fitHyperplane function was that its API was not generic enough. Anyway, hyperplane fitting is not complicated:
Code: Select all
Matrix3Xf points = ...;
Vector3f mean = points.rowwise().mean();
Matrix3Xf centered_points = points.colwise()-mean();
Matrix3f cov = centered_points * centered_points.transpose();
SelfAdjointEigenSolver<Matrix3f> eig(cov);
HyperPlane3f plane(mean, eig.eigenvectors()(0));

You can also directly use eig.eigenvectors() as a 3x3 rotation matrix to align your molecule.

If the data are too far away from the origin, you also directly compute the covariance matrix as follows:
Code: Select all
Matrix3f cov = points * points.transpose();
cov  =- points.cols() * mean * mean.transpose();


Bookmarks



Who is online

Registered users: bartoloni, Bing [Bot], Google [Bot], Yahoo [Bot]