@@ -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