DxfUtils.cs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. using System.Drawing;
  2. using System.Drawing.Drawing2D;
  3. using System.Security.Cryptography.X509Certificates;
  4. using netDxf;
  5. using netDxf.Entities;
  6. using Point = System.Drawing.Point;
  7. namespace InABox.Dxf
  8. {
  9. public static class DxfUtils
  10. {
  11. public static event ProcessError OnProcessError;
  12. // Draw a rotated string at a particular position.
  13. private static void DrawRotatedTextAt(Graphics gr, float angle,
  14. string txt, float x, float y, Font the_font, Brush the_brush)
  15. {
  16. // Save the graphics state.
  17. var state = gr.Save();
  18. gr.ResetTransform();
  19. // Rotate.
  20. gr.RotateTransform(angle);
  21. // Translate to desired position. Be sure to append
  22. // the rotation so it occurs after the rotation.
  23. gr.TranslateTransform(x, y, MatrixOrder.Append);
  24. // Draw the text at the origin.
  25. gr.DrawString(txt, the_font, the_brush, 0, 0);
  26. // Restore the graphics state.
  27. gr.Restore(state);
  28. }
  29. private static void CheckPoints(double x, double y, ref double minX, ref double minY, ref double maxX, ref double maxY)
  30. {
  31. minX = x < minX ? x : minX;
  32. minY = y < minY ? y : minY;
  33. maxX = x > maxX ? x : maxX;
  34. maxY = y > maxY ? y : maxY;
  35. }
  36. private static float Scale(int value, float offset, double scale, int border)
  37. {
  38. return (value - offset) * (float)scale + border;
  39. }
  40. private static float Scale(double value, float offset, int scale, int border)
  41. {
  42. return ((float)value - offset) * scale + border;
  43. }
  44. private static PointF VectorToPointF(Vector3 vector, PointF offset, int scale, Point border)
  45. {
  46. return new PointF(Scale(vector.X, offset.X, scale, border.X), Scale(vector.Y, offset.Y, scale, border.Y));
  47. }
  48. private static PointF VectorToPointF(Vector2 vector, PointF offset, int scale, Point border)
  49. {
  50. return new PointF(Scale(vector.X, offset.X, scale, border.X), Scale(vector.Y, offset.Y, scale, border.Y));
  51. }
  52. public delegate void ProcessError(string message);
  53. public static Bitmap ProcessImage(Stream stream, string caption)
  54. {
  55. var minX = double.MaxValue;
  56. var minY = double.MaxValue;
  57. var maxX = double.MinValue;
  58. var maxY = double.MinValue;
  59. var document = DxfDocument.Load(stream);
  60. // Lets Explode all the various bits into their component atoms
  61. // (i.e. everything is gonna be a line)
  62. var lines = new List<Line>();
  63. lines.AddRange(document.Lines);
  64. foreach (var polyline in document.LwPolylines)
  65. {
  66. var components = polyline.Explode();
  67. lines.AddRange(components.Where(x => x is Line).Select(x => x as Line));
  68. foreach (Arc arc in components.Where(x => x is Arc))
  69. ArcToLines(lines, arc);
  70. }
  71. foreach (var polyline in document.Polylines)
  72. {
  73. var components = polyline.Explode();
  74. lines.AddRange(components.Where(x => x is Line).Select(x => x as Line));
  75. foreach (Arc arc in components.Where(x => x is Arc))
  76. ArcToLines(lines, arc);
  77. }
  78. foreach (var arc in document.Arcs)
  79. ArcToLines(lines, arc);
  80. foreach (var ellipse in document.Ellipses)
  81. {
  82. var precision = (int)((ellipse.MajorAxis + ellipse.MinorAxis) * 2.0F * Math.PI);
  83. var polyline = ellipse.ToPolyline(precision);
  84. var segments = polyline.Explode();
  85. lines.AddRange(segments.Select(x => x as Line));
  86. }
  87. if (!lines.Any())
  88. throw new Exception(string.Format("No Data Found in {0}!", caption));
  89. foreach (var line in lines)
  90. {
  91. CheckPoints(line.StartPoint.X, line.StartPoint.Y, ref minX, ref minY, ref maxX, ref maxY);
  92. CheckPoints(line.EndPoint.X, line.EndPoint.Y, ref minX, ref minY, ref maxX, ref maxY);
  93. }
  94. var height = (int)Math.Abs(maxY - minY);
  95. var width = (int)Math.Abs(maxX - minX);
  96. var scale = 15;
  97. var margin = 100;
  98. var offset = new PointF((float)minX, (float)minY);
  99. var border = new Point(margin, margin);
  100. var result = new Bitmap(width * scale + margin * 2, height * scale + margin * 2);
  101. var pen = new Pen(new SolidBrush(Color.Black), 3.0F);
  102. using (var g = Graphics.FromImage(result))
  103. {
  104. Brush bg = new SolidBrush(Color.White);
  105. g.FillRectangle(bg, 0, 0, result.Width, result.Height);
  106. foreach (var line in lines)
  107. {
  108. var start = VectorToPointF(line.StartPoint, offset, scale, border);
  109. var end = VectorToPointF(line.EndPoint, offset, scale, border);
  110. g.DrawLine(pen, start, end);
  111. }
  112. var font = new Font("Arial", 20.0F);
  113. var brush = new SolidBrush(Color.Blue);
  114. pen = new Pen(brush);
  115. var crect = g.MeasureString(caption, font);
  116. g.DrawString(caption, font, brush, new PointF(result.Width / 2.0F - crect.Width / 2.0F, 10));
  117. var heightrect = g.MeasureString(height.ToString(), font);
  118. g.DrawLine(pen, new PointF(result.Width - (heightrect.Height + 10.0F), 100), new PointF(result.Width - 30, 100));
  119. g.DrawLine(pen, new PointF(result.Width - (heightrect.Height + 10.0F), result.Height - 100),
  120. new PointF(result.Width - 30, result.Height - 100));
  121. g.DrawLine(pen, new PointF(result.Width - (20.0F + heightrect.Height / 2.0F), 105),
  122. new PointF(result.Width - (20.0F + heightrect.Height / 2.0F), result.Height - 105));
  123. var aX = result.Width - (20.0F + heightrect.Height / 2.0F);
  124. float aY = 105;
  125. g.FillPolygon(brush, new[]
  126. {
  127. new(aX, aY),
  128. new PointF(aX - 10.0F, aY + 10.0F),
  129. new PointF(aX + 10.0F, aY + 10.0F)
  130. });
  131. aY = result.Height - 105;
  132. g.FillPolygon(brush, new[]
  133. {
  134. new(aX, aY),
  135. new PointF(aX - 10.0F, aY - 10.0F),
  136. new PointF(aX + 10.0F, aY - 10.0F)
  137. });
  138. g.FillRectangle(bg, result.Width - (heightrect.Height + 15.0F), result.Height / 2.0F - heightrect.Width / 2.0F, heightrect.Height,
  139. heightrect.Width);
  140. DrawRotatedTextAt(g, 270.0F, height.ToString(), result.Width - (heightrect.Height + 15.0F),
  141. result.Height / 2.0F + heightrect.Width / 2.0F, font, brush);
  142. var widthrect = g.MeasureString(width.ToString(), font);
  143. g.DrawLine(pen, new PointF(100, result.Height - (widthrect.Height + 10.0F)), new PointF(100, result.Height - 30));
  144. g.DrawLine(pen, new PointF(result.Width - 100, result.Height - (widthrect.Height + 10.0F)),
  145. new PointF(result.Width - 100, result.Height - 30));
  146. g.DrawLine(pen, new PointF(105, result.Height - (20.0F + widthrect.Height / 2.0F)),
  147. new PointF(result.Width - 105, result.Height - (20.0F + widthrect.Height / 2.0F)));
  148. aX = 105;
  149. aY = result.Height - (20.0F + widthrect.Height / 2.0F);
  150. g.FillPolygon(brush, new[]
  151. {
  152. new(aX, aY),
  153. new PointF(aX + 10.0F, aY - 10.0F),
  154. new PointF(aX + 10.0F, aY + 10.0F)
  155. });
  156. aX = result.Width - 105;
  157. g.FillPolygon(brush, new[]
  158. {
  159. new(aX, aY),
  160. new PointF(aX - 10.0F, aY - 10.0F),
  161. new PointF(aX - 10.0F, aY + 10.0F)
  162. });
  163. g.FillRectangle(bg, result.Width / 2.0F - widthrect.Width / 2.0F, result.Height - (widthrect.Height + 15.0F), widthrect.Width,
  164. widthrect.Height);
  165. g.DrawString(width.ToString(), font, brush,
  166. new PointF(result.Width / 2.0F - widthrect.Width / 2.0F, result.Height - (widthrect.Height + 15.0F)));
  167. }
  168. return result;
  169. }
  170. private static void ArcToLines(List<Line> lines, Arc arc)
  171. {
  172. var precision = Math.Max(2, (int)(arc.Radius * 2.0F * Math.PI));
  173. var polyline = arc.ToPolyline(precision);
  174. var segments = polyline.Explode();
  175. lines.AddRange(segments.Select(x => x as Line));
  176. }
  177. public static Bitmap DXFToBitmap(string filename)
  178. {
  179. Bitmap result = null;
  180. using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read))
  181. {
  182. try
  183. {
  184. result = ProcessImage(stream, Path.GetFileNameWithoutExtension(filename));
  185. }
  186. catch (Exception e)
  187. {
  188. result = null;
  189. OnProcessError?.Invoke(e.Message);
  190. }
  191. }
  192. return result;
  193. }
  194. }
  195. }