00001
00002
00003
00004
00005
00006
00007
00008 #ifndef IMPALGEBRA_GEOMETRIC_ALIGNMENT_H
00009 #define IMPALGEBRA_GEOMETRIC_ALIGNMENT_H
00010
00011 #include "algebra_config.h"
00012
00013 #include "Vector3D.h"
00014 #include "Rotation3D.h"
00015 #include "Transformation3D.h"
00016 #include "Transformation2D.h"
00017 #include "internal/tnt_array2d.h"
00018 #include "internal/jama_svd.h"
00019 #include <IMP/log.h>
00020
00021
00022 IMPALGEBRA_BEGIN_NAMESPACE
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 template <class Vector3DsOrXYZs0,
00043 class Vector3DsOrXYZs1>
00044 IMP::algebra::Transformation3D
00045 get_transformation_aligning_first_to_second(const Vector3DsOrXYZs0 &from,
00046 const Vector3DsOrXYZs1 &to) {
00047 IMP_INTERNAL_CHECK(from.size() == to.size(), "sizes don't match");
00048
00049
00050
00051 VectorD<3> center_from(0,0,0), center_to(0,0,0);
00052 for (unsigned int i=0; i< from.size(); ++i) {
00053
00054 center_from+= get_geometry(from[i]);
00055 center_to += get_geometry(to[i]);
00056 IMP_LOG(VERBOSE, i << ": (" << get_geometry(from[i])
00057 << ") (" << get_geometry(to[i]) << ")\n");
00058 }
00059 center_from = center_from/from.size();
00060 center_to = center_to/to.size();
00061
00062 IMP_LOG(VERBOSE, "Centers are (" << center_from << ") (" << center_to
00063 << ")\n");
00064 std::vector<VectorD<3> > shifted_from(from.size()), shifted_to(to.size());
00065 for (unsigned int i=0; i< from.size(); ++i) {
00066 shifted_from[i]=get_geometry(from[i])-center_from;
00067 shifted_to[i]= get_geometry(to[i])-center_to;
00068 }
00069
00070
00071 internal::TNT::Array2D<double> H(3, 3);
00072 for (int i = 0; i < 3; i++) {
00073 for (int j = 0; j < 3; j++) {
00074 H[i][j] = 0;
00075 }
00076 }
00077 for (unsigned int i = 0; i < from.size(); i++) {
00078 for (int j = 0; j < 3; j++) {
00079 for (int k = 0; k < 3; k++) {
00080 H[j][k] += shifted_from[i][j]*shifted_to[i][k];
00081 }
00082 }
00083 }
00084
00085 IMP_LOG(VERBOSE, "H is " << H << std::endl);
00086
00087 internal::JAMA::SVD<double> svd(H);
00088 internal::TNT::Array2D<double> U(3, 3), V(3, 3);
00089 svd.getU(U);
00090 svd.getV(V);
00091
00092 IMP_LOG(VERBOSE, "SVD is " << U << std::endl << V << std::endl);
00093
00094 internal::TNT::Array1D<double> SV;
00095 svd.getSingularValues(SV);
00096 double det= SV[0]*SV[1]*SV[2];
00097 IMP_IF_CHECK(USAGE) {
00098 if (det < .00001) {
00099 IMP_LOG(TERSE, "FROM:\n");
00100 for (unsigned int i=0; i< from.size(); ++i) {
00101 IMP_LOG(TERSE, from[i] << std::endl);
00102 }
00103 IMP_LOG(TERSE, "TO:\n");
00104 for (unsigned int i=0; i< from.size(); ++i) {
00105 IMP_LOG(TERSE, to[i] << std::endl);
00106 }
00107 IMP_LOG(TERSE, H);
00108 IMP_WARN("Degenerate point set. I may not be able to align them."
00109 << std::endl);
00110 }
00111 }
00112
00113 IMP_IF_LOG(VERBOSE) {
00114 internal::TNT::Array2D<double> Sigma(3,3, 0.0);
00115
00116 for (int i=0; i < 3; ++i) {
00117 Sigma[i][i]= SV[i];
00118 }
00119
00120 IMP_LOG(VERBOSE, "Reconstructed is "
00121 << internal::TNT::matmult(internal::TNT::matmult(U,Sigma),
00122 internal::TNT::transpose(V))
00123 << std::endl);
00124 }
00125
00126
00127 internal::TNT::Array2D<double> UT = internal::TNT::transpose(U);
00128 internal::TNT::Array2D<double> rot(3, 3);
00129 rot = matmult(V, UT);
00130
00131
00132 if (determinant(rot) < 0) {
00133 IMP_LOG(VERBOSE, "Flipping matrix"<<std::endl);
00134 internal::TNT::Array2D<double> VT = internal::TNT::transpose(V);
00135 internal::TNT::Array2D<double> UVT = internal::TNT::matmult(U, VT);
00136 internal::TNT::Array2D<double> S(3, 3);
00137 S[0][0] = S[1][1] = 1;
00138 S[2][2] = determinant(UVT);
00139 S[0][1] = S[0][2] = S[1][0] = S[1][2] = S[2][0] = S[2][1] = 0;
00140 rot = internal::TNT::matmult(internal::TNT::matmult(U, S), VT);
00141 }
00142
00143 IMP_LOG(VERBOSE, "Rotation matrix is " << rot << std::endl);
00144
00145 Rotation3D rotation
00146 = get_rotation_from_matrix(rot[0][0], rot[0][1], rot[0][2],
00147 rot[1][0], rot[1][1], rot[1][2],
00148 rot[2][0], rot[2][1], rot[2][2]);
00149 IMP_LOG(VERBOSE, "Rotation is " << rotation << std::endl);
00150 VectorD<3> translation=center_to - rotation.get_rotated(center_from);
00151
00152 Transformation3D ret(rotation, translation);
00153 return ret;
00154 }
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 IMPALGEBRAEXPORT Transformation2D get_transformation_aligning_pair(
00165 const std::vector<VectorD<2> >& set_from,
00166 const std::vector<VectorD<2> >& set_to);
00167
00168
00169
00170 IMPALGEBRA_END_NAMESPACE
00171
00172 #endif