Chaste Release::3.1
PapillaryFibreCalculator.hpp
00001 /*
00002 
00003 Copyright (c) 2005-2012, University of Oxford.
00004 All rights reserved.
00005 
00006 University of Oxford means the Chancellor, Masters and Scholars of the
00007 University of Oxford, having an administrative office at Wellington
00008 Square, Oxford OX1 2JD, UK.
00009 
00010 This file is part of Chaste.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014  * Redistributions of source code must retain the above copyright notice,
00015    this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright notice,
00017    this list of conditions and the following disclaimer in the documentation
00018    and/or other materials provided with the distribution.
00019  * Neither the name of the University of Oxford nor the names of its
00020    contributors may be used to endorse or promote products derived from this
00021    software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 
00034 */
00035 #ifndef PAPILLARYFIBRECALCULATOR_HPP_
00036 #define PAPILLARYFIBRECALCULATOR_HPP_
00037 
00038 #include "UblasCustomFunctions.hpp"
00039 #include "TetrahedralMesh.hpp"
00040 
00046 class PapillaryFibreCalculator
00047 {
00048 // Allow the test class to use the private functions.
00049 friend class TestPapillaryFibreCalculator;
00050 
00051 private:
00053     TetrahedralMesh<3,3>& mrMesh;
00055     std::vector< c_vector<double, 3> > mRadiusVectors;
00057     std::vector< c_matrix<double,3,3> > mStructureTensors;
00059     std::vector< c_matrix<double,3,3> > mSmoothedStructureTensors;
00060 
00068     c_vector<double,3> GetRadiusVectorForOneElement(unsigned elementIndex);
00069 
00074     void GetRadiusVectors();
00075 
00076 
00082     void ConstructStructureTensors();
00083 
00093     void SmoothStructureTensors();
00094 
00095 public:
00101     PapillaryFibreCalculator(TetrahedralMesh<3,3>& rMesh);
00102 
00108      std::vector<c_vector<double,3> > CalculateFibreOrientations();
00109 
00110 };
00111 
00112 // PUBLIC METHODS
00113 PapillaryFibreCalculator::PapillaryFibreCalculator(TetrahedralMesh<3,3>& rMesh)
00114     : mrMesh(rMesh)
00115 {
00116     mRadiusVectors.resize(mrMesh.GetNumElements());
00117     mStructureTensors.resize(mrMesh.GetNumElements());
00118     mSmoothedStructureTensors.resize(mrMesh.GetNumElements());
00119 }
00120 
00121 std::vector<c_vector<double,3> > PapillaryFibreCalculator::CalculateFibreOrientations()
00122 {
00123    GetRadiusVectors();
00124 
00125    ConstructStructureTensors();
00126 
00127    SmoothStructureTensors();
00128 
00129    // Calculate eigenvalues
00130    std::vector<c_vector<double,3> > fibre_orientations(mrMesh.GetNumElements());
00131    for(unsigned i=0; i<fibre_orientations.size(); i++)
00132    {
00133        fibre_orientations[i] = CalculateEigenvectorForSmallestNonzeroEigenvalue(mSmoothedStructureTensors[i]);
00134    }
00135 
00136    return fibre_orientations;
00137 }
00138 
00139 // PRIVATE METHODS
00140 c_vector<double,3> PapillaryFibreCalculator::GetRadiusVectorForOneElement(unsigned elementIndex)
00141 {
00142     c_vector<double, 3> centroid = (mrMesh.GetElement(elementIndex))->CalculateCentroid();
00143     // Loops over all papillary face nodes
00144     c_vector<double,3> coordinates;
00145 
00146     double nearest_r_squared=DBL_MAX;
00147     unsigned nearest_face_node = 0;
00148 
00149     TetrahedralMesh<3,3>::BoundaryNodeIterator bound_node_iter = mrMesh.GetBoundaryNodeIteratorBegin();
00150     while (bound_node_iter != mrMesh.GetBoundaryNodeIteratorEnd())
00151     {
00152         unsigned bound_node_index =  (*bound_node_iter)->GetIndex();
00153         coordinates=mrMesh.GetNode(bound_node_index)->rGetLocation();
00154 
00155         // Calculates the distance between the papillary face node and the centroid
00156         double r_squared =  norm_2(centroid-coordinates);
00157         // Checks to see if it is the smallest so far - if it is, update the current smallest distance
00158         if (r_squared < nearest_r_squared)
00159         {
00160             nearest_r_squared = r_squared;
00161             nearest_face_node = bound_node_index;
00162         }
00163         ++bound_node_iter;
00164     }
00165 
00166     coordinates = mrMesh.GetNode(nearest_face_node)->rGetLocation();
00167     c_vector<double,3> radial_vector = coordinates-centroid;
00168     return radial_vector;
00169 }
00170 
00171 void PapillaryFibreCalculator::GetRadiusVectors()
00172 {
00173     // Loops over all elements finding radius vector
00174     for (AbstractTetrahedralMesh<3,3>::ElementIterator iter = mrMesh.GetElementIteratorBegin();
00175          iter != mrMesh.GetElementIteratorEnd();
00176          ++iter)
00177     {
00178         unsigned element_index = iter->GetIndex();
00179         mRadiusVectors[element_index] = GetRadiusVectorForOneElement(element_index);
00180     }
00181 }
00182 
00183 void PapillaryFibreCalculator::ConstructStructureTensors()
00184 {
00185     for(unsigned i=0;i<mRadiusVectors.size();i++)
00186     {
00187         mStructureTensors[i] = outer_prod(mRadiusVectors[i],mRadiusVectors[i]);
00188     }
00189 }
00190 
00191 void PapillaryFibreCalculator::SmoothStructureTensors()
00192 {
00193     const double sigma = 0.05; //cm
00194     const double r_max = 0.1; //cm
00195     double g_factor_sum = 0;
00196     double g_factor = 0;
00197 
00198     for (AbstractTetrahedralMesh<3,3>::ElementIterator elem_iter = mrMesh.GetElementIteratorBegin();
00199          elem_iter != mrMesh.GetElementIteratorEnd();
00200          ++elem_iter)
00201     {
00202         mSmoothedStructureTensors[ elem_iter->GetIndex()] = zero_matrix<double>(3,3);
00203 
00204         c_vector<double, 3> centroid = elem_iter->CalculateCentroid();
00205         g_factor_sum = 0;
00206 
00207         for (AbstractTetrahedralMesh<3,3>::ElementIterator iter_2 = mrMesh.GetElementIteratorBegin();
00208              iter_2 != mrMesh.GetElementIteratorEnd();
00209              ++iter_2)
00210         {
00211             c_vector<double, 3> centroid_2 = iter_2->CalculateCentroid();
00212             double r = norm_2(centroid-centroid_2);
00213             if (r < r_max)
00214             {
00215                 g_factor = exp(-r/(2*sigma*sigma));
00216 
00217                 g_factor_sum += g_factor;
00218 
00219                 mSmoothedStructureTensors[elem_iter->GetIndex()] += g_factor*mStructureTensors[iter_2->GetIndex()];
00220             }
00221         }
00222 
00223         mSmoothedStructureTensors[elem_iter->GetIndex()] /= g_factor_sum;
00224     }
00225 }
00226 
00227 #endif /*PAPILLARYFIBRECALCULATOR_HPP_*/
00228