1using System; 2using System.Drawing; 3 4namespace WindowCapture.Models 5{ 6 public class ArrowAnnotation 7 { 8 public Point Start; 9 public Point End; 10 public PointF Control1; 11 public PointF Control2; 12 public bool HasCurve; 13 public Color Color; 14 public float Width; 15 16 public ArrowAnnotation(Point start, Point end) 17 { 18 Color = Settings.ArrowColor; 19 Width = Settings.ArrowWidth; 20 Start = start; 21 End = end; 22 // Initialize control points for a straight line initially 23 Control1 = new PointF( 24 start.X + (end.X - start.X) * 0.3f, 25 start.Y + (end.Y - start.Y) * 0.3f); 26 Control2 = new PointF( 27 start.X + (end.X - start.X) * 0.7f, 28 start.Y + (end.Y - start.Y) * 0.7f); 29 HasCurve = false; 30 } 31 32 public void UpdateControlPoints() 33 { 34 UpdateControlPointsForNewEndpoints(); 35 } 36 37 public void UpdateControlPointsForNewEndpoints() 38 { 39 Control1 = new PointF( 40 Start.X + (End.X - Start.X) * 0.3f, 41 Start.Y + (End.Y - Start.Y) * 0.3f); 42 Control2 = new PointF( 43 Start.X + (End.X - Start.X) * 0.7f, 44 Start.Y + (End.Y - Start.Y) * 0.7f); 45 } 46 47 public PointF GetBezierPoint(float t) 48 { 49 float u = 1 - t; 50 float tt = t * t; 51 float uu = u * u; 52 float uuu = uu * u; 53 float ttt = tt * t; 54 55 float x = uuu * Start.X + 3 * uu * t * Control1.X + 3 * u * tt * Control2.X + ttt * End.X; 56 float y = uuu * Start.Y + 3 * uu * t * Control1.Y + 3 * u * tt * Control2.Y + ttt * End.Y; 57 58 return new PointF(x, y); 59 } 60 61 public PointF GetBezierTangent(float t) 62 { 63 // Derivative of Bezier curve 64 float u = 1 - t; 65 66 float dx = 3 * u * u * (Control1.X - Start.X) + 67 6 * u * t * (Control2.X - Control1.X) + 68 3 * t * t * (End.X - Control2.X); 69 float dy = 3 * u * u * (Control1.Y - Start.Y) + 70 6 * u * t * (Control2.Y - Control1.Y) + 71 3 * t * t * (End.Y - Control2.Y); 72 73 // Normalize 74 float len = (float)Math.Sqrt(dx * dx + dy * dy); 75 if (len > 0.001f) 76 { 77 dx /= len; 78 dy /= len; 79 } 80 81 return new PointF(dx, dy); 82 } 83 84 public Rectangle GetStartRect(int size) 85 { 86 return new Rectangle(Start.X - size / 2, Start.Y - size / 2, size, size); 87 } 88 89 public Rectangle GetEndRect(int size) 90 { 91 return new Rectangle(End.X - size / 2, End.Y - size / 2, size, size); 92 } 93 94 public Rectangle GetControl1Rect(int size) 95 { 96 return new Rectangle((int)Control1.X - size / 2, (int)Control1.Y - size / 2, size, size); 97 } 98 99 public Rectangle GetControl2Rect(int size) 100 { 101 return new Rectangle((int)Control2.X - size / 2, (int)Control2.Y - size / 2, size, size); 102 } 103 } 104}