Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_GEOMETRY_GEOMETRY_PRISM_FIT_H
00002 #define OPENTISSUE_CORE_GEOMETRY_GEOMETRY_PRISM_FIT_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/geometry/geometry_plane.h>
00013 #include <OpenTissue/core/containers/mesh/mesh.h>
00014 #include <OpenTissue/core/math/math_eigen_system_decomposition.h>
00015 #include <OpenTissue/core/math/math_covariance.h>
00016 #include <OpenTissue/core/geometry/geometry_graham_scan.h>
00017 #include <OpenTissue/core/math/math_constants.h>
00018
00019
00020 #include <boost/numeric/conversion/cast.hpp>
00021
00022 #include <algorithm>
00023 #include <cmath>
00024 #include <iostream>
00025
00026 namespace OpenTissue
00027 {
00028 namespace geometry
00029 {
00030
00054 template <typename vector3_iterator,typename prism_type>
00055 void prism_fit(
00056 vector3_iterator begin
00057 , vector3_iterator end
00058 , prism_type & prism
00059 , bool const & use_convex_surface = true
00060 )
00061 {
00062 typedef typename prism_type::math_types math_types;
00063 typedef typename math_types::real_type real_type;
00064 typedef typename math_types::matrix3x3_type matrix3x3_type;
00065 typedef typename math_types::vector3_type vector3_type;
00066 typedef geometry::Plane<math_types> plane_type;
00067
00068 using std::min;
00069 using std::max;
00070 using std::fabs;
00071 using std::sqrt;
00072 using boost::numeric_cast;
00073
00074 assert(begin!=end || !"prism_fit(): beging was equal to end");
00075
00076 matrix3x3_type cov;
00077 vector3_type mean;
00078 if(use_convex_surface)
00079 {
00080 polymesh::PolyMesh<math_types> mesh;
00081 mesh::convex_hull(begin, end,mesh);
00082 mesh::compute_surface_covariance(mesh,mean,cov);
00083 }
00084 else
00085 {
00086 math::covariance(begin, end, mean, cov);
00087 }
00088 matrix3x3_type R;
00089 vector3_type d;
00090 math::eigen(cov,R,d);
00091
00092
00093 vector3_type axis(R(0,0),R(1,0),R(2,0));
00094 real_type s = d(0);
00095 if(fabs(d(1))<s)
00096 {
00097 s = d(1);
00098 axis = vector3_type(R(0,1),R(1,1),R(2,1));
00099 }
00100 if(fabs(d(2))<s)
00101 {
00102 s = d(2);
00103 axis = vector3_type(R(0,2),R(1,2),R(2,2));
00104 }
00105
00106
00107 real_type lower = math::detail::highest<real_type>();
00108 real_type upper = math::detail::lowest<real_type>();
00109 plane_type plane(axis,0.);
00110
00111 unsigned int count = std::distance(begin,end);
00112 std::vector<vector3_type> tmp(count);
00113
00114 vector3_iterator point = begin;
00115 for(unsigned int i=0; i<count; ++i,++point)
00116 {
00117 real_type l = axis * (*point);
00118 lower = min(lower,l);
00119 upper = max(upper,l);
00120 tmp[i] = plane.project((*point));
00121 }
00122 real_type height = (upper - lower);
00123
00124
00125 std::vector<vector3_type> hull;
00126 graham_scan(tmp.begin(),tmp.end(),hull,plane.n());
00127
00128
00129
00130 vector3_type pp,qq,rr;
00131 vector3_type p,q,r;
00132
00133
00134 real_type min_area = math::detail::highest<real_type>();
00135 int N = numeric_cast<int>( hull.size() );
00136 for(int j=0;j<N;++j)
00137 {
00138 int i = (j-1)%N;
00139 if(i<0)
00140 i += N;
00141 int k = (j+1)%N;
00142
00143 vector3_type u = unit( hull[k]-hull[j] );
00144 vector3_type v = unit( hull[i]-hull[j] );
00145 vector3_type bisector = unit(v + u);
00146
00147 real_type h = -1;
00148 for(int w=0;w<N;++w)
00149 {
00150 vector3_type d1 = hull[w] - hull[j];
00151 real_type val = bisector * d1;
00152 if(val>h)
00153 {
00154 h = val;
00155 }
00156 }
00157 real_type tu = h / (u * bisector);
00158 real_type tv = h / (v * bisector);
00159 pp = hull[j];
00160 qq = pp + tu*u;
00161 rr = pp + tv*v;
00162
00163 u = q - p;
00164 v = r - p;
00165 vector3_type uXv = u % v;
00166 real_type area = uXv*uXv;
00167 if(area<min_area)
00168 {
00169 min_area = area;
00170 p = pp;
00171 q = qq;
00172 r = rr;
00173 }
00174 }
00175
00176 plane.set(axis,lower);
00177 p = plane.project(p);
00178 q = plane.project(q);
00179 r = plane.project(r);
00180
00181 prism = prism_type(p,q,r,height);
00182 }
00183
00184 }
00185 }
00186
00187
00188 #endif