sclass GSI is HasBounds { int y1; // starting y coordinate int[] rowStarts; // where in data each row starts int[] data; // all x coordinates in a long list (x1, x2, x1, x2, ...) *(int *y1, int[] *rowStarts, int[] *data) {} public int getHeight() { ret l(data)/2; } int y2() { ret y1+rowStarts.length; } // bounds are calculated & cached transiently public simplyCached Rect bounds() { int x1 = Int.MAX_VALUE, x2 = 0; for (int i = 0; i < l(data); i += 2) { x1 = min(x1, data[i]); x2 = max(x2, data[i+1]); } ret rectFromPoints(x1, y1, x2, y2()); } public bool contains(Pt p) { ret contains(p.x, p.y); } public bool contains(int x, int y) { if (y < y1) false; int i = (y-y1)*2; if (i >= l(data)) false; ret x >= data[i] && x < data[i+1]; } int rowStart(int y) { ret rowStarts[y-y1]; } int rowEnd(int y) { ret y == y2()-1 ? data.length : data[y-y1+1]; } }