Pārlūkot izejas kodu

Improved Dxf, Image and Converter utilities

frogsoftware 10 mēneši atpakaļ
vecāks
revīzija
51c40fb7c3

+ 229 - 104
inabox.dxf/DxfUtils.cs

@@ -45,12 +45,12 @@ namespace InABox.Dxf
             return (value - offset) * (float)scale + border;
         }
 
-        private static float Scale(double value, float offset, int scale, int border)
+        private static float Scale(double value, float offset, double scale, int border)
         {
-            return ((float)value - offset) * scale + border;
+            return ((float)value - offset) * (float)scale + border;
         }
 
-        private static PointF VectorToPointF(Vector3 vector, PointF offset, int scale, Point border)
+        private static PointF VectorToPointF(Vector3 vector, PointF offset, float scale, Point border)
         {
             return new PointF(Scale(vector.X, offset.X, scale, border.X), Scale(vector.Y, offset.Y, scale, border.Y));
         }
@@ -62,7 +62,7 @@ namespace InABox.Dxf
 
         public delegate void ProcessError(string message);
 
-        public static Bitmap ProcessImage(Stream stream, string caption)
+        public static Bitmap ProcessImage(Stream stream, string caption = null, bool dimensionmarks = true)
         {         
             var minX = double.MaxValue;
             var minY = double.MaxValue;
@@ -73,39 +73,13 @@ namespace InABox.Dxf
 
             // Lets Explode all the various bits into their component atoms 
             // (i.e. everything is gonna be a line)
-            var lines = new List<Line>();
-            lines.AddRange(document.Entities.Lines);
-            foreach (var polyline in document.Entities.Polylines2D)
-            {
-                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.Entities.Polylines2D)
-            {
-                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.Entities.Arcs)
-                ArcToLines(lines, arc);
+            List<EntityObject> objects = new();
+            ProcessEntities(document.Entities.All, objects, new Vector3());
 
-            foreach (var ellipse in document.Entities.Ellipses)
-            {
-                var precision = (int)((ellipse.MajorAxis + ellipse.MinorAxis) * 2.0F * Math.PI);
-                var polyline = ellipse.ToPolyline2D(precision);
-                var segments = polyline.Explode();
-                lines.AddRange(segments.Select(x => x as Line));
-            }
-
-            if (!lines.Any())
+            if (!objects.Any())
                 throw new Exception(string.Format("No Data Found in {0}!", caption));
 
-            foreach (var line in lines)
+            foreach (var line in objects.OfType<Line>())
             {
                 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);
@@ -113,100 +87,251 @@ namespace InABox.Dxf
 
             var height = (int)Math.Abs(maxY - minY);
             var width = (int)Math.Abs(maxX - minX);
+            
+            // Calculate the scaling factor to fit the image within the bounds
+            float ratioX = (float)2048 / height;
+            float ratioY = (float)2048 / width;
 
-            var scale = 15;
+            var scale = Math.Min(ratioX, ratioY);
             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))
