Skip to content

Commit

Permalink
v3.4.2
Browse files Browse the repository at this point in the history
- **Core:**
   - (Add) Getter `FileFormat.DisplayPixelCount` Gets the display total number of pixels (ResolutionX * ResolutionY)
   - (Add) Getter `Layer.NonZeroPixelRatio` Gets the ratio between non zero pixels and display number of pixels
   - (Add) Getter `Layer.NonZeroPixelPercentage` Gets the percentage of non zero pixels relative to the display number of pixels
   - (Add) Getter `Layer.PreviousHeightLayer()` Gets the previous layer with a different height from the current, returns null if no previous layer
   - (Add) Getter `Layer.NextHeightLayer()` Gets the next layer with a different height from the current, returns null if no next layer
   - (Add) Method `Layer.GetPreviousLayerWithAtLeastPixelCountOf()` Gets the previous layer matching at least a number of pixels, returns null if no previous layer
   - (Add) Method `Layer.GetNextLayerWithAtLeastPixelCountOf()` Gets the next layer matching at least a number of pixels, returns null if no next layer
   - (Add) Method `Operation.GetRoiOrVolumeBounds()` returns the selected ROI rectangle or model volume bounds rectangle
   - (Add) Documentation around `Operation` methods
   - (Fix) Open files in partial mode when the resolution is not defined would cause a `NullPointerException` (#474)
- **Suggestion: Wait time before cure**
   - (Add) Proportional maximum time change: Sets the maximum allowed time difference relative to the previous layer (#471)
   - (Add) Proportional mass get modes: Previous, Average and Maximum relative to a defined height (#471)
   - (Change) Proportional set type sets fallback time to the first layer
   - (Fix) Proportional set type was taking current layer mass instead of looking to the previous cured layer (#471)
- **Tools:**
   - **Edit print parameters:**
      - (Change) Incorporate the unit label into the numeric input box
      - (Change) Allow TSMC speeds to be 0 as minimum value (#472)
   - (Fix) PCB Exposure: The thumbnail has random noise around the image
- **Settings:**
   - (Add) Tools: "Always prompt for confirmation before execute the operation"
   - (Fix) Changing layer compression method when no file is loaded would cause a error
- **UI:**
   - (Add) Holding Shift key while drag and drop a .uvtop file will try to execute the operation without showing the window or prompt
   - (Add) Drag and drop a .cs or .csx file into UVtools will load and show the scripting dialog with the file selected
- (Add) Errors that crash application will now show an report window with the crash information and able to fast report them
- (Add) "Version" key and value on registry to tell the current installed version (Windows MSI only)
- (Upgrade) AvaloniaUI from 0.10.13 to 0.10.14
- (Upgrade) .NET from 6.0.4 to 6.0.5
  • Loading branch information
sn4k3 committed May 16, 2022
1 parent 51e4f32 commit c800f88
Show file tree
Hide file tree
Showing 37 changed files with 1,196 additions and 216 deletions.
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,39 @@
# Changelog

## 16/05/2022 - v3.4.2

- **Core:**
- (Add) Getter `FileFormat.DisplayPixelCount` Gets the display total number of pixels (ResolutionX * ResolutionY)
- (Add) Getter `Layer.NonZeroPixelRatio` Gets the ratio between non zero pixels and display number of pixels
- (Add) Getter `Layer.NonZeroPixelPercentage` Gets the percentage of non zero pixels relative to the display number of pixels
- (Add) Getter `Layer.PreviousHeightLayer()` Gets the previous layer with a different height from the current, returns null if no previous layer
- (Add) Getter `Layer.NextHeightLayer()` Gets the next layer with a different height from the current, returns null if no next layer
- (Add) Method `Layer.GetPreviousLayerWithAtLeastPixelCountOf()` Gets the previous layer matching at least a number of pixels, returns null if no previous layer
- (Add) Method `Layer.GetNextLayerWithAtLeastPixelCountOf()` Gets the next layer matching at least a number of pixels, returns null if no next layer
- (Add) Method `Operation.GetRoiOrVolumeBounds()` returns the selected ROI rectangle or model volume bounds rectangle
- (Add) Documentation around `Operation` methods
- (Fix) Open files in partial mode when the resolution is not defined would cause a `NullPointerException` (#474)
- **Suggestion: Wait time before cure**
- (Add) Proportional maximum time change: Sets the maximum allowed time difference relative to the previous layer (#471)
- (Add) Proportional mass get modes: Previous, Average and Maximum relative to a defined height (#471)
- (Change) Proportional set type sets fallback time to the first layer
- (Fix) Proportional set type was taking current layer mass instead of looking to the previous cured layer (#471)
- **Tools:**
- **Edit print parameters:**
- (Change) Incorporate the unit label into the numeric input box
- (Change) Allow TSMC speeds to be 0 as minimum value (#472)
- (Fix) PCB Exposure: The thumbnail has random noise around the image
- **Settings:**
- (Add) Tools: "Always prompt for confirmation before execute the operation"
- (Fix) Changing layer compression method when no file is loaded would cause a error
- **UI:**
- (Add) Holding Shift key while drag and drop a .uvtop file will try to execute the operation without showing the window or prompt
- (Add) Drag and drop a .cs or .csx file into UVtools will load and show the scripting dialog with the file selected
- (Add) Errors that crash application will now show an report window with the crash information and able to fast report them
- (Add) "Version" key and value on registry to tell the current installed version (Windows MSI only)
- (Upgrade) AvaloniaUI from 0.10.13 to 0.10.14
- (Upgrade) .NET from 6.0.4 to 6.0.5
-
## 02/05/2022 - v3.4.1

- (Add) Suggestion - Wait time before cure: Allow to set the number of layers to smooth transition from bottom to normal wait time (Defaults to 8)
Expand Down
34 changes: 31 additions & 3 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,32 @@
- (Add) Suggestion - Wait time before cure: Allow to set the number of layers to smooth transition from bottom to normal wait time (Defaults to 8)
- (Fix) Tool - PCB Exposure: Pixels per millimeter was been set to fixed value instead of use printer lcd pitch, causing wrong dimentions on different from 50µm pitch
- (Fix) Tool - PCB Exposure: Unable to run the tool when the display size information isn't available
- **Core:**
- (Add) Getter `FileFormat.DisplayPixelCount` Gets the display total number of pixels (ResolutionX * ResolutionY)
- (Add) Getter `Layer.NonZeroPixelRatio` Gets the ratio between non zero pixels and display number of pixels
- (Add) Getter `Layer.NonZeroPixelPercentage` Gets the percentage of non zero pixels relative to the display number of pixels
- (Add) Getter `Layer.PreviousHeightLayer()` Gets the previous layer with a different height from the current, returns null if no previous layer
- (Add) Getter `Layer.NextHeightLayer()` Gets the next layer with a different height from the current, returns null if no next layer
- (Add) Method `Layer.GetPreviousLayerWithAtLeastPixelCountOf()` Gets the previous layer matching at least a number of pixels, returns null if no previous layer
- (Add) Method `Layer.GetNextLayerWithAtLeastPixelCountOf()` Gets the next layer matching at least a number of pixels, returns null if no next layer
- (Add) Method `Operation.GetRoiOrVolumeBounds()` returns the selected ROI rectangle or model volume bounds rectangle
- (Add) Documentation around `Operation` methods
- (Fix) Open files in partial mode when the resolution is not defined would cause a `NullPointerException` (#474)
- **Suggestion: Wait time before cure**
- (Add) Proportional maximum time change: Sets the maximum allowed time difference relative to the previous layer (#471)
- (Add) Proportional mass get modes: Previous, Average and Maximum relative to a defined height (#471)
- (Change) Proportional set type sets fallback time to the first layer
- (Fix) Proportional set type was taking current layer mass instead of looking to the previous cured layer (#471)
- **Tools:**
- **Edit print parameters:**
- (Change) Incorporate the unit label into the numeric input box
- (Change) Allow TSMC speeds to be 0 as minimum value (#472)
- (Fix) PCB Exposure: The thumbnail has random noise around the image
- **Settings:**
- (Add) Tools: "Always prompt for confirmation before execute the operation"
- (Fix) Changing layer compression method when no file is loaded would cause a error
- **UI:**
- (Add) Holding Shift key while drag and drop a .uvtop file will try to execute the operation without showing the window or prompt
- (Add) Drag and drop a .cs or .csx file into UVtools will load and show the scripting dialog with the file selected
- (Add) Errors that crash application will now show an report window with the crash information and able to fast report them
- (Upgrade) AvaloniaUI from 0.10.13 to 0.10.14
- (Upgrade) .NET from 6.0.4 to 6.0.5
-

2 changes: 1 addition & 1 deletion UVtools.AvaloniaControls/UVtools.AvaloniaControls.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Avalonia" Version="0.10.13" />
<PackageReference Include="Avalonia" Version="0.10.14" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion UVtools.Core/Extensions/EmguExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ public static Mat CropByBounds(this Mat src, Size margin)
using var roi = src.Size == rect.Size ? src.Roi(src.Size) : src.Roi(rect);

var numberOfChannels = roi.NumberOfChannels;
var cropped = new Mat(roi.Rows + margin.Height * 2, roi.Cols + margin.Width * 2, roi.Depth, numberOfChannels);
var cropped = InitMat(new Size(roi.Width + margin.Width * 2, roi.Height + margin.Height * 2), numberOfChannels, roi.Depth);

using var dest = new Mat(cropped, new Rectangle(margin.Width, margin.Height, roi.Width, roi.Height));
roi.CopyTo(dest);
Expand Down
1 change: 0 additions & 1 deletion UVtools.Core/FileFormats/CWSFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml.Serialization;
using UVtools.Core.Converters;
using UVtools.Core.Extensions;
Expand Down
31 changes: 18 additions & 13 deletions UVtools.Core/FileFormats/FileFormat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,42 +172,42 @@ public class PrintParameterModifier
#region Instances
public static PrintParameterModifier PositionZ { get; } = new ("Position Z", "Absolute Z position", "mm", 0, 100000, 0.01, Layer.HeightPrecision);
public static PrintParameterModifier BottomLayerCount { get; } = new ("Bottom layer count", "Number of bottom/burn-in layers", "layers", 0, ushort.MaxValue, 1, 0);
public static PrintParameterModifier TransitionLayerCount { get; } = new ("Transition layer count", "Number of transition layers", "layers",0, ushort.MaxValue, 1, 0);
public static PrintParameterModifier TransitionLayerCount { get; } = new ("Transition layer count", "Number of fade/transition layers", "layers",0, ushort.MaxValue, 1, 0);

public static PrintParameterModifier BottomLightOffDelay { get; } = new("Bottom light-off seconds", "Total motor movement time + rest time to wait before cure a new bottom layer", "s");
public static PrintParameterModifier LightOffDelay { get; } = new("Light-off seconds", "Total motor movement time + rest time to wait before cure a new layer", "s");

public static PrintParameterModifier BottomWaitTimeBeforeCure { get; } = new ("Bottom wait before cure", "Time to wait/rest before cure a new bottom layer\nChitubox: Rest after retract\nLychee: Wait before print", "s");
public static PrintParameterModifier WaitTimeBeforeCure { get; } = new ("Wait before cure", "Time to wait/rest before cure a new layer\nChitubox: Rest after retract\nLychee: Wait before print", "s");

public static PrintParameterModifier BottomExposureTime { get; } = new ("Bottom exposure time", "Bottom layers cure time", "s", 0.1M);
public static PrintParameterModifier ExposureTime { get; } = new ("Exposure time", "Layers cure time", "s", 0.1M);
public static PrintParameterModifier BottomExposureTime { get; } = new ("Bottom exposure time", "Bottom layers exposure time", "s", 0.1M);
public static PrintParameterModifier ExposureTime { get; } = new ("Exposure time", "Normal layers exposure time", "s", 0.1M);

public static PrintParameterModifier BottomWaitTimeAfterCure { get; } = new("Bottom wait after cure", "Time to wait/rest after cure a new bottom layer\nChitubox: Rest before lift\nLychee: Wait after print", "s");
public static PrintParameterModifier WaitTimeAfterCure { get; } = new("Wait after cure", "Time to wait/rest after cure a new bottom layer\nChitubox: Rest before lift\nLychee: Wait after print", "s");

public static PrintParameterModifier BottomLiftHeight { get; } = new ("Bottom lift height", "Bottom lift/peel height between layers", "mm");
public static PrintParameterModifier LiftHeight { get; } = new ("Lift height", @"Lift/peel height between layers", "mm");

public static PrintParameterModifier BottomLiftSpeed { get; } = new ("Bottom lift speed", null, "mm/min", 10, 5000, 5);
public static PrintParameterModifier LiftSpeed { get; } = new ("Lift speed", null, "mm/min", 10, 5000, 5);
public static PrintParameterModifier BottomLiftSpeed { get; } = new ("Bottom lift speed", "Lift speed of bottom layers", "mm/min", 10, 5000, 5);
public static PrintParameterModifier LiftSpeed { get; } = new ("Lift speed", "Lift speed of normal layers", "mm/min", 10, 5000, 5);

public static PrintParameterModifier BottomLiftHeight2 { get; } = new("2) Bottom lift height", "Bottom second lift/peel height between layers", "mm");
public static PrintParameterModifier LiftHeight2 { get; } = new("2) Lift height", @"Second lift/peel height between layers", "mm");

public static PrintParameterModifier BottomLiftSpeed2 { get; } = new("2) Bottom lift speed", null, "mm/min", 10, 5000, 5);
public static PrintParameterModifier LiftSpeed2 { get; } = new("2) Lift speed", null, "mm/min", 10, 5000, 5);
public static PrintParameterModifier BottomLiftSpeed2 { get; } = new("2) Bottom lift speed", "Lift speed of bottom layers for the second lift sequence (TSMC)", "mm/min", 0, 5000, 5);
public static PrintParameterModifier LiftSpeed2 { get; } = new("2) Lift speed", "Lift speed of normal layers for the second lift sequence (TSMC)", "mm/min", 0, 5000, 5);

public static PrintParameterModifier BottomWaitTimeAfterLift { get; } = new("Bottom wait after lift", "Time to wait/rest after a lift/peel sequence at bottom layers\nChitubox: Rest after lift\nLychee: Wait after lift", "s");
public static PrintParameterModifier WaitTimeAfterLift { get; } = new("Wait after lift", "Time to wait/rest after a lift/peel sequence at layers\nChitubox: Rest after lift\nLychee: Wait after lift", "s");

public static PrintParameterModifier BottomRetractSpeed { get; } = new ("Bottom retract speed", "Bottom down speed from lift height to next layer cure position", "mm/min", 10, 5000, 5);
public static PrintParameterModifier RetractSpeed { get; } = new ("Retract speed", "Down speed from lift height to next layer cure position", "mm/min", 10, 5000, 5);

public static PrintParameterModifier BottomRetractHeight2 { get; } = new("2) Bottom retract height", null, "mm");
public static PrintParameterModifier RetractHeight2 { get; } = new("2) Retract height", null, "mm");
public static PrintParameterModifier BottomRetractSpeed2 { get; } = new("2) Bottom retract speed", null, "mm/min", 10, 5000, 5);
public static PrintParameterModifier RetractSpeed2 { get; } = new("2) Retract speed", null, "mm/min", 10, 5000, 5);
public static PrintParameterModifier BottomRetractHeight2 { get; } = new("2) Bottom retract height", "Slow retract height of bottom layers (TSMC)", "mm");
public static PrintParameterModifier RetractHeight2 { get; } = new("2) Retract height", "Slow retract height of normal layers (TSMC)", "mm");
public static PrintParameterModifier BottomRetractSpeed2 { get; } = new("2) Bottom retract speed", "Slow retract speed of bottom layers (TSMC)", "mm/min", 0, 5000, 5);
public static PrintParameterModifier RetractSpeed2 { get; } = new("2) Retract speed", "Slow retract speed of normal layers (TSMC)", "mm/min", 0, 5000, 5);

public static PrintParameterModifier BottomLightPWM { get; } = new ("Bottom light PWM", "UV LED power for bottom layers", "", 1, byte.MaxValue, 5, 0);
public static PrintParameterModifier LightPWM { get; } = new ("Light PWM", "UV LED power for layers", "", 1, byte.MaxValue, 5, 0);
Expand Down Expand Up @@ -1428,7 +1428,7 @@ public bool IsModified
}

/// <summary>
/// Gets the bounding rectangle of the object
/// Gets the bounding rectangle of the model
/// </summary>
public Rectangle BoundingRectangle
{
Expand Down Expand Up @@ -1492,6 +1492,11 @@ public Size Resolution
/// </summary>
public abstract uint ResolutionY { get; set; }

/// <summary>
/// Gets the display total number of pixels (<see cref="ResolutionX"/> * <see cref="ResolutionY"/>)
/// </summary>
public uint DisplayPixelCount => ResolutionX * ResolutionY;

/// <summary>
/// Gets the size of display in millimeters
/// </summary>
Expand Down Expand Up @@ -5320,7 +5325,7 @@ public bool Sanitize()
throw new InvalidDataException($"Layer {layerIndex - 1} ({this[layerIndex - 1].PositionZ}mm) have a higher Z position than the successor layer {layerIndex} ({this[layerIndex].PositionZ}mm).\n");
}

if (ResolutionX == 0 || ResolutionY == 0)
if ((ResolutionX == 0 || ResolutionY == 0) && DecodeType == FileDecodeType.Full)
{
var layer = FirstLayer;
if (layer is not null)
Expand Down
16 changes: 8 additions & 8 deletions UVtools.Core/FileFormats/PhotonWorkshopFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ private unsafe Mat DecodePWS()
if (pixel > imageLength)
{
image.Dispose();
throw new FileLoadException("Error image ran off the end");
throw new FileLoadException("Image ran off the end.");
}
}
}
Expand Down Expand Up @@ -763,6 +763,12 @@ private Mat DecodePW0()

//color &= 0xff;

if (pixelPos + repeat > imageLength)
{
mat.Dispose();
throw new FileLoadException($"Image ran off the end: {pixelPos}+ {repeat} = {pixelPos + repeat}, expecting: {imageLength}");
}

// We only need to set the non-zero pixels
mat.FillSpan(ref pixelPos, repeat, color);

Expand All @@ -772,18 +778,12 @@ private Mat DecodePW0()
//i++;
break;
}

if (pixelPos > imageLength)
{
mat.Dispose();
throw new FileLoadException($"Error image ran off the end: {pixelPos - repeat}({repeat}) of {imageLength}");
}
}

if (pixelPos > 0 && pixelPos != imageLength)
{
mat.Dispose();
throw new FileLoadException($"Error image ended short: {pixelPos} of {imageLength}");
throw new FileLoadException($"Image ended short: {pixelPos}, expecting: {imageLength}");
}

return mat;
Expand Down
89 changes: 89 additions & 0 deletions UVtools.Core/Layers/Layer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,40 @@ public uint NonZeroPixelCount
internal set
{
if (!RaiseAndSetIfChanged(ref _nonZeroPixelCount, value)) return;
RaisePropertyChanged(nameof(NonZeroPixelRatio));
RaisePropertyChanged(nameof(NonZeroPixelPercentage));
RaisePropertyChanged(nameof(Area));
RaisePropertyChanged(nameof(Volume));
MaterialMilliliters = -1; // Recalculate
}
}

/// <summary>
/// Gets the ratio between non zero pixels and display number of pixels
/// </summary>
public double NonZeroPixelRatio
{
get
{
var displayPixelCount = SlicerFile.DisplayPixelCount;
if (displayPixelCount == 0) return double.NaN;
return (double)_nonZeroPixelCount / displayPixelCount;
}
}

/// <summary>
/// Gets the percentage of non zero pixels relative to the display number of pixels
/// </summary>
public double NonZeroPixelPercentage
{
get
{
var pixelRatio = NonZeroPixelRatio;
if (double.IsNaN(pixelRatio)) return double.NaN;
return pixelRatio * 100.0;
}
}

/// <summary>
/// Gets if this layer is empty/all black pixels
/// </summary>
Expand Down Expand Up @@ -214,7 +242,37 @@ public bool IsBottomLayer
if (IsFirstLayer || _index > SlicerFile.Count) return null;
return SlicerFile[_index - 1];
}
}

/// <summary>
/// Gets the previous layer with a different height from the current, returns null if no previous layer
/// </summary>
public Layer? PreviousHeightLayer
{
get
{
if (IsFirstLayer || _index > SlicerFile.Count) return null;
for (int i = (int)_index - 1; i >= 0; i--)
{
if (SlicerFile[i].PositionZ < _positionZ) return SlicerFile[i];
}

return null;
}
}

/// <summary>
/// Gets the previous layer matching at least <param name="numberOfPixels"/> pixels, returns null if no previous layer
/// </summary>
public Layer? GetPreviousLayerWithAtLeastPixelCountOf(uint numberOfPixels)
{
if (IsFirstLayer || _index > SlicerFile.Count) return null;
for (int i = (int)_index - 1; i >= 0; i--)
{
if (SlicerFile[i].NonZeroPixelCount >= numberOfPixels) return SlicerFile[i];
}

return null;
}

/// <summary>
Expand All @@ -229,6 +287,37 @@ public bool IsBottomLayer
}
}

/// <summary>
/// Gets the next layer with a different height from the current, returns null if no next layer
/// </summary>
public Layer? NextHeightLayer
{
get
{
if (_index >= SlicerFile.LastLayerIndex) return null;
for (var i = _index + 1; i < SlicerFile.LayerCount; i++)
{
if (SlicerFile[i].PositionZ > _positionZ) return SlicerFile[i];
}

return null;
}
}

/// <summary>
/// Gets the next layer matching at least <param name="numberOfPixels"/> pixels, returns null if no next layer
/// </summary>
public Layer? GetNextLayerWithAtLeastPixelCountOf(uint numberOfPixels)
{
if (_index >= SlicerFile.LastLayerIndex) return null;
for (var i = _index + 1; i < SlicerFile.LayerCount; i++)
{
if (SlicerFile[i].NonZeroPixelCount >= numberOfPixels) return SlicerFile[i];
}

return null;
}

/// <summary>
/// Gets the layer index
/// </summary>
Expand Down
Loading

0 comments on commit c800f88

Please sign in to comment.