月份信息二维坐标图绘制(绘制箭头算法)续

     赶着时间又把那个箭头的绘制算法写了出来,但是由于是通过中心点来计算对应的另外一点,因此偏差比较大。

     具体算法如下:

 1  //画折线、箭头
 2                 if (index < count - 1)
 3                 {
 4                     float x1=this.CenterPointF.X + (index) * this.XUnitWidth;
 5                     float y1=this.CenterPointF.Y - Values[index] / this.YUnitValue * this.YUnitHeight;
 6                     float x2=this.CenterPointF.X + (index+1* this.XUnitWidth;
 7                     float y2=this.CenterPointF.Y - Values[index + 1/ this.YUnitValue * this.YUnitHeight;
 8                     
 9                     //画折线
10                     graphics.DrawLine(Pens.Red,x1, y1, x2, y2);
11                     
12                     //画箭头
13                     DrawArrowHead(graphics, new PointF(x1,y1),new PointF(x2,y2));
14                 }

通过前后两点的X、Y坐标值进行比较,绘制的具体算法如下():

 1 private void DrawArrowHead(Graphics graphics, PointF beginPoint, PointF endPoint)
 2         {
 3             PointF p1 = beginPoint;
 4             PointF p2 = endPoint;
 5             float x = p2.X - p1.X;
 6             float y = p2.Y - p1.Y;
 7 
 8             if(x==0 && y==0)
 9             {
10                return ;
11             }
12 
13             if (y == 0)
14             {
15                 PointF[] polygonPoints =
16                 new PointF(p2.X, p2.Y), 
17                 new PointF(p2.X+(x>0?-this.ArrowLength:this.ArrowLength),p2.Y+this.ArrowWidth),
18                 new PointF(p2.X+(x>0?-this.ArrowLength:this.ArrowLength),p2.Y-this.ArrowWidth) };
19 
20                 DrawArrowHead(graphics, polygonPoints);
21             }
22             else if (x == 0)
23             {
24                 PointF[] polygonPoints =
25                 new PointF(p2.X, p2.Y), 
26                 new PointF(p2.X - this.ArrowWidth, p2.Y+(y<0?this.ArrowLength:-this.ArrowLength)),
27                 new PointF(p2.X + this.ArrowWidth,  p2.Y+(y<0?this.ArrowLength:-this.ArrowLength)) };
28 
29                 DrawArrowHead(graphics, polygonPoints);
30             }
31             else
32             {
33                 double p3x;
34                 double p3y;
35                 double p4x;
36                 double p4y;
37                 double p5x;
38                 double p5y;
39 
40                 p3x = Math.Round((p2.X - (p2.X - p1.X) * this.ArrowLength / Math.Sqrt((p2.Y - p1.Y) * (p2.Y - p1.Y) + (p2.X - p1.X) * (p2.X - p1.X))), 3);
41                 p3y = Math.Round((p2.Y - (p2.Y - p1.Y) * this.ArrowLength / Math.Sqrt((p2.Y - p1.Y) * (p2.Y - p1.Y) + (p2.X - p1.X) * (p2.X - p1.X))), 3);
42                 p4y = Math.Round((p3y + (p1.Y - p3y) * this.ArrowWidth / Math.Sqrt((p1.Y - p3y) * (p1.Y - p3y) + (p2.X - p3x) * (p2.X - p3x))), 3);
43                 p4x = Math.Round((p3x + (p2.X - p3x) * this.ArrowWidth / Math.Sqrt((p1.Y - p3y) * (p1.Y - p3y) + (p2.X - p3x) * (p2.X - p3x))), 3);
44                 p5x = Math.Round(p3x * 2 - p4x, 0);
45                 p5y = Math.Round(p3y * 2 - p4y, 0);
46 
47                 PointF[] polygonPoints =
48                 new PointF((p2.X) , (p2.Y)), 
49                 new PointF( (float)p4x   ,  (float)p4y),
50                 new PointF( (float)p5x   ,  (float)p5y)};
51 
52                 DrawArrowHead(graphics, polygonPoints);
53             }
54         }

关键点17-18行

17                 new PointF(p2.X+(x>0?-this.ArrowLength:this.ArrowLength),p2.Y+this.ArrowWidth),
18                 new PointF(p2.X+(x>0?-this.ArrowLength:this.ArrowLength),p2.Y-this.ArrowWidth) };
当y相等时,需要判断x的差值。

同理

26                 new PointF(p2.X - this.ArrowWidth, p2.Y+(y<0?this.ArrowLength:-this.ArrowLength)),
27                 new PointF(p2.X + this.ArrowWidth,  p2.Y+(y<0?this.ArrowLength:-this.ArrowLength)) };
当x相等时,需要判断y的差值。

40                 p3x = Math.Round((p2.X - (p2.X - p1.X) * this.ArrowLength / Math.Sqrt((p2.Y - p1.Y) * (p2.Y - p1.Y) + (p2.X - p1.X) * (p2.X - p1.X))), 3);
41                 p3y = Math.Round((p2.Y - (p2.Y - p1.Y) * this.ArrowLength / Math.Sqrt((p2.Y - p1.Y) * (p2.Y - p1.Y) + (p2.X - p1.X) * (p2.X - p1.X))), 3);
42                 p4y = Math.Round((p3y + (p1.Y - p3y) * this.ArrowWidth / Math.Sqrt((p1.Y - p3y) * (p1.Y - p3y) + (p2.X - p3x) * (p2.X - p3x))), 3);
43                 p4x = Math.Round((p3x + (p2.X - p3x) * this.ArrowWidth / Math.Sqrt((p1.Y - p3y) * (p1.Y - p3y) + (p2.X - p3x) * (p2.X - p3x))), 3);
44                 p5x = Math.Round(p3x * 2 - p4x, 0);
45                 p5y = Math.Round(p3y * 2 - p4y, 0);
数学方式通过坐标值找出其他的2个点。

纯粹的数学计算,误差比较大。本人想到过用角度来计算,但是公式都忘得差不多了,得哪天找点资料看看才行。

显示的效果如下:(图一)

(图2)

    估计通过角度来算的话,误差会比较少。这个当角度太大了的,误差越来越大,算法还有待提高。

原文地址:https://www.cnblogs.com/jasenkin/p/graphic_drawing_arrow_head.html