+            var _result = new Bitmap((int)(width * scale) + (margin * 2), (int)(height * scale) + (margin * 2));
+            var _pen = new Pen(new SolidBrush(Color.Black), 3.0F);
+            using (var _graphics = Graphics.FromImage(_result))
             {
-                Brush bg = new SolidBrush(Color.White);
-                g.FillRectangle(bg, 0, 0, result.Width, result.Height);
+                
+                Brush _brush = new SolidBrush(Color.White);
+                _graphics.FillRectangle(_brush, 0, 0, _result.Width, _result.Height);
 
-                foreach (var line in lines)
+                foreach (var line in objects.OfType<Line>())
                 {
-                    var start = VectorToPointF(line.StartPoint, offset, scale, border);
-                    var end = VectorToPointF(line.EndPoint, offset, scale, border);
-                    g.DrawLine(pen, start, end);
-                }
+                    try
+                    {
+                        var _start = VectorToPointF(line.StartPoint, offset, scale, border);
+                        var _end = VectorToPointF(line.EndPoint, offset, scale, border);
+                        _graphics.DrawLine(_pen, _start, _end);
+                    }
+                    catch (Exception e)
+                    {
+                        
+                    }
 
-                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));
+                foreach (var text in objects.OfType<MText>().Where(x=>!string.IsNullOrWhiteSpace(x.Value)))
+                {
+                    try
+                    {
+                        
+                        var font = new Font(text.Style.FontFamilyName, 12.0f, (FontStyle)text.Style.FontStyle);
+                        var dimensions = _graphics.MeasureString(text.Value, font);
+
+                        var anchor = VectorToPointF(text.Position, offset, scale, border);
+                        
+                        var textwidth = Scale(text.RectangleWidth, 0, scale, 0);
+                        float textRatioX = text.RectangleWidth == 0 ? int.MaxValue : textwidth / dimensions.Width;
+
+                        var textheight = Scale(text.Height, 0, scale, 0);
+                        float textRatioY =  textheight / dimensions.Height;
+                        
+                        var textScale = Math.Min(textRatioX, textRatioY);
+                        
+                        font = new Font(text.Style.FontFamilyName, 12.0f * textScale, (FontStyle)text.Style.FontStyle);
+
+                        var topleft = (text.AttachmentPoint) switch
+                        {
+                            MTextAttachmentPoint.TopLeft => anchor,
+                            MTextAttachmentPoint.TopCenter => new PointF(anchor.X - (dimensions.Width / 2.0f), anchor.Y),
+                            MTextAttachmentPoint.TopRight => new PointF(anchor.X - dimensions.Width, anchor.Y),
+                            MTextAttachmentPoint.MiddleLeft => new PointF(anchor.X, anchor.Y - (textheight / 2.0f)),
+                            MTextAttachmentPoint.MiddleCenter => new PointF(anchor.X - (dimensions.Width / 2.0f), anchor.Y- (textheight / 2.0f)),
+                            MTextAttachmentPoint.MiddleRight => new PointF(anchor.X - dimensions.Width, anchor.Y- (textheight / 2.0f)),
+                            MTextAttachmentPoint.BottomLeft => anchor,
+                            MTextAttachmentPoint.BottomCenter => new PointF(anchor.X - (dimensions.Width / 2.0f), anchor.Y - textheight),
+                            MTextAttachmentPoint.BottomRight => new PointF(anchor.X - dimensions.Width, anchor.Y - textheight),
+
+                        };
+                        //var rectangle = new RectangleF(topleft, new SizeF(dimensions.Width, textheight));
+                        //_graphics.FillRectangle(new SolidBrush(Color.Yellow), rectangle);
+                        
+                        _graphics.DrawString(text.Value, font, new SolidBrush(Color.Navy),topleft);
+                    }
+                    catch (Exception e)
+                    {
+                    }
+                    
+                }
+                
+                try
+                {
+                    var font = new Font("Arial", 20.0F);
+                    var brush = new SolidBrush(Color.Blue);
+                    _pen = new Pen(brush);
+
+                    if (!string.IsNullOrWhiteSpace(caption))
+                    {
+                        var crect = _graphics.MeasureString(caption, font);
+                        _graphics.DrawString(caption, font, brush,
+                            new PointF(_result.Width / 2.0F - crect.Width / 2.0F, 10));
+                    }
+
+                    if (dimensionmarks)
+                    {
+
+                        var heightrect = _graphics.MeasureString(height.ToString(), font);
+                        _graphics.DrawLine(_pen, new PointF(_result.Width - (heightrect.Height + 10.0F), 100),
+                            new PointF(_result.Width - 30, 100));
+                        _graphics.DrawLine(_pen,
+                            new PointF(_result.Width - (heightrect.Height + 10.0F), _result.Height - 100),
+                            new PointF(_result.Width - 30, _result.Height - 100));
+                        _graphics.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;
+                        _graphics.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;
+                        _graphics.FillPolygon(brush, new[]
+                        {
+                            new(aX, aY),
+                            new PointF(aX - 10.0F, aY - 10.0F),
+                            new PointF(aX + 10.0F, aY - 10.0F)
+                        });
+                        _graphics.FillRectangle(_brush, _result.Width - (heightrect.Height + 15.0F),
+                            _result.Height / 2.0F - heightrect.Width / 2.0F, heightrect.Height,
+                            heightrect.Width);
+                        DrawRotatedTextAt(_graphics, 270.0F, height.ToString(),
+                            _result.Width - (heightrect.Height + 15.0F),
+                            _result.Height / 2.0F + heightrect.Width / 2.0F, font, brush);
+
+                        var widthrect = _graphics.MeasureString(width.ToString(), font);
+                        _graphics.DrawLine(_pen, new PointF(100, _result.Height - (widthrect.Height + 10.0F)),
+                            new PointF(100, _result.Height - 30));
+                        _graphics.DrawLine(_pen,
+                            new PointF(_result.Width - 100, _result.Height - (widthrect.Height + 10.0F)),
+                            new PointF(_result.Width - 100, _result.Height - 30));
+                        _graphics.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);
+                        _graphics.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;
+                        _graphics.FillPolygon(brush, new[]
+                        {
+                            new(aX, aY),
+                            new PointF(aX - 10.0F, aY - 10.0F),
+                            new PointF(aX - 10.0F, aY + 10.0F)
+                        });
+
+                        _graphics.FillRectangle(_brush, _result.Width / 2.0F - widthrect.Width / 2.0F,
+                            _result.Height - (widthrect.Height + 15.0F), widthrect.Width,
+                            widthrect.Height);
+                        _graphics.DrawString(width.ToString(), font, brush,
+                            new PointF(_result.Width / 2.0F - widthrect.Width / 2.0F,
+                                _result.Height - (widthrect.Height + 15.0F)));
+                    }
+                }
+                catch (Exception e)
+                {
 
-                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)
-                });
+            return _result;
+        }
 
