clipToRectangle method
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);
}
}
}
}