collideEdgeAndCircle method

void collideEdgeAndCircle(
  1. Manifold manifold,
  2. EdgeShape edgeA,
  3. Transform xfA,
  4. CircleShape circleB,
  5. Transform xfB
)

Implementation

void collideEdgeAndCircle(Manifold manifold, final EdgeShape edgeA,
    final Transform xfA, final CircleShape circleB, final Transform xfB) {
  manifold.pointCount = 0;

  // Compute circle in frame of edge
  // Vec2 Q = MulT(xfA, Mul(xfB, circleB.p));
  Transform.mulToOutUnsafeVec2(xfB, circleB.p, _temp);
  Transform.mulTransToOutUnsafeVec2(xfA, _temp, _Q);

  final Vector2 A = edgeA.vertex1;
  final Vector2 B = edgeA.vertex2;
  _e
    ..setFrom(B)
    ..sub(A);

  // Barycentric coordinates
  double u = _e.dot(_temp
    ..setFrom(B)
    ..sub(_Q));
  double v = _e.dot(_temp
    ..setFrom(_Q)
    ..sub(A));

  double radius = edgeA.radius + circleB.radius;

  // ContactFeature cf;
  _cf.indexB = 0;
  _cf.typeB = ContactIDType.VERTEX.index & 0xFF;

  // Region A
  if (v <= 0.0) {
    final Vector2 P = A;
    _d
      ..setFrom(_Q)
      ..sub(P);
    double dd = _d.dot(_d);
    if (dd > radius * radius) {
      return;
    }

    // Is there an edge connected to A?
    if (edgeA.hasVertex0) {
      final Vector2 A1 = edgeA.vertex0;
      final Vector2 B1 = A;
      _e1
        ..setFrom(B1)
        ..sub(A1);
      double u1 = _e1.dot(_temp
        ..setFrom(B1)
        ..sub(_Q));

      // Is the circle in Region AB of the previous edge?
      if (u1 > 0.0) {
        return;
      }
    }

    _cf.indexA = 0;
    _cf.typeA = ContactIDType.VERTEX.index & 0xFF;
    manifold.pointCount = 1;
    manifold.type = ManifoldType.CIRCLES;
    manifold.localNormal.setZero();
    manifold.localPoint.setFrom(P);
    // manifold.points[0].id.key = 0;
    manifold.points[0].id.set(_cf);
    manifold.points[0].localPoint.setFrom(circleB.p);
    return;
  }

  // Region B
  if (u <= 0.0) {
    Vector2 P = B;
    _d
      ..setFrom(_Q)
      ..sub(P);
    double dd = _d.dot(_d);
    if (dd > radius * radius) {
      return;
    }

    // Is there an edge connected to B?
    if (edgeA.hasVertex3) {
      final Vector2 B2 = edgeA.vertex3;
      final Vector2 A2 = B;
      final Vector2 e2 = _e1;
      e2
        ..setFrom(B2)
        ..sub(A2);
      double v2 = e2.dot(_temp
        ..setFrom(_Q)
        ..sub(A2));

      // Is the circle in Region AB of the next edge?
      if (v2 > 0.0) {
        return;
      }
    }

    _cf.indexA = 1;
    _cf.typeA = ContactIDType.VERTEX.index & 0xFF;
    manifold.pointCount = 1;
    manifold.type = ManifoldType.CIRCLES;
    manifold.localNormal.setZero();
    manifold.localPoint.setFrom(P);
    // manifold.points[0].id.key = 0;
    manifold.points[0].id.set(_cf);
    manifold.points[0].localPoint.setFrom(circleB.p);
    return;
  }

  // Region AB
  double den = _e.dot(_e);
  assert(den > 0.0);

  // Vec2 P = (1.0f / den) * (u * A + v * B);
  _P
    ..setFrom(A)
    ..scale(u)
    ..add(_temp
      ..setFrom(B)
      ..scale(v));
  _P.scale(1.0 / den);
  _d
    ..setFrom(_Q)
    ..sub(_P);
  double dd = _d.dot(_d);
  if (dd > radius * radius) {
    return;
  }

  _n.x = -_e.y;
  _n.y = _e.x;
  if (_n.dot(_temp
        ..setFrom(_Q)
        ..sub(A)) <
      0.0) {
    _n.setValues(-_n.x, -_n.y);
  }
  _n.normalize();

  _cf.indexA = 0;
  _cf.typeA = ContactIDType.FACE.index & 0xFF;
  manifold.pointCount = 1;
  manifold.type = ManifoldType.FACE_A;
  manifold.localNormal.setFrom(_n);
  manifold.localPoint.setFrom(A);
  // manifold.points[0].id.key = 0;
  manifold.points[0].id.set(_cf);
  manifold.points[0].localPoint.setFrom(circleB.p);
}