-                aY = result.Height - 105;
-                g.FillPolygon(brush, new[]
+        private static void ProcessEntities(IEnumerable<EntityObject> entities, List<EntityObject> results, Vector3 offset)
+        {
+            foreach (var entity in entities)
+            {
+                try
                 {
-                    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[]
+                    if (entity is Line l)
+                        AddLine(l, results, offset);
+                    else if (entity is Insert i)
+                        InsertToLines(i, results, offset);
+                    else if (entity is Polyline2D p2d)
+                        PolylineToLines(p2d, results, offset);
+                    else if (entity is Arc a)
+                        ArcToLines(a, results, offset);
+                    else if (entity is Ellipse e)
+                        EllipseToLines(e, results, offset);
+                    else if (entity is MText t)
+                        AddText(t, results, offset);
+                    else if (entity is Dimension d)
+                        DimensionToLines(d, results, offset);
+                    else
+                    {
+                    }
+                }
+                catch (Exception e)
                 {
-                    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)));
+                }
+
             }
+        }
+
+        private static void DimensionToLines(Dimension dimension, List<EntityObject> results, Vector3 offset)
+        {
+            //dimension.
+            ProcessEntities(dimension.Block.Entities, results, offset);
+        }
+
+        private static void AddText(MText text, List<EntityObject> results, Vector3 offset)
+        {
+            text.Position += offset;
+            results.Add(text);
+        }
 
-            return result;
+        private static void AddLine(Line line, List<EntityObject> results, Vector3 offset)
+        {
+            line.StartPoint += offset;
+            line.EndPoint += offset;
+            results.Add(line);
+        }
+
+        private static void EllipseToLines(Ellipse ellipse, List<EntityObject> results, Vector3 offset)
+        {
+            var precision = Math.Max(2, (int)((ellipse.MajorAxis + ellipse.MinorAxis) * 2.0F * Math.PI));
+            var polyline = ellipse.ToPolyline2D(precision);
+            var segments = polyline.Explode();
+            ProcessEntities(segments, results, offset);
+        }
+
+        private static void InsertToLines(Insert insert, List<EntityObject> results, Vector3 offset)
+        {
+            ProcessEntities(insert.Block.Entities, results, insert.Position += offset);
+        }
+
+        private static void PolylineToLines(Polyline2D polyline, List<EntityObject> results, Vector3 offset)
+        {
+            var components = polyline.Explode();
+            ProcessEntities(components, results, offset);
         }
 
-        private static void ArcToLines(List<Line> lines, Arc arc)
+        private static void ArcToLines(Arc arc, List<EntityObject> results, Vector3 offset)
         {
             var precision = Math.Max(2, (int)(arc.Radius * 2.0F * Math.PI));
             var polyline = arc.ToPolyline2D(precision);
             var segments = polyline.Explode();
-            lines.AddRange(segments.Select(x => x as Line));
+            ProcessEntities(segments, results, offset);
         }
 
         public static Bitmap? DXFToBitmap(string filename)

+ 1 - 1
inabox.dxf/InABox.Dxf.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
     <PropertyGroup>
