Skip to content

Commit

Permalink
v5.0.4
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
sn4k3 committed Jan 8, 2025
1 parent bf423f4 commit d1c88b9
Show file tree
Hide file tree
Showing 17 changed files with 175 additions and 89 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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:
Expand Down
3 changes: 2 additions & 1 deletion CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,5 @@
- Jeremy Conoley
- Brady George
- Ryan Skow
- Cainam
- Cainam
- Cory Lytle
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
<AccelerateBuildsInVisualStudio>true</AccelerateBuildsInVisualStudio>

<!-- Versions -->
<UVtoolsVersion>5.0.3</UVtoolsVersion>
<UVtoolsVersion>5.0.4</UVtoolsVersion>
<AvaloniaVersion>11.2.3</AvaloniaVersion>

<!-- MvvmToolkit -->
Expand Down
15 changes: 5 additions & 10 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -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

26 changes: 19 additions & 7 deletions UVtools.Core/Gerber/Apertures/Aperture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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":
{
Expand All @@ -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":
{
Expand All @@ -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
{
Expand All @@ -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();
Expand Down
17 changes: 14 additions & 3 deletions UVtools.Core/Gerber/Apertures/CircleAperture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,38 @@
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using System.Drawing;
using UVtools.Core.Extensions;

namespace UVtools.Core.Gerber.Apertures;

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);
}
}
}
43 changes: 0 additions & 43 deletions UVtools.Core/Gerber/Apertures/EllipseAperture.cs

This file was deleted.

74 changes: 74 additions & 0 deletions UVtools.Core/Gerber/Apertures/ObroundAperture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* GNU AFFERO GENERAL PUBLIC LICENSE
* Version 3, 19 November 2007
* Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
* 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);
}
}
}
17 changes: 15 additions & 2 deletions UVtools.Core/Gerber/Apertures/PoygonAperture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
22 changes: 19 additions & 3 deletions UVtools.Core/Gerber/Apertures/RectangleAperture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,48 @@
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;

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);
}
}
}
4 changes: 2 additions & 2 deletions UVtools.Core/Gerber/Macro.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand All @@ -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]);
Expand Down
Loading

0 comments on commit d1c88b9

Please sign in to comment.