LayerIssue to support contours

This commit is contained in:
Tiago Conceição
2021-09-13 03:48:33 +01:00
parent 00e0d4c9ff
commit 1e5f94f5a8
5 changed files with 92 additions and 86 deletions
+71 -58
View File
@@ -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
/// <summary>
/// Gets the parent layer
/// </summary>
public Layer Layer { get; }
public Layer Layer { get; init; }
/// <summary>
/// Gets the layer index
@@ -286,66 +288,89 @@ namespace UVtools.Core
/// <summary>
/// Gets the issue type associated
/// </summary>
public IssueType Type { get; }
public IssueType Type { get; init; }
/// <summary>
/// Gets the pixels points containing the issue
/// </summary>
public Point[] Pixels { get; }
public int PixelsCount => Pixels?.Length ?? 0;
public Point[] Pixels { get; init; }
/// <summary>
/// Gets the bounding rectangle of the pixel area
/// Gets the contours containing the issue
/// </summary>
public Rectangle BoundingRectangle { get; }
public Point[][] Contours { get; init; }
/// <summary>
/// Gets the X coordinate for the first point, -1 if doesn't exists
/// </summary>
public int X => HaveValidPoint ? Pixels[0].X : -1;
/// <summary>
/// Gets the Y coordinate for the first point, -1 if doesn't exists
/// </summary>
public int Y => HaveValidPoint ? Pixels[0].Y : -1;
/// <summary>
/// Gets the XY point for first point
/// </summary>
public Point FirstPoint => HaveValidPoint ? Pixels[0] : new Point(-1, -1);
public string FirstPointStr => $"{FirstPoint.X}, {FirstPoint.Y}";
/// <summary>
/// Gets the number of pixels on this issue
/// </summary>
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;
}
}
/// <summary>
/// Gets the bounding rectangle of the pixel area
/// </summary>
public Rectangle BoundingRectangle { get; init; }
/// <summary>
/// Gets the area of the issue
/// </summary>
public double Area { get; init; }
/// <summary>
/// Gets the X coordinate for the first point, -1 if doesn't exists
/// </summary>
public int X => FirstPoint.X;
/// <summary>
/// Gets the Y coordinate for the first point, -1 if doesn't exists
/// </summary>
public int Y => FirstPoint.Y;
/// <summary>
/// Gets the XY point for first point
/// </summary>
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}";
/// <summary>
/// Check if this issue have a valid start point to show
/// </summary>
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
}
/// <summary>
/// Gets area pixels
/// Gets contours
/// </summary>
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<Point[]> 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;
}
}
+10 -9
View File
@@ -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<LayerHollowArea>();
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();
}
@@ -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);
}
}
}
+6 -9
View File
@@ -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)
+3 -4
View File
@@ -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
/// </summary>
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);