-        <TargetFramework>net6.0</TargetFramework>
+        <TargetFramework>net6.0-windows</TargetFramework>
         <ImplicitUsings>enable</ImplicitUsings>
         <Nullable>enable</Nullable>
     </PropertyGroup>

+ 2 - 9
inabox.wpf/Converters/AbstractConverter.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Globalization;
+using System.Text.RegularExpressions;
 using System.Windows;
 using System.Windows.Data;
 using Org.BouncyCastle.X509.Extension;
@@ -77,12 +78,4 @@ public abstract class AbstractConverter<TIn, TOut> : /*Freezable, */ IValueConve
     // #endregion
 
 
-}
-
-public class NullConverter<T> : AbstractConverter<T, T>
-{
-    public override T Convert(T value)
-    {
-        return value;
-    }
-}
+}

+ 54 - 0
inabox.wpf/Converters/EnumBindingSourceExtension.cs

@@ -0,0 +1,54 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using System.Windows.Markup;
+using InABox.Core;
+
+namespace InABox.WPF;
+
+public class EnumFormatterExtension : MarkupExtension
+{
+    private readonly Type _type;
+
+    public EnumFormatterExtension(Type type)
+    {
+        _type = type;
+    }
+
+    public override object ProvideValue(IServiceProvider serviceProvider)
+    {
+        return Enum.GetValues(_type)
+            .Cast<object>()
+            .Select(e => new { Value = (int)e, DisplayName = $"{e}".SplitCamelCase() });
+    }
+}
+
+public class EnumToStringConverter : AbstractConverter<object?,string>
+{
+    private string GetDescription(Type enumType, object? enumValue)
+    {
+        if (enumValue == null)
+            return string.Empty;
+
+        return
+            enumType
+                .GetField($"{enumValue}")?
+                .GetCustomAttributes(typeof(DescriptionAttribute), false)
+                .FirstOrDefault() is DescriptionAttribute _descriptionAttribute
+                ? _descriptionAttribute.Description
+                : $"{enumValue}".SplitCamelCase() ?? "";
+    }
+
+    public override string Convert(object? value)
+    {
+        if (value == null)
+            return String.Empty;
+
+        Type _type = value.GetType();
+
+        return
+            _type.IsEnum
+                ? GetDescription(_type, value)
+                : String.Empty;
+    }
+}

+ 9 - 0
inabox.wpf/Converters/NullConverter.cs

@@ -0,0 +1,9 @@
+namespace InABox.WPF;
+
+public class NullConverter<T> : AbstractConverter<T, T>
+{
+    public override T Convert(T value)
+    {
+        return value;
+    }
+}

+ 42 - 0
inabox.wpf/ImageUtils.cs

@@ -24,6 +24,7 @@ using System.Linq;
 using Syncfusion.Pdf.Graphics;
 using Syncfusion.Pdf;
 using System.Diagnostics.CodeAnalysis;
+using System.Runtime;
 using System.Text;
 using Encoder = System.Drawing.Imaging.Encoder;
 
@@ -833,6 +834,47 @@ namespace InABox.WPF
             }
             return null;
         }
+
+        public static byte[] BitmapToPdf(Bitmap bitmap)
+        {
+            byte[]? _result = null;
+            using (var _stream = new MemoryStream())
+            {
+                bitmap.Save(_stream, ImageFormat.Png);
+                _result = BitmapToPdf(_stream);
+            }
+            return _result;
+        }
+        
+        public static byte[] BitmapToPdf(byte[] bitmap)
+        {
+            byte[] _result = null;
+            using (var _stream = new MemoryStream(bitmap))
+                _result = BitmapToPdf(_stream);
+            
+            return _result;
+        }
+
+        public static byte[] BitmapToPdf(Stream stream)
+        {
+            byte[]? _result = null;
+            PdfDocument _doc = new PdfDocument();
+            PdfPage _page = _doc.Pages.Add();
+            PdfGraphics _graphics = _page.Graphics;
+            stream.Position = 0;
+            PdfBitmap _image = new PdfBitmap(stream);
+            _graphics.DrawImage(_image, 0, 0);
+            using (var _out = new MemoryStream())
+            {
+                _doc.Save(_out);
+                _out.Position = 0;
+                _doc.Close(true);
+                _result = _out.ToArray();
+            }
+            return _result;
+        }
+        
+
         
         public static bool IsPdf(byte[] data)
         {