Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/sn4k3/UVtools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTiago Conceição <Tiago_caza@hotmail.com>2022-06-25 04:02:59 +0300
committerTiago Conceição <Tiago_caza@hotmail.com>2022-06-25 04:02:59 +0300
commit9711bb7474d90ea6b54bbcae6db059364b44655e (patch)
treead52f4713d3273cbc2e4fc054acf9b63771aa64c
parent67fbec1fff373a6ca6ae9f512eb28fe3fc379bb7 (diff)
v3.5.2v3.5.2
- **PCB Exposure:** - (Add) Gerber file extensions: gko, gtl, gto, gts, gbl, gbo, gbs, gml - (Fix) Trailing zeros suppression mode and improve the parsing of the coordinate string (#492) - (Fix) Allow coordinates without number `XYD0*` to indicate `X=0` and `Y=0` - (Fix) Do not try to fetch apertures lower than index 10 when a `D02` (closed shutter) is found alone
-rw-r--r--CHANGELOG.md8
-rw-r--r--RELEASE_NOTES.md12
-rw-r--r--UVtools.Core/Gerber/Enumerations.cs16
-rw-r--r--UVtools.Core/Gerber/GerberDocument.cs137
-rw-r--r--UVtools.Core/Operations/OperationPCBExposure.cs20
-rw-r--r--UVtools.Core/UVtools.Core.csproj2
-rw-r--r--UVtools.InstallerMM/UVtools.InstallerMM.wxs2
-rw-r--r--UVtools.WPF/Controls/Tools/ToolPCBExposureControl.axaml.cs5
-rw-r--r--UVtools.WPF/UVtools.WPF.csproj2
9 files changed, 118 insertions, 86 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 47408b9..545eeb2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 25/06/2022 - v3.5.2
+
+- **PCB Exposure:**
+ - (Add) Gerber file extensions: gko, gtl, gto, gts, gbl, gbo, gbs, gml
+ - (Fix) Trailing zeros suppression mode and improve the parsing of the coordinate string (#492)
+ - (Fix) Allow coordinates without number `XYD0*` to indicate `X=0` and `Y=0`
+ - (Fix) Do not try to fetch apertures lower than index 10 when a `D02` (closed shutter) is found alone
+
## 24/06/2022 - v3.5.1
- **PCB Exposure:**
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 0dd9480..d42886c 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,10 +1,6 @@
- **PCB Exposure:**
- - (Fix) Able to omit X or Y coordinate and use last known value in place
- - (Fix) Reusing macros in apertures was causing to use the last aperture values for all previous apertures that share the same macro name
- - (Fix) Implement the inch measurement (%MOIN*%)
- - (Fix) Crash when redo the operation (Ctrl + Shift + Z)
-- **UI - Issue list:**
- - (Add) Context menu when right click issues to select an action
- - (Add) Option to solidify suction cups when right click on the issue
- - (Improvement) Better confirmation text when click on remove issue(s) with detailed list of actions
+ - (Add) Gerber file extensions: gko, gtl, gto, gts, gbl, gbo, gbs, gml
+ - (Fix) Trailing zeros suppression mode and improve the parsing of the coordinate string (#492)
+ - (Fix) Allow coordinates without number `XYD0*` to indicate `X=0` and `Y=0`
+ - (Fix) Do not try to fetch apertures lower than index 10 when a `D02` (closed shutter) is found alone
diff --git a/UVtools.Core/Gerber/Enumerations.cs b/UVtools.Core/Gerber/Enumerations.cs
index 0e38c42..d4ba962 100644
--- a/UVtools.Core/Gerber/Enumerations.cs
+++ b/UVtools.Core/Gerber/Enumerations.cs
@@ -7,6 +7,22 @@
*/
namespace UVtools.Core.Gerber;
+public enum GerberZerosSuppressionType : byte
+{
+ /// <summary>
+ /// Do not omit zeros
+ /// </summary>
+ NoSuppression,
+ /// <summary>
+ /// Omit left zeros
+ /// </summary>
+ Leading,
+ /// <summary>
+ /// Omit right zeros
+ /// </summary>
+ Trail
+}
+
public enum GerberPositionType : byte
{
Absolute,
diff --git a/UVtools.Core/Gerber/GerberDocument.cs b/UVtools.Core/Gerber/GerberDocument.cs
index 3bd3887..5bde5bf 100644
--- a/UVtools.Core/Gerber/GerberDocument.cs
+++ b/UVtools.Core/Gerber/GerberDocument.cs
@@ -13,30 +13,35 @@ using System.IO;
using System.Text.RegularExpressions;
using Emgu.CV;
using Emgu.CV.CvEnum;
-using Emgu.CV.Structure;
using Emgu.CV.Util;
using UVtools.Core.Extensions;
using UVtools.Core.Gerber.Apertures;
namespace UVtools.Core.Gerber;
+/// <summary>
+/// https://www.ucamco.com/files/downloads/file_en/456/gerber-layer-format-specification-revision-2022-02_en.pdf?ac97011bf6bce9aaf0b1aac43d84b05f
+/// </summary>
public class GerberDocument
{
#region Properties
+ public GerberZerosSuppressionType ZerosSuppressionType { get; set; } = GerberZerosSuppressionType.NoSuppression;
public GerberPositionType PositionType { get; set; } = GerberPositionType.Absolute;
public GerberUnitType UnitType { get; set; } = GerberUnitType.Millimeter;
public GerberPolarityType Polarity { get; set; } = GerberPolarityType.Dark;
public GerberMoveType MoveType { get; set; } = GerberMoveType.Linear;
- public bool LeadingZeroOmitted { get; set; } = true;
-
public byte CoordinateXIntegers { get; set; } = 3;
public byte CoordinateXFractionalDigits { get; set; } = 6;
+ public byte CoordinateXLength => (byte)(CoordinateXIntegers + CoordinateXFractionalDigits);
+
public byte CoordinateYIntegers { get; set; } = 3;
public byte CoordinateYFractionalDigits { get; set; } = 6;
+ public byte CoordinateYLength => (byte)(CoordinateYIntegers + CoordinateYFractionalDigits);
+
public Dictionary<int, Aperture> Apertures { get; } = new();
public Dictionary<string, Macro> Macros { get; } = new();
@@ -101,11 +106,11 @@ public class GerberDocument
{
// %FSLAX34Y34*%
// 0123456789
- document.LeadingZeroOmitted = line[3] switch
+ document.ZerosSuppressionType = line[3] switch
{
- 'L' => true,
- 'T' => false,
- _ => document.LeadingZeroOmitted
+ 'L' => GerberZerosSuppressionType.Leading,
+ 'T' => GerberZerosSuppressionType.Trail,
+ _ => document.ZerosSuppressionType
};
document.PositionType = line[4] switch
{
@@ -113,6 +118,7 @@ public class GerberDocument
'I' => GerberPositionType.Relative,
_ => document.PositionType
};
+ if (document.PositionType == GerberPositionType.Relative) throw new NotImplementedException("Relative positions are not implemented yet.\nPlease use Absolute position for now.");
if (line[5] != 'X') continue;
if (byte.TryParse(line[6].ToString(), out var x1)) document.CoordinateXIntegers = x1;
if (byte.TryParse(line[7].ToString(), out var x2)) document.CoordinateXFractionalDigits = x2;
@@ -191,6 +197,7 @@ public class GerberDocument
continue;
}
+ // Aperture selector
if (line[0] == 'D')
{
var matchD = Regex.Match(line, @"D(\d+)");
@@ -198,15 +205,17 @@ public class GerberDocument
if (!int.TryParse(matchD.Groups[1].Value, out var d)) continue;
+ if(d < 10) continue;
if (!document.Apertures.TryGetValue(d, out currentAperture)) continue;
continue;
}
+
if (line[0] == 'X' || line[0] == 'Y')
{
- var matchX = Regex.Match(line, @"X-?(\d+)");
- var matchY = Regex.Match(line, @"Y-?(\d+)");
+ var matchX = Regex.Match(line, @"X-?(\d+)?");
+ var matchY = Regex.Match(line, @"Y-?(\d+)?");
var matchD = Regex.Match(line, @"D(\d+)");
double nowX = 0;
@@ -215,25 +224,20 @@ public class GerberDocument
if (!matchD.Success || matchD.Groups.Count < 2) continue;
if (!int.TryParse(matchD.Groups[1].Value, out var d)) continue;
- if (matchX.Success && matchX.Groups.Count >= 2)
+ if (matchX.Success)
{
- if (double.TryParse(matchX.Groups[1].Value, out nowX))
+ if (matchX.Groups.Count >= 2)
{
- if (nowX != 0)
+ var valueStr = document.ZerosSuppressionType switch
{
- if (document.CoordinateXFractionalDigits > matchX.Groups[1].Value.Length) // Leading zero omitted
- {
- double.TryParse($"0.{matchX.Groups[1].Value}", out nowX);
- }
- else
- {
- var integers = matchX.Groups[1].Value[..^document.CoordinateXFractionalDigits];
- var fraction = matchX.Groups[1].Value.Substring(matchX.Groups[1].Value.Length - document.CoordinateXFractionalDigits, document.CoordinateXFractionalDigits);
- double.TryParse($"{integers}.{fraction}", out nowX);
- }
-
- nowX = document.GetMillimeters(nowX);
- }
+ GerberZerosSuppressionType.Trail => matchX.Groups[1].Value.PadRight(document.CoordinateXLength, '0'),
+ _ => matchX.Groups[1].Value.PadLeft(document.CoordinateXLength, '0'),
+ };
+
+ var integers = valueStr[..document.CoordinateXIntegers];
+ var fraction = valueStr[document.CoordinateXIntegers..];
+ double.TryParse($"{integers}.{fraction}", out nowX);
+ nowX = document.GetMillimeters(nowX);
}
}
else
@@ -241,24 +245,21 @@ public class GerberDocument
nowX = currentX;
}
- if (matchY.Success && matchY.Groups.Count >= 2)
+ if (matchY.Success)
{
- if (double.TryParse(matchY.Groups[1].Value, out nowY))
+ if (matchY.Groups.Count >= 2)
{
- if (nowY != 0)
+ var valueStr = document.ZerosSuppressionType switch
{
- if (document.CoordinateYFractionalDigits > matchY.Groups[1].Value.Length) // Leading zero omitted
- {
- double.TryParse($"0.{matchY.Groups[1].Value}", out nowY);
- }
- else
- {
- var integers = matchY.Groups[1].Value[..^document.CoordinateYFractionalDigits];
- var fraction = matchY.Groups[1].Value.Substring(matchY.Groups[1].Value.Length - document.CoordinateYFractionalDigits, document.CoordinateYFractionalDigits);
- double.TryParse($"{integers}.{fraction}", out nowY);
- }
- nowY = document.GetMillimeters(nowY);
- }
+ GerberZerosSuppressionType.Trail => matchY.Groups[1].Value.PadRight(document.CoordinateYLength, '0'),
+ _ => matchY.Groups[1].Value.PadLeft(document.CoordinateYLength, '0'),
+ };
+
+ var integers = valueStr[..document.CoordinateYIntegers];
+ var fraction = valueStr[document.CoordinateYIntegers..];
+ double.TryParse($"{integers}.{fraction}", out nowY);
+ nowY = document.GetMillimeters(nowY);
+
}
}
else
@@ -289,46 +290,38 @@ public class GerberDocument
{
if (document.MoveType is GerberMoveType.Arc or GerberMoveType.ArcCounterClockwise)
{
+ double xOffset = 0;
+ double yOffset = 0;
var matchI = Regex.Match(line, @"I(-?\d+)");
var matchJ = Regex.Match(line, @"J(-?\d+)");
if(!matchI.Success || !matchJ.Success || matchI.Groups.Count < 2 || matchJ.Groups.Count < 2) continue;
- if (double.TryParse(matchI.Groups[1].Value, out var xOffset))
+ var valueStr = document.ZerosSuppressionType switch
{
- if (xOffset != 0)
- {
- if (document.CoordinateXFractionalDigits > matchI.Groups[1].Value.Length) // Leading zero omitted
- {
- double.TryParse($"0.{matchI.Groups[1].Value}", out xOffset);
- }
- else
- {
- var integers = matchI.Groups[1].Value[..^document.CoordinateXFractionalDigits];
- var fraction = matchI.Groups[1].Value.Substring(matchI.Groups[1].Value.Length - document.CoordinateXFractionalDigits, document.CoordinateXFractionalDigits);
- double.TryParse($"{integers}.{fraction}", out xOffset);
- }
- xOffset = document.GetMillimeters(xOffset);
- }
- }
+ GerberZerosSuppressionType.Trail => matchI.Groups[1].Value.PadRight(document.CoordinateXLength, '0'),
+ _ => matchI.Groups[1].Value.PadLeft(document.CoordinateXLength, '0'),
+ };
+
- if (double.TryParse(matchJ.Groups[1].Value, out var yOffset))
+ var integers = valueStr[..document.CoordinateXIntegers];
+ var fraction = valueStr[document.CoordinateXIntegers..];
+ double.TryParse($"{integers}.{fraction}", out xOffset);
+ xOffset = document.GetMillimeters(xOffset);
+
+
+ valueStr = document.ZerosSuppressionType switch
{
- if(yOffset != 0)
- {
- if (document.CoordinateYFractionalDigits > matchJ.Groups[1].Value.Length) // Leading zero omitted
- {
- double.TryParse($"0.{matchJ.Groups[1].Value}", out yOffset);
- }
- else
- {
- var integers = matchJ.Groups[1].Value[..^document.CoordinateYFractionalDigits];
- var fraction = matchJ.Groups[1].Value.Substring(matchJ.Groups[1].Value.Length - document.CoordinateYFractionalDigits, document.CoordinateYFractionalDigits);
- double.TryParse($"{integers}.{fraction}", out yOffset);
- }
- yOffset = document.GetMillimeters(yOffset);
- }
- }
+ GerberZerosSuppressionType.Trail => matchJ.Groups[1].Value.PadRight(document.CoordinateYLength, '0'),
+ _ => matchJ.Groups[1].Value.PadLeft(document.CoordinateYLength, '0'),
+ };
+
+
+ integers = valueStr[..document.CoordinateYIntegers];
+ fraction = valueStr[document.CoordinateYIntegers..];
+ double.TryParse($"{integers}.{fraction}", out yOffset);
+ yOffset = document.GetMillimeters(yOffset);
+
if (currentX == nowX && currentY == nowY) // Closed circle
{
diff --git a/UVtools.Core/Operations/OperationPCBExposure.cs b/UVtools.Core/Operations/OperationPCBExposure.cs
index 96fd82d..45aefce 100644
--- a/UVtools.Core/Operations/OperationPCBExposure.cs
+++ b/UVtools.Core/Operations/OperationPCBExposure.cs
@@ -11,6 +11,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.IO.Compression;
+using System.Linq;
using System.Text;
using Emgu.CV;
using Emgu.CV.CvEnum;
@@ -25,6 +26,22 @@ namespace UVtools.Core.Operations;
[Serializable]
public class OperationPCBExposure : Operation
{
+ #region
+
+ public static string[] ValidExtensions => new[]
+ {
+ "gbr", // Gerber
+ "gko", // Board outline layer
+ "gtl", // Top layer
+ "gto", // Top silkscreen layer
+ "gts", // Top solder mask layer
+ "gbl", // Bottom layer
+ "gbo", // Bottom silkscreen layer
+ "gbs", // Bottom solder mask layer
+ "gml", // Mechanical layer
+ };
+ #endregion
+
#region Members
private RangeObservableCollection<ValueDescription> _files = new();
@@ -189,7 +206,8 @@ public class OperationPCBExposure : Operation
var tmpPath = PathExtensions.GetTemporaryDirectory($"{About.Software}.");
foreach (var entry in zip.Entries)
{
- if(!entry.Name.EndsWith(".gbr")) continue;
+ if(!ValidExtensions.Any(extension => entry.Name.EndsWith($".{extension}", StringComparison.InvariantCultureIgnoreCase))) continue;
+
var filePath = entry.ImprovedExtractToFile(tmpPath, false);
if (!string.IsNullOrEmpty(filePath))
{
diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj
index eb96200..f92c898 100644
--- a/UVtools.Core/UVtools.Core.csproj
+++ b/UVtools.Core/UVtools.Core.csproj
@@ -10,7 +10,7 @@
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
<Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description>
- <Version>3.5.1</Version>
+ <Version>3.5.2</Version>
<Copyright>Copyright © 2020 PTRTECH</Copyright>
<PackageIcon>UVtools.png</PackageIcon>
<Platforms>AnyCPU;x64</Platforms>
diff --git a/UVtools.InstallerMM/UVtools.InstallerMM.wxs b/UVtools.InstallerMM/UVtools.InstallerMM.wxs
index 03b3cc7..05a325e 100644
--- a/UVtools.InstallerMM/UVtools.InstallerMM.wxs
+++ b/UVtools.InstallerMM/UVtools.InstallerMM.wxs
@@ -2,7 +2,7 @@
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?define ComponentRules="OneToOne"?>
<!-- SourceDir instructs IsWiX the location of the directory that contains files for this merge module -->
- <?define SourceDir="..\publish\UVtools_win-x64_v3.5.1"?>
+ <?define SourceDir="..\publish\UVtools_win-x64_v3.5.2"?>
<Module Id="UVtools" Language="1033" Version="1.0.0.0">
<Package Id="12aaa1cf-ff06-4a02-abd5-2ac01ac4f83b" Manufacturer="PTRTECH" InstallerVersion="200" Keywords="MSLA, DLP" Description="MSLA/DLP, file analysis, repair, conversion and manipulation" InstallScope="perMachine" Platform="x64" />
<Directory Id="TARGETDIR" Name="SourceDir">
diff --git a/UVtools.WPF/Controls/Tools/ToolPCBExposureControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolPCBExposureControl.axaml.cs
index 4bcebac..ceb8d25 100644
--- a/UVtools.WPF/Controls/Tools/ToolPCBExposureControl.axaml.cs
+++ b/UVtools.WPF/Controls/Tools/ToolPCBExposureControl.axaml.cs
@@ -92,7 +92,8 @@ namespace UVtools.WPF.Controls.Tools
{
return;
}
- if (!_selectedFile.ValueAsString.EndsWith(".gbr", StringComparison.OrdinalIgnoreCase) || !File.Exists(_selectedFile.ValueAsString)) return;
+
+ if (!OperationPCBExposure.ValidExtensions.Any(extension => _selectedFile.ValueAsString.EndsWith($".{extension}", StringComparison.InvariantCultureIgnoreCase)) || !File.Exists(_selectedFile.ValueAsString)) return;
using var mat = Operation.GetMat(_selectedFile.ValueAsString);
using var matCropped = mat.CropByBounds(20);
_previewImage?.Dispose();
@@ -115,7 +116,7 @@ namespace UVtools.WPF.Controls.Tools
new()
{
Name = "Gerber files",
- Extensions = new List<string>{ "gbr" }
+ Extensions = new List<string>(OperationPCBExposure.ValidExtensions)
},
},
};
diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj
index e962877..7cb97cc 100644
--- a/UVtools.WPF/UVtools.WPF.csproj
+++ b/UVtools.WPF/UVtools.WPF.csproj
@@ -12,7 +12,7 @@
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
- <Version>3.5.1</Version>
+ <Version>3.5.2</Version>
<Platforms>AnyCPU;x64</Platforms>
<PackageIcon>UVtools.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>