31 const Eigen::MatrixXd &targetPoints,
38 Eigen::MatrixXd centeredRefPnts(
40 Eigen::MatrixXd centeredTargetPnts(
42 Eigen::MatrixXd S(dim,
46 Eigen::VectorXd calcEigenVec(
51 if (refPoints.rows() != targetPoints.rows() ||
52 refPoints.cols() != targetPoints.cols()) {
55 <<
"The reference and target point sets are not of the same size.\n";
77 Spectra::DenseSymMatProd<double> op(N);
81 Spectra::SymEigsSolver<double, Spectra::LARGEST_ALGE,
82 Spectra::DenseSymMatProd<double>>
87 int nconv = eigs.compute();
89 if (eigs.info() == Spectra::SUCCESSFUL) {
90 Eigen::VectorXd calcEigenValue = eigs.eigenvalues();
91 calcEigenVec = eigs.eigenvectors();
96 double qNorm = sqrt(calcEigenVec.dot(calcEigenVec));
97 calcEigenVec /= qNorm;
100 for (
int i = 0; i < 4; i++) {
101 (*quat)[i] = calcEigenVec(i);
109 (*rmsd) =
absor::getRMSD(centeredRefPnts, centeredTargetPnts, calcEigenVec,
110 rmsdList, nop, (*scale));
132 const Eigen::MatrixXd ¢eredTargetPnts,
134 Eigen::MatrixXd S(nop, dim);
135 Eigen::VectorXd targetCoord(nop);
136 Eigen::VectorXd refCoord(nop);
140 for (
int iCol = 0; iCol < dim; iCol++) {
142 for (
int jCol = 0; jCol < dim; jCol++) {
144 centeredTargetPnts.col(iCol);
145 refCoord = centeredRefPnts.col(jCol);
146 Svalue = targetCoord.dot(refCoord);
147 S(iCol, jCol) = Svalue;
174 Eigen::MatrixXd N(4, 4);
176 double Sxx = S(0, 0);
177 double Sxy = S(0, 1);
178 double Sxz = S(0, 2);
179 double Syx = S(1, 0);
180 double Syy = S(1, 1);
181 double Syz = S(1, 2);
182 double Szx = S(2, 0);
183 double Szy = S(2, 1);
184 double Szz = S(2, 2);
194 N(0, 0) = Sxx + Syy + Szz;
195 N(1, 1) = Sxx - Syy - Szz;
196 N(2, 2) = -Sxx + Syy - Szz;
197 N(3, 3) = -Sxx - Syy + Szz;
229 int nop = pointSet.rows();
230 int dim = pointSet.cols();
231 Eigen::MatrixXd centeredPointSet(nop, dim);
232 Eigen::VectorXd vecOfOnes(nop);
238 vecOfOnes = Eigen::VectorXd::Ones(nop);
241 for (
int i = 0; i < nop; i++) {
242 for (
int k = 0; k < dim; k++) {
243 coordValue = pointSet(i, k);
244 centroid[k] += coordValue;
253 for (
int i = 0; i < nop; i++) {
254 for (
int k = 0; k < dim; k++) {
255 coordValue = pointSet(i, k);
256 centeredVal = coordValue - centroid[k];
257 centeredPointSet(i, k) = centeredVal;
261 return centeredPointSet;
277 const Eigen::MatrixXd &leftSys,
int n) {
280 Eigen::VectorXd rightVec(
282 Eigen::VectorXd leftVec(3);
289 for (
int i = 0; i < n; i++) {
291 rightVec = rightSys.row(i);
292 leftVec = leftSys.row(i);
293 v1 += rightVec.dot(rightVec);
294 v2 += leftVec.dot(leftVec);
311 Eigen::MatrixXd R(3, 3);
327 R(0, 0) = q0 * q0 + qx * qx + qy * qy + qz * qz;
328 R(0, 1) = 2 * (qx * qy - q0 * qz);
329 R(0, 2) = 2 * (qx * qz + q0 * qy);
331 R(1, 0) = 2 * (qy * qx + q0 * qz);
332 R(1, 1) = q0 * q0 + qx * qx + qy * qy + qz * qz;
333 R(1, 2) = 2 * (qy * qz - q0 * qy);
335 R(2, 0) = 2 * (qz * qx - q0 * qy);
336 R(2, 1) = 2 * (qz * qy + q0 * qz);
337 R(2, 2) = q0 * q0 + qx * qx + qy * qy + qz * qz;
360 const Eigen::MatrixXd ¢eredTargetPnts,
361 const Eigen::VectorXd &quat,
363 Eigen::MatrixXd R(3, 3);
365 (*rmsdList).resize(nop);
372 Eigen::VectorXd errorVec(3);
373 Eigen::VectorXd rotatedLeft(3);
374 Eigen::VectorXd targetCol(3);
375 Eigen::VectorXd refCol(3);
377 for (
int i = 0; i < nop; i++) {
380 targetCol = (centeredTargetPnts.row(i)).transpose();
381 refCol = (centeredRefPnts.row(i)).transpose();
383 rotatedLeft = R * targetCol;
384 errorVec = refCol - scale * rotatedLeft;
385 rmsd += errorVec.dot(errorVec);
386 (*rmsdList)[i] = sqrt(errorVec.dot(errorVec));
389 return sqrt(rmsd / nop);
double getRMSD(const Eigen::MatrixXd ¢eredRefPnts, const Eigen::MatrixXd ¢eredTargetPnts, const Eigen::VectorXd &quat, std::vector< double > *rmsdList, int nop, double scale)
Calculate the RMSD.
Eigen::MatrixXd calcMatrixS(const Eigen::MatrixXd ¢eredRefPnts, const Eigen::MatrixXd ¢eredTargetPnts, int nop, int dim)
double calcScaleFactor(const Eigen::MatrixXd &rightSys, const Eigen::MatrixXd &leftSys, int n)
Calculate the scale factor from the centered left and right point sets.
Eigen::MatrixXd centerWRTcentroid(const Eigen::MatrixXd &pointSet)
Center a point set wrt the centroid.
int hornAbsOrientation(const Eigen::MatrixXd &refPoints, const Eigen::MatrixXd &targetPoints, std::vector< double > *quat, double *rmsd, std::vector< double > *rmsdList, double *scale)
Get the absolute orientation using Horn's algorithm (with quaternions)
Eigen::MatrixXd calcMatrixN(const Eigen::MatrixXd &S)
Eigen::MatrixXd quat2RotMatrix(const Eigen::VectorXd &quat)
Get a rotation matrix from a unit quaternion.