projectToRectEdge function

Offset projectToRectEdge({
  1. required Offset p,
  2. required Offset v,
  3. required Rect rect,
})

Implementation

Offset projectToRectEdge({required Offset p, required Offset v, required Rect rect}) {
  const double epsilon = 1e-10;
  final dx = v.dx;
  final dy = v.dy;

  final isNearlyZeroDx = _isNearlyZero(dx);
  final isNearlyZeroDy = _isNearlyZero(dy);
  if (isNearlyZeroDx && isNearlyZeroDy) return _closestPointOnRectEdge(p: p, rect: rect);

  double tx1, tx2, ty1, ty2;

  if (isNearlyZeroDx) {
    tx1 = double.negativeInfinity;
    tx2 = double.infinity;
  } else {
    tx1 = (rect.left - p.dx) / dx;
    tx2 = (rect.right - p.dx) / dx;
  }

  if (isNearlyZeroDy) {
    ty1 = double.negativeInfinity;
    ty2 = double.infinity;
  } else {
    ty1 = (rect.top - p.dy) / dy;
    ty2 = (rect.bottom - p.dy) / dy;
  }

  final txMin = min(tx1, tx2);
  final txMax = max(tx1, tx2);
  final tyMin = min(ty1, ty2);
  final tyMax = max(ty1, ty2);

  final tEnter = max(txMin, tyMin);
  final tExit = min(txMax, tyMax);

  if (tExit < max(tEnter, epsilon)) return _closestPointOnRectEdge(p: p, rect: rect);

  final clamped = _clampPoint(p, rect);
  final inside = (p == clamped);

  final tHit = inside ? tExit : max(tEnter, epsilon);

  return Offset(p.dx + dx * tHit, p.dy + dy * tHit);
}