PapillaryFibreCalculator.hpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
00042 friend class TestPapillaryFibreCalculator;
00043
00044 private:
00046 TetrahedralMesh<3,3>& mrMesh;
00048 std::vector< c_vector<double, 3> > mRadiusVectors;
00050 std::vector< c_matrix<double,3,3> > mStructureTensors;
00052 std::vector< c_matrix<double,3,3> > mSmoothedStructureTensors;
00053
00061 c_vector<double,3> GetRadiusVectorForOneElement(unsigned elementIndex);
00062
00067 void GetRadiusVectors();
00068
00069
00075 void ConstructStructureTensors();
00076
00086 void SmoothStructureTensors();
00087
00088 public:
00094 PapillaryFibreCalculator(TetrahedralMesh<3,3>& rMesh);
00095
00101 std::vector<c_vector<double,3> > CalculateFibreOrientations();
00102
00103 };
00104
00105
00106 PapillaryFibreCalculator::PapillaryFibreCalculator(TetrahedralMesh<3,3>& rMesh)
00107 : mrMesh(rMesh)
00108 {
00109 mRadiusVectors.resize(mrMesh.GetNumElements());
00110 mStructureTensors.resize(mrMesh.GetNumElements());
00111 mSmoothedStructureTensors.resize(mrMesh.GetNumElements());
00112 }
00113
00114 std::vector<c_vector<double,3> > PapillaryFibreCalculator::CalculateFibreOrientations()
00115 {
00116 GetRadiusVectors();
00117
00118 ConstructStructureTensors();
00119
00120 SmoothStructureTensors();
00121
00122
00123 std::vector<c_vector<double,3> > fibre_orientations(mrMesh.GetNumElements());
00124 for(unsigned i=0; i<fibre_orientations.size(); i++)
00125 {
00126 fibre_orientations[i] = CalculateEigenvectorForSmallestNonzeroEigenvalue(mSmoothedStructureTensors[i]);
00127 }
00128
00129 return fibre_orientations;
00130 }
00131
00132
00133 c_vector<double,3> PapillaryFibreCalculator::GetRadiusVectorForOneElement(unsigned elementIndex)
00134 {
00135 c_vector<double, 3> centroid = (mrMesh.GetElement(elementIndex))->CalculateCentroid();
00136
00137 c_vector<double,3> coordinates;
00138
00139 double nearest_r_squared=DBL_MAX;
00140 unsigned nearest_face_node = 0;
00141
00142 TetrahedralMesh<3,3>::BoundaryNodeIterator bound_node_iter = mrMesh.GetBoundaryNodeIteratorBegin();
00143 while (bound_node_iter != mrMesh.GetBoundaryNodeIteratorEnd())
00144 {
00145 unsigned bound_node_index = (*bound_node_iter)->GetIndex();
00146 coordinates=mrMesh.GetNode(bound_node_index)->rGetLocation();
00147
00148
00149 double r_squared = norm_2(centroid-coordinates);
00150
00151 if (r_squared < nearest_r_squared)
00152 {
00153 nearest_r_squared = r_squared;
00154 nearest_face_node = bound_node_index;
00155 }
00156 ++bound_node_iter;
00157 }
00158
00159 coordinates = mrMesh.GetNode(nearest_face_node)->rGetLocation();
00160 c_vector<double,3> radial_vector = coordinates-centroid;
00161 return radial_vector;
00162 }
00163
00164 void PapillaryFibreCalculator::GetRadiusVectors()
00165 {
00166
00167 for (AbstractTetrahedralMesh<3,3>::ElementIterator iter = mrMesh.GetElementIteratorBegin();
00168 iter != mrMesh.GetElementIteratorEnd();
00169 ++iter)
00170 {
00171 unsigned element_index = iter->GetIndex();
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;
00187 const double r_max = 0.1;
00188 double g_factor_sum = 0;
00189 double g_factor = 0;
00190
00191 for (AbstractTetrahedralMesh<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 (AbstractTetrahedralMesh<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
00221