using System.Drawing; using System.Drawing.Drawing2D; using netDxf; using netDxf.Entities; using Point = System.Drawing.Point; namespace InABox.Dxf { public static class DxfUtils { // Draw a rotated string at a particular position. private static void DrawRotatedTextAt(Graphics gr, float angle, string txt, float x, float y, Font the_font, Brush the_brush) { // Save the graphics state. var state = gr.Save(); gr.ResetTransform(); // Rotate. gr.RotateTransform(angle); // Translate to desired position. Be sure to append // the rotation so it occurs after the rotation. gr.TranslateTransform(x, y, MatrixOrder.Append); // Draw the text at the origin. gr.DrawString(txt, the_font, the_brush, 0, 0); // Restore the graphics state. gr.Restore(state); } private static void CheckPoints(double x, double y, ref double minX, ref double minY, ref double maxX, ref double maxY) { minX = x < minX ? x : minX; minY = y < minY ? y : minY; maxX = x > maxX ? x : maxX; maxY = y > maxY ? y : maxY; } private static float Scale(int value, float offset, double scale, int border) { return (value - offset) * (float)scale + border; } private static float Scale(double value, float offset, int scale, int border) { return ((float)value - offset) * scale + border; } private static PointF VectorToPointF(Vector3 vector, PointF offset, int scale, Point border) { return new PointF(Scale(vector.X, offset.X, scale, border.X), Scale(vector.Y, offset.Y, scale, border.Y)); } private static PointF VectorToPointF(Vector2 vector, PointF offset, int scale, Point border) { return new PointF(Scale(vector.X, offset.X, scale, border.X), Scale(vector.Y, offset.Y, scale, border.Y)); } public static Bitmap ProcessImage(Stream stream, string caption) { var minX = double.MaxValue; var minY = double.MaxValue; var maxX = double.MinValue; var maxY = double.MinValue; var document = DxfDocument.Load(stream); // Lets Explode all the various bits into their component atoms // (i.e. everything is gonna be a line) var lines = new List(); lines.AddRange(document.Lines); foreach (var polyline in document.LwPolylines) { var components = polyline.Explode(); lines.AddRange(components.Where(x => x is Line).Select(x => x as Line)); foreach (Arc arc in components.Where(x => x is Arc)) ArcToLines(lines, arc); } foreach (var polyline in document.Polylines) { var components = polyline.Explode(); lines.AddRange(components.Where(x => x is Line).Select(x => x as Line)); foreach (Arc arc in components.Where(x => x is Arc)) ArcToLines(lines, arc); } foreach (var arc in document.Arcs) ArcToLines(lines, arc); foreach (var ellipse in document.Ellipses) { var precision = (int)((ellipse.MajorAxis + ellipse.MinorAxis) * 2.0F * Math.PI); var polyline = ellipse.ToPolyline(precision); var segments = polyline.Explode(); lines.AddRange(segments.Select(x => x as Line)); } if (!lines.Any()) throw new Exception(string.Format("No Data Found in {0}!", caption)); foreach (var line in lines) { CheckPoints(line.StartPoint.X, line.StartPoint.Y, ref minX, ref minY, ref maxX, ref maxY); CheckPoints(line.EndPoint.X, line.EndPoint.Y, ref minX, ref minY, ref maxX, ref maxY); } var height = (int)Math.Abs(maxY - minY); var width = (int)Math.Abs(maxX - minX); var scale = 15; var margin = 100; var offset = new PointF((float)minX, (float)minY); var border = new Point(margin, margin); var result = new Bitmap(width * scale + margin * 2, height * scale + margin * 2); var pen = new Pen(new SolidBrush(Color.Black), 3.0F); using (var g = Graphics.FromImage(result)) { Brush bg = new SolidBrush(Color.White); g.FillRectangle(bg, 0, 0, result.Width, result.Height); foreach (var line in lines) { var start = VectorToPointF(line.StartPoint, offset, scale, border); var end = VectorToPointF(line.EndPoint, offset, scale, border); g.DrawLine(pen, start, end); } var font = new Font("Arial", 20.0F); var brush = new SolidBrush(Color.Blue); pen = new Pen(brush); var crect = g.MeasureString(caption, font); g.DrawString(caption, font, brush, new PointF(result.Width / 2.0F - crect.Width / 2.0F, 10)); var heightrect = g.MeasureString(height.ToString(), font); g.DrawLine(pen, new PointF(result.Width - (heightrect.Height + 10.0F), 100), new PointF(result.Width - 30, 100)); g.DrawLine(pen, new PointF(result.Width - (heightrect.Height + 10.0F), result.Height - 100), new PointF(result.Width - 30, result.Height - 100)); g.DrawLine(pen, new PointF(result.Width - (20.0F + heightrect.Height / 2.0F), 105), new PointF(result.Width - (20.0F + heightrect.Height / 2.0F), result.Height - 105)); var aX = result.Width - (20.0F + heightrect.Height / 2.0F); float aY = 105; g.FillPolygon(brush, new[] { new(aX, aY), new PointF(aX - 10.0F, aY + 10.0F), new PointF(aX + 10.0F, aY + 10.0F) }); aY = result.Height - 105; g.FillPolygon(brush, new[] { new(aX, aY), new PointF(aX - 10.0F, aY - 10.0F), new PointF(aX + 10.0F, aY - 10.0F) }); g.FillRectangle(bg, result.Width - (heightrect.Height + 15.0F), result.Height / 2.0F - heightrect.Width / 2.0F, heightrect.Height, heightrect.Width); DrawRotatedTextAt(g, 270.0F, height.ToString(), result.Width - (heightrect.Height + 15.0F), result.Height / 2.0F + heightrect.Width / 2.0F, font, brush); var widthrect = g.MeasureString(width.ToString(), font); g.DrawLine(pen, new PointF(100, result.Height - (widthrect.Height + 10.0F)), new PointF(100, result.Height - 30)); g.DrawLine(pen, new PointF(result.Width - 100, result.Height - (widthrect.Height + 10.0F)), new PointF(result.Width - 100, result.Height - 30)); g.DrawLine(pen, new PointF(105, result.Height - (20.0F + widthrect.Height / 2.0F)), new PointF(result.Width - 105, result.Height - (20.0F + widthrect.Height / 2.0F))); aX = 105; aY = result.Height - (20.0F + widthrect.Height / 2.0F); g.FillPolygon(brush, new[] { new(aX, aY), new PointF(aX + 10.0F, aY - 10.0F), new PointF(aX + 10.0F, aY + 10.0F) }); aX = result.Width - 105; g.FillPolygon(brush, new[] { new(aX, aY), new PointF(aX - 10.0F, aY - 10.0F), new PointF(aX - 10.0F, aY + 10.0F) }); g.FillRectangle(bg, result.Width / 2.0F - widthrect.Width / 2.0F, result.Height - (widthrect.Height + 15.0F), widthrect.Width, widthrect.Height); g.DrawString(width.ToString(), font, brush, new PointF(result.Width / 2.0F - widthrect.Width / 2.0F, result.Height - (widthrect.Height + 15.0F))); } return result; } private static void ArcToLines(List lines, Arc arc) { var precision = Math.Max(2, (int)(arc.Radius * 2.0F * Math.PI)); var polyline = arc.ToPolyline(precision); var segments = polyline.Explode(); lines.AddRange(segments.Select(x => x as Line)); } public static Bitmap DXFToBitmap(string filename) { Bitmap result = null; using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read)) { try { result = ProcessImage(stream, Path.GetFileNameWithoutExtension(filename)); } catch (Exception e) { result = null; } } return result; } } }