Beispiel #1
0
bool shape::intersects(shape const& shape) const {
  vector direction(shape.centroid() - centroid());

  std::vector<vector> simplex;
  simplex.push_back(vertices_[support(direction)] - shape.vertices()[shape.support(-direction)]);
  direction = -direction;

  for(;;) {
    vector const a(vertices_[support(direction)] - shape.vertices()[shape.support(-direction)]);
    if(a.dot(direction) <= 0.0f)
      return false;
    simplex.push_back(a);
    vector const ao(-a);

    if(simplex.size() == 3) {
      vector const b(simplex[1]);
      vector const c(simplex[0]);
      vector const ab(b - a);
      vector const ac(c - a);

      vector const ab_triple(vector::triple_product_left(ac, ab, ab));
      if(ab_triple.dot(ao) >= 0.0f) {
        simplex.erase(simplex.begin());
        direction = ab_triple;
      } else {
        vector const ac_triple(vector::triple_product_left(ab, ac, ac));
        if(ac_triple.dot(ao) >= 0.0f) {
          simplex.erase(simplex.begin() + 1);
          direction = ac_triple;
        } else
          return true;
      }
    } else {
      vector const b(simplex[0]);
      vector const ab(b - a);
      direction = vector::triple_product_left(ab, ao, ab);
      if(!direction)
        direction = ab.left();
    }
  }
}
Beispiel #2
0
std::tuple<bool, vector, float, vector, vector> shape::distance(shape const& shape) const {
  vector direction(shape.centroid() - centroid());

  vector a1(vertices_[support(direction)]);
  vector a2(shape.vertices()[shape.support(-direction)]);
  vector a(a1 - a2);

  vector b1(vertices_[support(-direction)]);
  vector b2(shape.vertices()[shape.support(direction)]);
  vector b(b1 - b2);

  vector c1, c2, c;

  direction = segment(b, a).closest(vector());
  for(int unsigned iterations(0); iterations < 10; ++iterations) {
    direction = -direction.normalize();

    if(!direction)
      return std::make_tuple(false, vector(), 0.0f, vector(), vector());

    c1 = vertices_[support(direction)];
    c2 = shape.vertices()[shape.support(-direction)];
    c = c1 - c2;

    if(a.cross(b) * b.cross(c) > 0.0f && a.cross(b) * c.cross(a) > 0.0f)
      return std::make_tuple(false, vector(), 0.0f, vector(), vector());

    float const projection(c.dot(direction));
    if(projection - a.dot(direction) < std::sqrt(std::numeric_limits<float>::epsilon())) {
      std::tuple<vector, vector> const closest_points(get_closest_points(a1, a2, a, b1, b2, b));
      return std::make_tuple(true, direction, -projection, std::get<0>(closest_points), std::get<1>(closest_points));
    }

    vector const point1(segment(a, c).closest(vector()));
    vector const point2(segment(c, b).closest(vector()));

    float const point1_length(point1.length());
    float const point2_length(point2.length());

    if(point1_length <= std::numeric_limits<float>::epsilon()) {
      std::tuple<vector, vector> const closest_points(get_closest_points(a1, a2, a, c1, c2, c));
      return std::make_tuple(true, direction, point1_length, std::get<0>(closest_points), std::get<1>(closest_points));
    } else if(point2_length <= std::numeric_limits<float>::epsilon()) {
      std::tuple<vector, vector> const closest_points(get_closest_points(c1, c2, c, b1, b2, b));
      return std::make_tuple(true, direction, point2_length, std::get<0>(closest_points), std::get<1>(closest_points));
    }

    if(point1_length < point2_length) {
      b1 = c1;
      b2 = c2;
      b = c;
      direction = point1;
    } else {
      a1 = c1;
      a2 = c2;
      a = c;
      direction = point2;
    }
  }

  std::tuple<vector, vector> const closest_points(get_closest_points(a1, a2, a, b1, b2, b));
  return std::make_tuple(true, direction, -c.dot(direction), std::get<0>(closest_points), std::get<1>(closest_points));
}