# What's the idea behind defining rectangles with two points?

It's not that this doesn't make sense, but it just works out awkward 99% of the time.

Often in 2D graphics rectangles are initialized, stored and manipulated as a pair of points. In no particular language,

``````class Rect:
p1, p2: point
``````

It makes more sense to define a rectangle as two x values and two y values, like this:

``````class Rect
xleft, xright: int
ytop, ybottom: int
``````

With two points, if at some place in the source code you want to make use of the y value of the top, you'd have to say rect.p1.y (hmmm, stop and think, is it p1 or p2) but with the four values as plain data members, it's clear and direct: rect.ytop (no thinking required!) The use of two points means that in dealing with the vertical, you have to tangle the horizontal; there's an extraneous relation between indepenent elements.

How did this two-point idea come about and why does it persists? Does it have some benefit over bare x and y coordinates?

ADDED NOTE: This question is in the context of X-Y aligned rectangles, such as in windows managers and GUI toolkits, not in the context of arbitrary shapes in drawing and painting app.

-
Have you written an substantial amount of code using Rects? –  user1249 Nov 30 '10 at 21:03
A rectangle is defined by two points, so representing them as two points makes a lot of sense. –  Adam Crossland Nov 30 '10 at 21:38
A rectangle is more naturally defined as a range of x values and a range of y values. –  DarenW Nov 30 '10 at 22:22
Great question! I never thought about it myself, but you make an interesting argument! FWIW, Windows has a RECT like you describe as well (top, left, bottom, right) –  Dean Harding Nov 30 '10 at 22:41
How do you define a rectangle with two points? Is it assumed to have no rotation? –  Nick T Dec 1 '10 at 4:33

Have you considered that it is less error prone?

If you use (Point1, Point2) it is then very clear what you are specifying. If you provide 2 points, then the only possible error is that the user has mixed up their x and y when constructing the points as the order of the points doesn't matter.

If you supply 4 integers, then if someone isn't paying attention, they may supply (x1,x2,y1,y2) when you wanted (x1,y1,x2,y2) or vice versa. Also, some APIs such as WCF's Rect structure define a rectangle as (x, y, width, height) which could then cause confusion over what (1, 2, 3, 4) means. Is that (x, y, w, h) or (x1, y1, x2, y2) or (x1, x2, y1, y2)?

All in all, (Point1, Point2) seems a bit safer to me.

-

Well `p1: Point` and `p2: Point` are each going to have two `int` coordinates in them anyway, so doesn't your class amount to the same thing?

And if you store those two points as first-class `Point` objects, don't you get a little more utility from them? In most graphical coordinate systems that I know of, points are subclassed in this way to create a hierarchy of objects: `point -> circle -> ellipse` and so on.

So if you make an object that doesn't use the `Point` class, you have divorced that object from the rest of the class hierarchy.

-
The advantage I see of OP's representation is if you want to know the lower y value of a rectangle, you know it's "ybottom", where as with p1/p2 you need to figure out which one is lower. This is unless you guarantee p1 will be the lower values, anyway. –  Jason Viers Nov 30 '10 at 21:08
While it's true the two different structs both boil down to four coordinates, the two-points version introduces an extraneous level that gathers one x and one y, with no particular rationale to which x goes with which y. I do not see this extra level as providing any utility whatsoever, after many years of graphics programming. –  DarenW Nov 30 '10 at 22:27
@Jason: Good point. With the `ytop`/`ybottom` approach, though, there would also need to be a guarantee somewhere that `ybottom` is actually below `ytop`. –  Dr. Wily's Apprentice Nov 30 '10 at 22:55

Isnt that exactly the same thing as 2 points? How is this awkward... most drawing routines require points, not separate x/y components.

-

i think it makes more sense for a rectangle to be represented by an x and y extent and a point; you could even make the location point the center of the rectangle so it would be independent of rotation

but it was probably easiest to code it as two points!

-

As @Steven says, I think it should be in terms of one (x,y) point, and a (w,h) size vector. That's because it's easy to fall into an ambiguity. Suppose you have the following filled-in rectangle starting at point (0,0).

``````  012
0 XXX
1 XXX
2 XXX
``````

Clearly it's width,height are (3,3), but what is it's second point? Is it (2,2) or (3,3)?

This ambiguity can cause all kinds of problems.

I learned the hard way years ago that it's better to think of graphic coordinates as the lines between the pixels, not as the lines the pixels are on. That way there's no ambiguity.

-
The original QuickDraw routines on the Mac (the ones from the 1980s) used the mathematical model that points were infinitely small. The points on the screen lay between the pixels. So a line drawn from (3,5) to (10,5) had a length of 7 and occupied 7 pixels. In today's coordinates, that line would have a length of 8. –  Barry Brown Dec 1 '10 at 2:34

This is why I like Delphi's `TRect`. It's defined as a variant record (union struct in C-speak) that can be interpreted either as a TopLeft and a BottomRight point, or Top, Left, Bottom and Right integers, whichever is more convenient at the moment.

-

Defining rectangles as point pairs allows you to reuse the point as a vertex for another shape. Just a thought...

