diff --git a/UVtools.Core/EmguCV/EmguContours.cs b/UVtools.Core/EmguCV/EmguContours.cs
index 8c0889e..62bfd47 100644
--- a/UVtools.Core/EmguCV/EmguContours.cs
+++ b/UVtools.Core/EmguCV/EmguContours.cs
@@ -210,6 +210,12 @@ namespace UVtools.Core.EmguCV
return result;
}
+ ///
+ /// Checks if two contours intersects
+ ///
+ /// Contour 1
+ /// Contour 2
+ ///
public static bool ContoursIntersect(VectorOfVectorOfPoint contour1, VectorOfVectorOfPoint contour2)
{
var contour1Rect = CvInvoke.BoundingRectangle(contour1[0]);
@@ -228,16 +234,14 @@ namespace UVtools.Core.EmguCV
using var contour1Mat = EmguExtensions.InitMat(totalRect.Size);
using var contour2Mat = EmguExtensions.InitMat(totalRect.Size);
- using var overlapCheck = EmguExtensions.InitMat(totalRect.Size);
var inverseOffset = new Point(minX * -1, minY * -1);
CvInvoke.DrawContours(contour1Mat, contour1, -1, EmguExtensions.WhiteColor, -1, Emgu.CV.CvEnum.LineType.EightConnected, null, int.MaxValue, inverseOffset);
CvInvoke.DrawContours(contour2Mat, contour2, -1, EmguExtensions.WhiteColor, -1, Emgu.CV.CvEnum.LineType.EightConnected, null, int.MaxValue, inverseOffset);
- CvInvoke.BitwiseAnd(contour1Mat, contour2Mat, overlapCheck);
-
- return CvInvoke.CountNonZero(overlapCheck) > 0;
+ CvInvoke.BitwiseAnd(contour1Mat, contour2Mat, contour1Mat);
+ return contour1Mat.FindFirstPositivePixel() != -1;
}
}
}
diff --git a/UVtools.Core/Extensions/EmguExtensions.cs b/UVtools.Core/Extensions/EmguExtensions.cs
index 7b4577e..90473c4 100644
--- a/UVtools.Core/Extensions/EmguExtensions.cs
+++ b/UVtools.Core/Extensions/EmguExtensions.cs
@@ -527,6 +527,114 @@ namespace UVtools.Core.Extensions
}
#endregion
+ #region Find methods
+
+ ///
+ /// Finds the first negative (Black) pixel
+ ///
+ ///
+ /// Pixel position in the span, or -1 if not found
+ public static int FindFirstNegativePixel(this Mat mat)
+ {
+ return mat.FindFirstPixelEqualTo(0);
+ }
+
+ ///
+ /// Finds the first positive pixel
+ ///
+ ///
+ /// Pixel position in the span, or -1 if not found
+ public static int FindFirstPositivePixel(this Mat mat)
+ {
+ return mat.FindFirstPixelEqualOrGreaterThan(1);
+ }
+
+ ///
+ /// Finds the first pixel that is
+ ///
+ ///
+ ///
+ /// Pixel position in the span, or -1 if not found
+ public static int FindFirstPixelEqualTo(this Mat mat, byte value)
+ {
+ var span = mat.GetDataByteSpan();
+ for (var i = 0; i < span.Length; i++)
+ {
+ if (span[i] == value) return i;
+ }
+
+ return -1;
+ }
+
+ ///
+ /// Finds the first pixel that is at less than
+ ///
+ ///
+ ///
+ /// Pixel position in the span, or -1 if not found
+ public static int FindFirstPixelLessThan(this Mat mat, byte value)
+ {
+ var span = mat.GetDataByteSpan();
+ for (var i = 0; i < span.Length; i++)
+ {
+ if (span[i] < value) return i;
+ }
+
+ return -1;
+ }
+
+ ///
+ /// Finds the first pixel that is at less or equal than
+ ///
+ ///
+ ///
+ /// Pixel position in the span, or -1 if not found
+ public static int FindFirstPixelEqualOrLessThan(this Mat mat, byte value)
+ {
+ var span = mat.GetDataByteSpan();
+ for (var i = 0; i < span.Length; i++)
+ {
+ if (span[i] <= value) return i;
+ }
+
+ return -1;
+ }
+
+ ///
+ /// Finds the first pixel that is at greater than
+ ///
+ ///
+ ///
+ /// Pixel position in the span, or -1 if not found
+ public static int FindFirstPixelGreaterThan(this Mat mat, byte value)
+ {
+ var span = mat.GetDataByteSpan();
+ for (var i = 0; i < span.Length; i++)
+ {
+ if (span[i] > value) return i;
+ }
+
+ return -1;
+ }
+
+ ///
+ /// Finds the first pixel that is at equal or greater than
+ ///
+ ///
+ ///
+ /// Pixel position in the span, or -1 if not found
+ public static int FindFirstPixelEqualOrGreaterThan(this Mat mat, byte value)
+ {
+ var span = mat.GetDataByteSpan();
+ for (var i = 0; i < span.Length; i++)
+ {
+ if (span[i] >= value) return i;
+ }
+
+ return -1;
+ }
+ #endregion
+
#region Transform methods
public static void Transform(this Mat src, double xScale, double yScale, double xTrans = 0, double yTrans = 0, Size dstSize = default, Inter interpolation = Inter.Linear)
{
@@ -1009,7 +1117,7 @@ namespace UVtools.Core.Extensions
// if there are no more 'white' pixels in the image, then
// break from the loop
- if (CvInvoke.CountNonZero(image) == 0) break;
+ if (image.FindFirstPixelEqualOrGreaterThan(1) == -1) break;
}
return skeleton;
diff --git a/UVtools.Core/Extensions/PointExtensions.cs b/UVtools.Core/Extensions/PointExtensions.cs
index 30202bd..d95572e 100644
--- a/UVtools.Core/Extensions/PointExtensions.cs
+++ b/UVtools.Core/Extensions/PointExtensions.cs
@@ -14,6 +14,7 @@ namespace UVtools.Core.Extensions
{
public static double FindLength(Point start, Point end) => Math.Sqrt(Math.Pow(end.Y - start.Y, 2) + Math.Pow(end.X - start.X, 2));
+ public static bool IsAnyNegative(this Point point) => point.X < 0 || point.Y < 0;
public static bool IsBothNegative(this Point point) => point.X < 0 && point.Y < 0;
public static bool IsBothZeroOrPositive(this Point point) => point.X >= 0 && point.Y >= 0;
diff --git a/UVtools.Core/Managers/IssueManager.cs b/UVtools.Core/Managers/IssueManager.cs
index 4de0495..6eb6874 100644
--- a/UVtools.Core/Managers/IssueManager.cs
+++ b/UVtools.Core/Managers/IssueManager.cs
@@ -606,12 +606,12 @@ namespace UVtools.Core.Managers
{
if (matCache[layerIndex] is not null) return;
int fromLayerIndex = (int)layerIndex;
- int toLayerIndex = (int)Math.Min(SlicerFile.LayerCount, layerIndex + Environment.ProcessorCount * 10 + 1);
+ int toLayerIndex = (int)Math.Min(SlicerFile.LayerCount, layerIndex + 1 + Environment.ProcessorCount * 5);
if (!direction)
{
toLayerIndex = fromLayerIndex + 1;
- fromLayerIndex = (int)Math.Max(resinTrapConfig.StartLayerIndex, fromLayerIndex - Environment.ProcessorCount * 10);
+ fromLayerIndex = (int)Math.Max(resinTrapConfig.StartLayerIndex, fromLayerIndex - Environment.ProcessorCount * 5);
}
Parallel.For(fromLayerIndex, toLayerIndex,
@@ -899,7 +899,6 @@ namespace UVtools.Core.Managers
resinTraps[layerIndex] = null;
break;
}
-
}
}
@@ -1031,9 +1030,8 @@ namespace UVtools.Core.Managers
var overlappingGroupIndexes = new List();
for (var x = 0; x < suctionGroups.Count; x++)
{
- if (suctionGroups[x].Last().LayerIndex != layerIndex + 1) continue;
-
- using var vec = new VectorOfVectorOfPoint(suctionGroups[x].Last().Contours);
+ if (suctionGroups[x][^1].LayerIndex != layerIndex + 1) continue;
+ using var vec = new VectorOfVectorOfPoint(suctionGroups[x][^1].Contours);
if (EmguContours.ContoursIntersect(trap, vec))
{
overlappingGroupIndexes.Add(x);
@@ -1103,25 +1101,23 @@ namespace UVtools.Core.Managers
public MainIssue[] DrillSuctionCupsForIssues(IEnumerable issues, int ventHoleDiameter, OperationProgress progress)
{
- (bool canDrill, Point location) GetDrillLocation(IssueOfContours issue, int diameter)
+ Point GetDrillLocation(IssueOfContours issue, int diameter)
{
using var vecCentroid = new VectorOfPoint(issue.Contours[0]);
var centroid = EmguContour.GetCentroid(vecCentroid);
+ if (centroid.IsAnyNegative()) return centroid;
using var circleCheck = EmguExtensions.InitMat(issue.BoundingRectangle.Size);
using var contourMat = EmguExtensions.InitMat(issue.BoundingRectangle.Size);
- using var overlapCheck = EmguExtensions.InitMat(issue.BoundingRectangle.Size);
var inverseOffset = new Point(issue.BoundingRectangle.X * -1, issue.BoundingRectangle.Y * -1);
using var vec = new VectorOfVectorOfPoint(issue.Contours);
CvInvoke.DrawContours(contourMat, vec, -1, EmguExtensions.WhiteColor, -1, LineType.EightConnected, null, int.MaxValue, inverseOffset);
-
CvInvoke.Circle(circleCheck, new(centroid.X + inverseOffset.X, centroid.Y + inverseOffset.Y), diameter, EmguExtensions.WhiteColor, -1);
+ CvInvoke.BitwiseAnd(circleCheck, contourMat, circleCheck);
- CvInvoke.BitwiseAnd(circleCheck, contourMat, overlapCheck);
-
- return CvInvoke.CountNonZero(overlapCheck) > 0
- ? (true, centroid) /* 5px centroid is inside layer! drill baby drill */
- : (false, new Point()); /* centroid is not inside the actual contour, no drill */
+ return circleCheck.FindFirstPositivePixel() != -1
+ ? centroid /* 5px centroid is inside layer! drill baby drill */
+ : new Point(-1,-1); /* centroid is not inside the actual contour, no drill */
}
var drillOps = new List();
@@ -1131,8 +1127,8 @@ namespace UVtools.Core.Managers
foreach (var mainIssue in issues)
{
var drillPoint = GetDrillLocation((IssueOfContours)mainIssue[0], ventHoleDiameter);
- if (!drillPoint.canDrill) continue;
- drillOps.Add(new PixelDrainHole(mainIssue.StartLayerIndex, drillPoint.location, (ushort)ventHoleDiameter));
+ if (drillPoint.IsAnyNegative()) continue;
+ drillOps.Add(new PixelDrainHole(mainIssue.StartLayerIndex, drillPoint, (ushort)ventHoleDiameter));
drilledIssues.Add(mainIssue);
}