contrib/mul/m23d/m23d_set_q_constraint.cxx
Go to the documentation of this file.
00001 #include "m23d_set_q_constraint.h"
00002 //:
00003 // \file
00004 // \author Tim Cootes
00005 // \brief Functions to construct linear constraints as rows in a matrix
00006 
00007 #include <vcl_algorithm.h>
00008 #include <vcl_cassert.h>
00009 
00010 //: Defines constraint on elements of Q of form a'Qb=r
00011 //  Q is a symmetric matrix, with n(n+1)/2 independent elements
00012 //  The constraints on these elements are placed in row c of A
00013 void m23d_set_q_constraint1(vnl_matrix<double> & A,
00014                       vnl_vector<double> & rhs,
00015                       unsigned c,
00016                       const vnl_vector<double>& a,
00017                       const vnl_vector<double>& b,
00018                       double r)
00019 {
00020    rhs[c]=r;
00021    unsigned n = a.size();
00022    unsigned k=0;
00023    for (unsigned i=0;i<n;++i)
00024      for (unsigned j=0;j<=i;++j,++k)
00025      {
00026        if (i==j) A(c,k)=a[i]*b[j];
00027        else      A(c,k)=a[i]*b[j]+a[j]*b[i];
00028      }
00029 }
00030 
00031 //: Defines constraint on elements of Q of form aQa'-bQb'=0
00032 //  Q is a symmetric matrix, with n(n+1)/2 independent elements
00033 //  The constraints on these elements are placed in row c of A
00034 void m23d_set_q_constraint2(vnl_matrix<double> & A,
00035                       vnl_vector<double> & rhs,
00036                       unsigned c,
00037                       const vnl_vector<double>& a,
00038                       const vnl_vector<double>& b)
00039 {
00040    rhs[c]=0;
00041    unsigned n = a.size();
00042    unsigned k=0;
00043    for (unsigned i=0;i<n;++i)
00044      for (unsigned j=0;j<=i;++j,++k)
00045      {
00046        if (i==j) A(c,k)=a[i]*a[j]-b[i]*b[j];
00047        else      A(c,k)=2*(a[i]*a[j]-b[i]*b[j]);
00048      }
00049 }
00050 
00051 
00052 //: Generate matrix of all constraints on elements of Q
00053 void m23d_set_q_constraints(const vnl_matrix<double> & M, unsigned k,
00054                             vnl_matrix<double>& A,
00055                             vnl_vector<double>& rhs)
00056 {
00057   unsigned m = M.cols()/3 -1;
00058   unsigned ns = M.rows()/2;
00059   unsigned nq = ((M.cols()+1)*M.cols())/2;
00060 
00061   unsigned n_con = 4*(m*(ns-m-1)+(m+m*m)/2)+3*m+2*(ns-m)+1;
00062 
00063   // Set up constraints on elements of Q
00064   A.set_size(n_con,nq);
00065   rhs.set_size(n_con);
00066 
00067   unsigned c=0;
00068 
00069   // Impose the basis constraints
00070   for (unsigned j=0;j<ns;++j)
00071   {
00072     vnl_vector<double> rxj = M.get_row(2*j);
00073     vnl_vector<double> ryj = M.get_row(2*j+1);
00074     for (unsigned i=0;i<=vcl_min(j,m);++i)
00075     {
00076       vnl_vector<double> rxi = M.get_row(2*i);
00077       vnl_vector<double> ryi = M.get_row(2*i+1);
00078 
00079       if (i==j)
00080       {
00081         if  (i==k)
00082         {
00083           // MiQMi' = I
00084           m23d_set_q_constraint1(A,rhs,c,rxi,rxi,1.0); ++c;
00085           m23d_set_q_constraint1(A,rhs,c,ryi,ryi,1.0); ++c;
00086           m23d_set_q_constraint1(A,rhs,c,rxi,ryi,0.0); ++c;
00087         }
00088         else
00089         {
00090           // MiQMi' = 0
00091           m23d_set_q_constraint1(A,rhs,c,rxi,rxi,0); ++c;
00092           m23d_set_q_constraint1(A,rhs,c,ryi,ryi,0); ++c;
00093           m23d_set_q_constraint1(A,rhs,c,rxi,ryi,0); ++c;
00094         }
00095       }
00096       else   // i!=j
00097       if (!((i==k) && j>m))
00098       {
00099         // MiQMj' = 0
00100         m23d_set_q_constraint1(A,rhs,c,rxi,rxj,0); ++c;
00101         m23d_set_q_constraint1(A,rhs,c,ryi,ryj,0); ++c;
00102         m23d_set_q_constraint1(A,rhs,c,rxi,ryj,0); ++c;
00103         m23d_set_q_constraint1(A,rhs,c,ryi,rxj,0); ++c;
00104       }
00105     }
00106   }
00107 
00108   // These constraints aim to impose orthogonality on rows of projection
00109   // matrices.
00110   for (unsigned i=m+1;i<ns;++i)
00111   {
00112     vnl_vector<double> rxi = M.get_row(2*i);
00113     vnl_vector<double> ryi = M.get_row(2*i+1);
00114     m23d_set_q_constraint2(A,rhs,c,rxi,ryi); ++c;
00115     m23d_set_q_constraint1(A,rhs,c,rxi,ryi,0); ++c;
00116   }
00117 
00118   assert(c==n_con);
00119 }