clip method

bool clip(
  1. double x1,
  2. double y1,
  3. double x2,
  4. double y2,
  5. double x3,
  6. double y3,
  7. Float32List clippingArea,
  8. Float32List output,
)

Implementation

bool clip(double x1, double y1, double x2, double y2, double x3, double y3,
    Float32List clippingArea, Float32List output) {
  final Float32List originalOutput = output;
  bool clipped = false;

  // Avoid copy at the end.
  Float32List input;
  if (clippingArea.length % 4 >= 2) {
    input = output;
    output = scratch as Float32List;
  } else {
    input = scratch as Float32List;
  }

  input
    ..length = 0
    ..add(x1)
    ..add(y1)
    ..add(x2)
    ..add(y2)
    ..add(x3)
    ..add(y3)
    ..add(x1)
    ..add(y1);
  output.length = 0;

  final Float32List clippingVertices = clippingArea;
  final int clippingVerticesLast = clippingArea.length - 4;
  for (int i = 0;; i += 2) {
    final double edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1];
    final double edgeX2 = clippingVertices[i + 2],
        edgeY2 = clippingVertices[i + 3];
    final double deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2;

    final Float32List inputVertices = input;
    final int inputVerticesLength = input.length - 2,
        outputStart = output.length;
    for (int ii = 0; ii < inputVerticesLength; ii += 2) {
      final double inputX = inputVertices[ii], inputY = inputVertices[ii + 1];
      final double inputX2 = inputVertices[ii + 2],
          inputY2 = inputVertices[ii + 3];
      final bool side2 =
          deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0;
      if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) {
        if (side2) {
          // v1 inside, v2 inside
          output
            ..add(inputX2)
            ..add(inputY2);
          continue;
        }
        // v1 inside, v2 outside
        final double c0 = inputY2 - inputY, c2 = inputX2 - inputX;
        final double ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) /
            (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
        output
          ..add(edgeX + (edgeX2 - edgeX) * ua)
          ..add(edgeY + (edgeY2 - edgeY) * ua);
      } else if (side2) {
        // v1 outside, v2 inside
        final double c0 = inputY2 - inputY, c2 = inputX2 - inputX;
        final double ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) /
            (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
        output
          ..add(edgeX + (edgeX2 - edgeX) * ua)
          ..add(edgeY + (edgeY2 - edgeY) * ua)
          ..add(inputX2)
          ..add(inputY2);
      }
      clipped = true;
    }

    if (outputStart == output.length) {
      // All edges outside.
      originalOutput.length = 0;
      return true;
    }

    output
      ..add(output[0])
      ..add(output[1]);

    if (i == clippingVerticesLast) break;
    final Float32List temp = output;
    output = input..length = 0;
    input = temp;
  }

  if (originalOutput != output) {
    originalOutput.length = 0;
    final int n = output.length - 2;
    for (int i = 0; i < n; i++) {
      originalOutput[i] = output[i];
    }
  } else {
    originalOutput.length = originalOutput.length - 2;
  }

  return clipped;
}