8 #ifndef IMPALGEBRA_GEOMETRIC_ALIGNMENT_H
9 #define IMPALGEBRA_GEOMETRIC_ALIGNMENT_H
11 #include <IMP/algebra/algebra_config.h>
17 #include "internal/tnt_array2d.h"
18 #include "internal/jama_svd.h"
22 IMPALGEBRA_BEGIN_NAMESPACE
41 template <
class Vector3DsOrXYZs0,
class Vector3DsOrXYZs1>
44 const Vector3DsOrXYZs1& target) {
50 Vector3D center_source(0, 0, 0), center_target(0, 0, 0);
51 for (
unsigned int i = 0; i < source.size(); ++i) {
53 center_source += get_vector_d_geometry(source[i]);
54 center_target += get_vector_d_geometry(target[i]);
56 << get_vector_d_geometry(target[i]) <<
")\n");
58 center_source = center_source / source.size();
59 center_target = center_target / target.size();
61 IMP_LOG_VERBOSE(
"Centers are (" << center_source <<
") (" << center_target
63 Vector3Ds shifted_source(source.size()), shifted_target(target.size());
64 for (
unsigned int i = 0; i < source.size(); ++i) {
65 shifted_source[i] = get_vector_d_geometry(source[i]) - center_source;
66 shifted_target[i] = get_vector_d_geometry(target[i]) - center_target;
70 internal::TNT::Array2D<double> H(3, 3);
71 for (
int i = 0; i < 3; i++) {
72 for (
int j = 0; j < 3; j++) {
76 for (
unsigned int i = 0; i < source.size(); i++) {
77 for (
int j = 0; j < 3; j++) {
78 for (
int k = 0; k < 3; k++) {
79 H[j][k] += shifted_source[i][j] * shifted_target[i][k];
86 internal::JAMA::SVD<double> svd(H);
87 internal::TNT::Array2D<double> U(3, 3), V(3, 3);
93 internal::TNT::Array1D<double> SV;
94 svd.getSingularValues(SV);
95 double det = SV[0] * SV[1] * SV[2];
99 for (
unsigned int i = 0; i < source.size(); ++i) {
103 for (
unsigned int i = 0; i < source.size(); ++i) {
107 IMP_WARN(
"Degenerate point set. I may not be able to align them."
113 internal::TNT::Array2D<double> Sigma(3, 3, 0.0);
115 for (
int i = 0; i < 3; ++i) {
120 internal::TNT::matmult(U, Sigma),
121 internal::TNT::transpose(V))
126 internal::TNT::Array2D<double> UT = internal::TNT::transpose(U);
127 internal::TNT::Array2D<double> rot(3, 3);
128 rot = matmult(V, UT);
131 if (determinant(rot) < 0) {
133 internal::TNT::Array2D<double> VT = internal::TNT::transpose(V);
134 internal::TNT::Array2D<double> UVT = internal::TNT::matmult(U, VT);
135 internal::TNT::Array2D<double> S(3, 3);
136 S[0][0] = S[1][1] = 1;
137 S[2][2] = determinant(UVT);
138 S[0][1] = S[0][2] = S[1][0] = S[1][2] = S[2][0] = S[2][1] = 0;
139 rot = internal::TNT::matmult(internal::TNT::matmult(U, S), VT);
145 rot[0][0], rot[0][1], rot[0][2], rot[1][0], rot[1][1], rot[1][2],
146 rot[2][0], rot[2][1], rot[2][2]);
160 IMPALGEBRAEXPORT Transformation2D
166 IMPALGEBRA_END_NAMESPACE
Vector3D get_rotated(const Vector3D &o) const
Rotate a vector around the origin.
Transformation2D get_transformation_aligning_pair(const Vector2Ds &set_from, const Vector2Ds &set_to)
#define IMP_WARN(expr)
Write a warning to a log.
base::Vector< VectorD< 2 > > Vector2Ds
#define IMP_LOG_TERSE(expr)
IMP::algebra::Transformation3D get_transformation_aligning_first_to_second(const Vector3DsOrXYZs0 &source, const Vector3DsOrXYZs1 &target)
Compute the rigid transform bringing the first point set to the second.
#define IMP_INTERNAL_CHECK(expr, message)
An assertion to check for internal errors in IMP. An IMP::ErrorException will be thrown.
#define IMP_IF_CHECK(level)
Execute the code block if a certain level checks are on.
Simple 3D rotation class.
Rotation3D get_rotation_from_matrix(double m00, double m01, double m02, double m10, double m11, double m12, double m20, double m21, double m22)
Generate a Rotation3D object from a rotation matrix.
Logging and error reporting support.
Exception definitions and assertions.
#define IMP_IF_LOG(level)
Execute the code block if a certain level of logging is on.
#define IMP_LOG_VERBOSE(expr)