using InABox.Core; using netDxf; using netDxf.Entities; using System; using System.Collections.Generic; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; namespace InABox.Dxf; internal interface IDxfObject { void Draw(DrawData data); RectangleF? GetBounds(TransformData data); } internal class DxfLine : IDxfObject { public Line Line { get; set; } public void Draw(DrawData data) { if (!data.Data.ShouldDraw(Line)) return; data.PushTransform(); //data.ArbitraryAxis(Line.Normal); data.Graphics.DrawLine( Color.Black, data.ConvertThickness((float)Line.Thickness), DrawData.ConvertPoint(Line.StartPoint), DrawData.ConvertPoint(Line.EndPoint)); data.PopTransform(); } public RectangleF? GetBounds(TransformData data) { if (!data.Data.ShouldDraw(Line)) return null; return Utils.RectangleFromPoints( data.TransformPoint(Line.StartPoint), data.TransformPoint(Line.EndPoint)); } } internal class DxfInsert : IDxfObject { public Insert Insert { get; set; } public List Objects { get; set; } public DxfInsert(Insert insert) { Insert = insert; Objects = insert.Block.Entities.Select(DxfUtils.ConvertEl).NotNull().ToList(); } public void Draw(DrawData data) { if (!data.Data.ShouldDraw(Insert)) return; // var transformation = Insert.GetTransformation(); // var translation = Insert.Position - transformation * Insert.Block.Origin; data.PushTransform(); data.Translate(new PointF((float)Insert.Position.X, (float)Insert.Position.Y)); data.ArbitraryAxis(Insert.Normal); data.Rotate((float)Insert.Rotation); data.Scale((float)Insert.Scale.X, (float)Insert.Scale.Y); foreach(var entity in Objects) { entity.Draw(data); } data.PopTransform(); // foreach(var entity in Insert.Explode()) // { // // var ent = entity.Clone() as EntityObject; // // ent.TransformBy(transformation, translation); // DxfUtils.ConvertEl(entity)?.Draw(data); // } // foreach(var obj in Insert.Explode()) // { // DxfUtils.ConvertEl(obj)?.Draw(data); // } } public RectangleF? GetBounds(TransformData data) { if (!data.Data.ShouldDraw(Insert)) return null; data.PushTransform(); data.Translate(new PointF((float)Insert.Position.X, (float)Insert.Position.Y)); data.ArbitraryAxis(Insert.Normal); data.Rotate((float)Insert.Rotation); data.Scale((float)Insert.Scale.X, (float)Insert.Scale.Y); var bounds = Utils.CombineBounds(Objects.Select(x => x.GetBounds(data))); data.PopTransform(); return bounds; } } internal class DxfEllipse : IDxfObject { public Ellipse Ellipse { get; set; } public DxfEllipse(Ellipse ellipse) { Ellipse = ellipse; } public void Draw(DrawData data) { if (!data.Data.ShouldDraw(Ellipse)) return; foreach(var obj in Ellipse.ToPolyline2D(100).Explode()) { DxfUtils.ConvertEl(obj)?.Draw(data); } // var center = DrawData.ConvertPoint(Ellipse.Center); // var size = new SizeF((float)Ellipse.MajorAxis, (float)Ellipse.MinorAxis); // var startAngle = (float)(Ellipse.StartAngle); // var endAngle = (float)(Ellipse.EndAngle); // data.Graphics.DrawArc(new Pen(Color.Black, data.ConvertThickness((float)Ellipse.Thickness)), center.X - size.Width / 2, center.Y - size.Height / 2, size.Width, size.Height, startAngle, Utils.Mod(endAngle - startAngle, 360)); } public RectangleF? GetBounds(TransformData data) { if (!data.Data.ShouldDraw(Ellipse)) return null; var halfSize = new netDxf.Vector3(Ellipse.MajorAxis / 2, Ellipse.MinorAxis / 2, 0); return Utils.RectangleFromPoints( data.TransformPoint(Ellipse.Center - halfSize), data.TransformPoint(Ellipse.Center + halfSize)); } } internal class DxfSolid : IDxfObject { public Solid Solid { get; set; } public DxfSolid(Solid solid) { Solid = solid; } public void Draw(DrawData data) { if (!data.Data.ShouldDraw(Solid)) return; var vertices = new Vector2[] { Solid.FirstVertex, Solid.SecondVertex, Solid.FourthVertex, // Apparently the third and fourth are the wrong way round, so I've mirrored that here. Solid.ThirdVertex }; data.Graphics.FillPolygon(Color.Black, vertices.ToArray(x => DrawData.ConvertPoint(x))); } public RectangleF? GetBounds(TransformData data) { if (!data.Data.ShouldDraw(Solid)) return null; var vertices = new Vector2[] { Solid.FirstVertex, Solid.SecondVertex, Solid.FourthVertex, // Apparently the third and fourth are the wrong way round, so I've mirrored that here. Solid.ThirdVertex }; return Utils.RectangleFromPoints( vertices.ToArray(data.TransformPoint)); } } internal class DxfPolyline2D : IDxfObject { public Polyline2D Polyline { get; set; } public DxfPolyline2D(Polyline2D polyline) { Polyline = polyline; } public void Draw(DrawData data) { if (!data.Data.ShouldDraw(Polyline)) return; var entities = Polyline.Explode(); foreach(var entity in entities) { DxfUtils.ConvertEl(entity)?.Draw(data); } // if(Polyline.SmoothType == PolylineSmoothType.NoSmooth) // { // var vertices = Polyline.Vertexes.ToArray(x => new PointF((float)x.Position.X, (float)x.Position.Y)); // if (Polyline.IsClosed) // { // data.Graphics.DrawPolygon( // new Pen(Color.Black, data.ConvertThickness((float)Polyline.Thickness)), // vertices); // } // else // { // data.Graphics.DrawLines( // new Pen(Color.Black, data.ConvertThickness((float)Polyline.Thickness)), // vertices); // } // } // else // { // } } public RectangleF? GetBounds(TransformData data) { if (!data.Data.ShouldDraw(Polyline)) return null; var entities = Polyline.Explode(); return Utils.CombineBounds(entities.Select(x => DxfUtils.ConvertEl(x)?.GetBounds(data))); } } internal class DxfMText : IDxfObject { public MText MText { get; set; } public DxfMText(MText text) { MText = text; } private Font GetFont() { FontFamily fontFamily; if (MText.Style.FontFamilyName.IsNullOrWhiteSpace()) { fontFamily = SystemFonts.DefaultFont.FontFamily; } else { fontFamily = new FontFamily(MText.Style.FontFamilyName); } return new Font(fontFamily, (float)MText.Height, MText.Style.FontStyle switch { netDxf.Tables.FontStyle.Bold => FontStyle.Bold, netDxf.Tables.FontStyle.Italic => FontStyle.Italic, netDxf.Tables.FontStyle.Regular or _ => FontStyle.Regular, }); } private string GetText() { return MText.PlainText().Replace("^M", ""); } private static Bitmap _placeholderBitmap = new Bitmap(1, 1); private void Transform(TransformData data, Font font, string text, Graphics g) { data.Translate(new PointF((float)MText.Position.X, (float)MText.Position.Y)); data.Rotate((float)MText.Rotation); data.Scale(1, -1); var size = g.MeasureString(text, font, new PointF(), StringFormat.GenericTypographic); switch (MText.AttachmentPoint) { case MTextAttachmentPoint.MiddleLeft: case MTextAttachmentPoint.MiddleCenter: case MTextAttachmentPoint.MiddleRight: data.Translate(new PointF(0, -size.Height / 2)); break; case MTextAttachmentPoint.BottomLeft: case MTextAttachmentPoint.BottomCenter: case MTextAttachmentPoint.BottomRight: data.Translate(new PointF(0, -size.Height)); break; default: var ascent = font.FontFamily.GetCellAscent(font.Style); var lineSpace = font.FontFamily.GetLineSpacing(font.Style); var baseline = ascent * font.Height / font.FontFamily.GetEmHeight(font.Style); var ratio = font.GetHeight(g) / lineSpace; data.Translate(new PointF(0, -baseline + ascent * ratio)); break; } switch (MText.AttachmentPoint) { case MTextAttachmentPoint.TopLeft: case MTextAttachmentPoint.MiddleLeft: case MTextAttachmentPoint.BottomLeft: break; case MTextAttachmentPoint.TopCenter: case MTextAttachmentPoint.MiddleCenter: case MTextAttachmentPoint.BottomCenter: data.Translate(new PointF(-(float)size.Width / 2, 0)); break; case MTextAttachmentPoint.TopRight: case MTextAttachmentPoint.MiddleRight: case MTextAttachmentPoint.BottomRight: data.Translate(new PointF(-(float)size.Width, 0)); break; } } public void Draw(DrawData data) { if (!data.Data.ShouldDraw(MText)) return; var text = GetText(); if (MText.Style.FontFamilyName.IsNullOrWhiteSpace()) { data.Graphics.SetFont((float)MText.Height, MText.Style.FontStyle switch { netDxf.Tables.FontStyle.Bold => FontStyle.Bold, netDxf.Tables.FontStyle.Italic => FontStyle.Italic, netDxf.Tables.FontStyle.Regular or _ => FontStyle.Regular, }); } else { data.Graphics.SetFont(MText.Style.FontFamilyName, (float)MText.Height, MText.Style.FontStyle switch { netDxf.Tables.FontStyle.Bold => FontStyle.Bold, netDxf.Tables.FontStyle.Italic => FontStyle.Italic, netDxf.Tables.FontStyle.Regular or _ => FontStyle.Regular, }); } data.PushTransform(); using var g = Graphics.FromImage(_placeholderBitmap); Transform(data, GetFont(), text, g); data.Graphics.DrawText(text, Color.Black, new PointF(0, 0)); data.PopTransform(); } public RectangleF? GetBounds(TransformData data) { if (!data.Data.ShouldDraw(MText)) return null; var font = GetFont(); var text = GetText(); data.PushTransform(); using var g = Graphics.FromImage(_placeholderBitmap); Transform(data, font, text, g); var size = g.MeasureString(text, font, new PointF(), StringFormat.GenericTypographic); var bounds = Utils.RectangleFromPoints( data.TransformPoint(0, 0), data.TransformPoint(size.Width, size.Height)); data.PopTransform(); return bounds; } } internal class DxfDimension : IDxfObject { public Dimension Dimension { get; set; } public List Objects { get; set; } public DxfDimension(Dimension dimension) { Dimension = dimension; if(Dimension.Block is null) { Objects = new(); } else { Objects = Dimension.Block.Entities.Select(DxfUtils.ConvertEl).NotNull().ToList(); } } public void Draw(DrawData data) { if (!data.Data.ShouldDraw(Dimension)) return; foreach(var entity in Objects) { entity.Draw(data); } } public RectangleF? GetBounds(TransformData data) { if (!data.Data.ShouldDraw(Dimension)) return null; return Utils.CombineBounds(Objects.Select(x => x.GetBounds(data))); } }