计算对角线的垂直偏移量

时间:2013-06-19 15:19:10

标签: math geometry 2d line point

我正在写一个音乐显示程序,需要在两个音符之间画一个“诽谤”。 诽谤是连接两个音符的曲线 - 只是为了清楚。

enter image description here

我知道音符位置并计算曲线起点和终点的位置 - 起点 A 和终点 B

我现在需要在给定所需距离的情况下获得偏移 C ,以便在二次曲线中使用。 这是我对数学公式的非常有限的了解和理解的地方。

我确实在SO中找到了我的答案,但提出的解决方案要么不起作用,要么我太限于无法正确编码。

有人可以用非数学形式来帮助我进行计算吗?

3 个答案:

答案 0 :(得分:26)

给定线段AB,您可以使用着名的中点公式(A + B)/2找到中点,例如 M 。现在计算从 B A

的向量

p =< p.x,p.y> = A - B

Rotate it about the origin逆时针旋转90°以获得垂直向量

n =< n.x,n.y> =< - p.y,p.x>

将其标准化:

n =< n.x,n.y> /‖n‖其中‖n‖=√(n.x²+n.y²)是欧几里德范数或长度

C = L(t)= M + t n

使用此公式 - 线的参数形式 - 您可以沿垂线找到任意数量的点(在 n 方向)。 t是获得的点 C M 之间的距离。当t = 0时,你得到 M ,当t = 1时,你得到 M 沿 n 1个单位>依此类推。这也适用于t的负值,其中获得的点将位于AB的相对侧,即朝向音符。由于t可以是十进制数字,因此您可以通过更改其值来使用它来从 M 获得所需点的所需距离和方向。

代码,因为你说你对数学术语不感兴趣;)

vec2d calculate_perp_point(vec2d A, vec2d B, float distance)
{
   vec2d M = (A + B) / 2;
   vec2d p = A - B;
   vec2d n = (-p.y, p.x);
   int norm_length = sqrt((n.x * n.x) + (n.y * n.y));
   n.x /= norm_length;
   n.y /= norm_length;
   return (M + (distance * n));
}

这只是伪代码,因为我不确定您为项目使用的矢量数学库。

上面的粗体变量是2-d向量;大写字母表示点,小写字母表示没有位置的矢量

答案 1 :(得分:1)

这是一个Swift版本:

func pointNormalToLine(startPoint: CGPoint, endPoint: CGPoint, distance: CGFloat) -> CGPoint {

    let midpoint = CGPoint(x: (startPoint.x + endPoint.x) / 2, y: (startPoint.y + endPoint.y) / 2)
    let p = CGPoint(x: startPoint.x - endPoint.x, y: startPoint.y - endPoint.y)
    var n = CGPoint(x: -p.y, y: p.x)
    let norm_length = sqrt((n.x * n.x) + (n.y * n.y))
    n.x /= norm_length
    n.y /= norm_length
    return CGPoint(x: midpoint.x + (distance * n.x), y: midpoint.y + (distance * n.y))
}

答案 2 :(得分:0)

我把legends2k的优秀答案转换为Android上的Java。这可能会帮助别人节省一些时间。

private PointF getPerpendicularPoint(int startX, int startY, int stopX, int stopY, float distance)
{
    PointF M = new PointF((startX + stopX) / 2, (startY + stopY) / 2);
    PointF p = new PointF(startX - stopX, startY - stopY);
    PointF n = new PointF(-p.y, p.x);
    int norm_length = (int) Math.sqrt((n.x * n.x) + (n.y * n.y));
    n.x /= norm_length;
    n.y /= norm_length;
    return new PointF(M.x + (distance * n.x), M.y + (distance * n.y));
}