pos + size wins by 3:1 on Mastodon. But a poll in a private Discord had start + end win by 3:1.
I use start + end in my code.
I did a survey of a bunch of popular systems to see what they use:
macOS Core Graphics CGRect: pos + size
Cairo cairo_rectangle_int_t: pos + size
GTK GdkRectangle: pos + size
dotnet System.Drawing.Rectangle: pos + size
xlib XDrawRectangle: pos + size
nanovg: pos + size
HTML5 canvas: pos + size
Unity OnGUI: pos + size
Blend2D BLBox: start + end
Skia SkRect: start + end
Classic Mac QuickDraw Rect: start + end
Win32 RECT: start + end
BeOS and Haiku BRect: start + end
Delphi & Lazarus TRect: start + end
anti-grain geometry rect_base: start + end
UE5 FRect: start + end
dear imgui: start + end
Qt QRect: start + end
Direct2D D2D_RECT_F: start + end
@neauoire it seems like the only places where pos + size are normal is web dev, gtk, and macos core graphics (for some reason)
The start + end ones cover a lot of areas, from pretty new libraries (blend2d) to ancient ones like quickdraw and 16-bit windows (RECT is older than win32.)
start + end seems better to me because it requires fewer instructions to do boundary testing on the mouse cursor, rectangle intersection, union, etc. with pos + size you're always having to keep adding and removing the size to do stuff. better to just do it once and keep the rectangle around to re-use.
in the systems that use pos + size like Cairo/gtk and nanovg, further in their drawing/pipeline implementation they always end up adding the size back to pos to do the drawing or calculate stuff. and if you look upwards in the stack you often see code that has to split a start + end rect back to pos + size before handing it off to Cairo again.
Blend2D also has a BLRect type, which is a pos + size rect, and if you follow its path in Blend2D it ends up getting turned into a BLBox (start + end) later in its pipeline, after the user code has submitted it.
@cancel More of an aside (I'm not recommending it at the API level) but one representation that's often forgotten is center and radius (half-extent) per axis. The center/radius representation of intervals is nice for overlap checking since an interval is just a 1-dimensional disk/ball. So for 2-dimensional rects:
abs(a.cx - b.cx) <= a.rx + b.rx && abs(a.cy - b.cy) <= a.ry + b.ry
Mentioned here, for example: https://fgiesen.wordpress.com/2011/10/16/checking-for-interval-overlap/
@cancel @pervognsen Each has their ideal use case...
pos, size and min, max are good if you're drawing pixels. Which one you like most largely depends if you prefer having -1 in some cases or +1 in others. min, max could be better because you never have to check for zero size (max = pos+size-1).
For bounds like in culling, center, half_extents is convenient.
min,max is inclusive
pos,size is exclusive
Let's take for example with integer pixel coords:
min=4
max=6
You would expect a loop over this interval to hit pixels 4,5,6
So it would be for(x=min; x<=max; ++x) {...}
That's equivalent to
pos=4
size=3 (there are 3 pixels in the interval)
And a loop would be for(x=pos; x<pos+size; ++x) {...}
So min=pos, max=pos+size-1
Or pos=min, size=max-min+1
Hope this explanation makes sense...
i wouldn't expect that to hit pixel 6. i write my loops like,
for (x = min.x; x < max.x; x++) { ..}
@cancel @pervognsen max is max, not size... you're using it as if it were a size.
If you think just of the name, min is the first pixel you loop over, and max is the last one, inclusively. As an analogy, if I say I can pay a maximum of 50$ for something, and someone sells that thing for precisely 50$, then I can buy it, it doesn't have to be 49.99$
So if I say the min pixel is 4 and the max pixel is 6, then I expect to loop over 4,5,6. But yeah, I'm particular about terminology hehehe
You're treating it as exclusive. It's fine, as long as that's your convention. I thought my analogy with money was a good one. For me, the term max implies that it is inclusive.
Depends on the case, I don't use it everywhere but in some cases it's simpler. Processing tiles where you need the last tile of the previous interval for the next one, and don't want overlap, for example.
@maliusarth @cancel @pervognsen yeah, you're right.
I realize I was being pedantic about terminology, which is not useful at all. You can use what you want as long as it's clear to you and you handle the boundary conditions. It's just different words...
@cancel the downside of using two corners is the ambiguity of if the second corner is included. The mathematically“right” answer puts pixel centers at half coordinates. But that’s not intuitive. People want to specify the stop pixel.. so (0,0) - (1,1) is a 2x2 rectangle. But that’s means you need to add 1 to get the width.
Using pixel edge coordinates + size solves all these problems and also appears to work right even if user assumes pixel center coordinates.