@@ -361,6 +361,61 @@ double NormalCollisions::compute_minimum_distance(
361361
362362// ============================================================================ 
363363
364+ //  NOTE: Actually distance squared
365+ double  NormalCollisions::compute_avg_distance (
366+         const  CollisionMesh& mesh,
367+         Eigen::ConstRef<Eigen::MatrixXd> vertices,
368+         const  double  dhat) const 
369+ {
370+     assert (vertices.rows () == mesh.num_vertices ());
371+     if  (empty ()) {
372+         return  std::numeric_limits<double >::infinity ();
373+     }
374+ 
375+     const  Eigen::MatrixXi& edges = mesh.edges ();
376+     const  Eigen::MatrixXi& faces = mesh.faces ();
377+     const  double  dhat_sq = dhat * dhat;
378+ 
379+     //  Thread-local storage: pair<sum_of_distances, count_of_distances>
380+     tbb::enumerable_thread_specific<std::pair<double , size_t >> storage{ {0.0 , 0 } };
381+ 
382+     tbb::parallel_for (
383+         tbb::blocked_range<size_t >(0 , size ()),
384+         [&](const  tbb::blocked_range<size_t >& range) {
385+             auto & local = storage.local ();
386+             double & sum = local.first ;
387+             size_t & count = local.second ;
388+ 
389+             for  (size_t  i = range.begin (); i != range.end (); ++i) {
390+                 const  double  dist = (*this )[i].compute_distance (
391+                     (*this )[i].dof (vertices, edges, faces));
392+ 
393+                 //  only accumulate those within threshold
394+                 if  (dist <= dhat_sq) {
395+                     sum   += dist;
396+                     count += 1 ;
397+                 }
398+             }
399+         }
400+     );
401+ 
402+     //  Combine sums and counts from all threads
403+     const  auto  total = storage.combine (
404+         [](const  std::pair<double , size_t >& a, const  std::pair<double , size_t >& b) {
405+             return  std::make_pair (a.first  + b.first , a.second  + b.second );
406+         }
407+     );
408+ 
409+     const  double  overall_sum   = total.first ;
410+     const  size_t  overall_count = total.second ;
411+ 
412+     if  (overall_count == 0 ) {
413+         return  std::numeric_limits<double >::infinity ();
414+     }
415+     return  overall_sum / static_cast <double >(overall_count);
416+ }
417+ 
418+ // ============================================================================ 
364419size_t  NormalCollisions::size () const 
365420{
366421    return  vv_collisions.size () + ev_collisions.size () + ee_collisions.size ()
0 commit comments