clipToRectangle method

LineSegment? clipToRectangle(
  1. Rectangle<num> r
)

Intersection of this LineSegment with the Rectangle as another LineSegment.

Algorithm is Cohen-Sutherland, see https://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland_algorithm .

@param r the rectangle to clip to. @return the LineSegment that falls into the Rectangle, null if there is no intersection.

Implementation

LineSegment? clipToRectangle(Rectangle r) {
  Mappoint a = start;
  Mappoint b = end;

  int codeStart = code(r, a);
  int codeEnd = code(r, b);

  while (true) {
    if (0 == (codeStart | codeEnd)) {
      // both points are inside, intersection is the computed line
      return LineSegment(a, b);
    } else if (0 != (codeStart & codeEnd)) {
      // both points are either below, above, left or right of the box, no intersection
      return null;
    } else {
      double newX;
      double newY;
      // At least one endpoint is outside the clip rectangle; pick it.
      int outsideCode = (0 != codeStart) ? codeStart : codeEnd;

      if (0 != (outsideCode & TOP)) {
        // point is above the clip rectangle
        newX = a.x + (b.x - a.x) * (r.top - a.y) / (b.y - a.y);
        newY = r.top as double;
      } else if (0 != (outsideCode & BOTTOM)) {
        // point is below the clip rectangle
        newX = a.x + (b.x - a.x) * (r.bottom - a.y) / (b.y - a.y);
        newY = r.bottom as double;
      } else if (0 != (outsideCode & RIGHT)) {
        // point is to the right of clip rectangle
        newY = a.y + (b.y - a.y) * (r.right - a.x) / (b.x - a.x);
        newX = r.right as double;
      } else if (0 != (outsideCode & LEFT)) {
        // point is to the left of clip rectangle
        newY = a.y + (b.y - a.y) * (r.left - a.x) / (b.x - a.x);
        newX = r.left as double;
      } else {
        throw Exception("Should not get here");
      }
      // Now we move outside point to intersection point to clip
      // and get ready for next pass.
      if (outsideCode == codeStart) {
        a = Mappoint(newX, newY);
        codeStart = code(r, a);
      } else {
        b = Mappoint(newX, newY);
        codeEnd = code(r, b);
      }
    }
  }
}