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:
Diffstat (limited to 'UVtools.Core/Operations/OperationPCBExposure.cs')
-rw-r--r--UVtools.Core/Operations/OperationPCBExposure.cs213
1 files changed, 213 insertions, 0 deletions
diff --git a/UVtools.Core/Operations/OperationPCBExposure.cs b/UVtools.Core/Operations/OperationPCBExposure.cs
new file mode 100644
index 0000000..8ec2f99
--- /dev/null
+++ b/UVtools.Core/Operations/OperationPCBExposure.cs
@@ -0,0 +1,213 @@
+/*
+ * 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 System;
+using System.IO;
+using System.Text;
+using Emgu.CV;
+using Emgu.CV.CvEnum;
+using UVtools.Core.Extensions;
+using UVtools.Core.FileFormats;
+using UVtools.Core.Gerber;
+using UVtools.Core.Layers;
+
+namespace UVtools.Core.Operations;
+
+[Serializable]
+public class OperationPCBExposure : Operation
+{
+ #region Enum
+
+ public enum LithophaneBaseType : byte
+ {
+ None,
+ Square,
+ Model
+ }
+
+ #endregion
+
+ #region Members
+ private string? _filePath;
+
+ private decimal _layerHeight;
+ private decimal _exposureTime;
+ private bool _mirror;
+ private bool _invertColor;
+ private bool _enableAntiAliasing;
+
+ #endregion
+
+ #region Overrides
+
+ public override LayerRangeSelection StartLayerRangeSelection => LayerRangeSelection.None;
+ public override string IconClass => "fas fa-microchip";
+ public override string Title => "PCB exposure";
+ public override string Description =>
+ "Converts a gerber file to a pixel perfect image given your printer LCD/resolution to exposure the copper traces.\n" +
+ "Note: The current opened file will be overwritten with this gerber image, use a dummy or a not needed file.";
+
+ public override string ConfirmationText =>
+ "generate the PCB traces?";
+
+ public override string ProgressTitle =>
+ "Generating PCB traces";
+
+ public override string ProgressAction => "Tracing";
+
+ public override string? ValidateInternally()
+ {
+ var sb = new StringBuilder();
+ if (string.IsNullOrWhiteSpace(_filePath))
+ {
+ sb.AppendLine("The input file is empty");
+ }
+ else if(!File.Exists(_filePath))
+ {
+ sb.AppendLine("The input file does not exists");
+ }
+
+ return sb.ToString();
+ }
+
+ public override string ToString()
+ {
+ var result = $"{(FileExists ? $"{Path.GetFileName(_filePath)} [Exposure: {_exposureTime}s] [Invert: {_invertColor}]" : $"[Exposure: {_exposureTime}s] [Invert: {_invertColor}]")}";
+ if (!string.IsNullOrEmpty(ProfileName)) result = $"{ProfileName}: {result}";
+ return result;
+ }
+ #endregion
+
+ #region Constructor
+
+ public OperationPCBExposure() { }
+
+ public OperationPCBExposure(FileFormat slicerFile) : base(slicerFile)
+ {
+ if (_layerHeight <= 0) _layerHeight = (decimal)SlicerFile.LayerHeight;
+ if (_exposureTime <= 0) _exposureTime = (decimal)SlicerFile.BottomExposureTime;
+ _mirror = SlicerFile.DisplayMirror != FlipDirection.None;
+ }
+
+ #endregion
+
+ #region Properties
+ public string? FilePath
+ {
+ get => _filePath;
+ set => RaiseAndSetIfChanged(ref _filePath, value);
+ }
+ public bool FileExists => !string.IsNullOrWhiteSpace(_filePath) && File.Exists(_filePath);
+
+ public decimal LayerHeight
+ {
+ get => _layerHeight;
+ set => RaiseAndSetIfChanged(ref _layerHeight, Layer.RoundHeight(value));
+ }
+
+ public decimal ExposureTime
+ {
+ get => _exposureTime;
+ set => RaiseAndSetIfChanged(ref _exposureTime, Math.Round(value, 2));
+ }
+
+ public bool Mirror
+ {
+ get => _mirror;
+ set => RaiseAndSetIfChanged(ref _mirror, value);
+ }
+
+ public bool InvertColor
+ {
+ get => _invertColor;
+ set => RaiseAndSetIfChanged(ref _invertColor, value);
+ }
+
+ public bool EnableAntiAliasing
+ {
+ get => _enableAntiAliasing;
+ set => RaiseAndSetIfChanged(ref _enableAntiAliasing, value);
+ }
+
+ #endregion
+
+ #region Equality
+
+ protected bool Equals(OperationPCBExposure other)
+ {
+ return _filePath == other._filePath && _layerHeight == other._layerHeight && _exposureTime == other._exposureTime && _mirror == other._mirror && _invertColor == other._invertColor && _enableAntiAliasing == other._enableAntiAliasing;
+ }
+
+ public override bool Equals(object? obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != this.GetType()) return false;
+ return Equals((OperationPCBExposure) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(_filePath, _layerHeight, _exposureTime, _mirror, _invertColor, _enableAntiAliasing);
+ }
+
+ #endregion
+
+ #region Methods
+
+ public Mat GetMat()
+ {
+ var mat = SlicerFile.CreateMat();
+ if (!FileExists) return mat;
+ GerberDocument.ParseAndDraw(_filePath!, mat, _enableAntiAliasing);
+
+ //var boundingRectangle = CvInvoke.BoundingRectangle(mat);
+ //var cropped = mat.Roi(new Size(boundingRectangle.Right, boundingRectangle.Bottom));
+ var cropped = mat.CropByBounds();
+
+ if (_invertColor) CvInvoke.BitwiseNot(cropped, cropped);
+ if (_mirror)
+ {
+ var flip = SlicerFile.DisplayMirror;
+ if (flip == FlipDirection.None) flip = FlipDirection.Horizontally;
+ CvInvoke.Flip(cropped, cropped, (FlipType)flip);
+ }
+
+ return mat;
+ }
+
+ protected override bool ExecuteInternally(OperationProgress progress)
+ {
+ using var mat = GetMat();
+ var layer = new Layer(mat, SlicerFile);
+ layer.SetNoDelays();
+
+ SlicerFile.SuppressRebuildPropertiesWork(() =>
+ {
+ SlicerFile.LayerHeight = (float) _layerHeight;
+ SlicerFile.BottomLayerCount = 1;
+ SlicerFile.BottomExposureTime = (float) _exposureTime;
+ SlicerFile.ExposureTime = (float)_exposureTime;
+ SlicerFile.LiftHeightTotal = 0;
+ SlicerFile.SetNoDelays();
+
+ SlicerFile.Layers = new[] { layer };
+ }, true);
+
+
+ using var croppedMat = mat.CropByBounds(20);
+ using var bgrMat = new Mat();
+ CvInvoke.CvtColor(croppedMat, bgrMat, ColorConversion.Gray2Bgr);
+ SlicerFile.SetThumbnails(bgrMat);
+
+ return !progress.Token.IsCancellationRequested;
+ }
+
+
+ #endregion
+} \ No newline at end of file