mirror of
https://github.com/riegera2412/UVtools.git
synced 2026-07-12 11:32:33 +02:00
ca6f623a9f
- **Layer:**
- (Add) Property: `LayerMatBoundingRectangle`
- (Add) Property: `LayerMatModelBoundingRectangle`
- (Add) Method: `GetLayerMat(roi)`
- **Issues:**
- **Islands:**
- (Improvement) Islands detection performance
- (Improvement) Required area to consider an island is now real area instead of bounding box area
- (Fix) Logic bug when combining with overhangs
- **Overhangs:**
- (Improvement) Overhangs detection performance
- (Improvement) Overhangs are now split and identified as separately in the layer
- (Improvement) Overhangs now shows the correct issue area and able to locate the problem region more precisely
- (Improvement) Compress overhangs into contours instead of using whole pixels, resulting in better render performance and less memory to hold the issue
- (Fix) Bug in overhang logic causing to detect the problem twice when combined with supports
- (Improvement) Touching bounds check logic to spare cycles
- **Tool - Raise platform on print finish:**
- (Add) Preset "Minimum": Sets to the minimum position
- (Add) Preset "Medium": Sets to half-way between minimum and maximum position
- (Add) Preset "Maximum": Sets to the maximum position
- (Add) Wait time: Sets the ensured wait time to stay still on the desired position.
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.
Note: The print time calculation will take this wait into consideration and display a longer print time.
- (Add) FileFormat: AnyCubic custom machine (.pwc)
- (Downgrade) OpenCV from 4.5.5 to 4.5.4 due a possible crash while detecting islands (Windows)
185 lines
5.5 KiB
C#
185 lines
5.5 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.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Text.Json.Serialization;
|
|
using UVtools.Core.Extensions;
|
|
|
|
namespace UVtools.Core.Layers;
|
|
|
|
public class MainIssue : IReadOnlyList<Issue>
|
|
{
|
|
public enum IssueType : byte
|
|
{
|
|
Island,
|
|
Overhang,
|
|
ResinTrap,
|
|
SuctionCup,
|
|
TouchingBound,
|
|
PrintHeight,
|
|
EmptyLayer,
|
|
Debug
|
|
//HoleSandwich,
|
|
}
|
|
|
|
public bool IsIsland => Type == IssueType.Island;
|
|
public bool IsOverhang => Type == IssueType.Overhang;
|
|
public bool IsResinTrap => Type == IssueType.ResinTrap;
|
|
public bool IsSuctionCup => Type == IssueType.SuctionCup;
|
|
public bool IsTouchingBound => Type == IssueType.TouchingBound;
|
|
public bool IsPrintHeight => Type == IssueType.PrintHeight;
|
|
public bool IsEmptyLayer => Type == IssueType.EmptyLayer;
|
|
public bool IsDebug => Type == IssueType.Debug;
|
|
|
|
/// <summary>
|
|
/// Gets the issue type associated
|
|
/// </summary>
|
|
public IssueType Type { get; init; }
|
|
|
|
/// <summary>
|
|
/// Gets the layer where issue is present and starts
|
|
/// </summary>
|
|
[JsonIgnore]
|
|
public Layer StartLayer => Childs[0].Layer;
|
|
|
|
/// <summary>
|
|
/// Gets the layer where issue ends
|
|
/// </summary>
|
|
[JsonIgnore]
|
|
public Layer EndLayer => Childs[^1].Layer;
|
|
|
|
/// <summary>
|
|
/// Gets the layer index
|
|
/// </summary>
|
|
public uint StartLayerIndex => StartLayer.Index;
|
|
|
|
/// <summary>
|
|
/// Gets the layer index
|
|
/// </summary>
|
|
public uint EndLayerIndex => EndLayer.Index;
|
|
|
|
/// <summary>
|
|
/// Gets the number of layers in this range
|
|
/// </summary>
|
|
public uint LayerRangeCount => 1 + EndLayerIndex - StartLayerIndex;
|
|
|
|
public string LayerInfoStr => StartLayerIndex == EndLayerIndex
|
|
? $"{StartLayerIndex}"
|
|
: $"{StartLayerIndex}-{EndLayerIndex} ({LayerRangeCount})";
|
|
|
|
/// <summary>
|
|
/// Gets the total height that represents this issue
|
|
/// </summary>
|
|
public float TotalHeight => Layer.RoundHeight(StartLayer.LayerHeight + EndLayer.PositionZ - StartLayer.PositionZ);
|
|
|
|
/// <summary>
|
|
/// Gets the bounding rectangle of the area
|
|
/// </summary>
|
|
public Rectangle BoundingRectangle { get; init; }
|
|
|
|
/// <summary>
|
|
/// Gets the area of the issue
|
|
/// </summary>
|
|
public uint PixelCount { get; init; }
|
|
|
|
/// <summary>
|
|
/// Gets the area of the issue
|
|
/// </summary>
|
|
public double Area { get; init; }
|
|
|
|
/// <summary>
|
|
/// Gets all issues inside this main issue
|
|
/// </summary>
|
|
public Issue[] Childs { get; init; } = null!;
|
|
|
|
public MainIssue(IssueType type, Rectangle boundingRectangle = default)
|
|
{
|
|
Type = type;
|
|
BoundingRectangle = boundingRectangle;
|
|
Area = boundingRectangle.Area();
|
|
}
|
|
|
|
public MainIssue(IssueType type, Issue issue) : this(type, issue.BoundingRectangle)
|
|
{
|
|
Childs = new[] { issue };
|
|
issue.Parent = this;
|
|
PixelCount = issue.PixelsCount;
|
|
if (issue is IssueOfPoints) Area = issue.PixelsCount;
|
|
}
|
|
|
|
public MainIssue(IssueType type, IEnumerable<Issue> issues) : this(type)
|
|
{
|
|
var boundingRectangle = Rectangle.Empty;
|
|
double area = 0;
|
|
foreach (var issue in issues)
|
|
{
|
|
issue.Parent = this;
|
|
area += issue.Area / issue.Layer.LayerHeight;
|
|
PixelCount += issue.PixelsCount;
|
|
if (issue.BoundingRectangle.IsEmpty) continue;
|
|
if (boundingRectangle.IsEmpty)
|
|
{
|
|
boundingRectangle = issue.BoundingRectangle;
|
|
continue;
|
|
}
|
|
|
|
boundingRectangle.Intersect(issue.BoundingRectangle);
|
|
}
|
|
|
|
BoundingRectangle = boundingRectangle;
|
|
Area = area;
|
|
Childs = issues.OrderBy(issue => issue.LayerIndex).ToArray();
|
|
Sort();
|
|
}
|
|
|
|
private void Sort()
|
|
{
|
|
Array.Sort(Childs, (issue, issue1) => issue.LayerIndex.CompareTo(issue1.LayerIndex));
|
|
}
|
|
|
|
public bool IsIssueInBetween(int layerIndex) => layerIndex >= StartLayerIndex && layerIndex <= EndLayerIndex;
|
|
public bool IsIssueInBetween(uint layerIndex) => layerIndex >= StartLayerIndex && layerIndex <= EndLayerIndex;
|
|
public bool IsIssueInBetween(Layer layer) => IsIssueInBetween(layer.Index);
|
|
|
|
|
|
public IEnumerator<Issue> GetEnumerator()
|
|
{
|
|
return ((IEnumerable<Issue>)Childs).GetEnumerator();
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
{
|
|
return Childs.GetEnumerator();
|
|
}
|
|
|
|
public int Count => Childs.Length;
|
|
|
|
public Issue this[int index] => Childs[index];
|
|
|
|
protected bool Equals(MainIssue other)
|
|
{
|
|
return Type == other.Type && BoundingRectangle.Equals(other.BoundingRectangle) && PixelCount == other.PixelCount && Area.Equals(other.Area) && Childs.SequenceEqual(other.Childs);
|
|
}
|
|
|
|
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((MainIssue)obj);
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return HashCode.Combine((int)Type, BoundingRectangle, PixelCount, Area, Childs);
|
|
}
|
|
} |