【问题标题】:Drawing rectangle between two points with arbitrary width在任意宽度的两点之间绘制矩形
【发布时间】:2011-12-12 20:00:27
【问题描述】:

当用户在触摸屏上滑动手指时,我试图在两个 (2D) 点之间画一条线。为此,我计划在上一次触摸更新的 X 和 Y 与最新触摸更新的 X 和 Y 之间的每次触摸更新上绘制一个矩形。当用户在屏幕上滑动手指时,这应该会创建一条连续的实线。但是,我也希望这条线具有任意宽度。我的问题是,我应该如何计算每个矩形(x1,y1,x2,y2)所需的坐标?

--

另外:如果有人有任何关于我如何着手对这条线应用抗锯齿的信息,那将是一个巨大的帮助。

【问题讨论】:

  • 我很困惑,所以你有左上角 (x1,y1) 和右下角 (x2,y2) 并且需要用这些点创建一个矩形?坐标不会只是 [(x1,y1),(x2,y1),(x1,y2),(x2,y2)]?
  • 我必须使用的所有信息都是用户手指在屏幕上的先前位置和最新位置。我需要在两者之间画一条任意宽度的线。请注意,矩形也需要居中。它并不像你想象的那么简单。这个骇人听闻的插图可能有帮助,也可能没有帮助。 link(请注意顶部矩形上的第二个坐标实际上应该是 150,50,但希望你能理解我的意思)
  • 为什么要使用矩形?为什么不用粗线段?
  • datenwolf:在我正在开发的平台上,OpenGL 只允许 1px 宽的抗锯齿线。

标签: qt opengl math 2d


【解决方案1】:

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

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 个点绘制矩形。

图片如下:

编辑:回答 cmets:如果 X 和 Y 相同,则该线恰好是对角线,垂直于对角线的是对角线。归一化是一种使长度等于 1 的方法,因此此示例中的线条宽度将不取决于垂线长度(此处等于线条长度)。

【讨论】:

  • @Krom Stern 请详细说明Draw rectangle using these 4 points. 您的回答很好,但我对通过这4 个点确定矩形大小感到困惑。请帮忙。谢谢。
  • @SalmanKhakwani:我不知道如何才能更简单地解释它。究竟是什么让您感到困惑?
  • 我正在关注stackoverflow.com/questions/18229683/resize-line-from-endpoints的问题,你的回答似乎很适合这个问题。你能回答这个问题吗,这对我很有帮助:)
  • 很好的答案。我会放弃 P 中间变量。并且可能值得将 `* Width / 2` 合并到 N 中。
  • 谢谢,这节省了我的时间。对于那些使用 Qt 绘图的人:-> 使用 QPolygon 绘制 4 个点(R1X、R1Y、R2X、R2Y、R3X、R3Y 和 R4X、R4Y),它完美地绘制为变量类型为“double/float”而不是“int” " 以避免在 2 个输入点倾斜时丢失点。
【解决方案2】:

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

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

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 // 按距离

将 (y3 - y1) 替换为 a 并将 (x3 - x1) 替换为 b 得到

a = b * s2 // 斜率方程

// 将 a 替换为 b*s2

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 = 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) 来计算其他两个角。

【讨论】:

  • 非常感谢您的回复,非常感谢。现在将着手处理。
【解决方案3】:

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

我们需要计算 2 个值,即 4 个角中每个角的 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 shift 和 y shift。

First coordinate is: (x1 - xS, y1 + yS)

Second: (x1 + xS, y1 - yS)

Third: (x2 + xS, y2 - yS)

Fourth: (x2 - xS, y2 + yS)

你去吧! (这些坐标是逆时针绘制的,OpenGL的默认值)

【讨论】:

  • 非常感谢,非常感谢您的帮助!
  • 我发现这更容易理解。虽然我不明白投票最多的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多