-

I believe it is mainly to establish uniformity between all shape primitives.

Sure you can define rectangle in many different ways, but how do you define a triangle, or a star, or a circle in a way that can use similar data structures?

All polygons can be defined by their points, with a short amount of logic to determine what to do with the points.

Graphics libraries primarily operate on these polygons in terms of vertices and edges, so points and the lines between them, all the calculations work on these two features, well that and facets, but that itself is just a function of the edges.

-

I always liked defining a rectangle as a point + width and height, where the point is the upper-left corner of the rectangle.

``````class Rect {
float x, y;
float width, height;
}
``````

And then add whatever methods you need to fetch the other metrics. Like the Java version

-
Is the top y+height, y-height or just y? –  Cameron MacFarland Dec 1 '10 at 6:21

Surely if you define your rectangle as:

``````class Rect
{
Point bottomLeft;
Point topRight;
}
``````

then you know straight away which point is which.

Even better would be to add extra properties that allowed you to manipulate the rectangle in which ever ways you needed for your application. These would simply update the underlying data structure.

By adding a transformation to the shape you can orient your rectangle any way you'd like. You'd still need an axis aligned bounding box for quick accept/reject checks :)

However, if your model allows rectangles in any orientation without applying a transformation then "bottom left" and "top right" have no meaning, which leads back to "p1" and "p2" (or something equivalent).

-

Actually, a rectagle isn't defined by 2 points. A rectangle can only be defined by two points if it is parallel to the axes.

There are several ways to represent rectangles that are parallel to the axes:

1. Two diagonally opposite points
2. One corner point, height and width
3. Centre point, half height and width (uncommon, but sometimes useful).
4. As two X coordinates and two Y coordinates

For (1), many libraries use a convention to determine which two points are used - topLeft and bottomRight, for example.

The choice of representation may be driven by the original purpose of the rectangle definition, but I imagine that it often arbitrary. The representations are equivalent in the information that they carry. They do, however, differ in the ease with which properties of the rectangle may be calculated and the the convenience with which operations can be performed on the reectangle.

Benefits of definition (1) over others include:

• Consistency of API with other polygons, lines etc.
• topLeft, bottomRight can be passed to any method that accepts points
• Methods of Point class can be called on topLeft, bottomRight
• Most properties can be derived easily, eg. bottomLeft, topRight, width, height, centre, diagonal length, etc.
-

In two dimensions, storing a rectangle as two points is clearer than defining a particular corner and a width and height - consider negative width or height, or the calculations required to determine each option from the other.

Performing rotations on a rectangle defined by points is also much simpler than one defined with a point plus width and height.

I'd expect encapsulation to make this differentiation unimportant as a user of the class.

A rectangle should be defined as three points to be well defined in 3 dimensions. I'm not entirely sure of the requirement for defining a rectangle in 4 or more dimensions.

-

I don't like it because we have thrown out a potential degree of freedom, which essentially allows for an arbitrary rotation. A general 2D rectangle has five unknowns (degrees of freedom). We could specify them as the coordinates of a point, the lengths of the two sides that form a vertex with this point, and the angle from the horizontal of the first line (the other being assumed to have an angle 90 degrees greater). An infinite number of other possibilities could also be used, but there are five independent quantities that must be specified. Some choices will lead to easier algebra than others, depending upon what is done with them.

-
It's important to realize that a "standard" rectangle structure is not a rigorously-defined mathematical rectangle, but a simplified version that's always parallel to the X and Y axes, because it was created to be used for one very specific thing: defining rectangular regions for a window manager, which are (almost) always parallel to the X and Y axes. –  Mason Wheeler Dec 1 '10 at 0:28
``````Pa(x,y)*-----------------------------------*Pb(x,y)
|                                   |
|                                   |
|                                   |
|                                   |
|                                   |
|                                   |
Pc(x,y)*-----------------------------------*Pd(x,y)
``````

We can define both Pb & Pc thus:

Pb(Pd(x),Pa(y))

and

Pc(Pa(x),Pd(y))

So there is no need to define all four points due to symmetry

-

It's completely arbitrary. You need four pieces of information to draw a rectangle. The library designer(s) decided to represent it with two points (each with an x-y coordinate), but could easily have done it with x/y/w/h or top/bottom/left/right.

-

The choice of parameters are only important to the low-level designers / coders.

High-level users only need to think about:

• IsPointInRect
• Area
• Intersection (or Clipping)
• HasOverlap (same as Intersection.Area > 0)
• Union (becomes a list of rectangles)
• Subtraction (a list of rectangles that represent the same point set that is in rect A but not in rect B)
• Transform
• Shifts in X and Y
• Rotation (0, 90, 180, 270)
• Scaling in X and Y (see note)
• Simple syntax for properties Xmin, Xmax, Ymin, Ymax, Width, Height so that the user does not need to know the exact choice of parameters.

Note: In order to minimize loss of precision during scaling transform, it is sometimes appropriate to implement a second Rect class that uses floating-point coordinates, so that intermediate results can be stored accurately in a sequence of transforms and only rounded to integer in the last step.

-