static class Rectangle { final float left, top, right, bottom, width, height; Rectangle(float top, float left, float bottom, float right) { this.top = top; this.left = left; this.bottom = bottom; this.right = right; this.width = right - left; this.height = bottom - top; } static Rectangle tlbr(float top, float left, float bottom, float right) { return new Rectangle(top, left, bottom, right); } static Rectangle xywh(float left, float top, float width, float height) { return new Rectangle(top, left, top + height, left + width); } float centerX() { return left + width / 2F; } float centerY() { return top + height / 2F; } PVector center() { return new PVector(centerX(), centerY()); } boolean contains(float x, float y) { return x >= left && x < right && y >= top && y < bottom; } Rectangle offset(float dx, float dy) { return xywh(left + dx, top + dy, width, height); } Rectangle[] splitVerticallyAt(float dx) { return new Rectangle[] { new Rectangle(top, left, bottom, left + dx), new Rectangle(top, left + dx, bottom, right) }; } Rectangle[] splitHorizontallyAt(float dy) { return new Rectangle[] { new Rectangle(top, left, top + dy, right), new Rectangle(top + dy, left, bottom, right) }; } Rectangle[] splitVerticallyInto(int n) { var count = floor(width / n); var result = new Rectangle[count]; for (var i = 0; i < count; i++) { result[i] = new Rectangle(top, lerp(left, right, (float) i / n), bottom, lerp(left, right, (float) (i + 1) / n)); } return result; } Rectangle[] splitHorizontallyInto(int n) { var count = floor(height / n); var result = new Rectangle[count]; for (var i = 0; i < count; i++) { result[i] = new Rectangle(lerp(top, bottom, (float) i / n), left, lerp(top, bottom, (float) (i + 1) / n), right); } return result; } }