Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_GEOMETRY_GEOMETRY_CYLINDER_FIT_H
00002 #define OPENTISSUE_CORE_GEOMETRY_GEOMETRY_CYLINDER_FIT_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/math_basic_types.h>
00013 #include <OpenTissue/core/math/math_eigen_system_decomposition.h>
00014 #include <OpenTissue/core/math/math_covariance.h>
00015
00016 #include <OpenTissue/core/containers/mesh/mesh.h>
00017
00018 #include <OpenTissue/core/geometry/geometry_plane.h>
00019 #include <OpenTissue/core/geometry/geometry_compute_smallest_sphere.h>
00020
00021 #include <OpenTissue/core/math/math_constants.h>
00022
00023
00024 #include <algorithm>
00025 #include <vector>
00026 #include <cmath>
00027 #include <iostream>
00028
00029
00030 namespace OpenTissue
00031 {
00032 namespace geometry
00033 {
00062 template <typename vector3_iterator,typename cylinder_type>
00063 void cylinder_fit(
00064 vector3_iterator begin
00065 , vector3_iterator end
00066 , cylinder_type & cylinder
00067 , bool const & use_convex_surface = true
00068 )
00069 {
00070 using std::min;
00071 using std::max;
00072 using std::fabs;
00073
00074 typedef typename cylinder_type::math_types math_types;
00075 typedef typename math_types::real_type real_type;
00076 typedef typename math_types::matrix3x3_type matrix3x3_type;
00077 typedef typename math_types::vector3_type vector3_type;
00078 typedef geometry::Sphere<math_types> sphere_type;
00079
00080 assert(begin!=end || !"cylinder_fit(): begin was equal to end");
00081
00082 matrix3x3_type cov;
00083 vector3_type mean;
00084 if(use_convex_surface)
00085 {
00086 polymesh::PolyMesh<math_types> mesh;
00087 mesh::convex_hull(begin, end,mesh);
00088 mesh::compute_surface_covariance(mesh,mean,cov);
00089 }
00090 else
00091 {
00092 math::covariance(begin, end, mean, cov);
00093 }
00094 matrix3x3_type R;
00095 vector3_type d;
00096 math::eigen(cov,R,d);
00097
00098
00099 vector3_type axis(R(0,0),R(1,0),R(2,0));
00100 real_type s = fabs(d(0));
00101 if(fabs(d(1))>s)
00102 {
00103 s = fabs(d(1));
00104 axis = vector3_type(R(0,1),R(1,1),R(2,1));
00105 }
00106 if(fabs(d(2))>s)
00107 {
00108 s = fabs(d(2));
00109 axis = vector3_type(R(0,2),R(1,2),R(2,2));
00110 }
00111
00112 real_type lower = math::detail::highest<real_type>();
00113 real_type upper = math::detail::lowest<real_type>();
00114
00115 geometry::Plane<math_types> plane(axis,0.);
00116 std::size_t size = std::distance(begin,end);
00117 std::vector<vector3_type> tmp(size);
00118 typename std::vector<vector3_type>::iterator p = tmp.begin();
00119 for(vector3_iterator v=begin; v!=end; ++v)
00120 {
00121 real_type l = axis * (*v);
00122 lower = min(lower,l);
00123 upper = max(upper,l);
00124 *p++ = plane.project(*v);
00125 }
00126 sphere_type minimal;
00127 compute_smallest_sphere(tmp.begin(),tmp.end(),minimal);
00128 real_type radius = minimal.radius();
00129 real_type height = (upper - lower);
00130 vector3_type center = minimal.center() + .5*(upper+lower)*axis;
00131 cylinder = cylinder_type(center,axis,height,radius);
00132 }
00133
00134 }
00135 }
00136
00137
00138 #endif