computeDistanceToOut method

  1. @override
double computeDistanceToOut(
  1. Transform xf,
  2. Vector2 p,
  3. int childIndex,
  4. Vector2 normalOut,
)
override

Compute the distance from the current shape to the specified point. This only works for convex shapes.

xf is the shape world transform. p is a point in world coordinates. normalOut returns the direction in which the distance increases. Returns the distance from the current shape.

Implementation

@override
double computeDistanceToOut(
  Transform xf,
  Vector2 p,
  int childIndex,
  Vector2 normalOut,
) {
  final xfqc = xf.q.cos;
  final xfqs = xf.q.sin;
  var tx = p.x - xf.p.x;
  var ty = p.y - xf.p.y;
  final pLocalx = xfqc * tx + xfqs * ty;
  final pLocaly = -xfqs * tx + xfqc * ty;

  var maxDistance = -double.maxFinite;
  var normalForMaxDistanceX = pLocalx;
  var normalForMaxDistanceY = pLocaly;

  for (var i = 0; i < vertices.length; ++i) {
    final vertex = vertices[i];
    final normal = normals[i];
    tx = pLocalx - vertex.x;
    ty = pLocaly - vertex.y;
    final dot = normal.x * tx + normal.y * ty;
    if (dot > maxDistance) {
      maxDistance = dot;
      normalForMaxDistanceX = normal.x;
      normalForMaxDistanceY = normal.y;
    }
  }

  double distance;
  if (maxDistance > 0) {
    var minDistanceX = normalForMaxDistanceX;
    var minDistanceY = normalForMaxDistanceY;
    var minDistance2 = maxDistance * maxDistance;
    for (var i = 0; i < vertices.length; ++i) {
      final vertex = vertices[i];
      final distanceVecX = pLocalx - vertex.x;
      final distanceVecY = pLocaly - vertex.y;
      final distance2 =
          distanceVecX * distanceVecX + distanceVecY * distanceVecY;
      if (minDistance2 > distance2) {
        minDistanceX = distanceVecX;
        minDistanceY = distanceVecY;
        minDistance2 = distance2;
      }
    }
    distance = sqrt(minDistance2);
    normalOut.x = xfqc * minDistanceX - xfqs * minDistanceY;
    normalOut.y = xfqs * minDistanceX + xfqc * minDistanceY;
    normalOut.normalize();
  } else {
    distance = maxDistance;
    normalOut.x = xfqc * normalForMaxDistanceX - xfqs * normalForMaxDistanceY;
    normalOut.y = xfqs * normalForMaxDistanceX + xfqc * normalForMaxDistanceY;
  }

  return distance;
}