如何以编程方式在 WPF 中绘制箭头?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16714011/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 08:51:20  来源:igfitidea点击:

How to draw an arrow in WPF programatically?

wpfdrawingcap

提问by Daniel Pe?alba

I need to draw an arrow in WPF programatically. I remember that Windows Forms had primitives to draw an arrow, setting the Capto the Pen.

我需要以编程方式在 WPF 中绘制一个箭头。我记得Windows窗体有原语来画一个箭头,设置CapPen

mMyPen.CustomEndCap =
    new AdjustableArrowCap(arrowSize, arrowSize, true);

Is it possible with WPF?

WPF可以吗?

回答by AlSki

I've used about Charles Petzold's ArrowLine before.

我以前使用过 Charles Petzold 的 ArrowLine。

http://www.charlespetzold.com/blog/2007/04/191200.html

http://www.charlespetzold.com/blog/2007/04/191200.html

回答by Andrej Benedik

I have created the following method that creates the PointCollection for the line with arrow:

我创建了以下方法,为带箭头的线创建 PointCollection:

private const double _maxArrowLengthPercent = 0.3; // factor that determines how the arrow is shortened for very short lines
private const double _lineArrowLengthFactor = 3.73205081; // 15 degrees arrow:  = 1 / Math.Tan(15 * Math.PI / 180); 

public static PointCollection CreateLineWithArrowPointCollection(Point startPoint, Point endPoint, double lineWidth)
{
    Vector direction = endPoint - startPoint;

    Vector normalizedDirection = direction;
    normalizedDirection.Normalize();

    Vector normalizedlineWidenVector = new Vector(-normalizedDirection.Y, normalizedDirection.X); // Rotate by 90 degrees
    Vector lineWidenVector = normalizedlineWidenVector * lineWidth * 0.5;

    double lineLength = direction.Length;

    double defaultArrowLength = lineWidth * _lineArrowLengthFactor;

    // Prepare usedArrowLength
    // if the length is bigger than 1/3 (_maxArrowLengthPercent) of the line length adjust the arrow length to 1/3 of line length

    double usedArrowLength;
    if (lineLength * _maxArrowLengthPercent < defaultArrowLength)
        usedArrowLength = lineLength * _maxArrowLengthPercent;
    else
        usedArrowLength = defaultArrowLength;

    // Adjust arrow thickness for very thick lines
    double arrowWidthFactor;
    if (lineWidth <= 1.5)
        arrowWidthFactor = 3;
    else if (lineWidth <= 2.66)
        arrowWidthFactor = 4;
    else
        arrowWidthFactor = 1.5 * lineWidth;

    Vector arrowWidthVector = normalizedlineWidenVector * arrowWidthFactor;


    // Now we have all the vectors so we can create the arrow shape positions
    var pointCollection = new PointCollection(7);

    Point endArrowCenterPosition = endPoint - (normalizedDirection * usedArrowLength);

    pointCollection.Add(endPoint); // Start with tip of the arrow
    pointCollection.Add(endArrowCenterPosition + arrowWidthVector);
    pointCollection.Add(endArrowCenterPosition + lineWidenVector);
    pointCollection.Add(startPoint + lineWidenVector);
    pointCollection.Add(startPoint - lineWidenVector);
    pointCollection.Add(endArrowCenterPosition - lineWidenVector);
    pointCollection.Add(endArrowCenterPosition - arrowWidthVector);

    return pointCollection;
}

You can than easily create the line shape with the following code:

您可以使用以下代码轻松创建线条形状:

var points = CreateLineWithArrowPointCollection(new Point(0, 0), new Point(200, 100), 5);

var polygon = new Polygon();
polygon.Points = points;
polygon.Fill = Brushes.Red;

RootCanvas.Children.Add(polygon);

The code also supports shortening the arrows for short lines.

该代码还支持缩短短线的箭头。