DrawData.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. using netDxf;
  2. using netDxf.Tables;
  3. using Svg;
  4. using Svg.Transforms;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Drawing;
  8. using System.Drawing.Drawing2D;
  9. using System.Linq;
  10. using System.Numerics;
  11. using System.Text;
  12. using System.Threading.Tasks;
  13. using FontStyle = System.Drawing.FontStyle;
  14. using Vector2 = System.Numerics.Vector2;
  15. using Vector3 = System.Numerics.Vector3;
  16. using Vector4 = System.Numerics.Vector4;
  17. namespace InABox.Dxf;
  18. internal class TransformData
  19. {
  20. public DxfData Data { get; set; }
  21. private Stack<Matrix4x4> MatrixStack = new();
  22. public Matrix4x4 Transform { get; private set; } = Matrix4x4.Identity;
  23. public void PushTransform()
  24. {
  25. MatrixStack.Push(Transform);
  26. }
  27. protected virtual void UpdateTransform()
  28. {
  29. }
  30. protected Matrix ProjectMatrix(Matrix4x4 matrix)
  31. {
  32. var elMatrix = new Matrix3x2();
  33. elMatrix.M11 = (float)matrix.M11;
  34. elMatrix.M12 = (float)matrix.M12;
  35. elMatrix.M21 = (float)matrix.M21;
  36. elMatrix.M22 = (float)matrix.M22;
  37. elMatrix.M31 = (float)matrix.M41;
  38. elMatrix.M32 = (float)matrix.M42;
  39. var newMatrix = new Matrix();
  40. newMatrix.MatrixElements = elMatrix;
  41. return newMatrix;
  42. }
  43. public void PopTransform()
  44. {
  45. Transform = MatrixStack.Pop();
  46. UpdateTransform();
  47. }
  48. public static Matrix4x4 ArbitraryAxisMatrix(Vector3 zAxis)
  49. {
  50. if (zAxis.Equals(Vector3.UnitZ))
  51. {
  52. return Matrix4x4.Identity;
  53. }
  54. var unitY = Vector3.UnitY;
  55. var unitZ = Vector3.UnitZ;
  56. var v = ((!(Math.Abs(zAxis.X) < 1.0 / 64.0) || !(Math.Abs(zAxis.Y) < 1.0 / 64.0)) ? Vector3.Cross(unitZ, zAxis) : Vector3.Cross(unitY, zAxis));
  57. v = Vector3.Normalize(v);
  58. var vector = Vector3.Cross(zAxis, v);
  59. vector = Vector3.Normalize(vector);
  60. return new Matrix4x4(v.X, vector.X, zAxis.X, 0, v.Y, vector.Y, zAxis.Y, 0, v.Z, vector.Z, zAxis.Z, 0, 0, 0, 0, 1);
  61. }
  62. public void ArbitraryAxis(netDxf.Vector3 zAxis)
  63. {
  64. Transform = ArbitraryAxisMatrix(new((float)zAxis.X, (float)zAxis.Y, (float)zAxis.Z)) * Transform;
  65. UpdateTransform();
  66. }
  67. public void ArbitraryAxis(Vector3 zAxis)
  68. {
  69. Transform = ArbitraryAxisMatrix(zAxis) * Transform;
  70. UpdateTransform();
  71. }
  72. public void Translate(float x, float y)
  73. {
  74. Transform = Transform.Translate(x, y, 0);
  75. UpdateTransform();
  76. }
  77. public void Translate(PointF point)
  78. {
  79. Transform = Transform.Translate(point.X, point.Y, 0);
  80. UpdateTransform();
  81. }
  82. public void Rotate(float angle)
  83. {
  84. Transform = Transform.Rotate(0, 0, 1, angle);
  85. UpdateTransform();
  86. }
  87. public void Scale(float scale)
  88. {
  89. Scale(scale, scale);
  90. }
  91. public void Scale(float scaleX, float scaleY)
  92. {
  93. Transform = Transform.Scale(scaleX, scaleY, 1);
  94. UpdateTransform();
  95. }
  96. public float ConvertThickness(float thickness)
  97. {
  98. return thickness == 0 ? 1f / ScaleFactor() : thickness;
  99. }
  100. public PointF TransformPoint(float x, float y)
  101. {
  102. var nVec = Vector4.Transform(new Vector4(x, y, 0, 1), Transform);
  103. return new(nVec.X, nVec.Y);
  104. }
  105. public PointF TransformPoint(PointF vec)
  106. {
  107. var nVec = Vector4.Transform(new Vector4(vec.X, vec.Y, 0, 1), Transform);
  108. return new(nVec.X, nVec.Y);
  109. }
  110. public PointF TransformPoint(netDxf.Vector2 vec)
  111. {
  112. var nVec = Vector4.Transform(new Vector4((float)vec.X, (float)vec.Y, 0, 1), Transform);
  113. return new(nVec.X, nVec.Y);
  114. }
  115. public PointF TransformPoint(netDxf.Vector3 vec)
  116. {
  117. var nVec = Vector4.Transform(new Vector4((float)vec.X, (float)vec.Y, (float)vec.Z, 1), Transform);
  118. return new(nVec.X, nVec.Y);
  119. }
  120. public PointF TransformVec(PointF vec)
  121. {
  122. var nVec = Vector4.Transform(new Vector4(vec.X, vec.Y, 0, 0), Transform);
  123. return new(nVec.X, nVec.Y);
  124. }
  125. public Vector2 TransformVec(Vector2 vec)
  126. {
  127. var nVec = Vector4.Transform(new Vector4(vec.X, vec.Y, 0, 0), Transform);
  128. return new(nVec.X, nVec.Y);
  129. }
  130. public float ScaleFactor()
  131. {
  132. return (TransformVec(new Vector2(1, 0))).Length();
  133. }
  134. public static PointF ConvertPoint(netDxf.Vector2 vec)
  135. {
  136. return new PointF((float)vec.X, (float)vec.Y);
  137. }
  138. public static PointF ConvertPoint(netDxf.Vector3 vec)
  139. {
  140. return new PointF((float)vec.X, (float)vec.Y);
  141. }
  142. }
  143. internal class DrawData : TransformData
  144. {
  145. public IGraphics Graphics { get; set; }
  146. protected override void UpdateTransform()
  147. {
  148. base.UpdateTransform();
  149. Graphics.SetTransform(ProjectMatrix(Transform));
  150. }
  151. }
  152. public interface IGraphics
  153. {
  154. void SetTransform(Matrix transform);
  155. void DrawLine(Color color, float thickness, params PointF[] points);
  156. void FillPolygon(Color color, params PointF[] points);
  157. /// <summary>
  158. /// Set the current font to be the default font at the given <paramref name="fontSize"/>.
  159. /// </summary>
  160. /// <param name="fontSize">Size of the new font.</param>
  161. void SetFont(float fontSize, FontStyle fontStyle = FontStyle.Regular);
  162. void SetFont(string fontName, float fontSize, FontStyle fontStyle = FontStyle.Regular);
  163. void DrawText(string text, Color color, PointF position);
  164. void Clear(Color color);
  165. }
  166. public class GdiGraphics : IGraphics
  167. {
  168. public Graphics Graphics { get; set; }
  169. private Font Font { get; set; }
  170. public GdiGraphics(Graphics graphics)
  171. {
  172. Graphics = graphics;
  173. }
  174. public void DrawLine(Color color, float thickness, params PointF[] points)
  175. {
  176. if(points.Length == 2)
  177. {
  178. Graphics.DrawLine(new Pen(color, thickness), points[0], points[1]);
  179. }
  180. else
  181. {
  182. Graphics.DrawLines(new Pen(color, thickness), points);
  183. }
  184. }
  185. public void DrawText(string text, Color color, PointF position)
  186. {
  187. Graphics.DrawString(text, Font, new SolidBrush(color), position, StringFormat.GenericTypographic);
  188. }
  189. public void FillPolygon(Color color, params PointF[] points)
  190. {
  191. Graphics.FillPolygon(new SolidBrush(color), points);
  192. }
  193. public void SetFont(string fontName, float fontSize, FontStyle fontStyle)
  194. {
  195. var fontFamily = new FontFamily(fontName);
  196. var font = new Font(fontFamily, fontSize, fontStyle);
  197. Font = font;
  198. }
  199. public void SetFont(float fontSize, FontStyle fontStyle)
  200. {
  201. var fontFamily = SystemFonts.DefaultFont.FontFamily;
  202. var font = new Font(fontFamily, fontSize, fontStyle);
  203. Font = font;
  204. }
  205. public void SetTransform(Matrix transform)
  206. {
  207. Graphics.Transform = transform;
  208. }
  209. public void Clear(Color color)
  210. {
  211. Graphics.Clear(color);
  212. }
  213. }
  214. public class SvgGraphics : IGraphics
  215. {
  216. public SvgDocument Document { get; set; }
  217. private SvgMatrix _transform;
  218. private SvgGroup _group;
  219. public SvgGraphics(SvgDocument document)
  220. {
  221. Document = document;
  222. _group = new SvgGroup();
  223. }
  224. public void SetTransform(Matrix transform)
  225. {
  226. _transform = new(transform.Elements.ToList());
  227. }
  228. public void DrawLine(Color color, float thickness, params PointF[] points)
  229. {
  230. if(points.Length == 2)
  231. {
  232. Document.Children.Add(new SvgLine
  233. {
  234. StartX = points[0].X,
  235. StartY = points[0].Y,
  236. EndX = points[1].X,
  237. EndY = points[1].Y,
  238. Transforms = new()
  239. {
  240. _transform
  241. },
  242. Stroke = new SvgColourServer(color),
  243. StrokeWidth = thickness
  244. });
  245. }
  246. else
  247. {
  248. var line = new SvgPolyline
  249. {
  250. Transforms = new()
  251. {
  252. _transform
  253. },
  254. Stroke = new SvgColourServer(color),
  255. StrokeWidth = thickness
  256. };
  257. foreach(var point in points)
  258. {
  259. line.Points.Add(point.X);
  260. line.Points.Add(point.Y);
  261. }
  262. Document.Children.Add(line);
  263. }
  264. }
  265. public void FillPolygon(Color color, params PointF[] points)
  266. {
  267. }
  268. public void SetFont(float fontSize, FontStyle fontStyle = FontStyle.Regular)
  269. {
  270. }
  271. public void SetFont(string fontName, float fontSize, FontStyle fontStyle = FontStyle.Regular)
  272. {
  273. }
  274. public void DrawText(string text, Color color, PointF position)
  275. {
  276. }
  277. public void Clear(Color color)
  278. {
  279. }
  280. }