Go to the documentation of this file.00001 #ifndef OPENTISSUE_DYNAMICS_MBD_COLLISION_DETECTION_MBD_SWEEP_AND_PRUNE_H
00002 #define OPENTISSUE_DYNAMICS_MBD_COLLISION_DETECTION_MBD_SWEEP_AND_PRUNE_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <list>
00013
00014 namespace OpenTissue
00015 {
00016 namespace mbd
00017 {
00018
00022 template<typename types>
00023 class IntervalEndpoint
00024 {
00025 public:
00026
00027 typedef typename types::math_policy::index_type size_type;
00028 typedef typename types::math_policy::real_type real_type;
00029 typedef typename types::body_type body_type;
00030
00031 public:
00032
00033 IntervalEndpoint()
00034 : m_type(0)
00035 , m_body(0)
00036 {}
00037
00038 void init(body_type * body, size_type const & type)
00039 {
00040 assert(body);
00041 assert(type==0 || type==1);
00042 this->m_body = body;
00043 this->m_type = type;
00044 };
00045
00046 public:
00047
00048 real_type m_value;
00049 body_type * m_body;
00050 size_type m_type;
00051
00052 };
00053
00057 template<typename types>
00058 class AABB
00059 {
00060 public:
00061
00062 typedef typename types::math_policy::real_type real_type;
00063 typedef typename types::math_policy::vector3_type vector3_type;
00064 typedef typename types::math_policy::matrix3x3_type matrix3x3_type;
00065 typedef typename types::body_type body_type;
00066
00067 public:
00068
00072 AABB(void):m_body(0){};
00073
00083 void update(body_type * body,real_type const & envelope)
00084 {
00085 if(!m_body)
00086 {
00087 m_body = body;
00088 m_beginX.init(body,0);
00089 m_beginY.init(body,0);
00090 m_beginZ.init(body,0);
00091 m_endX.init(body,1);
00092 m_endY.init(body,1);
00093 m_endZ.init(body,1);
00094 }
00095 assert(m_body);
00096 vector3_type pmin,pmax,r;
00097 matrix3x3_type R;
00098 body->get_position(r);
00099 body->get_orientation(R);
00100 body->compute_collision_aabb(r,R,pmin,pmax,envelope);
00101 m_beginX.m_value = pmin(0);
00102 m_beginY.m_value = pmin(1);
00103 m_beginZ.m_value = pmin(2);
00104 m_endX.m_value = pmax(0);
00105 m_endY.m_value = pmax(1);
00106 m_endZ.m_value = pmax(2);
00107 };
00108
00109 public:
00110
00111 body_type * m_body;
00112
00113 IntervalEndpoint<types> m_beginX;
00114 IntervalEndpoint<types> m_beginY;
00115 IntervalEndpoint<types> m_beginZ;
00116 IntervalEndpoint<types> m_endX;
00117 IntervalEndpoint<types> m_endY;
00118 IntervalEndpoint<types> m_endZ;
00119
00120 };
00121
00122
00126 template<typename types>
00127 class SweepNPrune
00128 {
00129 protected:
00130
00131 typedef IntervalEndpoint<types> EndPoint;
00132 typedef std::list<EndPoint *> CoordinateAxis;
00133 typedef typename types::math_policy::real_type real_type;
00134 typedef typename types::configuration_type configuration_type;
00135 typedef typename types::contact_type contact_type;
00136 typedef typename types::body_type body_type;
00137 typedef typename types::edge_type edge_type;
00138 typedef typename types::edge_ptr_container edge_ptr_container;
00139
00140
00141 CoordinateAxis m_axisX;
00142 CoordinateAxis m_axisY;
00143 CoordinateAxis m_axisZ;
00144 configuration_type * m_configuration;
00145
00146
00147 edge_ptr_container m_reported;
00148
00149 public:
00150
00151 class node_traits
00152 {
00153 public:
00154 AABB<types> m_snp_aabb;
00155 };
00156
00157 class edge_traits
00158 {
00159 public:
00160 edge_traits():m_snp_axis_overlap_count(0),m_snp_overlap_reported(false){};
00161 public:
00162 short m_snp_axis_overlap_count;
00163 typename edge_ptr_container::iterator m_snp_reported_overlap;
00164 bool m_snp_overlap_reported;
00165 };
00166 class constraint_traits { };
00167
00168 public:
00169
00170 SweepNPrune()
00171 : m_configuration(0)
00172 {}
00173
00174 public:
00175
00176 void clear()
00177 {
00178 m_axisX.clear();
00179 m_axisY.clear();
00180 m_axisZ.clear();
00181 m_reported.clear();
00182 this->m_configuration = 0;
00183 }
00184
00185 void init(configuration_type & configuration)
00186 {
00187 clear();
00188 m_configuration = &configuration;
00189 }
00190
00191 void add(body_type * body)
00192 {
00193 assert(m_configuration);
00194 m_axisX.push_back(&body->m_snp_aabb.m_beginX);
00195 m_axisX.push_back(&body->m_snp_aabb.m_endX);
00196 m_axisY.push_back(&body->m_snp_aabb.m_beginY);
00197 m_axisY.push_back(&body->m_snp_aabb.m_endY);
00198 m_axisZ.push_back(&body->m_snp_aabb.m_beginZ);
00199 m_axisZ.push_back(&body->m_snp_aabb.m_endZ);
00200 }
00201
00202 void remove(body_type * body)
00203 {
00204 assert(m_configuration);
00205 m_axisX.remove(&body->m_snp_aabb.m_beginX);
00206 m_axisX.remove(&body->m_snp_aabb.m_endX);
00207 m_axisY.remove(&body->m_snp_aabb.m_beginY);
00208 m_axisY.remove(&body->m_snp_aabb.m_endY);
00209 m_axisZ.remove(&body->m_snp_aabb.m_beginZ);
00210 m_axisZ.remove(&body->m_snp_aabb.m_endZ);
00211 for(typename body_type::indirect_edge_iterator edge = body->edge_begin();edge!=body->edge_end();++edge)
00212 {
00213 if(edge->m_snp_overlap_reported)
00214 {
00215 m_reported.erase(edge->m_snp_reported_overlap);
00216 edge->m_snp_overlap_reported = false;
00217 }
00218 }
00219 }
00220
00230 void run(edge_ptr_container & edges)
00231 {
00232 assert(m_configuration);
00233 real_type envelope = m_configuration->get_collision_envelope();
00234 for(typename configuration_type::body_iterator body = m_configuration->body_begin();body!=m_configuration->body_end();++body)
00235 {
00236 body->m_snp_aabb.update(&(*body),envelope);
00237 }
00238 sort(m_axisX);
00239 sort(m_axisY);
00240 sort(m_axisZ);
00241
00242
00243
00244
00245
00246
00247
00248 edges.assign(m_reported.begin(),m_reported.end());
00249 }
00250
00251 protected:
00252
00263 void sort(CoordinateAxis & axis)
00264 {
00265
00266
00267
00268
00269
00270
00271 typename CoordinateAxis::iterator left;
00272 typename CoordinateAxis::iterator right;
00273 typename CoordinateAxis::iterator scan = axis.begin();
00274 left = scan;
00275 ++scan;
00276
00277
00278 for(;scan!=axis.end();)
00279 {
00280 right = scan;
00281 ++right;
00282
00283
00284 if( isWrong(*left,*scan) )
00285 {
00286
00287
00288
00289 typename CoordinateAxis::iterator _right = scan;
00290 typename CoordinateAxis::iterator _left = left;
00291 do
00292 {
00293
00294
00295
00296 swapAction(*_left,*_right);
00297 std::iter_swap(_right,_left);
00298 _right = _left;
00299 --_left;
00300 }
00301 while(_right!=axis.begin()&&isWrong(*_left,*_right));
00302 }
00303
00304 left = scan;
00305 scan = right;
00306 }
00307 }
00308
00328 const bool isWrong(EndPoint * left,EndPoint * right)
00329 {
00330
00331 if(right->m_value<left->m_value)
00332 return true;
00333
00334 if(right->m_value==left->m_value)
00335 {
00336 if((right->m_type==0)&&(left->m_type==1))
00337 return true;
00338 }
00339 return false;
00340 }
00341
00360 void swapAction(EndPoint * left,EndPoint * right)
00361 {
00362 assert(m_configuration);
00363 edge_type * edge = m_configuration->get_edge(left->m_body,right->m_body);
00364 if(edge==0)
00365 {
00366 edge = m_configuration->add(left->m_body,right->m_body);
00367 }
00368 if((left->m_type==1) && (right->m_type==0))
00369 {
00370 ++(edge->m_snp_axis_overlap_count);
00371 if(edge->m_snp_axis_overlap_count==3)
00372 {
00373 edge->m_snp_reported_overlap = m_reported.insert(m_reported.end(),edge);
00374 edge->m_snp_overlap_reported = true;
00375 }
00376 }
00377 if((left->m_type==0) && (right->m_type==1))
00378 {
00379 --(edge->m_snp_axis_overlap_count);
00380 if(edge->m_snp_axis_overlap_count==2)
00381 {
00382 if(edge->m_snp_overlap_reported)
00383 {
00384 m_reported.erase(edge->m_snp_reported_overlap);
00385 edge->m_snp_overlap_reported = false;
00386 }
00387 }
00388 }
00389 }
00390
00391 public:
00392
00393 const real_type getMin(CoordinateAxis & axis) { return (axis.front())->m_value; };
00394 const real_type getMax(CoordinateAxis & axis) { return (axis.back())->m_value; };
00395
00407 const bool isConsistent(CoordinateAxis & axis)
00408 {
00409 typename CoordinateAxis::iterator scan = axis.begin();
00410 typename CoordinateAxis::iterator right = scan;
00411 ++right;
00412 for(;right!=axis.end();)
00413 {
00414 if((*scan)->m_value > (*right)->m_value)
00415 return false;
00416 scan = right;
00417 ++right;
00418 }
00419 return true;
00420 }
00421
00422 };
00423
00424 }
00425 }
00426
00427
00428 #endif