DimensionObject.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. using Avalonia;
  2. using Avalonia.Controls;
  3. using Avalonia.Controls.Primitives;
  4. using Avalonia.Controls.Shapes;
  5. using Avalonia.Input;
  6. using Avalonia.Media;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Text;
  11. using System.Threading.Tasks;
  12. using System.Xml;
  13. namespace InABox.Avalonia.Components.ImageEditing;
  14. internal class DimensionObject : IImageEditorObject
  15. {
  16. public IBrush? PrimaryBrush { get; set; }
  17. public Point Point1 { get; set; }
  18. public Point Point2 { get; set; }
  19. public double LineThickness { get; set; }
  20. public string Text { get; set; } = "";
  21. public double Offset { get; set; } = 10;
  22. public bool Complete { get; set; } = false;
  23. private Canvas Control = new();
  24. private Thumb? Thumb;
  25. private bool _active = true;
  26. public Control GetControl() => Control;
  27. private Vector GetMainVec()
  28. {
  29. var p1 = new Vector(Point1.X, Point1.Y);
  30. var p2 = new Vector(Point2.X, Point2.Y);
  31. var mainVec = p2 - p1;
  32. var length = mainVec.Length;
  33. if(length == 0)
  34. {
  35. mainVec = new Vector(0, 0);
  36. }
  37. else
  38. {
  39. mainVec /= length;
  40. }
  41. return mainVec;
  42. }
  43. private Vector GetPerpVec()
  44. {
  45. var mainVec = GetMainVec();
  46. return new Vector(mainVec.Y, -mainVec.X);
  47. }
  48. public void Update()
  49. {
  50. Control.Children.RemoveAll(Control.Children.Where(x => !(x is Thumb)));
  51. Point Point(Vector v) => new(v.X, v.Y);
  52. var p1 = new Vector(Point1.X, Point1.Y);
  53. var p2 = new Vector(Point2.X, Point2.Y);
  54. var mainVec = p2 - p1;
  55. var length = mainVec.Length;
  56. if(length == 0)
  57. {
  58. mainVec = new Vector(0, 0);
  59. }
  60. else
  61. {
  62. mainVec /= length;
  63. }
  64. var perpVec = new Vector(mainVec.Y, -mainVec.X);
  65. var arrowLength = LineThickness * 2;
  66. var offset = perpVec * Offset;
  67. var mainLines = new List<Line>()
  68. {
  69. new()
  70. {
  71. StartPoint = Point(p1 + offset),
  72. EndPoint = Point(p2 + offset),
  73. StrokeLineCap = PenLineCap.Round
  74. },
  75. new()
  76. {
  77. StartPoint = Point(p1 + offset),
  78. EndPoint = Point(p1 + mainVec * arrowLength + perpVec * arrowLength + offset),
  79. StrokeLineCap = PenLineCap.Square
  80. },
  81. new()
  82. {
  83. StartPoint = Point(p1 + offset),
  84. EndPoint = Point(p1 + mainVec * arrowLength - perpVec * arrowLength + offset),
  85. StrokeLineCap = PenLineCap.Square
  86. },
  87. new()
  88. {
  89. StartPoint = Point(p2 + offset),
  90. EndPoint = Point(p2 - mainVec * arrowLength + perpVec * arrowLength + offset),
  91. StrokeLineCap = PenLineCap.Square
  92. },
  93. new()
  94. {
  95. StartPoint = Point(p2 + offset),
  96. EndPoint = Point(p2 - mainVec * arrowLength - perpVec * arrowLength + offset),
  97. StrokeLineCap = PenLineCap.Square
  98. }
  99. };
  100. var dotLines = new List<Line>()
  101. {
  102. new()
  103. {
  104. StartPoint = Point(p1),
  105. EndPoint = Point(p1 + offset)
  106. },
  107. new()
  108. {
  109. StartPoint = Point(p2),
  110. EndPoint = Point(p2 + offset)
  111. },
  112. };
  113. foreach (var line in dotLines)
  114. {
  115. line.StrokeThickness = LineThickness;
  116. line.Stroke = PrimaryBrush;
  117. line.StrokeDashArray = [2, 2];
  118. Control.Children.Add(line);
  119. }
  120. foreach (var line in mainLines)
  121. {
  122. line.StrokeThickness = LineThickness;
  123. line.Stroke = PrimaryBrush;
  124. Control.Children.Add(line);
  125. }
  126. var textHeight = 20;
  127. var text = new TextBlock
  128. {
  129. Text = Text,
  130. FontSize = textHeight,
  131. TextAlignment = TextAlignment.Center,
  132. Width = length,
  133. Foreground = PrimaryBrush
  134. };
  135. text.RenderTransform = new RotateTransform(Math.Atan2(mainVec.Y, mainVec.X) * 180 / Math.PI);
  136. var textPos = p1 + offset + mainVec * length / 2 + perpVec * (textHeight / 2 + 5);
  137. Canvas.SetLeft(text, textPos.X - length / 2);
  138. Canvas.SetTop(text, textPos.Y - textHeight / 2);
  139. Control.Children.Add(text);
  140. if(Thumb is null && _active && length > 0)
  141. {
  142. Thumb = new();
  143. Thumb.Width = 10;
  144. Thumb.Height = 10;
  145. Thumb.Cursor = new(StandardCursorType.SizeAll);
  146. Thumb.DragDelta += Thumb_DragDelta;
  147. Thumb.ZIndex = 1;
  148. Control.Children.Add(Thumb);
  149. }
  150. if(Thumb is not null)
  151. {
  152. Thumb.RenderTransform = new RotateTransform(Math.Atan2(mainVec.Y, mainVec.X) * 180 / Math.PI);
  153. var thumbPos = p1 + offset + mainVec * length / 2;
  154. Canvas.SetLeft(Thumb, thumbPos.X - 5);
  155. Canvas.SetTop(Thumb, thumbPos.Y - 5);
  156. }
  157. }
  158. private Vector Rotate(Vector v, double angle)
  159. {
  160. angle = Math.Atan2(v.Y, v.X) + angle;
  161. var length = v.Length;
  162. return new Vector(
  163. length * Math.Cos(angle),
  164. length * Math.Sin(angle));
  165. }
  166. private void Thumb_DragDelta(object? sender, VectorEventArgs e)
  167. {
  168. var main = GetMainVec();
  169. var v = Vector.Dot(Rotate(e.Vector, Math.Atan2(main.Y, main.X)), GetPerpVec());
  170. Offset += v;
  171. Update();
  172. }
  173. public void SetActive(bool active)
  174. {
  175. _active = active;
  176. if(Thumb is not null)
  177. {
  178. Control.Children.Remove(Thumb);
  179. Thumb = null;
  180. }
  181. }
  182. }