Blender  V2.59
LOD_NdQuadric.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: LOD_NdQuadric.cpp 35147 2011-02-25 10:47:28Z jesterking $
00003  * ***** BEGIN GPL LICENSE BLOCK *****
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  *
00019  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00020  * All rights reserved.
00021  *
00022  * The Original Code is: all of this file.
00023  *
00024  * Contributor(s): none yet.
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include "LOD_NdQuadric.h"
00035 
00036 #include <iostream>
00037 
00038 // for Lower Upper decompostion code.
00039 #include "TNT/lu.h"
00040 
00041 //soon to be template parameter.
00042 #define MAT_SIZE 3
00043 
00044 LOD_NdQuadric::
00045 LOD_NdQuadric(
00046         const MT_Vector3 & vec,
00047         const MT_Scalar & offset
00048 ):
00049         m_q(vec,offset),
00050         m_prop_grad1(int(MAT_SIZE),MT_Scalar(0)),
00051         m_prop_grad2(int(MAT_SIZE),MT_Scalar(0)),
00052         m_prop_grad3(int(MAT_SIZE),MT_Scalar(0)),
00053         m_bbottom(int(MAT_SIZE),MT_Scalar(0)),
00054         m_diag (int(MAT_SIZE),MT_Scalar(0))
00055 {
00056         // nothing to do
00057 }
00058 // Initialize a quadric from a linear functional describing
00059 // the property gradient.pos is the position where this
00060 // functional is placed in the array.
00061 
00062 LOD_NdQuadric::
00063 LOD_NdQuadric(
00064         const MT_Vector3 & vec,
00065         const MT_Scalar & offset,
00066         int pos
00067 ):
00068         m_q(vec,offset),
00069         m_prop_grad1(int(MAT_SIZE),MT_Scalar(0)),
00070         m_prop_grad2(int(MAT_SIZE),MT_Scalar(0)),
00071         m_prop_grad3(int(MAT_SIZE),MT_Scalar(0)),
00072         m_bbottom(int(MAT_SIZE),MT_Scalar(0)),
00073         m_diag (int(MAT_SIZE),MT_Scalar(0))
00074 {
00075         m_prop_grad1[pos] = -vec[0];
00076         m_prop_grad2[pos] = -vec[1];
00077         m_prop_grad3[pos] = -vec[2];
00078         
00079         m_bbottom[pos] = -offset;
00080         m_diag[pos] = MT_Scalar(1);
00081 }
00082 
00083 
00084 LOD_NdQuadric::
00085 LOD_NdQuadric(
00086 ):
00087         m_prop_grad1(int(MAT_SIZE),MT_Scalar(0)),
00088         m_prop_grad2(int(MAT_SIZE),MT_Scalar(0)),
00089         m_prop_grad3(int(MAT_SIZE),MT_Scalar(0)),
00090         m_bbottom(int(MAT_SIZE),MT_Scalar(0)),
00091         m_diag (int(MAT_SIZE),MT_Scalar(0)),
00092         m_q()
00093 {
00094 }
00095 
00096 
00097 
00098 // This class also has the default copy constructors
00099 // available.
00100 
00101         void
00102 LOD_NdQuadric::
00103 Tensor(
00104         TNT::Matrix<MT_Scalar> &tensor          
00105 ) const {
00106         
00107         // Set the matrix to zero
00108         tensor = 0;
00109         
00110         // Fill in the matrix values from d variables.
00111 
00112         MT_Matrix3x3 tensor3x3 = m_q.Tensor();
00113         int i,j;
00114 
00115         for (j=0; j<=2; j++) {
00116                 for (i=0; i<=2; i++) {
00117                         tensor[j][i] = tensor3x3[j][i];
00118                 }
00119         }
00120 
00121         // now the diagonal entry.
00122 
00123         for (i=3;i <3+MAT_SIZE;++i) {
00124                 tensor[i][i] = m_diag[i-3];
00125         }
00126 
00127         // now the property gradients rows and symmetrical columns
00128 
00129         for (i=3; i < 3+MAT_SIZE; i++) {
00130                 tensor[0][i] = m_prop_grad1[i-3];
00131                 tensor[i][0] = m_prop_grad1[i-3];
00132 
00133                 tensor[1][i] = m_prop_grad2[i-3];
00134                 tensor[i][1] = m_prop_grad2[i-3];
00135 
00136                 tensor[2][i] = m_prop_grad3[i-3];
00137                 tensor[i][2] = m_prop_grad3[i-3];
00138         }
00139 
00140 
00141 }
00142                 
00143         void
00144 LOD_NdQuadric::
00145 Vector(
00146         TNT::Vector<MT_Scalar> &vector
00147 ) const {
00148         int i;
00149 
00150         MT_Vector3 q_vec = m_q.Vector();
00151 
00152         vector[0] = q_vec[0];   
00153         vector[1] = q_vec[1];
00154         vector[2] = q_vec[2];
00155 
00156         for (i = 3; i < 3 + MAT_SIZE; ++i) {
00157                 vector[i] = m_bbottom[i-3];
00158         }
00159 }                
00160 
00161         void 
00162 LOD_NdQuadric::
00163 Clear(
00164         MT_Scalar val
00165 ) {
00166         m_q.Clear(val);
00167         m_prop_grad1 = val;
00168         m_prop_grad2 = val;
00169         m_prop_grad3 = val;
00170         m_bbottom = val;
00171         m_diag = val;
00172 };
00173 
00174         LOD_NdQuadric & 
00175 LOD_NdQuadric::
00176 operator=(
00177         const LOD_NdQuadric& Q
00178 ){
00179 
00180         m_q = Q.m_q;
00181         m_prop_grad1 = Q.m_prop_grad1;
00182         m_prop_grad2 = Q.m_prop_grad2;
00183         m_prop_grad3 = Q.m_prop_grad3;
00184         m_bbottom = Q.m_bbottom;
00185         m_diag = Q.m_diag;
00186 
00187         return (*this);
00188 }
00189         
00190         LOD_NdQuadric& 
00191 LOD_NdQuadric::
00192 operator+=(
00193         const LOD_NdQuadric& Q
00194 ){      
00195         m_q += Q.m_q;
00196         TNT::vectoradd(m_prop_grad1,Q.m_prop_grad1);
00197         TNT::vectoradd(m_prop_grad2,Q.m_prop_grad2);
00198         TNT::vectoradd(m_prop_grad3,Q.m_prop_grad3);
00199         TNT::vectoradd(m_bbottom,Q.m_bbottom);
00200         TNT::vectoradd(m_diag,Q.m_diag);
00201 
00202         return (*this);
00203 }
00204 
00205         LOD_NdQuadric& 
00206 LOD_NdQuadric::
00207 operator*=(
00208         const MT_Scalar & s
00209 ){
00210         // multiply everything by s
00211 
00212         m_q *= s;
00213         TNT::vectorscale(m_prop_grad1,s);
00214         TNT::vectorscale(m_prop_grad2,s);
00215         TNT::vectorscale(m_prop_grad3,s);
00216         TNT::vectorscale(m_bbottom,s);
00217         TNT::vectorscale(m_diag,s);
00218 
00219         return (*this);
00220 }
00221 
00222         MT_Scalar 
00223 LOD_NdQuadric::
00224 Evaluate(
00225         const TNT::Vector<MT_Scalar> & vec
00226 ) const {
00227         // compute the quadric error cost for the vector.
00228 
00229         //FIXME very inefficient memory usage here 
00230         //Way to many computations-these are symmetric!
00231 
00232         TNT::Matrix<MT_Scalar>  Atensor(3+MAT_SIZE,3+MAT_SIZE,MT_Scalar(0));
00233         Tensor(Atensor);
00234         
00235         TNT::Vector<MT_Scalar>  Bvector(3+MAT_SIZE);
00236         Vector(Bvector);
00237 
00238         TNT::Vector<MT_Scalar> temp1(3+MAT_SIZE);
00239 
00240         TNT::matmult(temp1,Atensor,vec);
00241 
00242         return TNT::dot_prod(vec,temp1) + 2*TNT::dot_prod(Bvector,vec) + m_q.Scalar();
00243 }       
00244 
00245 
00246         bool 
00247 LOD_NdQuadric::
00248 Optimize(
00249         TNT::Vector<MT_Scalar> & vec
00250 ) const {
00251         
00252         // Return the solution to Tensor().invers() * Vector();
00253         // Use lower upper decomposition --again we're creating
00254         // heap memory for this function.
00255         
00256         TNT::Vector<TNT::Subscript> pivots(3+MAT_SIZE,0);
00257         TNT::Matrix<MT_Scalar> Atensor(3+MAT_SIZE,3+MAT_SIZE,MT_Scalar(0));
00258         
00259         Tensor(Atensor);
00260         Vector(vec);
00261 
00262         // Find the decomposition of the matrix. If none available 
00263         // matrix is singular return false.
00264 
00265         if (TNT::LU_factor(Atensor,pivots)) {
00266                 return false;
00267         }
00268 
00269         if (TNT::LU_solve(Atensor,pivots,vec)) {
00270                 return false;
00271         }
00272         
00273         // Now we should return -Ainv(B)!
00274         
00275         TNT::Vector<MT_Scalar>::iterator start = vec.begin();
00276         TNT::Vector<MT_Scalar>::const_iterator end = vec.end();
00277 
00278         while (start != end) {
00279                 *start = -(*start);
00280                 ++start;
00281         }
00282 
00283 #if 0
00284         std::cout << vec << "\n";
00285 #endif
00286         return true;
00287 };
00288 
00289 
00290 #undef MAT_SIZE