PapillaryFibreCalculator.hpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2009
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 #ifndef PAPILLARYFIBRECALCULATOR_HPP_
00029 #define PAPILLARYFIBRECALCULATOR_HPP_
00030 
00031 #include "UblasCustomFunctions.hpp"
00032 #include "TetrahedralMesh.hpp"
00033 
00039 class PapillaryFibreCalculator
00040 {
00041 // Allow the test class to use the private functions.
00042 friend class TestPapillaryFibreCalculator;
00043 
00044 private:
00045     TetrahedralMesh<3,3>& mrMesh;
00047     std::vector< c_vector<double, 3> > mRadiusVectors;
00049     std::vector< c_matrix<double,3,3> > mStructureTensors;
00051     std::vector< c_matrix<double,3,3> > mSmoothedStructureTensors;
00052 
00060     c_vector<double,3> GetRadiusVectorForOneElement(unsigned elementIndex);
00061 
00066     void GetRadiusVectors();
00067 
00068 
00074     void ConstructStructureTensors();
00075 
00085     void SmoothStructureTensors();
00086 
00087 public:
00093     PapillaryFibreCalculator(TetrahedralMesh<3,3>& rMesh);
00094 
00100      std::vector<c_vector<double,3> > CalculateFibreOrientations();
00101 
00102 };
00103 
00104 // PUBLIC METHODS
00105 PapillaryFibreCalculator::PapillaryFibreCalculator(TetrahedralMesh<3,3>& rMesh)
00106     : mrMesh(rMesh)
00107 {
00108     mRadiusVectors.resize(mrMesh.GetNumElements());
00109     mStructureTensors.resize(mrMesh.GetNumElements());
00110     mSmoothedStructureTensors.resize(mrMesh.GetNumElements());
00111 }
00112 
00113 std::vector<c_vector<double,3> > PapillaryFibreCalculator::CalculateFibreOrientations()
00114 {
00115    GetRadiusVectors();
00116 
00117    ConstructStructureTensors();
00118 
00119    SmoothStructureTensors();
00120 
00121    // Calculate eigenvalues
00122    std::vector<c_vector<double,3> > fibre_orientations(mrMesh.GetNumElements());
00123    for(unsigned i=0; i<fibre_orientations.size(); i++)
00124    {
00125        fibre_orientations[i] = CalculateEigenvectorForSmallestNonzeroEigenvalue(mSmoothedStructureTensors[i]);
00126    }
00127 
00128    return fibre_orientations;
00129 }
00130 
00131 // PRIVATE METHODS
00132 c_vector<double,3> PapillaryFibreCalculator::GetRadiusVectorForOneElement(unsigned elementIndex)
00133 {
00134     c_vector<double, 3> centroid = (mrMesh.GetElement(elementIndex))->CalculateCentroid();
00135     // Loops over all papillary face nodes
00136     c_vector<double,3> coordinates;
00137 
00138     double nearest_r_squared=DBL_MAX;
00139     unsigned nearest_face_node = 0;
00140 
00141     TetrahedralMesh<3,3>::BoundaryNodeIterator bound_node_iter = mrMesh.GetBoundaryNodeIteratorBegin();
00142     while (bound_node_iter != mrMesh.GetBoundaryNodeIteratorEnd())
00143     {
00144         unsigned bound_node_index =  (*bound_node_iter)->GetIndex();
00145         coordinates=mrMesh.GetNode(bound_node_index)->rGetLocation();
00146 
00147         // Calculates the distance between the papillary face node and the centroid
00148         double r_squared =  norm_2(centroid-coordinates);
00149         // Checks to see if it is the smallest so far - if it is, update the current smallest distance
00150         if (r_squared < nearest_r_squared)
00151         {
00152             nearest_r_squared = r_squared;
00153             nearest_face_node = bound_node_index;
00154         }
00155         ++bound_node_iter;
00156     }
00157 
00158     coordinates = mrMesh.GetNode(nearest_face_node)->rGetLocation();
00159     c_vector<double,3> radial_vector = coordinates-centroid;
00160     return radial_vector;
00161 }
00162 
00163 void PapillaryFibreCalculator::GetRadiusVectors()
00164 {
00165     // Loops over all elements finding radius vector
00166     for(TetrahedralMesh<3,3>::ElementIterator iter = mrMesh.GetElementIteratorBegin();
00167         iter != mrMesh.GetElementIteratorEnd();
00168         ++iter)
00169     {
00170         unsigned element_index = (*iter)->GetIndex();
00171 
00172         mRadiusVectors[element_index] = GetRadiusVectorForOneElement(element_index);
00173     }
00174 }
00175 
00176 void PapillaryFibreCalculator::ConstructStructureTensors()
00177 {
00178     for(unsigned i=0;i<mRadiusVectors.size();i++)
00179     {
00180         mStructureTensors[i] = outer_prod(mRadiusVectors[i],mRadiusVectors[i]);
00181     }
00182 }
00183 
00184 void PapillaryFibreCalculator::SmoothStructureTensors()
00185 {
00186     const double sigma = 0.05; //cm
00187     const double r_max = 0.1; //cm
00188     double g_factor_sum = 0;
00189     double g_factor = 0;
00190 
00191     for(TetrahedralMesh<3,3>::ElementIterator elem_iter = mrMesh.GetElementIteratorBegin();
00192         elem_iter != mrMesh.GetElementIteratorEnd();
00193         ++elem_iter)
00194     {
00195         mSmoothedStructureTensors[ (*elem_iter)->GetIndex()] = zero_matrix<double>(3,3);
00196 
00197         c_vector<double, 3> centroid = (*elem_iter)->CalculateCentroid();
00198         g_factor_sum = 0;
00199 
00200         for(TetrahedralMesh<3,3>::ElementIterator iter_2 = mrMesh.GetElementIteratorBegin();
00201             iter_2 != mrMesh.GetElementIteratorEnd();
00202             ++iter_2)
00203         {
00204             c_vector<double, 3> centroid_2 = (*iter_2)->CalculateCentroid();
00205             double r = norm_2(centroid-centroid_2);
00206             if (r < r_max)
00207             {
00208                 g_factor = exp(-r/(2*sigma*sigma));
00209 
00210                 g_factor_sum += g_factor;
00211 
00212                 mSmoothedStructureTensors[ (*elem_iter)->GetIndex()] += g_factor*mStructureTensors[ (*iter_2)->GetIndex()];
00213             }
00214         }
00215 
00216         mSmoothedStructureTensors[ (*elem_iter)->GetIndex()] /= g_factor_sum;
00217     }
00218 }
00219 
00220 #endif /*PAPILLARYFIBRECALCULATOR_HPP_*/
00221 

Generated on Wed Mar 18 12:51:52 2009 for Chaste by  doxygen 1.5.5