12#include <dolfinx/common/math.h> 
   28template <std::
floating_po
int T>
 
   29std::pair<std::vector<T>, std::array<T, 3>>
 
   30nearest_simplex(std::span<const T> s)
 
   32  assert(s.size() % 3 == 0);
 
   33  const std::size_t s_rows = s.size() / 3;
 
   39    auto s0 = s.template subspan<0, 3>();
 
   40    auto s1 = s.template subspan<3, 3>();
 
   41    std::array ds = {s1[0] - s0[0], s1[1] - s0[1], s1[2] - s0[2]};
 
   42    const T lm = -(s0[0] * ds[0] + s0[1] * ds[1] + s0[2] * ds[2])
 
   43                 / (ds[0] * ds[0] + ds[1] * ds[1] + ds[2] * ds[2]);
 
   44    if (lm >= 0.0 and lm <= 1.0)
 
   49          = {s0[0] + lm * ds[0], s0[1] + lm * ds[1], s0[2] + lm * ds[2]};
 
   50      return {std::vector<T>(s.begin(), s.end()), v};
 
   54      return {std::vector<T>(s0.begin(), s0.end()), {s0[0], s0[1], s0[2]}};
 
   56      return {std::vector<T>(s1.begin(), s1.end()), {s1[0], s1[1], s1[2]}};
 
   60    auto a = s.template subspan<0, 3>();
 
   61    auto b = s.template subspan<3, 3>();
 
   62    auto c = s.template subspan<6, 3>();
 
   63    auto length = [](
auto& x, 
auto& y)
 
   65      return std::transform_reduce(x.begin(), x.end(), y.begin(), 0.0,
 
   66                                   std::plus{}, [](
auto x, 
auto y)
 
   67                                   { return (x - y) * (x - y); });
 
   69    const T ab2 = length(a, b);
 
   70    const T ac2 = length(a, c);
 
   71    const T bc2 = length(b, c);
 
   74    auto helper = [](
auto& x, 
auto& y)
 
   76      return std::transform_reduce(x.begin(), x.end(), y.begin(), 0.0,
 
   78                                   [](
auto x, 
auto y) { return x * (x - y); });
 
   81        = {helper(a, b) / ab2, helper(a, c) / ac2, helper(b, c) / bc2};
 
   84    for (std::size_t i = 0; i < 3; ++i)
 
   85      caba += (c[i] - a[i]) * (b[i] - a[i]);
 
   88    const T c2 = 1 - caba * caba / (ab2 * ac2);
 
   89    const T lbb = (lm[0] - lm[1] * caba / ab2) / c2;
 
   90    const T lcc = (lm[1] - lm[0] * caba / ac2) / c2;
 
   93    if (lbb >= 0.0 and lcc >= 0.0 and (lbb + lcc) <= 1.0)
 
   97      std::array dx0 = {c[0] - a[0], c[1] - a[1], c[2] - a[2]};
 
   98      std::array dx1 = {b[0] - a[0], b[1] - a[1], b[2] - a[2]};
 
   99      std::array v = math::cross(dx0, dx1);
 
  102      std::array p = {(a[0] + b[0] + c[0]) / 3, (a[1] + b[1] + c[1]) / 3,
 
  103                      (a[2] + b[2] + c[2]) / 3};
 
  105      T sum = v[0] * p[0] + v[1] * p[1] + v[2] * p[2];
 
  106      T vnorm2 = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
 
  107      for (std::size_t i = 0; i < 3; ++i)
 
  108        v[i] *= sum / vnorm2;
 
  110      return {std::vector(s.begin(), s.end()), v};
 
  116      T norm0 = std::numeric_limits<T>::max();
 
  117      for (std::size_t i = 0; i < s.size(); i += 3)
 
  119        std::span<const T, 3> p(s.data() + i, 3);
 
  120        T 
