如何根据箭头计算箭头的坐标?

9 algorithm

我有一条基于我知道的两个(x,y)坐标的线.该行有一个起点和终点.现在我想在线的终点添加一个箭头.

我知道箭头是等边三角形,因此每个角度都有60度.另外,我知道一边的长度,即20.我也没有三角形的边缘(这是直线的终点).

如何计算三角形的其他两个点?我知道我应该使用一些三角函数但是如何?

Ps线的终点应该是箭头的尖端.

ang*_*son 8

这是一个示例LINQPad程序,它显示了如何执行此操作:

void Main()
{
    const int imageWidth = 512;
    Bitmap b = new Bitmap(imageWidth , imageWidth , PixelFormat.Format24bppRgb);

    Random r = new Random();
    for (int index = 0; index < 10; index++)
    {
        Point fromPoint = new Point(0, 0);
        Point toPoint = new Point(0, 0);

        // Ensure we actually have a line
        while (fromPoint == toPoint)
        {
            fromPoint = new Point(r.Next(imageWidth ), r.Next(imageWidth ));
            toPoint = new Point(r.Next(imageWidth ), r.Next(imageWidth ));
        }

        // dx,dy = arrow line vector
        var dx = toPoint.X - fromPoint.X;
        var dy = toPoint.Y - fromPoint.Y;

        // normalize
        var length = Math.Sqrt(dx * dx + dy * dy);
        var unitDx = dx / length;
        var unitDy = dy / length;

        // increase this to get a larger arrow head
        const int arrowHeadBoxSize = 10;

        var arrowPoint1 = new Point(
            Convert.ToInt32(toPoint.X - unitDx * arrowHeadBoxSize - unitDy * arrowHeadBoxSize),
            Convert.ToInt32(toPoint.Y - unitDy * arrowHeadBoxSize + unitDx * arrowHeadBoxSize));
        var arrowPoint2 = new Point(
            Convert.ToInt32(toPoint.X - unitDx * arrowHeadBoxSize + unitDy * arrowHeadBoxSize),
            Convert.ToInt32(toPoint.Y - unitDy * arrowHeadBoxSize - unitDx * arrowHeadBoxSize));

        using (Graphics g = Graphics.FromImage(b))
        {
            if (index == 0)
                g.Clear(Color.White);

            g.DrawLine(Pens.Black, fromPoint, toPoint);
            g.DrawLine(Pens.Black, toPoint, arrowPoint1);
            g.DrawLine(Pens.Black, toPoint, arrowPoint2);
        }
    }

    using (var stream = new MemoryStream())
    {
        b.Save(stream, ImageFormat.Png);
        Util.Image(stream.ToArray()).Dump();
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上,你:

  1. 计算箭头线的矢量
  2. 归一化矢量,即.使其长度为1
  3. 通过以下方式计算箭头的末端:
    1. 首先从头部回来一定距离
    2. 然后从线垂直出一定距离

请注意,如果您希望箭头线的角度不同于45度,则必须使用其他方法.

上面的程序每次都会绘制10个随机箭头,这是一个例子:

箭头示例


Mar*_*tos 8

你不需要触发器,只需要一些矢量算术......

假设线从A到B,箭头的前顶点在B处.箭头的长度是h = 10(√3),它的半宽是w = 10.我们将表示单位矢量来自A至B为U =(B-A)/ | B-A | (即,差值除以差值的长度),与此垂直的单位矢量为V = [-U y,U x ].

从这些量,您可以计算箭头的两个后顶点B - hU±wV.

在C++中:

struct vec { float x, y; /* … */ };

void arrowhead(vec A, vec B, vec& v1, vec& v2) {
    float h = 10*sqrtf(3), w = 10;
    vec U = (B - A)/(B - A).length();
    vec V = vec(-U.y, U.x);
    v1 = B - h*U + w*V;
    v2 = B - h*U - w*V;
}
Run Code Online (Sandbox Code Playgroud)

如果要指定不同的角度,则需要一些触发.计算的不同的值hw.假设你想要一个长度为h和尖角θ的箭头,那么w = h tan(θ/ 2).然而在实践中,这是最简单的指定hw直接.