diff --git a/CHANGELOG.md b/CHANGELOG.md index e8bfefb8..4c941466 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 08/01/2025 - v5.0.4 + +- PCB Exposure: + - (Fix) Polygon primitive vertex count not parsing correctly when having argument (#976) + - (Fix) Obround aperture to follow the correct implementation (two semicircles connected by parallel lines tangent to their endpoints) (#976) + - (Fix) Implement the "hole diameter" argument in all apertures (#976) + - (Fix) Implement the "rotation" argument for the polygon aperture + ## 28/12/2024 - v5.0.3 - Anycubic file format: diff --git a/CREDITS.md b/CREDITS.md index 882644c7..c91a8936 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -94,4 +94,5 @@ - Jeremy Conoley - Brady George - Ryan Skow -- Cainam \ No newline at end of file +- Cainam +- Cory Lytle \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props index ea7971f1..83c02323 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -37,7 +37,7 @@ true - 5.0.3 + 5.0.4 11.2.3 diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 608f2a44..115fcc4d 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,11 +1,6 @@ -- Anycubic file format: - - (Fix) Reset TSMC values to comply with globals when decoding file and AdvancedMode is disabled (#971) - - (Fix) Setting the LiftHeight2 was setting the base value to BottomLiftHeight2 - - (Fix) Setting the BottomRetractSpeed was not applying the value in the base property -- Multiple exposure finder: - - (Fix) Counter triangles not taking all the new left space - - (Fix) When doing multiple heights the text label always show the base height -- (Improvement) Layer image viewer internal handling -- (Fix) Settings - Send to process: Unable to pick a process file, it was selecting folder instead -- (Fix) Save As can show incorrect file extension description when there are other file formats with the same extension +- PCB Exposure: + - (Fix) Polygon primitive vertex count not parsing correctly when having argument (#976) + - (Fix) Obround aperture to follow the correct implementation (two semicircles connected by parallel lines tangent to their endpoints) (#976) + - (Fix) Implement the "hole diameter" argument in all apertures (#976) + - (Fix) Implement the "rotation" argument for the polygon aperture diff --git a/UVtools.Core/Gerber/Apertures/Aperture.cs b/UVtools.Core/Gerber/Apertures/Aperture.cs index f255161d..cb23112d 100644 --- a/UVtools.Core/Gerber/Apertures/Aperture.cs +++ b/UVtools.Core/Gerber/Apertures/Aperture.cs @@ -64,18 +64,24 @@ protected Aperture(GerberFormat document, string name) case "C": { if (match.Groups.Count < 4) return null; - if (!double.TryParse(match.Groups[3].Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var diameter)) return null; - return new CircleAperture(document, index, diameter); + var split = match.Groups[3].Value.Split('X', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + if (split.Length == 0) return null; + if (!double.TryParse(split[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var diameter)) return null; + var holeDiameter = 0.0; + if (split.Length > 1 && !double.TryParse(split[1], NumberStyles.Float, CultureInfo.InvariantCulture, out holeDiameter)) return null; + return new CircleAperture(document, index, diameter, holeDiameter); } - case "O": + case "O": // OBround { if (match.Groups.Count < 4) return null; var split = match.Groups[3].Value.Split('X', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); if (split.Length < 2) return null; if (!float.TryParse(split[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var width)) return null; if (!float.TryParse(split[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var height)) return null; + var holeDiameter = 0.0; + if (split.Length > 2 && !double.TryParse(split[2], NumberStyles.Float, CultureInfo.InvariantCulture, out holeDiameter)) return null; - return new EllipseAperture(document, index, width, height); + return new ObroundAperture(document, index, width, height, holeDiameter); } case "R": { @@ -84,8 +90,10 @@ protected Aperture(GerberFormat document, string name) if (split.Length < 2) return null; if (!float.TryParse(split[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var width)) return null; if (!float.TryParse(split[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var height)) return null; + var holeDiameter = 0.0; + if (split.Length > 2 && !double.TryParse(split[2], NumberStyles.Float, CultureInfo.InvariantCulture, out holeDiameter)) return null; - return new RectangleAperture(document, index, width, height); + return new RectangleAperture(document, index, width, height, holeDiameter); } case "P": { @@ -94,8 +102,12 @@ protected Aperture(GerberFormat document, string name) if (split.Length < 2) return null; if (!double.TryParse(split[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var diameter)) return null; if (!ushort.TryParse(split[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var vertices)) return null; + var rotation = 0.0; + if (split.Length > 2 && !double.TryParse(split[2], NumberStyles.Float, CultureInfo.InvariantCulture, out rotation)) return null; + var holeDiameter = 0.0; + if (split.Length > 3 && !double.TryParse(split[3], NumberStyles.Float, CultureInfo.InvariantCulture, out holeDiameter)) return null; - return new PolygonAperture(document, index, diameter, vertices); + return new PolygonAperture(document, index, diameter, vertices, rotation, holeDiameter); } default: // macro { @@ -104,7 +116,7 @@ protected Aperture(GerberFormat document, string name) //var parseLine = line.TrimEnd('%', '*'); //var commaIndex = parseLine.IndexOf(',')+1; //parseLine = parseLine[commaIndex..]; - string[] args = { "0" }; + string[] args = ["0"]; if (match.Groups.Count >= 4) { args = args.Concat(match.Groups[3].Value.Split('X', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)).ToArray(); diff --git a/UVtools.Core/Gerber/Apertures/CircleAperture.cs b/UVtools.Core/Gerber/Apertures/CircleAperture.cs index 464c2198..ea5a3984 100644 --- a/UVtools.Core/Gerber/Apertures/CircleAperture.cs +++ b/UVtools.Core/Gerber/Apertures/CircleAperture.cs @@ -10,6 +10,7 @@ using Emgu.CV.CvEnum; using Emgu.CV.Structure; using System.Drawing; +using UVtools.Core.Extensions; namespace UVtools.Core.Gerber.Apertures; @@ -17,20 +18,30 @@ public class CircleAperture : Aperture { #region Properties public double Diameter { get; set; } + public double HoleDiameter { get; set; } #endregion #region Constructor public CircleAperture(GerberFormat document) : base(document, "Circle") { } - public CircleAperture(GerberFormat document, int index, double diameter) : base(document, index, "Circle") + public CircleAperture(GerberFormat document, int index, double diameter, double holeDiameter = 0) : base(document, index, "Circle") { Diameter = document.GetMillimeters(diameter); + if (holeDiameter > 0) HoleDiameter = document.GetMillimeters(holeDiameter); } #endregion public override void DrawFlashD3(Mat mat, PointF at, MCvScalar color, LineType lineType = LineType.EightConnected) { - CvInvoke.Ellipse(mat, Document.PositionMmToPx(at), Document.SizeMmToPx(Diameter / 2.0, Diameter / 2.0), 0, 0, 360, color, -1, lineType); - //CvInvoke.Circle(mat, Document.PositionMmToPx(at), Document.SizeMmToPx(Diameter / 2), color, -1, lineType); + var location = Document.PositionMmToPx(at); + CvInvoke.Ellipse(mat, location, Document.SizeMmToPx(Diameter / 2.0, Diameter / 2.0), 0, 0, 360, color, -1, lineType); + if (HoleDiameter > 0) + { + var invertColor = color.Equals(EmguExtensions.BlackColor) ? EmguExtensions.WhiteColor : EmguExtensions.BlackColor; + CvInvoke.Ellipse(mat, + location, + Document.SizeMmToPx(HoleDiameter / 2.0, HoleDiameter / 2.0), + 0, 0, 360, invertColor, -1, lineType); + } } } \ No newline at end of file diff --git a/UVtools.Core/Gerber/Apertures/EllipseAperture.cs b/UVtools.Core/Gerber/Apertures/EllipseAperture.cs deleted file mode 100644 index 13453989..00000000 --- a/UVtools.Core/Gerber/Apertures/EllipseAperture.cs +++ /dev/null @@ -1,43 +0,0 @@ -/* - * GNU AFFERO GENERAL PUBLIC LICENSE - * Version 3, 19 November 2007 - * Copyright (C) 2007 Free Software Foundation, Inc. - * Everyone is permitted to copy and distribute verbatim copies - * of this license document, but changing it is not allowed. - */ - -using Emgu.CV; -using Emgu.CV.CvEnum; -using Emgu.CV.Structure; -using System.Drawing; - -namespace UVtools.Core.Gerber.Apertures; - -public class EllipseAperture : Aperture -{ - #region Properties - public SizeF Axes { get; set; } - #endregion - - #region Constructor - public EllipseAperture(GerberFormat document) : base(document, "Ellipse") { } - - public EllipseAperture(GerberFormat document, int index, float width, float height) : this(document, index, new SizeF(width, height)) - { - - } - - public EllipseAperture(GerberFormat document, int index, SizeF axes) : base(document, index, "Ellipse") - { - Axes = document.GetMillimeters(axes); - } - #endregion - - public override void DrawFlashD3(Mat mat, PointF at, MCvScalar color, LineType lineType = LineType.EightConnected) - { - CvInvoke.Ellipse(mat, - Document.PositionMmToPx(at), - Document.SizeMmToPx(Axes.Width / 2, Axes.Height / 2), - 0, 0, 360, color, -1, lineType); - } -} \ No newline at end of file diff --git a/UVtools.Core/Gerber/Apertures/ObroundAperture.cs b/UVtools.Core/Gerber/Apertures/ObroundAperture.cs new file mode 100644 index 00000000..64cb7434 --- /dev/null +++ b/UVtools.Core/Gerber/Apertures/ObroundAperture.cs @@ -0,0 +1,74 @@ +/* + * GNU AFFERO GENERAL PUBLIC LICENSE + * Version 3, 19 November 2007 + * Copyright (C) 2007 Free Software Foundation, Inc. + * Everyone is permitted to copy and distribute verbatim copies + * of this license document, but changing it is not allowed. + */ + +using Emgu.CV; +using Emgu.CV.CvEnum; +using Emgu.CV.Structure; +using System.Drawing; +using UVtools.Core.Extensions; + +namespace UVtools.Core.Gerber.Apertures; + +public class ObroundAperture : Aperture +{ + #region Properties + public SizeF Axes { get; set; } + public double HoleDiameter { get; set; } + #endregion + + #region Constructor + public ObroundAperture(GerberFormat document) : base(document, "Obround") { } + + public ObroundAperture(GerberFormat document, int index, float width, float height, double holeDiameter = 0) : this(document, index, new SizeF(width, height), holeDiameter) + { + + } + + public ObroundAperture(GerberFormat document, int index, SizeF axes, double holeDiameter = 0) : base(document, index, "Obround") + { + Axes = document.GetMillimeters(axes); + if (holeDiameter > 0) HoleDiameter = document.GetMillimeters(holeDiameter); + } + #endregion + + public override void DrawFlashD3(Mat mat, PointF at, MCvScalar color, LineType lineType = LineType.EightConnected) + { + var location = Document.PositionMmToPx(at); + // Calculate radii of the semicircles + var radius = Document.SizeMmToPx(Axes.Width / 2, Axes.Height / 2); + var radiusFromHeight = Document.SizeMmToPx(Axes.Height / 2, Axes.Height / 2); + var diameter = Document.SizeMmToPx(Axes.Width, Axes.Height); + + // Calculate centers for the semicircles + var leftCircleCenter = location with { X = location.X - radius.Width + radiusFromHeight.Width }; + var rightCircleCenter = location with { X = location.X + radius.Width - radiusFromHeight.Width }; + + // Draw the two semicircles + CvInvoke.Ellipse(mat, leftCircleCenter, radiusFromHeight, 0, 90, 270, color, -1, lineType); + CvInvoke.Ellipse(mat, rightCircleCenter, radiusFromHeight, 0, -90, 90, color, -1, lineType); + + /*CvInvoke.Ellipse(mat, + location, + radius, + 0, 0, 360, color, -1, lineType);*/ + + // Draw the rectangle connecting the semicircles + var rect = new Rectangle(leftCircleCenter with { Y = location.Y - radius.Height }, + diameter with { Width = diameter.Width - diameter.Height }); + CvInvoke.Rectangle(mat, rect, color, -1, lineType); + + if (HoleDiameter > 0) + { + var invertColor = color.Equals(EmguExtensions.BlackColor) ? EmguExtensions.WhiteColor : EmguExtensions.BlackColor; + CvInvoke.Ellipse(mat, + location, + Document.SizeMmToPx(HoleDiameter / 2.0, HoleDiameter / 2.0), + 0, 0, 360, invertColor, -1, lineType); + } + } +} \ No newline at end of file diff --git a/UVtools.Core/Gerber/Apertures/PoygonAperture.cs b/UVtools.Core/Gerber/Apertures/PoygonAperture.cs index 3edc2b39..b6460a36 100644 --- a/UVtools.Core/Gerber/Apertures/PoygonAperture.cs +++ b/UVtools.Core/Gerber/Apertures/PoygonAperture.cs @@ -19,20 +19,33 @@ public class PolygonAperture : Aperture #region Properties public double Diameter { get; set; } public ushort Vertices { get; set; } + public double Rotation { get; set; } + public double HoleDiameter { get; set; } #endregion #region Constructor public PolygonAperture(GerberFormat document) : base(document, "Polygon") { } - public PolygonAperture(GerberFormat document, int index, double diameter, ushort vertices) : base(document, index, "Polygon") + public PolygonAperture(GerberFormat document, int index, double diameter, ushort vertices, double rotation = 0.0, double holeDiameter = 0) : base(document, index, "Polygon") { Diameter = document.GetMillimeters(diameter); Vertices = vertices; + Rotation = rotation; + if (holeDiameter > 0) HoleDiameter = document.GetMillimeters(holeDiameter); } #endregion public override void DrawFlashD3(Mat mat, PointF at, MCvScalar color, LineType lineType = LineType.EightConnected) { - mat.DrawPolygon(Vertices, Document.SizeMmToPx(Diameter), Document.PositionMmToPx(at), color, 0, -1, lineType); + var location = Document.PositionMmToPx(at); + mat.DrawPolygon(Vertices, Document.SizeMmToPx(Diameter), location, color, Rotation, -1, lineType); + if (HoleDiameter > 0) + { + var invertColor = color.Equals(EmguExtensions.BlackColor) ? EmguExtensions.WhiteColor : EmguExtensions.BlackColor; + CvInvoke.Ellipse(mat, + location, + Document.SizeMmToPx(HoleDiameter / 2.0, HoleDiameter / 2.0), + 0, 0, 360, invertColor, -1, lineType); + } } } \ No newline at end of file diff --git a/UVtools.Core/Gerber/Apertures/RectangleAperture.cs b/UVtools.Core/Gerber/Apertures/RectangleAperture.cs index fc531bc1..f9f221cc 100644 --- a/UVtools.Core/Gerber/Apertures/RectangleAperture.cs +++ b/UVtools.Core/Gerber/Apertures/RectangleAperture.cs @@ -9,8 +9,10 @@ using Emgu.CV; using Emgu.CV.CvEnum; using Emgu.CV.Structure; +using Microsoft.CodeAnalysis; using System; using System.Drawing; +using UVtools.Core.Extensions; namespace UVtools.Core.Gerber.Apertures; @@ -18,23 +20,37 @@ public class RectangleAperture : Aperture { #region Properties public SizeF Size { get; set; } + public double HoleDiameter { get; set; } #endregion #region Constructor public RectangleAperture(GerberFormat document) : base(document, "Rectangle") { } - public RectangleAperture(GerberFormat document, int index, float width, float height) : this(document, index, new SizeF(width, height)) - { } + public RectangleAperture(GerberFormat document, int index, float width, float height, double holeDiameter = 0) : this(document, index, new SizeF(width, height), holeDiameter) + { + } - public RectangleAperture(GerberFormat document, int index, SizeF size) : base(document, index, "Rectangle") + public RectangleAperture(GerberFormat document, int index, SizeF size, double holeDiameter = 0) : base(document, index, "Rectangle") { Size = document.GetMillimeters(size); + if (holeDiameter > 0) HoleDiameter = document.GetMillimeters(holeDiameter); } #endregion public override void DrawFlashD3(Mat mat, PointF at, MCvScalar color, LineType lineType = LineType.EightConnected) { + var location = Document.PositionMmToPx(at); + at = new PointF(Math.Max(0, at.X - Size.Width / 2), Math.Max(0, at.Y - Size.Height / 2)); CvInvoke.Rectangle(mat, new Rectangle(Document.PositionMmToPx(at), Document.SizeMmToPx(Size)), color, -1, lineType); + + if (HoleDiameter > 0) + { + var invertColor = color.Equals(EmguExtensions.BlackColor) ? EmguExtensions.WhiteColor : EmguExtensions.BlackColor; + CvInvoke.Ellipse(mat, + location, + Document.SizeMmToPx(HoleDiameter / 2.0, HoleDiameter / 2.0), + 0, 0, 360, invertColor, -1, lineType); + } } } \ No newline at end of file diff --git a/UVtools.Core/Gerber/Macro.cs b/UVtools.Core/Gerber/Macro.cs index bc331fb5..0a49492e 100644 --- a/UVtools.Core/Gerber/Macro.cs +++ b/UVtools.Core/Gerber/Macro.cs @@ -71,7 +71,7 @@ public void ParsePrimitive(string line) Primitives.Add(primitive); break; } - // 21 Center Line: Exposure, Width, Hight, Center X, Center Y, Rotation + // 21 Center Line: Exposure, Width, Height, Center X, Center Y, Rotation case CenterLinePrimitive.Code: { var primitive = new CenterLinePrimitive(Document, commaSplit[1], commaSplit[2], commaSplit[3], commaSplit[4], commaSplit[5]); @@ -85,7 +85,7 @@ public void ParsePrimitive(string line) Primitives.Add(new OutlinePrimitive(Document, commaSplit[1], commaSplit[3..^1], commaSplit[^1])); break; } - // 5 Outline: Exposure, # vertices, Start X, Start Y, Subsequent points..., Rotation + // 5 Outline: Exposure, # vertices, Center X, Center Y, Diameter, Rotation case PolygonPrimitive.Code: { var primitive = new PolygonPrimitive(Document, commaSplit[1], commaSplit[2], commaSplit[3], commaSplit[4], commaSplit[5]); diff --git a/UVtools.Core/Gerber/Primitives/CenterLinePrimitive.cs b/UVtools.Core/Gerber/Primitives/CenterLinePrimitive.cs index f7bcaa7c..5429b83c 100644 --- a/UVtools.Core/Gerber/Primitives/CenterLinePrimitive.cs +++ b/UVtools.Core/Gerber/Primitives/CenterLinePrimitive.cs @@ -80,11 +80,11 @@ protected CenterLinePrimitive(GerberFormat document) : base(document) { } public CenterLinePrimitive(GerberFormat document, string exposureExpression, string widthExpression = "0", string heightExpression = "0", string centerXExpression = "0", string centerYExpression = "0", string rotationExpression = "0") : base(document) { ExposureExpression = exposureExpression; - WidthExpression = widthExpression; - HeightExpression = heightExpression; - CenterXExpression = centerXExpression; - CenterYExpression = centerYExpression; - RotationExpression = rotationExpression; + WidthExpression = widthExpression.Replace("X", "*", StringComparison.OrdinalIgnoreCase); + HeightExpression = heightExpression.Replace("X", "*", StringComparison.OrdinalIgnoreCase); + CenterXExpression = centerXExpression.Replace("X", "*", StringComparison.OrdinalIgnoreCase); + CenterYExpression = centerYExpression.Replace("X", "*", StringComparison.OrdinalIgnoreCase); + RotationExpression = rotationExpression.Replace("X", "*", StringComparison.OrdinalIgnoreCase); } diff --git a/UVtools.Core/Gerber/Primitives/CirclePrimitive.cs b/UVtools.Core/Gerber/Primitives/CirclePrimitive.cs index 544b83bc..77547a37 100644 --- a/UVtools.Core/Gerber/Primitives/CirclePrimitive.cs +++ b/UVtools.Core/Gerber/Primitives/CirclePrimitive.cs @@ -72,10 +72,10 @@ protected CirclePrimitive(GerberFormat document) : base(document) { } public CirclePrimitive(GerberFormat document, string exposureExpression = "1", string diameterExpression = "0", string centerXExpression = "0", string centerYExpression = "0", string rotationExpression = "0") : base(document) { ExposureExpression = exposureExpression; - DiameterExpression = diameterExpression; - CenterXExpression = centerXExpression; - CenterYExpression = centerYExpression; - RotationExpression = rotationExpression; + DiameterExpression = diameterExpression.Replace("X", "*", StringComparison.OrdinalIgnoreCase); + CenterXExpression = centerXExpression.Replace("X", "*", StringComparison.OrdinalIgnoreCase); + CenterYExpression = centerYExpression.Replace("X", "*", StringComparison.OrdinalIgnoreCase); + RotationExpression = rotationExpression.Replace("X", "*", StringComparison.OrdinalIgnoreCase); } public override void DrawFlashD3(Mat mat, PointF at, LineType lineType = LineType.EightConnected) diff --git a/UVtools.Core/Gerber/Primitives/OutlinePrimitive.cs b/UVtools.Core/Gerber/Primitives/OutlinePrimitive.cs index 1f99b00d..79b08e8a 100644 --- a/UVtools.Core/Gerber/Primitives/OutlinePrimitive.cs +++ b/UVtools.Core/Gerber/Primitives/OutlinePrimitive.cs @@ -72,7 +72,7 @@ public OutlinePrimitive(GerberFormat document, string exposureExpression, string { ExposureExpression = exposureExpression; CoordinatesExpression = coordinatesExpression; - RotationExpression = rotationExpression; + RotationExpression = rotationExpression.Replace("X", "*", StringComparison.OrdinalIgnoreCase); ; } diff --git a/UVtools.Core/Gerber/Primitives/PolygonPrimitive.cs b/UVtools.Core/Gerber/Primitives/PolygonPrimitive.cs index 7db36c54..749d8894 100644 --- a/UVtools.Core/Gerber/Primitives/PolygonPrimitive.cs +++ b/UVtools.Core/Gerber/Primitives/PolygonPrimitive.cs @@ -81,8 +81,8 @@ public PolygonPrimitive(GerberFormat document, string exposureExpression, string VerticesCountExpression = verticesCountExpression; CenterXExpression = centerXExpression; CenterYExpression = centerYExpression; - DiameterExpression = diameterExpression; - RotationExpression = rotationExpression; + DiameterExpression = diameterExpression.Replace("X", "*", StringComparison.OrdinalIgnoreCase); + RotationExpression = rotationExpression.Replace("X", "*", StringComparison.OrdinalIgnoreCase); } public override void DrawFlashD3(Mat mat, PointF at, LineType lineType = LineType.EightConnected) @@ -110,10 +110,10 @@ public override void ParseExpressions(params string[] args) if (temp is not DBNull) Exposure = Convert.ToByte(temp); } - if (byte.TryParse(DiameterExpression, out var vertices)) VerticesCount = vertices; + if (byte.TryParse(VerticesCountExpression, out var vertices)) VerticesCount = vertices; else { - csharpExp = Regex.Replace(DiameterExpression, @"\$([0-9]+)", "{$1}"); + csharpExp = Regex.Replace(VerticesCountExpression, @"\$([0-9]+)", "{$1}"); csharpExp = string.Format(csharpExp, args); var temp = exp.Compute(csharpExp, null); if (temp is not DBNull) VerticesCount = Convert.ToByte(temp); diff --git a/UVtools.Core/Gerber/Primitives/VectorLinePrimitive.cs b/UVtools.Core/Gerber/Primitives/VectorLinePrimitive.cs index e80141f6..5e60e09b 100644 --- a/UVtools.Core/Gerber/Primitives/VectorLinePrimitive.cs +++ b/UVtools.Core/Gerber/Primitives/VectorLinePrimitive.cs @@ -89,12 +89,12 @@ protected VectorLinePrimitive(GerberFormat document) : base(document) { } public VectorLinePrimitive(GerberFormat document, string exposureExpression, string lineWidthExpression, string startXExpression, string startYExpression, string endXExpression, string endYExpression, string rotationExpression = "0") : base(document) { ExposureExpression = exposureExpression; - LineWidthExpression = lineWidthExpression; + LineWidthExpression = lineWidthExpression.Replace("X", "*", StringComparison.OrdinalIgnoreCase); ; StartXExpression = startXExpression; StartYExpression = startYExpression; EndXExpression = endXExpression; EndYExpression = endYExpression; - RotationExpression = rotationExpression; + RotationExpression = rotationExpression.Replace("X", "*", StringComparison.OrdinalIgnoreCase); ; } public override void DrawFlashD3(Mat mat, PointF at, LineType lineType = LineType.EightConnected) diff --git a/UVtools.UI/Controls/WindowEx.cs b/UVtools.UI/Controls/WindowEx.cs index abd5b804..422722f0 100644 --- a/UVtools.UI/Controls/WindowEx.cs +++ b/UVtools.UI/Controls/WindowEx.cs @@ -14,7 +14,6 @@ using System.Threading.Tasks; using Avalonia.Platform.Storage; using UVtools.Core.FileFormats; -using UVtools.Core.SystemOS; using UVtools.UI.Extensions; using Size = Avalonia.Size;