使用任意宽度在两点之间绘制矩形

17
我正在尝试在触摸屏幕上滑动手指时,在两个(2D)点之间画一条线。为了做到这一点,我计划在每次触摸更新之间的X和Y以及最新触摸更新的X和Y之间绘制一个矩形。这应该会在用户在屏幕上滑动手指时创建一条连续而坚实的线。但是,我还希望这条线具有任意的宽度。我的问题是,我应该如何计算我需要每个矩形的坐标(x1,y1,x2,y2)?
此外,如果有人知道如何对这条线应用抗锯齿功能,那将是非常有帮助的。

2
我有些困惑,所以你已经拥有左上角(x1,y1)和右下角(x2,y2),需要用这些点创建一个矩形吗?坐标不就应该是[(x1,y1),(x2,y1),(x1,y2),(x2,y2)]吗? - Danny
我可以使用的所有信息仅限于用户手指在屏幕上之前和最新位置。我需要在两者之间绘制一条带有任意宽度的线条,并使矩形居中对齐。这并不像您所认为的那么简单。这张糟糕的示意图可能有助于理解。[链接](http://dl.dropbox.com/u/17610534/picutre.png)(请注意,顶部矩形的第二个坐标实际上应为150,50,但希望您明白我的意思) - AaronDS
你为什么想要使用矩形?为什么不用粗线段呢? - datenwolf
datenwolf:在我正在开发的平台上,OpenGL只允许使用1像素宽的抗锯齿线。 - AaronDS
3个回答

25

计算起始点和终止点之间的向量

V.X := Point2.X - Point1.X;
V.Y := Point2.Y - Point1.Y;

然后计算其垂线(只需交换X和Y坐标即可)

P.X := V.Y; //Use separate variable otherwise you overwrite X coordinate here
P.Y := -V.X; //Flip the sign of either the X or Y (edit by adam.wulf)

将那个垂直方向归一化

Length = sqrt(P.X * P.X + P.Y * P.Y); //Thats length of perpendicular
N.X = P.X / Length;
N.Y = P.Y / Length; //Now N is normalized perpendicular

通过添加标准化的垂线并将其乘以所需宽度的一半,计算形成矩形的4个点

R1.X := Point1.X + N.X * Width / 2;
R1.Y := Point1.Y + N.Y * Width / 2;
R2.X := Point1.X - N.X * Width / 2;
R2.Y := Point1.Y - N.Y * Width / 2;
R3.X := Point2.X + N.X * Width / 2;
R3.Y := Point2.Y + N.Y * Width / 2;
R4.X := Point2.X - N.X * Width / 2;
R4.Y := Point2.Y - N.Y * Width / 2;

使用这4个点绘制矩形。

这是图片:

Drawing rectangle between two points

编辑: 回答评论: 如果X和Y相同,则该线正好是对角线,垂直于对角线的是对角线。归一化是一种使长度等于1的方法,因此在这个例子中,你的线条宽度不会取决于垂线的长度(在这里等于线条长度)。


1
@Krom Stern 请详细说明“使用这4个点绘制矩形”的方法。你的回答很好,但我对通过这4个点确定矩形的大小感到困惑。请帮忙解答,谢谢。 - Salman Khakwani
@SalmanKhakwani:我不确定我该如何更简单地解释它。你到底是被什么困惑了? - Kromster
我正在关注http://stackoverflow.com/questions/18229683/resize-line-from-endpoints问题,你的答案似乎非常适合这个问题。你能否回答那个问题,对我来说将非常有帮助 :) - Salman Khakwani
很好的答案。但我会放弃中间变量P,并且把* Width / 2 加入N中可能更值得考虑。 - drewish
谢谢,这节省了我的时间。对于那些使用Qt绘图的人:-> 使用QPolygon绘制4个点(R1X、R1Y、R2X、R2Y、R3X、R3Y和R4X、R4Y),并且变量类型为"double/float"而不是"int",以避免在两个输入点倾斜时丢失点。 - Ashif
使用QPolygon定义多边形:QPolygon polygon; polygon << QPoint(R1X, R1Y) << QPoint(R2X, R2Y) << QPoint(R4X, R4Y) << QPoint(R3X, R3Y); - Ashif

8

简单的方法(我将把“宽度”称为线条的厚度):

我们需要计算每个角落在x轴和y轴上的移位量,这很容易。

线的尺寸为:

width = x2 - x1

height = y2 - y1

现在的x轴偏移(我们称之为xS):
xS = (thickness * height / length of line) / 2

yS = (thickness * width / length of line) / 2

要找到线的长度,请使用勾股定理:

length = square_root(width * width + height * height)

现在您拥有了x偏移量和y偏移量。
First coordinate is: (x1 - xS, y1 + yS)

Second: (x1 + xS, y1 - yS)

Third: (x2 + xS, y2 - yS)

Fourth: (x2 - xS, y2 + yS)

好的,完成了!(这些坐标是逆时针绘制的,这是OpenGL的默认设置)


1
我发现这个更容易理解,而我不理解得票最高的答案。 - Elliot Yap

0

如果我理解正确,您有两个端点A(x1,y1)和B(x2,y2),以及一个任意的矩形宽度w。我假设端点将恰好位于矩形较短的一侧的中间位置,这意味着最终矩形的角坐标距离A和B的距离将为w/2。

您可以通过以下方式计算线的斜率;

s1 = (y2 - y1) / (x2 - x1) //假设x1 != x2

短边的斜率就是s2 = -1/s1。

我们有斜率,距离和参考点。

然后我们可以为每个角点推导出两个方程式:

对于靠近A的一个角落

C(x3,y3):

(y3 - y1) / (x3 - x1) = s2 //通过斜率

(y3 - y1)^2 + (x3 - x1)^2 = (w/2)^2 // 通过距离

用a替换(y3 - y1),用b替换(x3 - x1):

a = b * s2 //斜率公式

//用b*s2代替a

b^2 * s2^2 + b^2 = (w/2)^2 // 距离公式

b^2 = (w/2)^2 / (s2^2+1)

b = sqrt((w/2)^2 / (s2^2+1))

我们知道 w 和 s2,因此可以计算出 b

如果已知 b,则可以推导出 x3

x3 = b + x1

以及 a

a = b * s2

和 y3

y3 = b*s2 + y1

我们有一个角点 C(x3,y3)。

要计算靠近 A 的另一个角点 D(x4,y4),可以构建斜率方程

(y1 - y4) / (x1 - x4) = s2 并应用上述计算。

其他两个角落可以使用此处列出的步骤进行计算,将 A(x1, y1) 替换为 B(x2,y2)。


非常感谢您的回复,非常感激。我现在会开始处理这个问题了。 - AaronDS

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