raycast method

void raycast(
  1. ParticleRaycastCallback callback,
  2. Vector2 point1,
  3. Vector2 point2
)

Implementation

void raycast(
  ParticleRaycastCallback callback,
  Vector2 point1,
  Vector2 point2,
) {
  if (proxyBuffer.isEmpty) {
    return;
  }
  final firstProxy = lowerBound(
    proxyBuffer,
    computeTag(
      inverseDiameter * min(point1.x, point2.x) - 1,
      inverseDiameter * min(point1.y, point2.y) - 1,
    ),
  );
  final lastProxy = upperBound(
    proxyBuffer,
    computeTag(
      inverseDiameter * max(point1.x, point2.x) + 1,
      inverseDiameter * max(point1.y, point2.y) + 1,
    ),
  );
  var fraction = 1.0;
  // solving the following equation:
  // ((1-t)*point1+t*point2-position)^2=diameter^2
  // where t is a potential fraction
  final vx = point2.x - point1.x;
  final vy = point2.y - point1.y;
  var v2 = vx * vx + vy * vy;
  v2 = v2 == 0 ? double.maxFinite : v2;
  for (var i = firstProxy; i < lastProxy; ++i) {
    // TODO(spydon): Is this correct now when we are not rotating the buffers?
    final positionI = proxyBuffer[i].particle.position;
    final px = point1.x - positionI.x;
    final py = point1.y - positionI.y;
    final pv = px * vx + py * vy;
    final p2 = px * px + py * py;
    final determinant = pv * pv - v2 * (p2 - squaredDiameter);
    if (determinant >= 0) {
      final sqrtDeterminant = sqrt(determinant);
      // find a solution between 0 and fraction
      var t = (-pv - sqrtDeterminant) / v2;
      if (t > fraction) {
        continue;
      }
      if (t < 0) {
        t = (-pv + sqrtDeterminant) / v2;
        if (t < 0 || t > fraction) {
          continue;
        }
      }
      final n = _tempVec;
      _tempVec.x = px + t * vx;
      _tempVec.y = py + t * vy;
      n.normalize();
      final point = Vector2(point1.x + t * vx, point1.y + t * vy);
      final f = callback.reportParticle(i, point, n, t);
      fraction = min(fraction, f);
      if (fraction <= 0) {
        break;
      }
    }
  }
}