using System.Drawing; using System.Drawing.Drawing2D; using InABox.Core; using netDxf; using netDxf.Entities; using netDxf.Objects; using netDxf.Tables; using Point = System.Drawing.Point; namespace InABox.Dxf; public class DxfImportSettings { public Size ImageSize; public string[]? SupportFolders; public string? LayoutName { get; set; } public DxfImportSettings(Size? imageSize = null, string[]? supportFolders = null, string? layoutName = null) { ImageSize = imageSize ?? new(2048, 2048); SupportFolders = supportFolders; LayoutName = layoutName; } } public class DxfData { public DxfDocument Document { get; set; } public DxfImportSettings Settings { get; set; } public SizeF Size { get; set; } public PointF Origin { get; set; } public Layout Layout { get; set; } public IEnumerable LayoutNames => Document.Layouts.Select(x => x.Name); public HashSet? Layers { get; set; } public bool HasLayer(Layer layer) { return Layers is null || Layers.Contains(layer.Name); } public void SetLayers(params string[] layers) { Layers = layers.ToHashSet(); } public void SetLayers(IEnumerable layers) { Layers = layers.ToHashSet(); } public string LayoutName { get => Layout.Name; set { Layout = Document.Layouts.First(x => x.Name == value); Size = new((float)(Layout.MaxLimit.X - Layout.MinLimit.X), (float)(Layout.MaxLimit.Y - Layout.MinLimit.Y)); Origin = new((float)Layout.MinLimit.X, (float)Layout.MinLimit.Y); } } public DxfData(DxfDocument document, DxfImportSettings settings) { Document = document; Settings = settings; Layout = settings.LayoutName is not null ? document.Layouts.First(x => x.Name == settings.LayoutName) : document.Layouts.First(); Size = new((float)(Layout.MaxLimit.X - Layout.MinLimit.X), (float)(Layout.MaxLimit.Y - Layout.MinLimit.Y)); Origin = new((float)Layout.MinLimit.X, (float)Layout.MinLimit.Y); } } public static class DxfUtils { public static event ProcessError OnProcessError; public delegate void ProcessError(string message); internal static IDxfObject? ConvertEl(EntityObject el) { if(el is Line line) { return new DxfLine { Line = line }; } else if(el is Insert insert) { return new DxfInsert(insert); } else if(el is Ellipse ellipse) { return new DxfEllipse(ellipse); } else if(el is MText text) { return new DxfMText(text); } else if(el is Polyline2D ln2D) { return new DxfPolyline2D(ln2D); } else if(el is Dimension dim) { return new DxfDimension(dim); } else if(el is Solid solid) { return new DxfSolid(solid); } else if (el is netDxf.Entities.Point point) { return null; } else { return null; } } public static void DrawDxf(DxfData data, Graphics graphics) { // Calculate the scaling factor to fit the image within the bounds float ratioX = (float)data.Settings.ImageSize.Width / data.Size.Width; float ratioY = (float)data.Settings.ImageSize.Height / data.Size.Height; var scale = Math.Min(ratioX, ratioY); var drawData = new DrawData() { Graphics = graphics, Data = data }; Brush _brush = new SolidBrush(Color.White); graphics.FillRectangle(_brush, 0, 0, graphics.VisibleClipBounds.Width, graphics.VisibleClipBounds.Height); drawData.Translate(graphics.VisibleClipBounds.Width / 2, graphics.VisibleClipBounds.Height / 2); drawData.Scale(scale, scale); drawData.Translate(-data.Origin.X - data.Size.Width / 2, -data.Origin.Y - data.Size.Height / 2); foreach(var el in data.Document.Entities.All) { var item = ConvertEl(el); item?.Draw(drawData); } } public static DxfData LoadDxf(string filename, DxfImportSettings? settings = null) { using var stream = new FileStream(filename, FileMode.Open, FileAccess.Read); settings ??= new(); var document = DxfDocument.Load(stream, settings.SupportFolders ?? Array.Empty()); document.BuildDimensionBlocks = true; return new(document, settings); } public static DxfData LoadDxf(Stream stream, DxfImportSettings? settings = null) { settings ??= new(); var document = DxfDocument.Load(stream, settings.SupportFolders ?? Array.Empty()); return new(document, settings); } public static Bitmap ProcessImage(DxfData data) { var height = data.Size.Height; var width = data.Size.Width; // Calculate the scaling factor to fit the image within the bounds float ratioX = (float)data.Settings.ImageSize.Width / width; float ratioY = (float)data.Settings.ImageSize.Height / height; var scale = Math.Min(ratioX, ratioY); var margin = 100; var _result = new Bitmap((int)(width * scale) + (margin * 2), (int)(height * scale) + (margin * 2)); using (var _graphics = Graphics.FromImage(_result)) { _graphics.SmoothingMode = SmoothingMode.AntiAlias; DrawDxf(data, _graphics); } _result.RotateFlip(RotateFlipType.RotateNoneFlipY); return _result; } public static Bitmap ProcessImage(Stream stream, DxfImportSettings? settings = null) { return ProcessImage(LoadDxf(stream, settings)); } public static Result DXFToBitmap(string filename, DxfImportSettings? settings = null) { using var stream = new FileStream(filename, FileMode.Open, FileAccess.Read); try { return Result.Ok(ProcessImage(stream, settings: settings)); } catch (Exception e) { OnProcessError?.Invoke(e.Message); return Result.Error(e); } } }