【问题标题】:Draw arrow between on line between two points在两点之间的线上绘制箭头
【发布时间】:2020-09-23 02:57:07
【问题描述】:

我怎样才能画一个箭头来显示线的方向?我设法做到了,但箭头的形状不正确。

//For Line
Point point1 = new Point(100, 110);
Point point2 = new Point(300, 210);
Point point3 = new Point(200, 310);
Point point4 = new Point(100,310); 

e.Graphics.DrawLines(pen, points);

//For Arrow
e.Graphics.DrawLine(pen, 200, 150, 180, 130);
e.Graphics.DrawLine(pen, 200, 150, 180, 150);

【问题讨论】:

  • 我不明白这个问题。如果您所做的只是对坐标进行硬编码,那么只需对 正确 坐标进行硬编码。如果您想要某种计算箭头,那么您需要在您的问题中提供更多详细信息。这包括一个minimal reproducible example,它显示了您已经尝试过的内容,以及对您需要帮助的具体的详细说明。
  • 我认为问题很明确。如何在 Windows 窗体中为GDI 绘制的线添加箭头功能。

标签: c# winforms graphics gdi+


【解决方案1】:

另一个例子:

制作者:

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    Point[] points = {
        new Point(100, 110),
        new Point(300, 210),
        new Point(200, 310),
        new Point(100, 310)
    };
    for(int i=0; i<(points.Length-1); i++)
    {
        Point p1 = points[i];
        Point p2 = points[i + 1];                
        e.Graphics.DrawLine(Pens.Black, p1, p2);

        float angle = getAngle(p1, p2);
        Point mid = getMidPoint(p1, p2);
        e.Graphics.TranslateTransform(mid.X, mid.Y);
        e.Graphics.RotateTransform(angle);
        e.Graphics.RotateTransform(135);
        e.Graphics.DrawLine(Pens.Black, new Point(0, 0), new Point(8, 0));
        e.Graphics.RotateTransform(-270);
        e.Graphics.DrawLine(Pens.Black, new Point(0, 0), new Point(8, 0));
        e.Graphics.ResetTransform();
    }
}

private float getAngle(Point p1, Point p2)
{
    float deltaX = p2.X - p1.X;
    float deltaY = p2.Y - p1.Y;
    return (float)(Math.Atan2(deltaY, deltaX) * 180.0 / Math.PI);
}

private Point getMidPoint(Point p1, Point p2)
{
    return new Point((p1.X + p2.X)/2,(p1.Y+p2.Y)/2);
}

【讨论】:

    【解决方案2】:

    我想你想要这样的东西:

    这是执行此操作的代码:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
    
            this.pictureBox1.Paint += PictureBox1_Paint;
        }
    
        private void PictureBox1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
    
            for (int i = 0; i < 5; i++)
            {
                DrawLineWithArrow(e.Graphics,
                    Color.Blue,
                    new PointF(50, 50),
                    new PointF(340, 120+35*i),
                    4f+3f*i, false);
                DrawLineWithArrow(e.Graphics,
                    Color.Red,
                    new PointF(340, 120+35*i),
                    new PointF(340+290, 50),
                    4f+3f*i, true);
            }
    
        }
    
        public void DrawLineWithArrow(Graphics g, Color color, PointF start, PointF end, float arrowSize=8f, bool filled = false)
        {
            if (start==end) return;
    
            PointF mid = new PointF((start.X+end.X)/2, (start.Y+end.Y)/2);
    
            float angle = (float)(180/Math.PI*Math.Atan2(end.Y-start.Y, end.X-start.X));
    
            var gp = new GraphicsPath();
            gp.AddLines(
                new PointF[] 
                {
                    new PointF(-arrowSize, -arrowSize/3),
                    new PointF(0, 0),
                    new PointF(-arrowSize, arrowSize/3)
                }
            );
            if (filled)
            {
                gp.CloseFigure();
            }
            var state = g.Save();
            using (Pen pen = new Pen(color, 0)) 
            {
                g.DrawLine(pen, start, end);
                g.TranslateTransform(
                    mid.X,
                    mid.Y);
                g.RotateTransform(angle);
                if (filled)
                {
                    using (Brush fill = new SolidBrush(color))
                    {
                        g.FillPath(fill, gp);
                    }
                }
                g.DrawPath(pen, gp);
            }
            g.Restore(state);
        }
    }
    

    我利用Graphics.TranslateTransform()Graphics.RotateTransform() 在直线的中间和沿直线移动和对齐坐标系。箭头的绘制比尝试手动进行矢量旋转要简单得多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-13
      • 1970-01-01
      • 2014-05-05
      • 2013-06-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多