diff --git a/UVtools.Core/Layer/LayerIssue.cs b/UVtools.Core/Layer/LayerIssue.cs
index 6ccc644..c4b742d 100644
--- a/UVtools.Core/Layer/LayerIssue.cs
+++ b/UVtools.Core/Layer/LayerIssue.cs
@@ -11,6 +11,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
+using UVtools.Core.Extensions;
using UVtools.Core.Objects;
namespace UVtools.Core
@@ -267,6 +268,7 @@ namespace UVtools.Core
Island,
Overhang,
ResinTrap,
+ SuctionCup,
TouchingBound,
PrintHeight,
EmptyLayer,
@@ -276,7 +278,7 @@ namespace UVtools.Core
///
/// Gets the parent layer
///
- public Layer Layer { get; }
+ public Layer Layer { get; init; }
///
/// Gets the layer index
@@ -286,66 +288,89 @@ namespace UVtools.Core
///
/// Gets the issue type associated
///
- public IssueType Type { get; }
+ public IssueType Type { get; init; }
///
/// Gets the pixels points containing the issue
///
- public Point[] Pixels { get; }
-
- public int PixelsCount => Pixels?.Length ?? 0;
+ public Point[] Pixels { get; init; }
///
- /// Gets the bounding rectangle of the pixel area
+ /// Gets the contours containing the issue
///
- public Rectangle BoundingRectangle { get; }
+ public Point[][] Contours { get; init; }
- ///
- /// Gets the X coordinate for the first point, -1 if doesn't exists
- ///
- public int X => HaveValidPoint ? Pixels[0].X : -1;
-
- ///
- /// Gets the Y coordinate for the first point, -1 if doesn't exists
- ///
- public int Y => HaveValidPoint ? Pixels[0].Y : -1;
-
- ///
- /// Gets the XY point for first point
- ///
- public Point FirstPoint => HaveValidPoint ? Pixels[0] : new Point(-1, -1);
- public string FirstPointStr => $"{FirstPoint.X}, {FirstPoint.Y}";
-
- ///
- /// Gets the number of pixels on this issue
- ///
- public uint Size
+ public int PixelsCount
{
get
{
- if (Type == IssueType.ResinTrap && !BoundingRectangle.IsEmpty)
- {
- return (uint)(BoundingRectangle.Width * BoundingRectangle.Height);
- }
-
- if (Pixels is null) return 0;
- return (uint)Pixels.Length;
+ if (Pixels is not null) return Pixels.Length;
+ if (Contours is not null) return (int)Area;
+ return 0;
}
}
+ ///
+ /// Gets the bounding rectangle of the pixel area
+ ///
+ public Rectangle BoundingRectangle { get; init; }
+
+ ///
+ /// Gets the area of the issue
+ ///
+ public double Area { get; init; }
+
+ ///
+ /// Gets the X coordinate for the first point, -1 if doesn't exists
+ ///
+ public int X => FirstPoint.X;
+
+ ///
+ /// Gets the Y coordinate for the first point, -1 if doesn't exists
+ ///
+ public int Y => FirstPoint.Y;
+
+ ///
+ /// Gets the XY point for first point
+ ///
+ public Point FirstPoint
+ {
+ get
+ {
+ if (Pixels?.Length > 0) return Pixels[0];
+ if (Contours?.Length > 0) return Contours[0][0];
+ return new Point(-1, -1);
+ }
+ }
+
+ public string FirstPointStr => $"{FirstPoint.X}, {FirstPoint.Y}";
+
///
/// Check if this issue have a valid start point to show
///
- public bool HaveValidPoint => Pixels?.Length > 0;
+ public bool HaveValidPoint => Pixels?.Length > 0 || Contours?.Length > 0;
- public LayerIssue(Layer layer, IssueType type, Point[] pixels = null, Rectangle boundingRectangle = default)
+ public LayerIssue(Layer layer, IssueType type, Point[] pixels = null, Point[][] contours = null, Rectangle boundingRectangle = default)
{
Layer = layer;
Type = type;
+ Contours = contours;
Pixels = pixels;
BoundingRectangle = boundingRectangle;
+ Area = (uint)boundingRectangle.Area();
}
+ public LayerIssue(Layer layer, IssueType type, Point[] pixels = null, Rectangle boundingRectangle = default) :
+ this(layer, type, pixels, null, boundingRectangle) { }
+
+
+ public LayerIssue(Layer layer, IssueType type, Point[][] contours, Rectangle boundingRectangle = default) :
+ this(layer, type, null, contours, boundingRectangle) { }
+
+ public LayerIssue(Layer layer, IssueType type) :
+ this(layer, type, null, null, default)
+ { }
+
public Point this[uint index] => Pixels[index];
public Point this[int index] => Pixels[index];
@@ -362,9 +387,10 @@ namespace UVtools.Core
public override string ToString()
{
- return $"{nameof(Type)}: {Type}, Layer: {Layer.Index}, {nameof(X)}: {X}, {nameof(Y)}: {Y}, {nameof(Size)}: {Size}";
+ return $"{nameof(Type)}: {Type}, Layer: {Layer.Index}, {nameof(X)}: {X}, {nameof(Y)}: {Y}, {nameof(PixelsCount)}: {PixelsCount}";
}
+
public bool Equals(LayerIssue other)
{
if (other is null) return false;
@@ -373,6 +399,7 @@ namespace UVtools.Core
&& Type == other.Type
&& PixelsCount == other.PixelsCount
&& Pixels is not null && other.Pixels is not null && Pixels.SequenceEqual(other.Pixels)
+ && Contours is not null && other.Contours is not null && Contours.SequenceEqual(other.Contours)
//&& BoundingRectangle.Equals(other.BoundingRectangle)
;
}
@@ -392,6 +419,7 @@ namespace UVtools.Core
var hashCode = (Layer != null ? Layer.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (int) Type;
hashCode = (hashCode * 397) ^ (Pixels != null ? Pixels.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (Contours != null ? Contours.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ BoundingRectangle.GetHashCode();
return hashCode;
}
@@ -410,12 +438,14 @@ namespace UVtools.Core
Drain
}
///
- /// Gets area pixels
+ /// Gets contours
///
public Point[][] Contours { get; }
public Rectangle BoundingRectangle { get; }
+ public double Area { get; set; }
+
public AreaType Type { get; set; } = AreaType.Unknown;
public bool Processed { get; set; }
@@ -433,22 +463,6 @@ namespace UVtools.Core
set => Contours[index] = value;
}
- /*public Point[] this[uint x, uint y]
- {
- get
- {
- for (uint i = 0; i < Contours.Length; i++)
- {
- if (Contours[i].X == x && Contours[i].Y == y) return Contours[i];
- }
- return Point.Empty;
- }
- }
-
- public Point this[int x, int y] => this[(uint)x, (uint)y];
-
- public Point this[Point point] => this[point.X, point.Y];*/
-
#endregion
public IEnumerator GetEnumerator()
@@ -461,14 +475,13 @@ namespace UVtools.Core
return GetEnumerator();
}
- public LayerHollowArea()
- {
- }
+ public LayerHollowArea() { }
- public LayerHollowArea(Point[][] contours, Rectangle boundingRectangle, AreaType type = AreaType.Unknown)
+ public LayerHollowArea(Point[][] contours, Rectangle boundingRectangle, double area, AreaType type = AreaType.Unknown)
{
Contours = contours;
BoundingRectangle = boundingRectangle;
+ Area = area;
Type = type;
}
}
diff --git a/UVtools.Core/Layer/LayerManager.cs b/UVtools.Core/Layer/LayerManager.cs
index 325ebc0..ce5e935 100644
--- a/UVtools.Core/Layer/LayerManager.cs
+++ b/UVtools.Core/Layer/LayerManager.cs
@@ -904,8 +904,7 @@ namespace UVtools.Core
if (pixels.Count > 0)
{
- AddIssue(new LayerIssue(layer, LayerIssue.IssueType.TouchingBound,
- pixels.ToArray()));
+ AddIssue(new LayerIssue(layer, LayerIssue.IssueType.TouchingBound, pixels.ToArray(), null));
}
}
@@ -1168,13 +1167,15 @@ namespace UVtools.Core
//
var listHollowArea = new List();
var hollowGroups = EmguContours.GetNegativeContoursInGroups(contours, hierarchy);
+ var areas = EmguContours.GetContoursArea(hollowGroups);
- foreach (var group in hollowGroups)
+ for (var i = 0; i < hollowGroups.Count; i++)
{
- if(CvInvoke.ContourArea(group[0]) < resinTrapConfig.RequiredAreaToProcessCheck) continue;
- var rect = CvInvoke.BoundingRectangle(group[0]);
- listHollowArea.Add(new LayerHollowArea(group.ToArrayOfArray(),
+ if (areas[i] < resinTrapConfig.RequiredAreaToProcessCheck) continue;
+ var rect = CvInvoke.BoundingRectangle(hollowGroups[i][0]);
+ listHollowArea.Add(new LayerHollowArea(hollowGroups[i].ToArrayOfArray(),
rect,
+ areas[i],
layer.Index <= resinTrapConfig.StartLayerIndex ||
layer.Index == LayerCount - 1 // First and Last layers, always drains
? LayerHollowArea.AreaType.Drain
@@ -1415,7 +1416,7 @@ namespace UVtools.Core
int ret = issue.Type.CompareTo(layerIssue.Type);
return ret != 0 ? ret : issue.LayerIndex.CompareTo(layerIssue.LayerIndex);
});*/
- if (progress.Token.IsCancellationRequested) return result.OrderBy(issue => issue.Type).ThenBy(issue => issue.LayerIndex).ThenBy(issue => issue.PixelsCount).ToList();
+ if (progress.Token.IsCancellationRequested) return result.OrderBy(issue => issue.Type).ThenBy(issue => issue.LayerIndex).ThenBy(issue => issue.Area).ToList();
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
{
@@ -1425,13 +1426,13 @@ namespace UVtools.Core
from area
in list
where area.Type == LayerHollowArea.AreaType.Trap
- select new LayerIssue(this[layerIndex], LayerIssue.IssueType.ResinTrap, area.Contours[0], area.BoundingRectangle))
+ select new LayerIssue(this[layerIndex], LayerIssue.IssueType.ResinTrap, area.Contours, area.BoundingRectangle){Area = area.Area})
{
AddIssue(issue);
}
}
- return result.OrderBy(issue => issue.Type).ThenBy(issue => issue.LayerIndex).ThenBy(issue => issue.PixelsCount).ToList();
+ return result.OrderBy(issue => issue.Type).ThenBy(issue => issue.LayerIndex).ThenBy(issue => issue.Area).ToList();
}
diff --git a/UVtools.Core/Operations/OperationRepairLayers.cs b/UVtools.Core/Operations/OperationRepairLayers.cs
index c554e26..425e1f2 100644
--- a/UVtools.Core/Operations/OperationRepairLayers.cs
+++ b/UVtools.Core/Operations/OperationRepairLayers.cs
@@ -358,12 +358,8 @@ namespace UVtools.Core.Operations
foreach (var issue in Issues.Where(issue => issue.LayerIndex == layerIndex && issue.Type == LayerIssue.IssueType.ResinTrap))
{
initImage();
- using var vec = new VectorOfVectorOfPoint(new VectorOfPoint(issue.Pixels));
- CvInvoke.DrawContours(image,
- vec,
- -1,
- EmguExtensions.WhiteColor,
- -1);
+ using var vec = new VectorOfVectorOfPoint(issue.Contours);
+ CvInvoke.DrawContours(image, vec, -1, EmguExtensions.WhiteColor, -1);
}
}
}
diff --git a/UVtools.WPF/MainWindow.Issues.cs b/UVtools.WPF/MainWindow.Issues.cs
index c9612a8..f0dfd4e 100644
--- a/UVtools.WPF/MainWindow.Issues.cs
+++ b/UVtools.WPF/MainWindow.Issues.cs
@@ -146,15 +146,11 @@ namespace UVtools.WPF
}
else if (issue.Type == LayerIssue.IssueType.ResinTrap)
{
- using (var contours =
- new VectorOfVectorOfPoint(new VectorOfPoint(issue.Pixels)))
- {
- CvInvoke.DrawContours(image, contours, -1, new MCvScalar(255), -1);
- }
-
+ using var contours = new VectorOfVectorOfPoint(issue.Contours);
+ CvInvoke.DrawContours(image, contours, -1, EmguExtensions.WhiteColor, -1);
edited = true;
}
-
+
}
if (edited)
@@ -351,11 +347,12 @@ namespace UVtools.WPF
return;
}
- if (issue.Type is LayerIssue.IssueType.TouchingBound or LayerIssue.IssueType.EmptyLayer || (issue.X == -1 && issue.Y == -1))
+ var firstPoint = issue.FirstPoint;
+ if (issue.Type is LayerIssue.IssueType.TouchingBound or LayerIssue.IssueType.EmptyLayer || (firstPoint.X == -1 && firstPoint.Y == -1))
{
ZoomToFit();
}
- else if (issue.X >= 0 && issue.Y >= 0)
+ else if (firstPoint.X >= 0 && firstPoint.Y >= 0)
{
if (Settings.LayerPreview.ZoomIssues ^ (_globalModifiers & KeyModifiers.Alt) != 0)
diff --git a/UVtools.WPF/MainWindow.LayerPreview.cs b/UVtools.WPF/MainWindow.LayerPreview.cs
index f1306e4..05a2364 100644
--- a/UVtools.WPF/MainWindow.LayerPreview.cs
+++ b/UVtools.WPF/MainWindow.LayerPreview.cs
@@ -963,10 +963,9 @@ namespace UVtools.WPF
: Settings.LayerPreview.ResinTrapColor;
- using (var vec = new VectorOfVectorOfPoint(new VectorOfPoint(issue.Pixels)))
+ using (var vec = new VectorOfVectorOfPoint(issue.Contours))
{
- CvInvoke.DrawContours(LayerCache.ImageBgr, vec, -1,
- new MCvScalar(color.B, color.G, color.R), -1);
+ CvInvoke.DrawContours(LayerCache.ImageBgr, vec, -1, new MCvScalar(color.B, color.G, color.R), -1);
}
if (_showLayerImageCrosshairs &&
@@ -1496,7 +1495,7 @@ namespace UVtools.WPF
///
private Rectangle GetTransposedIssueBounds(LayerIssue issue)
{
- if (issue.X >= 0 && issue.Y >= 0 && (issue.BoundingRectangle.IsEmpty || issue.Size == 1))
+ if (issue.X >= 0 && issue.Y >= 0 && (issue.BoundingRectangle.IsEmpty || issue.PixelsCount == 1))
return new Rectangle(GetTransposedPoint(issue.FirstPoint, true), new Size(1, 1));
//return new Rectangle(LayerCache.Image.Height - 1 - issue.Y, issue.X, 1, 1);