Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_CONTAINERS_MESH_COMMON_UTIL_PROFILE_SWEEP_H
00002 #define OPENTISSUE_CORE_CONTAINERS_MESH_COMMON_UTIL_PROFILE_SWEEP_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/math_constants.h>
00013
00014 #include <boost/multi_array.hpp>
00015
00016 namespace OpenTissue
00017 {
00018 namespace mesh
00019 {
00020
00033 template<typename mesh_type,typename vector3_iterator,typename real_type>
00034 bool profile_sweep(
00035 vector3_iterator profile_begin
00036 , vector3_iterator profile_end
00037 , real_type sweep_angle
00038 , unsigned int slices
00039 , mesh_type & mesh
00040 )
00041 {
00042 typedef typename mesh_type::math_types math_types;
00043 typedef typename math_types::value_traits value_traits;
00044 typedef typename math_types::vector3_type vector3_type;
00045
00046 typedef typename mesh_type::vertex_handle vertex_handle;
00047
00048 assert(slices >= 0 || !"At least one slice must be created");
00049 assert(sweep_angle > static_cast<real_type>(0.0)|| !"Sweep angle must be positive");
00050 assert(sweep_angle <= static_cast<real_type>(math::detail::pi<real_type>()*2.0)|| !"Sweep angle must be less than equal 2PI");
00051
00052
00053 unsigned int i,j,k;
00054 vector3_iterator p;
00055
00056 unsigned int K = static_cast<unsigned int>( std::distance(profile_begin,profile_end) );
00057 assert(K>=2);
00058
00059 unsigned int I = slices + 1;
00060 assert(I>=2);
00061
00062 p = profile_begin;
00063 real_type max_z_value = (*p)(2);
00064 real_type min_z_value = (*p)(2);
00065 for(;p != profile_end;++p)
00066 {
00067 max_z_value = std::max(max_z_value, (*p)(2));
00068 min_z_value = std::min(min_z_value, (*p)(2));
00069 }
00070 real_type range_z_value = max_z_value - min_z_value;
00071 assert(range_z_value > 0 || !"z-value range must be positive");
00072
00073
00074
00075
00076
00077
00078
00079
00080 mesh.clear();
00081
00082
00083
00084 boost::multi_array<vector3_type, 2> vector3_grid(boost::extents[K][I]);
00085
00086 for(p = profile_begin,k=0; p != profile_end;++p,++k)
00087 {
00088 vector3_grid[k][0] = *p;
00089 }
00090
00091 real_type delta_angle = static_cast<real_type>( sweep_angle / (I - 1));
00092 real_type angle = delta_angle;
00093 for(i=1;i<I;++i)
00094 {
00095 real_type cosinus = static_cast<real_type>(std::cos(angle));
00096 real_type sinus = static_cast<real_type>(std::sin(angle));
00097 for(p = profile_begin,k=0; p != profile_end;++p,++k)
00098 {
00099 vector3_grid[k][i](0) = cosinus*(*p)(0) - sinus*(*p)(1);
00100 vector3_grid[k][i](1) = sinus*(*p)(0) + cosinus*(*p)(1);
00101 vector3_grid[k][i](2) = (*p)(2);
00102 }
00103 angle += delta_angle;
00104 }
00105
00106
00107 real_type tolerance = 10e-5;
00108 boost::multi_array<vertex_handle, 2> grid(boost::extents[K][I]);
00109 for(k=0;k<K;++k)
00110 {
00111 for(i=0;i<I;++i)
00112 {
00113 vertex_handle v;
00114 for(j=0;j<i;++j)
00115 {
00116 vector3_type diff = vector3_grid[k][j] - vector3_grid[k][i];
00117 if(diff*diff < tolerance)
00118 {
00119 v = grid[k][j];
00120 break;
00121 }
00122 }
00123 if(v.is_null())
00124 {
00125 v = mesh.add_vertex(vector3_grid[k][i]);
00126 }
00127 grid[k][i] = v;
00128 typename mesh_type::vertex_iterator vit = mesh.get_vertex_iterator(v);
00129 vit->m_normal = normalize(vit->m_coord);
00130 vit->m_u = (i*delta_angle)/sweep_angle;
00131 vit->m_v = (vit->m_coord(2)-min_z_value)/range_z_value;
00132 vit->m_color = vector3_type( vit->m_u, 0.0, vit->m_v);
00133 }
00134 }
00135
00136 for(i=0;i<I-1;++i)
00137 {
00138 for(k=0;k<(K-1);++k)
00139 {
00140 vertex_handle v0 = grid[k+1][i];
00141 vertex_handle v1 = grid[k][i];
00142 vertex_handle v2 = grid[k][i+1];
00143 vertex_handle v3 = grid[k+1][i+1];
00144
00145
00146
00147
00148
00149
00150
00151
00152 if(v0!=v3 && v1!=v2)
00153 {
00154 vertex_handle tmp[4];
00155 tmp[0] = v0;
00156 tmp[1] = v1;
00157 tmp[2] = v2;
00158 tmp[3] = v3;
00159 vertex_handle * handles = &tmp[0];
00160 mesh.add_face(handles,handles+4);
00161 }
00162 else
00163 {
00164 if(v0!=v3)
00165 mesh.add_face(v0,v1,v3);
00166 if(v1!=v2)
00167 mesh.add_face(v1,v2,v3);
00168 }
00169 }
00170 }
00171 return true;
00172 }
00173
00174 }
00175 }
00176
00177
00178 #endif