GDI+画直线带箭头
1.直线起前p0,终点p1, 那么向量<p0,p1> 为v0, 将v0转成单位向量并放大10个像素。
2.将v0乘以绕z轴旋转的变换矩阵,并同时做平移,得向量v2,v3
3.v1,v2直接作为p2,p3点并连接p2 p1, p3,p1
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/// <summary> /// 给定一线段坐标点 /// 计算p1点两边箭头坐标点 /// 左右按15度角偏转 /// </summary> /// <param name="p0"></param> /// <param name="p1"></param> /// <returns></returns> public static PointF[] CalcArrowPoint(PointF p0, PointF p1) { var v1 = CalcVector(p1, p0); //计算单位向量 var v1_1 = CalcUV(v1, 10.0d);//单位向量放大10个像素 var c=0.9659d;//cos(15) var s=0.2588d; //sin(15) var p_s=new PointF(); p_s.X =(float)( c * v1_1.X - s * v1_1.Y + p1.X); p_s.Y =(float)( s * v1_1.X + c * v1_1.Y + p1.Y); //sin是奇函数要变符号 var p_e = new PointF(); p_e.X = (float)(c * v1_1.X + s * v1_1.Y + p1.X); p_e.Y = (float)(-s * v1_1.X + c * v1_1.Y + p1.Y); return new PointF[2] { p_s, p_e }; } public static PointF TransCoordinate(PointF p,double theta,double x_offset=0,double y_offset=0 ) { #region double[,] a = { {Math.Cos(theta), -Math.Sin(theta) ,0 ,x_offset }, {Math.Sin(theta) , Math.Cos(theta) ,0 ,y_offset }, {0 , 0 ,1 , 0}, {0, 0 ,0 ,1} }; var _M = DenseMatrix.OfArray(a); #endregion var B = DenseVector.OfEnumerable(new double[] { p.X, p.Y, 0,1}); var C = _M.Multiply(B); return new PointF((float)C[0], (float)C[1]); } var g = pictureBox1.CreateGraphics(); Console.WriteLine(pictureBox1.Width+","+ pictureBox1.Height); g.Clear(pictureBox1.BackColor); var rnd=new Random(Environment.TickCount); var x = rnd.Next(0, 700); var y = rnd.Next(0, 700); var p0 = new Point(x, y); var p1 = new Point(300, 300); var pen = new Pen(Color.Tan) { Width = 1 }; //pen.EndCap = LineCap.ArrowAnchor; var pen2 = Pens.Red; g.DrawLine(pen, p0, p1); var pArr= Algorithm.CalcArrowPoint(p0, p1); g.DrawLine(pen2,pArr[0], p1); g.DrawLine(pen2,pArr[1], p1);
2.使用.net自带的样式
AdjustableArrowCap aac = new AdjustableArrowCap(2, 3);
pen1.CustomEndCap = aac;//定义线尾的样式为箭头
pen2.CustomEndCap = aac;