collideEdgeAndCircle method

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

Implementation

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

  // Compute circle in frame of edge
  // Vec2 Q = MulT(xfA, Mul(xfB, circleB.p));
  _temp.setFrom(Transform.mulVec2(xfB, circleB.position));
  _q.setFrom(Transform.mulTransVec2(xfA, _temp));

  final a = edgeA.vertex1;
  final b = edgeA.vertex2;
  _e
    ..setFrom(b)
    ..sub(a);

  // Barycentric coordinates
  final u = _e.dot(
    _temp
      ..setFrom(b)
      ..sub(_q),
  );
  final v = _e.dot(
    _temp
      ..setFrom(_q)
      ..sub(a),
  );

  final radius = edgeA.radius + circleB.radius;

  _cf.indexB = 0;
  _cf.typeB = ContactIDType.vertex.index & 0xFF;

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

    // Is there an edge connected to A?
    if (edgeA.hasVertex0) {
      final a1 = edgeA.vertex0;
      final b1 = a;
      _e1
        ..setFrom(b1)
        ..sub(a1);
      final 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.position);
    return;
  }

  // Region B
  if (u <= 0.0) {
    final p = b;
    _d
      ..setFrom(_q)
      ..sub(p);
    final dd = _d.dot(_d);
    if (dd > radius * radius) {
      return;
    }

    // Is there an edge connected to B?
    if (edgeA.hasVertex3) {
      final b2 = edgeA.vertex3;
      final a2 = b;
      final e2 = _e1;
      e2
        ..setFrom(b2)
        ..sub(a2);
      final 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.set(_cf);
    manifold.points[0].localPoint.setFrom(circleB.position);
    return;
  }

  // Region AB
  final 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);
  final 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.faceA;
  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.position);
}