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:
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
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
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
00132 c_vector<double,3> PapillaryFibreCalculator::GetRadiusVectorForOneElement(unsigned elementIndex)
00133 {
00134 c_vector<double, 3> centroid = (mrMesh.GetElement(elementIndex))->CalculateCentroid();
00135
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
00148 double r_squared = norm_2(centroid-coordinates);
00149
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
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;
00187 const double r_max = 0.1;
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
00221