norm = p[0] * p[0] + p[1] * p[1] + p[2] * p[2];
 
  129    std::array vmin = {s[3 * pos], s[3 * pos + 1], s[3 * pos + 2]};
 
  131    for (std::size_t k = 0; k < 3; ++k)
 
  132      qmin += vmin[k] * vmin[k];
 
  134    std::vector smin = {vmin[0], vmin[1], vmin[2]};
 
  137    constexpr int f[3][2] = {{0, 1}, {0, 2}, {1, 2}};
 
  138    for (std::size_t i = 0; i < s_rows; ++i)
 
  140      auto s0 = s.subspan(3 * f[i][0], 3);
 
  141      auto s1 = s.subspan(3 * f[i][1], 3);
 
  142      if (lm[i] > 0 and lm[i] < 1)
 
  145        for (std::size_t k = 0; k < 3; ++k)
 
  146          v[k] = s0[k] + lm[i] * (s1[k] - s0[k]);
 
  148        for (std::size_t k = 0; k < 3; ++k)
 
  149          qnorm += v[k] * v[k];
 
  152          std::ranges::copy(v, vmin.begin());
 
  155          std::span<T, 3> smin0(smin.data(), 3);
 
  156          std::ranges::copy(s0, smin0.begin());
 
  157          std::span<T, 3> smin1(smin.data() + 3, 3);
 
  158          std::ranges::copy(s1, smin1.begin());
 
  162    return {std::move(smin), vmin};
 
  166    auto s0 = s.template subspan<0, 3>();
 
  167    auto s1 = s.template subspan<3, 3>();
 
  168    auto s2 = s.template subspan<6, 3>();
 
  169    auto s3 = s.template subspan<9, 3>();
 
  170    auto W1 = math::cross(s0, s1);
 
  171    auto W2 = math::cross(s2, s3);
 
  174    B[0] = std::transform_reduce(s2.begin(), s2.end(), W1.begin(), 0.0);
 
  175    B[1] = -std::transform_reduce(s3.begin(), s3.end(), W1.begin(), 0.0);
 
  176    B[2] = std::transform_reduce(s0.begin(), s0.end(), W2.begin(), 0.0);
 
  177    B[3] = -std::transform_reduce(s1.begin(), s1.end(), W2.begin(), 0.0);
 
  179    const bool signDetM = std::signbit(std::reduce(B.begin(), B.end(), 0.0));
 
  180    std::array<bool, 4> f_inside;
 
  181    for (
int i = 0; i < 4; ++i)
 
  182      f_inside[i] = (std::signbit(B[i]) == signDetM);
 
  184    if (f_inside[1] and f_inside[2] and f_inside[3])
 
  187        return {std::vector<T>(s.begin(), s.end()), {0, 0, 0}};
 
  189        return nearest_simplex<T>(s.template subspan<0, 3 * 3>());
 
  194    std::array<T, 3> vmin = {0, 0, 0};
 
  195    constexpr int facets[3][3] = {{0, 1, 3}, {0, 2, 3}, {1, 2, 3}};
 
  196    T qmin = std::numeric_limits<T>::max();
 
  198    for (
int i = 0; i < 3; ++i)
 
  200      if (f_inside[i + 1] == 
false)
 
  202        std::copy_n(std::next(s.begin(), 3 * facets[i][0]), 3, M.begin());
 
  203        std::copy_n(std::next(s.begin(), 3 * facets[i][1]), 3,
 
  204                    std::next(M.begin(), 3));
 
  205        std::copy_n(std::next(s.begin(), 3 * facets[i][2]), 3,
 
  206                    std::next(M.begin(), 6));
 
  208        const auto [snew, v] = nearest_simplex<T>(M);
 
  209        T q = std::transform_reduce(v.begin(), v.end(), v.begin(), 0);
 
  221    throw std::runtime_error(
"Number of rows defining simplex not supported.");
 
  226template <std::
floating_po
int T>
 
  227std::array<T, 3> support(std::span<const T> bd, std::array<T, 3> v)
 
  230  T qmax = bd[0] * v[0] + bd[1] * v[1] + bd[2] * v[2];
 
  231  for (std::size_t m = 1; m < bd.size() / 3; ++m)
 
  233    T q = bd[3 * m] * v[0] + bd[3 * m + 1] * v[1] + bd[3 * m + 2] * v[2];
 
  241  return {bd[3 * i], bd[3 * i + 1], bd[3 * i + 2]};
 
  255template <std::
floating_po
int T>
 
  257                                      std::span<const T> q)
 
  259  assert(p.size() % 3 == 0);
 
  260  assert(q.size() % 3 == 0);
 
  262  constexpr int maxk = 15; 
 
  265  constexpr T eps = 1.0e4 * std::numeric_limits<T>::epsilon();
 
  268  std::array<T, 3> v = {p[0] - q[0], p[1] - q[1], p[2] - q[2]};
 
  269  std::vector<T> s = {v[0], v[1], v[2]};
 
  273  for (k = 0; k < maxk; ++k)
 
  276    std::array w1 = impl_gjk::support(p, {-v[0], -v[1], -v[2]});
 
  277    std::array w0 = impl_gjk::support(q, {v[0], v[1], v[2]});
 
  278    const std::array w = {w1[0] - w0[0], w1[1] - w0[1], w1[2] - w0[2]};
 
  281    assert(s.size() % 3 == 0);
 
  283    for (m = 0; m < s.size() / 3; ++m)
 
  285      auto it = std::next(s.begin(), 3 * m);
 
  286      if (std::equal(it, std::next(it, 3), w.begin(), w.end()))
 
  290    if (m != s.size() / 3)
 
  294    const T vnorm2 = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
 
  295    const T vw = vnorm2 - (v[0] * w[0] + v[1] * w[1] + v[2] * w[2]);
 
  296    if (vw < (eps * vnorm2) or vw < eps)
 
  300    s.insert(s.end(), w.begin(), w.end());
 
  303    auto [snew, vnew] = impl_gjk::nearest_simplex<T>(s);
 
  304    s.assign(snew.data(), snew.data() + snew.size());
 
  305    v = {vnew[0], vnew[1], vnew[2]};
 
  308    if ((v[0] * v[0] + v[1] * v[1] + v[2] * v[2]) < eps * eps)
 
  313    throw std::runtime_error(
"GJK error - max iteration limit reached");
 
 
Geometry data structures and algorithms.
Definition BoundingBoxTree.h:21
std::array< T, 3 > compute_distance_gjk(std::span< const T > p, std::span< const T > q)
Compute the distance between two convex bodies p and q, each defined by a set of points.
Definition gjk.h:256
auto norm(const V &x, Norm type=Norm::l2)
Definition Vector.h:268