Files
UVtools/UVtools.Core/Operations/OperationRaiseOnPrintFinish.cs
Tiago Conceição 8e4995a6a5 v3.8.3
- **UVtoolsCmd:**
  - **print-properties:**
    - (Change) `-b`, `--base` option to `-a`, `-all` to indicate all properties and sub-properties, now defaults to only show base properties
    - (Add) `-r`, `--range` option to prints only the matching layer(s) index(es) in a range
    - (Add) `-i`, `--indexes` option to prints only the matching layer(s) index(es)
  - (Add) Command: `set-properties <input-file> <property=value> Set properties in a file or to it layers with new values`
  - (Add) Command: `print-issues <input-file> Detect and print issues in a file`
  - (Add) New option to the `run` command: `-p, --property <property=value>  Set a property with a new value (Compatible with operations only)`
  - (Remove) Command: `print-layers` as it has been moved to `print-properties`, use `-r :` to obtain same result as default on `print-layers`
- **Issues:**
  - (Fix) Issues groups with only one issue was displaying the wrong area value
  - (Fix) Volume incorrectly calculated, resulting in a high value for group of issues
  - (Fix) Incorrect calculation of the bounding rectangle for a group of issues
- **Repair layers:**
  - (Add) Switch to opt between "Re-detect the selected issues before repair" and "Use and repair the previous detected issues" (Default)
  - (Improvement) Do not allow to run the tool if there are no detected issues when the option "Use and repair the previous detected issues" is selected
