From f914d77538c693155de9333d746d29d6c9958178 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Concei=C3=A7=C3=A3o?= Date: Thu, 8 Apr 2021 00:16:29 +0100 Subject: v2.8.4 * (Improvement) Layers: "IsBottomLayer" property will now computing the value taking the height into consideration instead of it index, this allow to identify the real bottom layers when using multiple layers with same heights * (Fix) GCode Builder: Finish print lift to top was setting the incorrect feedrate if the file format is not in mm/m speed units * **Operations:** * **Exposure time finder:** * Add option to "Also set light-off delay to zero" when "Do not perform the lifting sequence for layers with same Z positioning" is enabled * Layers heights with more than 3 decimals was limiting the layer generation to 2 decimals leading to wrong the layer thickness * Allow set layer heights with 3 decimals * **Elephant foot:** * Bottom and normal layers count was showing with decimals * Allow set layer heights with 3 decimals * XYZ Accuracy: Allow set layer heights with 3 decimals * Tolerance XYZ: Allow set layer heights with 3 decimals * Grayscale: Allow set layer heights with 3 decimals * Stress tower: Allow set layer heights with 3 decimals * Calculator - Optimal model tilt: Allow layer heights with 3 decimals --- CHANGELOG.md | 18 +++ UVtools.Core/FileFormats/ZCodeFile.cs | 3 + UVtools.Core/GCode/GCodeBuilder.cs | 15 +- UVtools.Core/Layer/Layer.cs | 5 +- UVtools.Core/Layer/LayerManager.cs | 2 +- UVtools.Core/Operations/OperationCalculator.cs | 2 +- .../Operations/OperationCalibrateExposureFinder.cs | 16 +- UVtools.Core/Operations/OperationLayerReHeight.cs | 8 +- UVtools.Core/UVtools.Core.csproj | 2 +- .../Calibrators/CalibrateElephantFootControl.axaml | 7 +- .../CalibrateExposureFinderControl.axaml | 55 ++++--- .../Calibrators/CalibrateGrayscaleControl.axaml | 6 +- .../Calibrators/CalibrateStressTowerControl.axaml | 22 +-- .../Calibrators/CalibrateToleranceControl.axaml | 163 ++------------------- .../Calibrators/CalibrateXYZAccuracyControl.axaml | 24 +-- .../Controls/Tools/ToolCalculatorControl.axaml | 27 ++-- .../Tools/ToolDynamicLayerHeightControl.axaml | 33 ----- UVtools.WPF/Controls/Tools/ToolRotateControl.axaml | 2 +- UVtools.WPF/UVtools.WPF.csproj | 2 +- UVtools.WPF/Windows/SettingsWindow.axaml | 4 +- 20 files changed, 146 insertions(+), 270 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81741cf..3336159 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## 08/04/2021 - v2.8.4 + +* (Improvement) Layers: "IsBottomLayer" property will now computing the value taking the height into consideration instead of it index, this allow to identify the real bottom layers when using multiple layers with same heights +* (Fix) GCode Builder: Finish print lift to top was setting the incorrect feedrate if the file format is not in mm/m speed units +* **Operations:** + * **Exposure time finder:** + * Add option to "Also set light-off delay to zero" when "Do not perform the lifting sequence for layers with same Z positioning" is enabled + * Layers heights with more than 3 decimals was limiting the layer generation to 2 decimals leading to wrong the layer thickness + * Allow set layer heights with 3 decimals + * **Elephant foot:** + * Bottom and normal layers count was showing with decimals + * Allow set layer heights with 3 decimals + * XYZ Accuracy: Allow set layer heights with 3 decimals + * Tolerance XYZ: Allow set layer heights with 3 decimals + * Grayscale: Allow set layer heights with 3 decimals + * Stress tower: Allow set layer heights with 3 decimals + * Calculator - Optimal model tilt: Allow layer heights with 3 decimals + ## 07/04/2021 - v2.8.3 * File formats: Sanitize and check layers on encoding/saving file, will thrown a error and prevent the save if found any diff --git a/UVtools.Core/FileFormats/ZCodeFile.cs b/UVtools.Core/FileFormats/ZCodeFile.cs index 86e08e3..4d42c1d 100644 --- a/UVtools.Core/FileFormats/ZCodeFile.cs +++ b/UVtools.Core/FileFormats/ZCodeFile.cs @@ -426,6 +426,7 @@ namespace UVtools.Core.FileFormats #endregion + #region Constructor public ZCodeFile() { GCode.UseTailComma = true; @@ -435,7 +436,9 @@ namespace UVtools.Core.FileFormats GCode.GCodeTimeUnit = GCodeBuilder.GCodeTimeUnits.Milliseconds; GCode.GCodeShowImageType = GCodeBuilder.GCodeShowImageTypes.FilenameNonZeroPNG; GCode.MaxLEDPower = MaxLEDPower; + GCode.CommandClearImage.Enabled = false; } + #endregion #region Methods diff --git a/UVtools.Core/GCode/GCodeBuilder.cs b/UVtools.Core/GCode/GCodeBuilder.cs index ebe238b..c59bb56 100644 --- a/UVtools.Core/GCode/GCodeBuilder.cs +++ b/UVtools.Core/GCode/GCodeBuilder.cs @@ -554,7 +554,18 @@ namespace UVtools.Core.GCode break; } - AppendEndGCode(finalRaiseZPosition, slicerFile.LiftSpeed); + float endFeedRate = 0; + switch (GCodeSpeedUnit) + { + case GCodeSpeedUnits.MillimetersPerSecond: + endFeedRate = (float)Math.Round(slicerFile.RetractSpeed / 60, 2); + break; + case GCodeSpeedUnits.CentimetersPerMinute: + endFeedRate = (float)Math.Round(slicerFile.RetractSpeed / 10, 2); + break; + } + + AppendEndGCode(finalRaiseZPosition, endFeedRate); } public void RebuildGCode(FileFormat slicerFile, object[] configs, string separator = ":") @@ -769,7 +780,7 @@ namespace UVtools.Core.GCode if (bottomLayer.LightPWM > 0) slicerFile.BottomLightPWM = bottomLayer.LightPWM; } - var normalLayer = slicerFile[slicerFile.LastLayerIndex]; + var normalLayer = slicerFile.LastLayer; if (normalLayer is not null) { if (normalLayer.ExposureTime > 0) slicerFile.ExposureTime = normalLayer.ExposureTime; diff --git a/UVtools.Core/Layer/Layer.cs b/UVtools.Core/Layer/Layer.cs index b01fc52..a5dc4e9 100644 --- a/UVtools.Core/Layer/Layer.cs +++ b/UVtools.Core/Layer/Layer.cs @@ -26,6 +26,9 @@ namespace UVtools.Core { #region Constants public const byte HeightPrecision = 3; + public const decimal HeightPrecisionIncrement = 0.001M; + public const decimal MinimumHeight = 0.01M; + public const decimal MaximumHeight = 0.2M; #endregion #region Members @@ -113,7 +116,7 @@ namespace UVtools.Core } } - public bool IsBottomLayer => Index < ParentLayerManager.SlicerFile.BottomLayerCount; + public bool IsBottomLayer => (uint)(PositionZ / SlicerFile.LayerHeight) <= ParentLayerManager.SlicerFile.BottomLayerCount; public bool IsNormalLayer => !IsBottomLayer; /// diff --git a/UVtools.Core/Layer/LayerManager.cs b/UVtools.Core/Layer/LayerManager.cs index 1862223..1895bcd 100644 --- a/UVtools.Core/Layer/LayerManager.cs +++ b/UVtools.Core/Layer/LayerManager.cs @@ -520,7 +520,7 @@ namespace UVtools.Core var layer = this[layerIndex]; if (this[layerIndex - 1].PositionZ != layer.PositionZ) continue; layer.LiftHeight = 0; - //if(zeroLightOffDelay) layer.LightOffDelay = 0; + if(zeroLightOffDelay) layer.LightOffDelay = 0; } SlicerFile?.RebuildGCode(); } diff --git a/UVtools.Core/Operations/OperationCalculator.cs b/UVtools.Core/Operations/OperationCalculator.cs index 68aa251..d4c0384 100644 --- a/UVtools.Core/Operations/OperationCalculator.cs +++ b/UVtools.Core/Operations/OperationCalculator.cs @@ -390,7 +390,7 @@ namespace UVtools.Core.Operations get => _layerHeight; set { - if (!RaiseAndSetIfChanged(ref _layerHeight, value)) return; + if (!RaiseAndSetIfChanged(ref _layerHeight, Layer.RoundHeight(value))) return; RaisePropertyChanged(nameof(XYResolution)); RaisePropertyChanged(nameof(XYResolutionUm)); RaisePropertyChanged(nameof(TiltAngleDegrees)); diff --git a/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs b/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs index e9bdbb0..7f60893 100644 --- a/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs +++ b/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs @@ -78,6 +78,7 @@ namespace UVtools.Core.Operations private decimal _multipleLayerHeightStep = 0.01m; private bool _dontLiftSamePositionedLayers; + private bool _zeroLightOffSamePositionedLayers; private bool _multipleExposures; private ExposureGenTypes _exposureGenType = ExposureGenTypes.Linear; private bool _exposureGenIgnoreBaseExposure; @@ -600,6 +601,12 @@ namespace UVtools.Core.Operations set => RaiseAndSetIfChanged(ref _dontLiftSamePositionedLayers, value); } + public bool ZeroLightOffSamePositionedLayers + { + get => _zeroLightOffSamePositionedLayers; + set => RaiseAndSetIfChanged(ref _zeroLightOffSamePositionedLayers, value); + } + public bool MultipleExposures { get => _multipleExposures; @@ -758,7 +765,7 @@ namespace UVtools.Core.Operations private bool Equals(OperationCalibrateExposureFinder other) { - return _layerHeight == other._layerHeight && _bottomLayers == other._bottomLayers && _bottomExposure == other._bottomExposure && _normalExposure == other._normalExposure && _topBottomMargin == other._topBottomMargin && _leftRightMargin == other._leftRightMargin && _chamferLayers == other._chamferLayers && _erodeBottomIterations == other._erodeBottomIterations && _partMargin == other._partMargin && _enableAntiAliasing == other._enableAntiAliasing && _mirrorOutput == other._mirrorOutput && _baseHeight == other._baseHeight && _featuresHeight == other._featuresHeight && _featuresMargin == other._featuresMargin && _unitOfMeasure == other._unitOfMeasure && _holeDiametersPx == other._holeDiametersPx && _holeDiametersMm == other._holeDiametersMm && _barSpacing == other._barSpacing && _barLength == other._barLength && _barVerticalSplitter == other._barVerticalSplitter && _barThicknessesPx == other._barThicknessesPx && _barThicknessesMm == other._barThicknessesMm && _textFont == other._textFont && _textScale.Equals(other._textScale) && _textThickness == other._textThickness && _text == other._text && _multipleBrightness == other._multipleBrightness && _multipleBrightnessExcludeFrom == other._multipleBrightnessExcludeFrom && _multipleBrightnessValues == other._multipleBrightnessValues && _dontLiftSamePositionedLayers == other._dontLiftSamePositionedLayers && _multipleLayerHeight == other._multipleLayerHeight && _multipleLayerHeightMaximum == other._multipleLayerHeightMaximum && _multipleLayerHeightStep == other._multipleLayerHeightStep && _multipleExposures == other._multipleExposures && _exposureGenType == other._exposureGenType && _exposureGenIgnoreBaseExposure == other._exposureGenIgnoreBaseExposure && _exposureGenBottomStep == other._exposureGenBottomStep && _exposureGenNormalStep == other._exposureGenNormalStep && _exposureGenTests == other._exposureGenTests && Equals(_exposureTable, other._exposureTable) && _holeShape == other._holeShape; + return _layerHeight == other._layerHeight && _bottomLayers == other._bottomLayers && _bottomExposure == other._bottomExposure && _normalExposure == other._normalExposure && _topBottomMargin == other._topBottomMargin && _leftRightMargin == other._leftRightMargin && _chamferLayers == other._chamferLayers && _erodeBottomIterations == other._erodeBottomIterations && _partMargin == other._partMargin && _enableAntiAliasing == other._enableAntiAliasing && _mirrorOutput == other._mirrorOutput && _baseHeight == other._baseHeight && _featuresHeight == other._featuresHeight && _featuresMargin == other._featuresMargin && _unitOfMeasure == other._unitOfMeasure && _holeDiametersPx == other._holeDiametersPx && _holeDiametersMm == other._holeDiametersMm && _barSpacing == other._barSpacing && _barLength == other._barLength && _barVerticalSplitter == other._barVerticalSplitter && _barThicknessesPx == other._barThicknessesPx && _barThicknessesMm == other._barThicknessesMm && _textFont == other._textFont && _textScale.Equals(other._textScale) && _textThickness == other._textThickness && _text == other._text && _multipleBrightness == other._multipleBrightness && _multipleBrightnessExcludeFrom == other._multipleBrightnessExcludeFrom && _multipleBrightnessValues == other._multipleBrightnessValues && _dontLiftSamePositionedLayers == other._dontLiftSamePositionedLayers && _zeroLightOffSamePositionedLayers == other._zeroLightOffSamePositionedLayers && _multipleLayerHeight == other._multipleLayerHeight && _multipleLayerHeightMaximum == other._multipleLayerHeightMaximum && _multipleLayerHeightStep == other._multipleLayerHeightStep && _multipleExposures == other._multipleExposures && _exposureGenType == other._exposureGenType && _exposureGenIgnoreBaseExposure == other._exposureGenIgnoreBaseExposure && _exposureGenBottomStep == other._exposureGenBottomStep && _exposureGenNormalStep == other._exposureGenNormalStep && _exposureGenTests == other._exposureGenTests && Equals(_exposureTable, other._exposureTable) && _holeShape == other._holeShape; } public override bool Equals(object obj) @@ -802,6 +809,7 @@ namespace UVtools.Core.Operations hashCode.Add(_multipleLayerHeightMaximum); hashCode.Add(_multipleLayerHeightStep); hashCode.Add(_dontLiftSamePositionedLayers); + hashCode.Add(_zeroLightOffSamePositionedLayers); hashCode.Add(_multipleExposures); hashCode.Add((int) _exposureGenType); hashCode.Add(_exposureGenIgnoreBaseExposure); @@ -1156,7 +1164,7 @@ namespace UVtools.Core.Operations if (!layerDifference.IsInteger()) return; // Not at right height to process with layer height //Debug.WriteLine($"{currentHeight} / {layerHeight} = {layerDifference}, Floor={Math.Floor(layerDifference)}"); - using Mat mat = EmguExtensions.InitMat(SlicerFile.Resolution); + using var mat = EmguExtensions.InitMat(SlicerFile.Resolution); int layerCountOnHeight = (int)Math.Floor(currentHeight / layerHeight); bool isBottomLayer = layerCountOnHeight <= _bottomLayers; bool isBaseLayer = currentHeight <= _baseHeight; @@ -1263,7 +1271,7 @@ namespace UVtools.Core.Operations progress++; } - for (decimal currentHeight = _layerHeight; currentHeight <= totalHeight; currentHeight += 0.01m) + for (decimal currentHeight = _layerHeight; currentHeight <= totalHeight; currentHeight += Layer.HeightPrecisionIncrement) { currentHeight = Layer.RoundHeight(currentHeight); for (decimal layerHeight = _layerHeight; layerHeight <= endLayerHeight; layerHeight += _multipleLayerHeightStep) @@ -1302,7 +1310,7 @@ namespace UVtools.Core.Operations if (_dontLiftSamePositionedLayers) { - SlicerFile.LayerManager.SetNoLiftForSamePositionedLayers(); + SlicerFile.LayerManager.SetNoLiftForSamePositionedLayers(_zeroLightOffSamePositionedLayers); } if (_mirrorOutput) diff --git a/UVtools.Core/Operations/OperationLayerReHeight.cs b/UVtools.Core/Operations/OperationLayerReHeight.cs index 7b26095..a7fa89e 100644 --- a/UVtools.Core/Operations/OperationLayerReHeight.cs +++ b/UVtools.Core/Operations/OperationLayerReHeight.cs @@ -78,9 +78,9 @@ namespace UVtools.Core.Operations var list = new List(); for (byte i = 2; i < 255; i++) // Go lower heights { - if (layerHeight / i < 0.01m) break; + if (layerHeight / i < Layer.MinimumHeight) break; if ((layerCount * (decimal)i).DecimalDigits() > 0) continue; // Cant multiply layers, no half layers! - if ((layerHeight / i).DecimalDigits() > 3) continue; // Cant divide height, more than 3 digits + if ((layerHeight / i).DecimalDigits() > Layer.HeightPrecision) continue; // Cant divide height, more than 3 digits var item = new OperationLayerReHeightItem(false, i, Layer.RoundHeight(layerHeight / i), layerCount * i); list.Add(item); @@ -88,9 +88,9 @@ namespace UVtools.Core.Operations for (byte i = 2; i < 255; i++) // Go higher heights { - if (layerHeight * i > 0.20m) break; + if (layerHeight * i > Layer.MaximumHeight) break; if ((layerCount / (decimal)i).DecimalDigits() > 0) continue; // Cant divide layers, no half layers! - if ((layerHeight * i).DecimalDigits() > 3) continue; // Cant multiply height, more than 3 digits + if ((layerHeight * i).DecimalDigits() > Layer.HeightPrecision) continue; // Cant multiply height, more than 3 digits var item = new OperationLayerReHeightItem(true, i, Layer.RoundHeight(layerHeight * i), layerCount / i); list.Add(item); diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj index e0cf444..01dd2dc 100644 --- a/UVtools.Core/UVtools.Core.csproj +++ b/UVtools.Core/UVtools.Core.csproj @@ -10,7 +10,7 @@ https://github.com/sn4k3/UVtools https://github.com/sn4k3/UVtools MSLA/DLP, file analysis, calibration, repair, conversion and manipulation - 2.8.3 + 2.8.4 Copyright © 2020 PTRTECH UVtools.png AnyCPU;x64 diff --git a/UVtools.WPF/Controls/Calibrators/CalibrateElephantFootControl.axaml b/UVtools.WPF/Controls/Calibrators/CalibrateElephantFootControl.axaml index 416e9d9..82863cf 100644 --- a/UVtools.WPF/Controls/Calibrators/CalibrateElephantFootControl.axaml +++ b/UVtools.WPF/Controls/Calibrators/CalibrateElephantFootControl.axaml @@ -20,7 +20,7 @@ Increment="0.01" Minimum="0.01" Maximum="0.30" - FormatString="F02" + FormatString="F3" Value="{Binding Operation.LayerHeight}"/> + Value="{Binding Operation.BottomLayers}"/> @@ -58,7 +56,6 @@ Increment="1" Minimum="1" Maximum="1000" - FormatString="F02" Value="{Binding Operation.NormalLayers}"/> + FormatString="F3" + Value="{Binding Operation.LayerHeight}"/> @@ -85,7 +84,7 @@ Increment="0.5" Minimum="0.1" Maximum="200" - FormatString="F02" + FormatString="F2" Value="{Binding Operation.BottomExposure}"/> - + + + + - - - + @@ -374,7 +374,7 @@ Minimum="0" Maximum="100" Width="150" - FormatString="F02" + FormatString="F2" Value="{Binding Operation.ObservedYSize}"/> @@ -386,7 +386,7 @@ Minimum="0" Maximum="100" Width="150" - FormatString="F02" + FormatString="F2" Value="{Binding Operation.ObservedZSize}"/> diff --git a/UVtools.WPF/Controls/Tools/ToolCalculatorControl.axaml b/UVtools.WPF/Controls/Tools/ToolCalculatorControl.axaml index 2610afd..c179b3b 100644 --- a/UVtools.WPF/Controls/Tools/ToolCalculatorControl.axaml +++ b/UVtools.WPF/Controls/Tools/ToolCalculatorControl.axaml @@ -85,7 +85,7 @@ Minimum="0" Maximum="100000" Increment="0.01" - FormatString="F02" + FormatString="F2" Value="{Binding Operation.CalcMillimetersToPixels.DisplayWidth}" /> - - diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj index 192c8c1..14e4907 100644 --- a/UVtools.WPF/UVtools.WPF.csproj +++ b/UVtools.WPF/UVtools.WPF.csproj @@ -12,7 +12,7 @@ LICENSE https://github.com/sn4k3/UVtools Git - 2.8.3 + 2.8.4 diff --git a/UVtools.WPF/Windows/SettingsWindow.axaml b/UVtools.WPF/Windows/SettingsWindow.axaml index cd66987..1799cf3 100644 --- a/UVtools.WPF/Windows/SettingsWindow.axaml +++ b/UVtools.WPF/Windows/SettingsWindow.axaml @@ -1472,7 +1472,7 @@ Minimum="0" Maximum="255" Increment="0.5" - FormatString="F02" + FormatString="F2" Value="{Binding Settings.Automations.LightOffDelay}"/>