Define a rectangle as two points or origin / size?

This is a question that has arisen several times in my career, and which divides me and my colleagues into two camps. I thought that this site is best answered once and for all.

Almost all graphical UIs implement the Rectangle structure, but the way they do it is usually divided into two possible options:

  • A rectangle is defined as two two-dimensional points within the same coordinate system, usually called p0 and p1, or with separate components, like x0, y0, x1, y1.
  • A rectangle is defined as two-dimensional vectors of origin and size, usually called position and size, or, individually, x, y, width, height.

Now, let's say I have to write a user interface library, which of the two options to choose?

Refresh . The question is about implementation, not interface. Of course, a rectangle's interface can support both approaches well, but how can you store data in a rectangle?

+6
source share
2 answers

Why not choose both?

Indeed, the only thing that matters is the interface between your library and its internal elements. Or how your users will use the library. You can store information for the rectangle, but you want to, but it needs to be encapsulated far, far from the user, so they don’t need to worry about how their rectangle is stored, just that it is really a rectangle.

In other words, if you select both, if you write object-oriented code, you can save the rectangle as you want, and then let your user create the rectangle using either of these methods.

For example, your declaration might look something like this:

class Rectangle { public: Rectangle(Point p1, Point p2); Rectangle(Point origin, int width, int height); ... }; 

(C ++, as you noted this)

Where Point is some class:

 class Point { public: Point(int x, int y) : mX(x), mY(y) {} private: int mX; int mY; }; 

Thus, your library is not limited to supporting only one type of specification for creating a rectangle.

As for the implementation specifically, it really doesn't matter. They both work and can be easily converted to each other and use the same amount of memory, and therefore there will be no significant consequences for using one on top of the other.

For simple development simplicity, consider what are the options for using your rectangle. Take a look at each member function that you will need to write for this class, and consider which format will make it easier to write these functions.

If it were me, I would probably use it with two dots.

Edit: An academic approach to why I think that implementing it in any case will have absolutely no meaning in most cases.

Let there be a member function or operation on our Rectangle class that works on our rectangle or does some calculations. Suppose that one implementation method (width / height / start or two points) will perform this operation much faster than the other implementation.

We can convert from width to implementation / height / origin using the following:

 // assuming x0,y0 is top left and x1,y1 is bottom right x0 = originX; y0 = originY; x1 = originX + width; y1 = originY + height; 

And we can convert two points from the implementation with the following:

 // assuming x0,y0 is top left and x1,y1 is bottom right originX = x0; originY = y0; width = x1 - x0; height = y1 - y0; 

Therefore, an implementation that performs this operation is much slower / worse than another implementation can be converted to another implementation at O ​​(1) runtime, so that another implementation cannot be much better than the first implementation.

If you do not perform this operation several thousand times per second or on a device with very high bandwidth, I am very sure that there will not be a difference in performance. There is no longer any difference in memory, because both implementations pretty much just store 4 float / ints.

This leaves a lot of coding convenience, and, as I said above, in my original post, you can simply “consider what options for using your rectangle are. Look at each member function that you will need to write a class for this and think about which format makes writing these features easier. "

+8
source

Without any question, this, of course, depends entirely on the problem you are facing.

For the graphical drawing algorithm, the second option seems to have a very slight advantage IMHO. While for the general "geometric" algorithms defined on the Euclidean plane, the 1st option is somewhat more convenient.

In addition, as soon as I worked on an algorithm defined on the surface of the Earth. The values, x, y coordinates represent longitude / latitude, respectively. The X coordinate is obviously cyclic . In this particular case, in order to determine (look) rect - it is not enough to determine only the angles, you also need a direction . This can be achieved by agreeing that the first point (p0) is the leftmost point, while the second point (p1) is the rightmost one. But I preferred instead to switch to the second convention, where you naturally have an angle and a displacement vector.

+1
source

Source: https://habr.com/ru/post/912483/


All Articles