- (Improvement) Linux: Recompile libcvextern.so on a older system to be able to run on both older and newest system (#603)
- (Upgrade) .NET from 6.0.10 to 6.0.11
2022-11-10 04:09:00 +00:00

205 lines
7.0 KiB
C#

/*
* 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.Text;
using UVtools.Core.Extensions;
using UVtools.Core.FileFormats;
using UVtools.Core.Layers;
namespace UVtools.Core.Operations;
public class OperationRaiseOnPrintFinish : Operation
{
#region Constants
#endregion
#region Members
private decimal _positionZ;
private decimal _waitTime = 1200; // 20m
private bool _outputDummyPixel = true;
#endregion
#region Overrides
public override LayerRangeSelection StartLayerRangeSelection => LayerRangeSelection.None;
public override string IconClass => "fa-solid fa-level-up-alt";
public override string Title => "Raise platform on print finish";
public override string Description =>
"Raise the build platform to a set position after finish the print.\n\n" +
"NOTE: Only use this tool once and if your printer firmware don't already raise the build platform after finish the print.\n" +
"This will create a \"empty\" layer on end to simulate a print at a defined height.\n" +
"Not compatible with all printers, still it won't cause any harm if printer don't support this strategy.";
public override string ConfirmationText =>
$"raise the platform on print finish to Z={_positionZ}mm";
public override string ProgressTitle =>
$"Inserting dummy layer on end";
public override string ProgressAction => "Inserted layer";
public override string? ValidateSpawn()
{
if(!SlicerFile.CanUseLayerPositionZ)
{
return NotSupportedMessage;
}
if (SlicerFile.LayerCount >= 2)
{
var layerHeight = SlicerFile.LastLayer!.LayerHeight;
var criteria = Math.Max((float) Layer.MaximumHeight, SlicerFile.LayerHeight);
if (layerHeight > criteria)
{
return $"With a difference of {layerHeight}mm between the last two layers, it looks like this tool had already been applied.\n" +
$"The difference must be less or equal to {criteria}mm in order to run this tool.";
}
}
return null;
}
public override string? ValidateInternally()
{
var sb = new StringBuilder();
if (!ValidateSpawn(out var message))
{
sb.AppendLine(message);
}
if((float)_positionZ < SlicerFile.PrintHeight)
{
sb.AppendLine($"Can't raise to {_positionZ}mm, because it's below the maximum print height of {SlicerFile.PrintHeight}mm.");
}
else if ((float)_positionZ == SlicerFile.PrintHeight)
{
sb.AppendLine($"Raise to {_positionZ}mm will have no effect because it's the same height as last layer of {SlicerFile.PrintHeight}mm.");
}
return sb.ToString();
}
public override string ToString()
{
var result = $"[Z={_positionZ}mm] [Wait: {_waitTime}s] [Dummy pixel: {_outputDummyPixel}]";
if (!string.IsNullOrEmpty(ProfileName)) result = $"{ProfileName}: {result}";
return result;
}
#endregion
#region Properties
public float MinimumPositionZ => Layer.RoundHeight(SlicerFile.PrintHeight + SlicerFile.LayerHeight);
public float MediumPositionZ => Layer.RoundHeight(MinimumPositionZ + (MaximumPositionZ - MinimumPositionZ) / 2);
public float MaximumPositionZ => Math.Max(MinimumPositionZ, Layer.RoundHeight(SlicerFile.MachineZ));
/// <summary>
/// Gets or sets the Z position to raise to
/// </summary>
public decimal PositionZ
{
get => _positionZ;
set => RaiseAndSetIfChanged(ref _positionZ, Layer.RoundHeight(value));
}
/// <summary>
/// <para>Gets or sets the ensured wait time to stay still on the desired position.</para>
/// <para>This is useful if the printer firmware always move to top and you want to stay still on the set position for at least the desired time.</para>
/// <para>Note: The print time calculation will take this wait into consideration and display a longer print time.</para>
/// </summary>
public decimal WaitTime
{
get => _waitTime;
set => RaiseAndSetIfChanged(ref _waitTime, Math.Round(Math.Max(0, value), 2));
}
/// <summary>
/// True to output a dummy pixel on bounding rectangle position to avoid empty layer and blank image, otherwise set to false
/// </summary>
public bool OutputDummyPixel
{
get => _outputDummyPixel;
set => RaiseAndSetIfChanged(ref _outputDummyPixel, value);
}
#endregion
#region Constructor
public OperationRaiseOnPrintFinish()
{
//_outputDummyPixel = !SlicerFile.SupportsGCode;
}
public OperationRaiseOnPrintFinish(FileFormat slicerFile) : base(slicerFile)
{ }
public override void InitWithSlicerFile()
{
if (_positionZ <= 0) _positionZ = (decimal)SlicerFile.MachineZ;
}
#endregion
#region Equality
protected bool Equals(OperationRaiseOnPrintFinish other)
{
return _positionZ == other._positionZ && _outputDummyPixel == other._outputDummyPixel && _waitTime == other._waitTime;
}
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((OperationRaiseOnPrintFinish) obj);
}
public override int GetHashCode()
{
return HashCode.Combine(_positionZ, _outputDummyPixel, _waitTime);
}
#endregion
#region Methods
public void SetToMinimumPosition() => PositionZ = (decimal)MinimumPositionZ;
public void SetToMediumPosition() => PositionZ = (decimal)MediumPositionZ;
public void SetToMaximumPosition() => PositionZ = (decimal)MaximumPositionZ;
public void SetWaitTime(decimal time) => WaitTime = time;
protected override bool ExecuteInternally(OperationProgress progress)
{
var layer = SlicerFile.LastLayer!.Clone();
layer.PositionZ = (float)_positionZ;
layer.ExposureTime = SlicerFile.SupportsGCode ? 0 : 0.05f; // Very low exposure time
layer.LightPWM = 0; // Try to disable light if possible
layer.SetNoDelays();
using var newMat = _outputDummyPixel
? SlicerFile.CreateMatWithDummyPixel(layer.BoundingRectangle.Center())
: SlicerFile.CreateMat();
layer.LayerMat = newMat;
if(_waitTime > 0) layer.SetWaitTimeBeforeCureOrLightOffDelay((float)_waitTime);
SlicerFile.SuppressRebuildPropertiesWork(() =>
{
SlicerFile.Append(layer);
});
return true;
//return !progress.Token.IsCancellationRequested;
}
#endregion
}