在给定距离的直线右侧找到一个点
Finding a point on the right side of a line at a given distance
我想在 P1(x1,y1)
和 P2(x2,y2)
定义的直线右侧找到距离 d
处的点(距离是从直线的中间计算的) .我想出了下面的代码,效果很好,但我认为我做了不必要的计算,它可以更快地完成。
#define PI 3.141592653589793238462643383279502884197169399375105820974944592308
double x2, x1, y1, y2, px, py, p1x, p1y, p2x, p2y, d, ax, ay, b, dx, dy;
d = 2.0; // given distance
ax = (x1 + x2) / 2; // middle point
ay = (y1 + y2) / 2; // middle point
b = tan(atan2(y2 - y1, x2 - x1) + PI / 2); // slope of the perpendicular line
dx = (d / sqrt(1 + (b * b)));
dy = b * dx;
p1x = ax + dx;
p1y = ay + dy;
p2x = ax - dx;
p2y = ay - dy;
// cross product
if (((x2 - x1) * (p1y - y1) - (y2 - y1) * (p1x - x1)) > 0)
{
px = p1x;
py = p1y;
}
else
{
px = p2x;
py = p2y;
}
您不需要 atan
、b
值、叉积来检查方向(此外,b
可能为零并导致除法错误)。
改为计算归一化(单位长度)方向向量并使其垂直:
d = 2.0; // given distance
ax = (x1 + x2) / 2; // middle point
ay = (y1 + y2) / 2; // middle point
dx = x2 - x1;
dy = y2 - y1;
scale = d / sqrt(dx*dx + dy*dy); //distance/vector length
px = ax + dy * scale; // add normal vector to the right side of p1-p2 direction
py = ay - dx * scale; //note minus sign
对于生成一个垂直于另一个的二维向量,点积的一个特殊情况的一个结果是你可以交换向量的两个分量并取反其中之一。
例如,假设您有向量 d
,它指向 p1
到 p2
:
dx = p2x - p1x;
dy = p2y - p1y;
而现在你要生成垂直的right
,就是:
rightx = dy;
righty = -dx;
现在,让我们快速检查一下“在右边”的定义,以防我们真的想取反这两个值...
o p2 = [2, 3]
/
o p1 = [0, 0]
上面,d
很简单:[2, 3]
。直观地,我们会想到(从上面看)从 p1
走到 p2
并向右看,这意味着一个正 X 方向和负 Y 方向的向量。所以是的,看起来不错。
注意:如果您的坐标系是基于屏幕的(即 正 Y 方向向下),则反之亦然(并且您将否定这两个项right
向量的计算)。这是由于坐标系的 惯用手 是左手而不是右手。
现在,您可以将中点 mid
计算为 (p1 + p2) / 2
或 p1 + d / 2
。
midx = (p1x + p2x) / 2;
midy = (p1y + p2y) / 2;
最后要生成 p3
,您从 mid
开始并将向量 right
向下扩展一个量 height
,您需要通过除以对该向量进行归一化它的长度和比例 height
。形式上,最后一点将是 mid + right * height / length(right)
.
这是计算中唯一特别昂贵的部分,因为它需要一个平方根。
rdist = height / sqrt(rightx * rightx + righty * righty);
p3x = midx + rightx * rdist;
p3y = midy + righty * rdist;
恭喜!你现在有一个等腰三角形!
我想在 P1(x1,y1)
和 P2(x2,y2)
定义的直线右侧找到距离 d
处的点(距离是从直线的中间计算的) .我想出了下面的代码,效果很好,但我认为我做了不必要的计算,它可以更快地完成。
#define PI 3.141592653589793238462643383279502884197169399375105820974944592308
double x2, x1, y1, y2, px, py, p1x, p1y, p2x, p2y, d, ax, ay, b, dx, dy;
d = 2.0; // given distance
ax = (x1 + x2) / 2; // middle point
ay = (y1 + y2) / 2; // middle point
b = tan(atan2(y2 - y1, x2 - x1) + PI / 2); // slope of the perpendicular line
dx = (d / sqrt(1 + (b * b)));
dy = b * dx;
p1x = ax + dx;
p1y = ay + dy;
p2x = ax - dx;
p2y = ay - dy;
// cross product
if (((x2 - x1) * (p1y - y1) - (y2 - y1) * (p1x - x1)) > 0)
{
px = p1x;
py = p1y;
}
else
{
px = p2x;
py = p2y;
}
您不需要 atan
、b
值、叉积来检查方向(此外,b
可能为零并导致除法错误)。
改为计算归一化(单位长度)方向向量并使其垂直:
d = 2.0; // given distance
ax = (x1 + x2) / 2; // middle point
ay = (y1 + y2) / 2; // middle point
dx = x2 - x1;
dy = y2 - y1;
scale = d / sqrt(dx*dx + dy*dy); //distance/vector length
px = ax + dy * scale; // add normal vector to the right side of p1-p2 direction
py = ay - dx * scale; //note minus sign
对于生成一个垂直于另一个的二维向量,点积的一个特殊情况的一个结果是你可以交换向量的两个分量并取反其中之一。
例如,假设您有向量 d
,它指向 p1
到 p2
:
dx = p2x - p1x;
dy = p2y - p1y;
而现在你要生成垂直的right
,就是:
rightx = dy;
righty = -dx;
现在,让我们快速检查一下“在右边”的定义,以防我们真的想取反这两个值...
o p2 = [2, 3]
/
o p1 = [0, 0]
上面,d
很简单:[2, 3]
。直观地,我们会想到(从上面看)从 p1
走到 p2
并向右看,这意味着一个正 X 方向和负 Y 方向的向量。所以是的,看起来不错。
注意:如果您的坐标系是基于屏幕的(即 正 Y 方向向下),则反之亦然(并且您将否定这两个项right
向量的计算)。这是由于坐标系的 惯用手 是左手而不是右手。
现在,您可以将中点 mid
计算为 (p1 + p2) / 2
或 p1 + d / 2
。
midx = (p1x + p2x) / 2;
midy = (p1y + p2y) / 2;
最后要生成 p3
,您从 mid
开始并将向量 right
向下扩展一个量 height
,您需要通过除以对该向量进行归一化它的长度和比例 height
。形式上,最后一点将是 mid + right * height / length(right)
.
这是计算中唯一特别昂贵的部分,因为它需要一个平方根。
rdist = height / sqrt(rightx * rightx + righty * righty);
p3x = midx + rightx * rdist;
p3y = midy + righty * rdist;
恭喜!你现在有一个等腰三角形!