将矩形定义为两个点或原点/大小?

9
这是我职业生涯中遇到过多次的问题,也让我和同事们分成了两个阵营。我觉得最好在这个网站上回答一次,以便一劳永逸。
几乎所有图形用户界面库都实现了一个矩形结构,但它们通常会分为两种可能的选项:
1. 矩形被定义为同一坐标系内的两个2D点,通常命名为p0和p1,或具有单独的组件,如x0、y0、x1、y1。
2. 矩形被定义为2D原点和大小向量,通常命名为位置和大小,或单独命名为x、y、宽度、高度。
现在,假设我要编写一个UI库,我应该选择哪个选项呢?
更新:此问题涉及实现,而不是接口。当然,矩形的接口可以支持两种方法,但是你会如何存储矩形内的数据?

5
我认为只有当我们决定a)花括号应该放在哪里,以及b)使用vi还是emacs之后,这个问题才会得到明确的答案。 - molbdnilo
2个回答

8
为什么不两者兼备呢?
实际上,唯一重要的是你的库和其内部之间的接口。或者说,你的用户将如何使用该库。你可以按照任何方式存储矩形的信息,但应将其封装在远离用户的地方,以便他们不必担心如何存储他们的矩形,只需要知道它确实是一个矩形。
换句话说,如果你正在编写面向对象的代码,可以按照自己的方式存储矩形,然后让用户使用两种方法之一创建矩形。
例如,你的声明可能会像这样:
class Rectangle
{
public:
    Rectangle(Point p1, Point p2);
    Rectangle(Point origin, int width, int height);
    ...
};

(由于您标记了C ++),

其中Point是某个类:

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

这样,您的库不仅支持创建矩形的一种规范类型。至于具体实现,其实并不重要。它们都可以工作,并且可以轻松地相互转换并使用相同的内存,因此在使用其中一种而不是另一种时不会有任何主要性能影响。
为了简化开发,请考虑矩形的用例。查看每个类需要编写的成员函数,并考虑哪种格式将使编写这些函数更容易。
如果我是您,我可能会使用两个点来实现。
编辑:从学术角度来看,我认为在大多数情况下,使用任何一种实现方式都不会有太大区别。
假设我们的Rectangle类有一个成员函数或操作,用于对矩形进行操作或进行某些计算。假设一种实现方法(宽度/高度/原点或两个点)比另一种实现方法执行此操作快得多。
我们可以通过以下方式从宽度/高度/原点实现进行转换:
// assuming x0,y0 is top left and x1,y1 is bottom right
x0 = originX;
y0 = originY;
x1 = originX + width;
y1 = originY + height;

我们可以使用以下方法将实现的两个点进行转换:

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

因此,执行此操作速度/效率比另一种实现要慢/差得多的实现可以在O(1)运行时间内转换为另一种实现,因此其他实现不能比第一种实现好太多。
除非您每秒执行此操作数千次或在性能非常有限的设备上执行此操作,否则我非常确定不会有性能差异。由于两种实现基本上只存储4个浮点数/整数,因此已经没有任何存储器差异。
这几乎只剩下编码方便性了,就像我在我的原始帖子中所说的那样,你可以简单地“考虑你的矩形使用情况。查看你需要编写的每个成员函数并考虑哪种格式会使编写这些函数更容易。”

2
这只是给出了接口应该长什么样的提示,我同意。然而问题是关于实现的。我正在扩展原始问题以使其更清晰。 - paniq
上面的最后三个块没有回答你的实现问题吗?我会留意你的问题并更新答案。 - Andrew Rasmussen
哦,是的,我忽略了那个,抱歉。但我并不认为这没关系。 - paniq
1
居中?在计算机科学中,这是一个奇怪、非正统的矩形引用方式,我以前从未见过。声明它们最常见的方式是使用left、top、right、bottom,其中每个变量都是像素的高度或宽度,或者使用x、y、width、height - Lundin
嗯,我也是这么想的。甚至没有考虑过原点/宽度/高度。谢谢!已经修复了。 - Andrew Rasmussen
1
甚至可以创建一个包含与点相同数据但允许一定类型安全的 Size 类。 - Karl Knechtel

2

毫无疑问,这完全取决于你所面临的问题。

对于图形绘制算法而言,我认为第二个选项略微更有优势。而对于在欧几里得平面上定义的一般“几何”算法而言,第一个选项则更为方便。

此外,我曾经处理过一个在地球表面定义的算法。这意味着,x、y坐标分别表示经度/纬度。x坐标显然是循环的。在这种情况下,为了定义一个(类似)矩形,仅定义角落是不够的,还需要一个方向。可以通过约定第一个点(p0)是最左边的点,而第二个点(p1)是最右边的点来处理这个问题。但是我更喜欢使用第二种约定,其中您自然拥有一个角和一个偏移向量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接