* (Add) Resin Trap issue validator and repairer - Experimental Feature (#3)
* (Add) Layer Repair tool can now fix Resin Traps when selected
* (Add) "Remove" issues button fix selected Resin traps, the operation now run under a thread and in a parallel way, preventing the GUI from freeze
* (Change) "Repair Layers" button renamed to "Repair Layers and Issues"
* (Fix) When do a "repair layers" before open the Issue tab, when open next it will recompute issues without the need
This commit is contained in:
Tiago Conceição
2020-06-19 23:52:08 +01:00
parent 93e548c7de
commit fc73f2ff75
10 changed files with 354 additions and 297 deletions
+8
View File
@@ -1,5 +1,13 @@
# Changelog
## 19/06/2020 - v0.5.2
* (Add) Resin Trap issue validator and repairer - Experimental Feature (#3)
* (Add) Layer Repair tool can now fix Resin Traps when selected
* (Add) "Remove" issues button fix selected Resin traps, the operation now run under a thread and in a parallel way, preventing the GUI from freeze
* (Change) "Repair Layers" button renamed to "Repair Layers and Issues"
* (Fix) When do a "repair layers" before open the Issue tab, when open next it will recompute issues without the need
## 18/06/2020 - v0.5.1.3
* (Add) Button save layer image to Clipboard
+29 -31
View File
@@ -46,12 +46,12 @@ namespace UVtools.GUI.Forms
this.btnLayerRangeNormalLayers = new System.Windows.Forms.ToolStripMenuItem();
this.btnCancel = new System.Windows.Forms.Button();
this.btnRepair = new System.Windows.Forms.Button();
this.cbRepairLayers = new System.Windows.Forms.CheckBox();
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.cbRepairIslands = new System.Windows.Forms.CheckBox();
this.label1 = new System.Windows.Forms.Label();
this.cbRepairIslands = new System.Windows.Forms.CheckBox();
this.numOpeningIterations = new System.Windows.Forms.NumericUpDown();
this.btnLayerRangeSelect = new SplitButton();
this.cbRepairResinTraps = new System.Windows.Forms.CheckBox();
this.btnLayerRangeSelect = new UVtools.GUI.Controls.SplitButton();
((System.ComponentModel.ISupportInitialize)(this.numClosingIterations)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nmLayerRangeStart)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nmLayerRangeEnd)).BeginInit();
@@ -217,19 +217,6 @@ namespace UVtools.GUI.Forms
this.btnRepair.UseVisualStyleBackColor = true;
this.btnRepair.Click += new System.EventHandler(this.ItemClicked);
//
// cbRepairLayers
//
this.cbRepairLayers.AutoSize = true;
this.cbRepairLayers.Checked = true;
this.cbRepairLayers.CheckState = System.Windows.Forms.CheckState.Checked;
this.cbRepairLayers.Enabled = false;
this.cbRepairLayers.Location = new System.Drawing.Point(17, 242);
this.cbRepairLayers.Name = "cbRepairLayers";
this.cbRepairLayers.Size = new System.Drawing.Size(126, 24);
this.cbRepairLayers.TabIndex = 15;
this.cbRepairLayers.Text = "Repair Layers";
this.cbRepairLayers.UseVisualStyleBackColor = true;
//
// toolTip
//
this.toolTip.AutoPopDelay = 32767;
@@ -239,19 +226,6 @@ namespace UVtools.GUI.Forms
this.toolTip.ToolTipIcon = System.Windows.Forms.ToolTipIcon.Info;
this.toolTip.ToolTipTitle = "Information";
//
// cbRepairIslands
//
this.cbRepairIslands.AutoSize = true;
this.cbRepairIslands.Checked = true;
this.cbRepairIslands.CheckState = System.Windows.Forms.CheckState.Checked;
this.cbRepairIslands.Enabled = false;
this.cbRepairIslands.Location = new System.Drawing.Point(17, 272);
this.cbRepairIslands.Name = "cbRepairIslands";
this.cbRepairIslands.Size = new System.Drawing.Size(130, 24);
this.cbRepairIslands.TabIndex = 16;
this.cbRepairIslands.Text = "Repair Islands";
this.cbRepairIslands.UseVisualStyleBackColor = true;
//
// label1
//
this.label1.AutoSize = true;
@@ -263,6 +237,18 @@ namespace UVtools.GUI.Forms
this.label1.Text = "Opening Iterations:";
this.toolTip.SetToolTip(this.label1, resources.GetString("label1.ToolTip"));
//
// cbRepairIslands
//
this.cbRepairIslands.AutoSize = true;
this.cbRepairIslands.Checked = true;
this.cbRepairIslands.CheckState = System.Windows.Forms.CheckState.Checked;
this.cbRepairIslands.Location = new System.Drawing.Point(17, 246);
this.cbRepairIslands.Name = "cbRepairIslands";
this.cbRepairIslands.Size = new System.Drawing.Size(194, 24);
this.cbRepairIslands.TabIndex = 16;
this.cbRepairIslands.Text = "Repair Layers + Islands";
this.cbRepairIslands.UseVisualStyleBackColor = true;
//
// numOpeningIterations
//
this.numOpeningIterations.Location = new System.Drawing.Point(459, 208);
@@ -276,6 +262,18 @@ namespace UVtools.GUI.Forms
0,
0});
//
// cbRepairResinTraps
//
this.cbRepairResinTraps.AutoSize = true;
this.cbRepairResinTraps.Checked = true;
this.cbRepairResinTraps.CheckState = System.Windows.Forms.CheckState.Checked;
this.cbRepairResinTraps.Location = new System.Drawing.Point(17, 272);
this.cbRepairResinTraps.Name = "cbRepairResinTraps";
this.cbRepairResinTraps.Size = new System.Drawing.Size(164, 24);
this.cbRepairResinTraps.TabIndex = 19;
this.cbRepairResinTraps.Text = "Repair Resin Traps";
this.cbRepairResinTraps.UseVisualStyleBackColor = true;
//
// btnLayerRangeSelect
//
this.btnLayerRangeSelect.Location = new System.Drawing.Point(459, 168);
@@ -292,10 +290,10 @@ namespace UVtools.GUI.Forms
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.btnCancel;
this.ClientSize = new System.Drawing.Size(606, 308);
this.Controls.Add(this.cbRepairResinTraps);
this.Controls.Add(this.numOpeningIterations);
this.Controls.Add(this.label1);
this.Controls.Add(this.cbRepairIslands);
this.Controls.Add(this.cbRepairLayers);
this.Controls.Add(this.btnLayerRangeSelect);
this.Controls.Add(this.lbLayerRangeTo);
this.Controls.Add(this.nmLayerRangeEnd);
@@ -344,10 +342,10 @@ namespace UVtools.GUI.Forms
private System.Windows.Forms.ToolStripMenuItem btnLayerRangeCurrentLayer;
private System.Windows.Forms.ToolStripMenuItem btnLayerRangeBottomLayers;
private System.Windows.Forms.ToolStripMenuItem btnLayerRangeNormalLayers;
private System.Windows.Forms.CheckBox cbRepairLayers;
private System.Windows.Forms.ToolTip toolTip;
private System.Windows.Forms.CheckBox cbRepairIslands;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.NumericUpDown numOpeningIterations;
private System.Windows.Forms.CheckBox cbRepairResinTraps;
}
}
+13
View File
@@ -44,6 +44,12 @@ namespace UVtools.GUI.Forms
get => cbRepairIslands.Checked;
set => cbRepairIslands.Checked = value;
}
public bool RepairResinTraps
{
get => cbRepairResinTraps.Checked;
set => cbRepairResinTraps.Checked = value;
}
#endregion
#region Constructors
@@ -154,6 +160,13 @@ namespace UVtools.GUI.Forms
numClosingIterations.Select();
return;
}
if (!cbRepairIslands.Enabled && !cbRepairResinTraps.Enabled)
{
MessageBox.Show("You must select at least one repair operation.", Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (MessageBox.Show("Are you sure you want to attempt this repair?", Text, MessageBoxButtons.YesNo,
MessageBoxIcon.Question) == DialogResult.Yes)
{
-3
View File
@@ -138,9 +138,6 @@ Note: "Layer Start" start can't be higher than "Layer End".</value>
<metadata name="cmLayerRange.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>148, 17</value>
</metadata>
<data name="label1.ToolTip" xml:space="preserve">
<value>Selects the number of iterations/passes to perform on each layer.
Choose 0 to disable this step.
+5 -3
View File
@@ -320,8 +320,8 @@
this.menuToolsRepairLayers.Name = "menuToolsRepairLayers";
this.menuToolsRepairLayers.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Alt)
| System.Windows.Forms.Keys.R)));
this.menuToolsRepairLayers.Size = new System.Drawing.Size(204, 22);
this.menuToolsRepairLayers.Text = "&Repair layers";
this.menuToolsRepairLayers.Size = new System.Drawing.Size(261, 22);
this.menuToolsRepairLayers.Text = "&Repair layers and Issues";
this.menuToolsRepairLayers.Click += new System.EventHandler(this.EventClick);
//
// viewToolStripMenuItem
@@ -1041,7 +1041,9 @@
this.tsIssueRemove.Name = "tsIssueRemove";
this.tsIssueRemove.Size = new System.Drawing.Size(70, 22);
this.tsIssueRemove.Text = "Remove";
this.tsIssueRemove.ToolTipText = "Remove selected issue when possible";
this.tsIssueRemove.ToolTipText = "Remove selected issue when possible\r\nIslands: All pixels are removed (turn black)" +
"\r\nResinTrap: All trap areas are filled with white pixels.\r\nTouchingBounds: No ac" +
"tion, need reslice.";
this.tsIssueRemove.Click += new System.EventHandler(this.EventClick);
//
// toolStripSeparator12
+242 -208
View File
@@ -553,6 +553,8 @@ namespace UVtools.GUI
uint layerEnd;
uint closingIterations;
uint openingIterations;
bool repairIslands;
bool repairResinTraps;
using (var frmRepairLayers = new FrmRepairLayers(2))
{
if (frmRepairLayers.ShowDialog() != DialogResult.OK) return;
@@ -561,10 +563,17 @@ namespace UVtools.GUI
layerEnd = frmRepairLayers.LayerRangeEnd;
closingIterations = frmRepairLayers.ClosingIterations;
openingIterations = frmRepairLayers.OpeningIterations;
repairIslands = frmRepairLayers.RepairIslands;
repairResinTraps = frmRepairLayers.RepairResinTraps;
}
if (repairResinTraps && ReferenceEquals(Issues, null))
{
ComputeIssues();
}
DisableGUI();
FrmLoading.SetDescription("Reparing Layers");
FrmLoading.SetDescription("Reparing Layers and Issues");
Task<bool> task = Task<bool>.Factory.StartNew(() =>
{
@@ -572,26 +581,43 @@ namespace UVtools.GUI
try
{
Parallel.For(layerStart, layerEnd + 1, i =>
Parallel.For(layerStart, layerEnd + 1, layerIndex =>
{
Layer layer = SlicerFile[i];
var image = layer.Image;
var imageEgmu = image.ToEmguImage();
if (closingIterations > 0)
Layer layer = SlicerFile[layerIndex];
using (var image = layer.Image)
{
imageEgmu = imageEgmu.Dilate((int) closingIterations);
imageEgmu = imageEgmu.Erode((int) closingIterations);
}
var imageEgmu = image.ToEmguImage();
if (openingIterations > 0)
{
imageEgmu = imageEgmu.Erode((int) openingIterations);
imageEgmu = imageEgmu.Dilate((int) openingIterations);
}
if (repairResinTraps)
{
if (Issues.TryGetValue((uint) layerIndex, out var issues))
{
foreach (var issue in issues)
{
if(issue.Type != LayerIssue.IssueType.ResinTrap) continue;
imageEgmu.Draw(new VectorOfVectorOfPoint(new VectorOfPoint(issue.Pixels)), -1, new Gray(255), -1);
}
}
}
layer.Image = imageEgmu.ToImageSharpL8();
imageEgmu.Dispose();
if (repairIslands)
{
if (closingIterations > 0)
{
imageEgmu = imageEgmu.Dilate((int) closingIterations);
imageEgmu = imageEgmu.Erode((int) closingIterations);
}
if (openingIterations > 0)
{
imageEgmu = imageEgmu.Erode((int) openingIterations);
imageEgmu = imageEgmu.Dilate((int) openingIterations);
}
}
layer.Image = imageEgmu.ToImageSharpL8();
imageEgmu.Dispose();
}
});
result = true;
}
@@ -870,43 +896,105 @@ namespace UVtools.GUI
if (MessageBox.Show("Are you sure you want to remove all selected issues from image?\n" +
"Warning: Removing a island can cause another issues to appears if the next layer have land in top of the removed island.\n" +
"Always check previous and next layer before perform a island removal to ensure safe operation.",
"Remove islands?",
"Remove Issues?",
MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) return;
Dictionary<uint, List<LayerIssue>> processIssues = new Dictionary<uint, List<LayerIssue>>();
foreach (ListViewItem item in lvIssues.SelectedItems)
{
if (!(item.Tag is LayerIssue issue)) continue;
if (!issue.HaveValidPoint) continue;
var image = ActualLayer == issue.Layer.Index ? ActualLayerImage : issue.Layer.Image;
if(!issue.HaveValidPoint) continue;
foreach (var pixel in issue)
if (!processIssues.TryGetValue(issue.Layer.Index, out var issueList))
{
image[pixel.X, pixel.Y] = Helpers.L8Black;
if (ActualLayer == issue.Layer.Index)
{
int x = pixel.X;
int y = pixel.Y;
if (tsLayerImageRotate.Checked)
{
x = ActualLayerImage.Height - 1 - pixel.Y;
y = pixel.X;
}
((Bitmap) pbLayer.Image).SetPixel(x, y, Color.DarkRed);
}
issueList = new List<LayerIssue>();
processIssues.Add(issue.Layer.Index, issueList);
}
if (ActualLayer == issue.Layer.Index) pbLayer.Invalidate();
issue.Layer.Image = image;
Issues[issue.Layer.Index].Remove(issue);
TotalIssues--;
item.Remove();
issueList.Add(issue);
}
DisableGUI();
FrmLoading.SetDescription("Removing selected issues");
Task<bool> task = Task<bool>.Factory.StartNew(() =>
{
bool result = false;
try
{
Parallel.ForEach(processIssues, layerIssues =>
{
using (var image = SlicerFile[layerIssues.Key].Image)
{
using (var imageEmgu = image.ToEmguImage())
{
var data = imageEmgu.Data;
bool edited = false;
foreach (var issue in layerIssues.Value)
{
if (issue.Type == LayerIssue.IssueType.Island)
{
foreach (var pixel in issue)
{
data[pixel.Y, pixel.X, 0] = 0;
}
edited = true;
}
else if (issue.Type == LayerIssue.IssueType.ResinTrap)
{
imageEmgu.Draw(new VectorOfVectorOfPoint(new VectorOfPoint(issue.Pixels)),
-1, new Gray(255), -1);
edited = true;
}
}
if (!edited) return;
SlicerFile[layerIssues.Key].Image = imageEmgu.ToImageSharpL8();
result = true;
}
}
});
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Unsuccessful Removal", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
Invoke((MethodInvoker)delegate {
// Running on the UI thread
EnableGUI(true);
});
}
return result;
});
FrmLoading.ShowDialog();
if (!task.Result) return;
// Update GUI
lvIssues.BeginUpdate();
foreach (ListViewItem item in lvIssues.SelectedItems)
{
if (!(item.Tag is LayerIssue issue)) continue;
if (!issue.HaveValidPoint) continue;
if (issue.Type == LayerIssue.IssueType.TouchingBound) continue;
Issues[issue.Layer.Index].Remove(issue);
item.Remove();
TotalIssues--;
}
lvIssues.EndUpdate();
ShowLayer();
UpdateIssuesInfo();
menuFileSave.Enabled =
menuFileSaveAs.Enabled = true;
@@ -1181,7 +1269,7 @@ namespace UVtools.GUI
}
pbLayer.ZoomToRegion(x, y, 5, 5);
//pbLayer.ZoomOut(true);
pbLayer.ZoomOut(true);
}
else
{
@@ -1191,6 +1279,7 @@ namespace UVtools.GUI
tsLayerImageRotate.Checked ? issue.BoundingRectangle.Height : issue.BoundingRectangle.Width,
tsLayerImageRotate.Checked ? issue.BoundingRectangle.Width : issue.BoundingRectangle.Height
);
pbLayer.ZoomOut(true);
}
}
@@ -1629,19 +1718,23 @@ namespace UVtools.GUI
Image<Gray, byte> greyscale = ActualLayerImage.ToEmguImage();
#if DEBUG
grayscale = grayscale.ThresholdBinary(new Gray(254), new Gray(255));
greyscale = greyscale.ThresholdBinary(new Gray(254), new Gray(255));
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
Mat external = new Mat();
CvInvoke.FindContours(grayscale, contours, external, RetrType.Ccomp, ChainApproxMethod.ChainApproxSimple);
CvInvoke.FindContours(greyscale, contours, external, RetrType.Ccomp, ChainApproxMethod.ChainApproxSimple);
var arr = external.GetData();
for (int i = 0; i < contours.Size; i++)
{
if ((int)arr.GetValue(0, i, 2) != -1 || (int)arr.GetValue(0, i, 3) == -1) continue;
var r = CvInvoke.BoundingRectangle(contours[i]);
CvInvoke.Rectangle(grayscale, r, new MCvScalar(125), 10);
CvInvoke.Rectangle(greyscale, r, new MCvScalar(80), 3);
greyscale.Draw(contours, i, new Gray(125), -1);
}
#else
greyscale = greyscale.Canny(80, 40, 3, true);
#endif
@@ -1738,8 +1831,9 @@ namespace UVtools.GUI
using (var dummyImage = new Image<Gray, byte>(ActualLayerImage.Width,
ActualLayerImage.Height))
{
dummyImage.FillConvexPoly(issue.Pixels, new Gray(255));
dummyImage.DrawPolyline(issue.Pixels, true, new Gray(125), 2);
dummyImage.Draw(new VectorOfVectorOfPoint(new VectorOfPoint(issue.Pixels)), -1, new Gray(255), -1);
//dummyImage.FillConvexPoly(issue.Pixels, new Gray(255));
dummyImage.DrawPolyline(issue.Pixels, true, new Gray(125), 1);
byte[,,] data = dummyImage.Data;
for (int y = issue.BoundingRectangle.Y; y < issue.BoundingRectangle.Bottom; y++)
{
@@ -1884,7 +1978,6 @@ namespace UVtools.GUI
if(ReferenceEquals(tabControlLeft.SelectedTab, tabPageIssues))
{
if (!ReferenceEquals(tabPageIssues.Tag, null)) return;
tabPageIssues.Tag = true;
ComputeIssues();
}
return;
@@ -2144,7 +2237,7 @@ namespace UVtools.GUI
imageEgmu = resizedImage.Copy(new Rectangle(0, 0, image.Width, image.Height));
break;
case Mutation.Mutates.Solidify:
for (byte pass = 0; pass < 2; pass++) // Passes
for (byte pass = 0; pass < 1; pass++) // Passes
{
var imageThreshold = imageEgmu.ThresholdBinary(new Gray(254), new Gray(255)); // Clean AA
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
@@ -2164,9 +2257,9 @@ namespace UVtools.GUI
{
if ((int)arr.GetValue(0, i, 2) != -1 || (int)arr.GetValue(0, i, 3) == -1) continue;
var r = CvInvoke.BoundingRectangle(contours[i]);
imageEgmu.FillConvexPoly(contours[i].ToArray(), new Gray(255));
//imageEgmu.FillConvexPoly(contours[i].ToArray(), new Gray(255));
//imageThreshold.FillConvexPoly(contours[i].ToArray(), new Gray(255));
//CvInvoke.po
imageEgmu.Draw(contours, i, new Gray(255), -1);
}
// Attempt to close any tiny region
@@ -2276,6 +2369,7 @@ namespace UVtools.GUI
private void ComputeIssues()
{
tabPageIssues.Tag = true;
TotalIssues = 0;
lvIssues.BeginUpdate();
lvIssues.Items.Clear();
@@ -2290,23 +2384,24 @@ namespace UVtools.GUI
bool result = false;
try
{
var issues = SlicerFile.LayerManager.GetAllIssues();
Issues = new Dictionary<uint, List<LayerIssue>>();
for (uint i = 0; i < SlicerFile.LayerCount; i++)
Task taskGenericIssues = Task.Factory.StartNew(() =>
{
if (issues.TryGetValue(i, out var list))
{
Issues.Add(i, list);
}
}
var issues = SlicerFile.LayerManager.GetAllIssues();
Issues = new Dictionary<uint, List<LayerIssue>>();
for (uint i = 0; i < SlicerFile.LayerCount; i++)
{
if (issues.TryGetValue(i, out var list))
{
Issues.Add(i, list);
}
}
});
return true;
var layerHollowAreas = new ConcurrentDictionary<uint, List<LayerHollowArea>>();
Stopwatch sw = new Stopwatch();
sw.Start();
Parallel.ForEach(SlicerFile,
//new ParallelOptions{MaxDegreeOfParallelism = 1},
layer =>
@@ -2344,95 +2439,119 @@ namespace UVtools.GUI
}
});
List<LayerHollowArea> linkedAreas = new List<LayerHollowArea>();
LayerHollowArea lastCheckedArea;
for (uint layerIndex = 1; layerIndex < SlicerFile.LayerCount-1; layerIndex++) // Ignore first and last layers, always drains
{
if(!layerHollowAreas.TryGetValue(layerIndex, out var areas)) continue; // No hollow areas in this layer, ignore
byte areaCount = 0;
foreach (var area in areas)
//foreach (var area in areas)
Parallel.ForEach(areas, area =>
{
if (area.Type != LayerHollowArea.AreaType.Unknown) continue; // processed, ignore
if (area.Type != LayerHollowArea.AreaType.Unknown) return; // processed, ignore
area.Type = LayerHollowArea.AreaType.Trap;
areaCount++;
linkedAreas.Clear();
List<LayerHollowArea> linkedAreas = new List<LayerHollowArea>();
for (sbyte dir = 1; dir >= -1 && area.Type != LayerHollowArea.AreaType.Drain; dir -= 2)
//Parallel.ForEach(dirs, new ParallelOptions {MaxDegreeOfParallelism = 2}, dir =>
{
Queue<LayerHollowArea> queue = new Queue<LayerHollowArea>();
queue.Enqueue(area);
area.Processed = false;
int nextLayerIndex = (int) layerIndex;
while (queue.Count > 0 && area.Type != LayerHollowArea.AreaType.Drain)
{
lastCheckedArea = queue.Dequeue();
LayerHollowArea checkArea = queue.Dequeue();
if (checkArea.Processed) continue;
checkArea.Processed = true;
nextLayerIndex += dir;
Debug.WriteLine($"Area Count: {areaCount} | Layer: {layerIndex} | Next Layer: {nextLayerIndex} | Dir: {dir}");
if (nextLayerIndex < 0 && nextLayerIndex >= SlicerFile.LayerCount) break; // Exhaust layers
bool haveNextAreas = layerHollowAreas.TryGetValue((uint)nextLayerIndex, out var nextAreas);
Debug.WriteLine(
$"Area Count: {areaCount} | Layer: {layerIndex} | Next Layer: {nextLayerIndex} | Dir: {dir}");
if (nextLayerIndex < 0 && nextLayerIndex >= SlicerFile.LayerCount)
break; // Exhaust layers
bool haveNextAreas =
layerHollowAreas.TryGetValue((uint) nextLayerIndex, out var nextAreas);
using (var image = SlicerFile[nextLayerIndex].Image)
{
using (var emguImage = new Image<Gray, byte>(ActualLayerImage.Width, ActualLayerImage.Height))
using (var emguImage = new Image<Gray, byte>(ActualLayerImage.Width,
ActualLayerImage.Height))
{
image.TryGetSinglePixelSpan(out var span);
emguImage.FillConvexPoly(lastCheckedArea.Contour, new Gray(255));
//emguImage.FillConvexPoly(checkArea.Contour, new Gray(255));
emguImage.Draw(new VectorOfVectorOfPoint(new VectorOfPoint(checkArea.Contour)), -1,
new Gray(255), -1);
bool exitPixelLoop = false;
uint blackCount = 0;
byte[,,] data = emguImage.Data;
for (int y = lastCheckedArea.BoundingRectangle.Y;
y <= lastCheckedArea.BoundingRectangle.Bottom && area.Type != LayerHollowArea.AreaType.Drain && !exitPixelLoop;
for (int y = checkArea.BoundingRectangle.Y;
y <= checkArea.BoundingRectangle.Bottom &&
area.Type != LayerHollowArea.AreaType.Drain && !exitPixelLoop;
y++)
{
for (int x = lastCheckedArea.BoundingRectangle.X;
x <= lastCheckedArea.BoundingRectangle.Right && area.Type != LayerHollowArea.AreaType.Drain && !exitPixelLoop;
for (int x = checkArea.BoundingRectangle.X;
x <= checkArea.BoundingRectangle.Right &&
area.Type != LayerHollowArea.AreaType.Drain && !exitPixelLoop;
x++)
{
if (data[y, x, 0] != 255) continue;
if (span[y * image.Width + x].PackedValue > 30) continue;
blackCount++;
if (span[y * image.Width + x] == Helpers.L8Black) // Found a black pixel: Drain or trap
if (haveNextAreas
) // Have areas, can be on same area path or not
{
if (haveNextAreas)
foreach (var nextArea in nextAreas)
{
foreach (var nextArea in nextAreas)
/*if (!area.BoundingRectangle.IntersectsWith(nextArea.BoundingRectangle)) // If not intersect futher ispection is useless
{
if (!area.BoundingRectangle.IntersectsWith(nextArea.BoundingRectangle)) // If not intersect futher ispection is useless
{
continue;
}
if (CvInvoke.PointPolygonTest(new VectorOfPoint(nextArea.Contour),
new PointF(x, y), false) >= 0)
{
if (nextArea.Type == LayerHollowArea.AreaType.Drain) // Found a drain, stop query
{
area.Type = LayerHollowArea.AreaType.Drain;
}
else
{
queue.Enqueue(nextArea);
}
linkedAreas.Add(nextArea);
exitPixelLoop = true;
break;
}
continue;
}*/
if (!(CvInvoke.PointPolygonTest(
new VectorOfPoint(nextArea.Contour),
new PointF(x, y), false) >= 0)) continue;
if (nextArea.Type == LayerHollowArea.AreaType.Drain
) // Found a drain, stop query
{
area.Type = LayerHollowArea.AreaType.Drain;
}
}
else // Black pixel without next areas = Drain
{
area.Type = LayerHollowArea.AreaType.Drain;
else
{
queue.Enqueue(nextArea);
}
linkedAreas.Add(nextArea);
exitPixelLoop = true;
break;
}
} // black check
}
else if(blackCount > Math.Min(checkArea.Contour.Length / 2, 10)) // Black pixel without next areas = Drain
{
area.Type = LayerHollowArea.AreaType.Drain;
exitPixelLoop = true;
break;
}
} // X loop
} // Y loop
if (queue.Count == 0 && blackCount > Math.Min(checkArea.Contour.Length / 2, 10))
{
/*Invoke((MethodInvoker)delegate
{
// Running on the UI thread
ShowLayer((uint)nextLayerIndex);
});*/
area.Type = LayerHollowArea.AreaType.Drain;
}
} // Dispose emgu image
} // Dispose image
} // Areas loop
@@ -2442,101 +2561,11 @@ namespace UVtools.GUI
{
linkedArea.Type = area.Type;
}
/*for (sbyte dir = 1; dir >= -1; dir-=2)
{
Debug.WriteLine($"dir: {dir}");
for (int nextLayerIndex = (int) (layerIndex + dir); nextLayerIndex >= 0 && nextLayerIndex < SlicerFile.LayerCount; nextLayerIndex+= dir) // Search on next layer
{
Debug.WriteLine($"Next Layer: {nextLayerIndex}");
bool nextHaveAreas = layerHollowAreas.TryGetValue((uint) nextLayerIndex, out var nextList);
// if (!layerHollowAreas.TryGetValue((uint) i, out var nextList)) // No areas found on next layer, check for tops
// {
area.Type = LayerHollowArea.AreaType.Trap;
using (var image = SlicerFile[nextLayerIndex].Image)
{
using (var emguImage = new Image<Gray, byte>(ActualLayerImage.Width, ActualLayerImage.Height))
{
image.TryGetSinglePixelSpan(out var span);
emguImage.FillConvexPoly(lastCheckedArea.Contour, new Gray(255));
byte[,,] data = emguImage.Data;
for (int y = lastCheckedArea.BoundingRectangle.Y;
y < lastCheckedArea.BoundingRectangle.Bottom && area.Type != LayerHollowArea.AreaType.Drain;
y++)
{
for (int x = lastCheckedArea.BoundingRectangle.X;
x < lastCheckedArea.BoundingRectangle.Right && area.Type != LayerHollowArea.AreaType.Drain;
x++)
{
if (data[y, x, 0] != 255) continue;
var pixelIndex = y * image.Width + x;
if (span[pixelIndex] == Helpers.L8Black) // Found a black pixel: Drain
{
if (nextHaveAreas)
{
foreach (var nextArea in nextList)
{
if (CvInvoke.PointPolygonTest(new VectorOfPoint(nextArea.Contour),
new PointF(x, y), false) > 0)
{
linkedAreas.Add(nextArea);
if (nextArea.Type == LayerHollowArea.AreaType.Drain) // Found a drain, stop query
{
area.Type = nextArea.Type;
}
break;
}
}
}
else
{
area.Type = LayerHollowArea.AreaType.Drain;
break;
}
}
}
}
}
}
if (area.Type == LayerHollowArea.AreaType.Drain) // Found a drain, stop query
{
break;
}
//}
/*foreach (var nextArea in nextList)
{
if (area.BoundingRectangle.IntersectsWith(nextArea.BoundingRectangle))
{
lastCheckedArea = nextArea;
linkedAreas.Add(nextArea);
if (nextArea.Type == LayerHollowArea.AreaType.Drain) // Found a drain, stop query
{
area.Type = nextArea.Type;
break;
}
}
}*/
/*}
if(area.Type == LayerHollowArea.AreaType.Drain) // Found a drain, stop query
break;
}
foreach (var linkedArea in linkedAreas) // Update linked areas
{
linkedArea.Type = area.Type;
}*/
}
});
}
Issues = new Dictionary<uint, List<LayerIssue>>();
taskGenericIssues.Wait();
for (uint layerIndex = 0; layerIndex < SlicerFile.LayerCount; layerIndex++)
{
if (!layerHollowAreas.TryGetValue(layerIndex, out var list)) continue;
@@ -2552,15 +2581,20 @@ namespace UVtools.GUI
}
}
if (issues.Count > 0)
if (issuesHollow.Count > 0)
{
Issues.Add(layerIndex, issuesHollow);
if (Issues.TryGetValue(layerIndex, out var currentIssue))
{
currentIssue.AddRange(issuesHollow);
}
else
{
Issues.Add(layerIndex, issuesHollow);
}
}
}
}
sw.Stop();
Debug.WriteLine($"RectSearch: {sw.ElapsedMilliseconds}ms");
result = true;
}
@@ -2615,8 +2649,8 @@ namespace UVtools.GUI
}
lvIssues.EndUpdate();
UpdateIssuesInfo();
ShowLayer();
}
private void EventMouseDown(object sender, MouseEventArgs e)
+37 -46
View File
@@ -126,6 +126,12 @@
<metadata name="tsLayer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>201, 17</value>
</metadata>
<metadata name="tsThumbnails.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>291, 17</value>
</metadata>
<metadata name="tsProperties.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>649, 17</value>
</metadata>
<metadata name="tsGCode.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>551, 17</value>
</metadata>
@@ -140,84 +146,69 @@
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAA4
DgAAAk1TRnQBSQFMAgEBBAEAASABBAEgAQQBEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA
DgAAAk1TRnQBSQFMAgEBBAEAAUABBAFAAQQBEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA
AwABIAMAAQEBAAEgBgABIP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8AZgADUAGjA1IBqQNS
AakDUgGpA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1ABo1wAAxUBHQFCAXABgAH1
AUABhQGMAfcDQwF3A1sByAJCAXsB9QJYAV8B4wNKAYwDCgENBAADVQG0A1kBxwMvAUkDAAEBAxsBJgMc
AakDUgGpA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1ABo1wAAxUBHQFCAWwBcwH1
AUgBgQGHAfcDQwF3A1sByAJCAW8B9QJYAV8B4wNKAYwDCgENBAADVQG0A1kBxwMvAUkDAAEBAxsBJgMc
AScDHAEnAxwBJwMcAScDHAEnAxwBJwMcAScDHAEnAxwBJwMcAScDAgEDBAADUgGpMAADUgGpEAADJwE6
AzABTAMwAUwDMAFMAzABTAMwAUwDMAFMAzABTAMwAUwDJwE6FAADBQEHA0wBkgFWAlgBwQMVAR0DPQFp
AQkByAHzAf8BFwGQAeYB/wItAdwB/wItAd0B/wJiAeMB/wI4Ad4B/wItAd0B/wJYAVsBywMGAQgDAAH/
AQUByAHzAf8BEwGQAeYB/wIpAdwB/wIpAd0B/wJeAeMB/wI0Ad4B/wIpAd0B/wJYAVsBywMGAQgDAAH/
AwAB/wNDAXcDKQE+AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DMgFR
BAADUgGpBAADUAGdA1MBqgNTAaoDUwGqA1MBqgNTAaoDUwGqA1ABnQwAA1IBqRAAA04B+wMAAf8DAAH/
AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/A04B+xQAATACMQFNAQoByQHzAf8BCgHJAfQB/wFZAWcBaQHr
AVsCXgHZAQ0BwAHxAf8BLgE2Ad8B/wIwAeAB/wIwAeAB/wJpAekB/wI7AeIB/wIwAeAB/wIwAeAB/wNA
AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/A04B+xQAATACMQFNAQYByQHzAf8BBgHJAfQB/wFZAWIBZAHr
AVsCXgHZAQkBwAHxAf8BKgEyAd8B/wIsAeAB/wIsAeAB/wJlAekB/wI3AeIB/wIsAeAB/wIsAeAB/wNA
AXEDUQGiA1YBtgMqAUAEAAMQARUDEQEXAxEBFwMRARcDEQEXAxEBFwMRARcDEQEXAxEBFwMRARcDEAEW
CAADUgGpBAADUAGdA1MBqgNTAaoDHwEsHAADUgGpEwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMA
Af8DAAH/AwAB/xQAAwcBCgFPAXIBeQHyAQwBygH0Af8BDAHKAfQB/wEMAcoB9AH/ARgBoQHuAf8CMwHj
Af8CMwHjAf8CMwHjAf8CqQHvAf8COgHjAf8CMwHjAf8CMwHjAf8CVgFYAbkDCgEOAxEBFwMAAQE4AANS
Af8DAAH/AwAB/xQAAwcBCgFWAWkBbwHyAQgBygH0Af8BCAHKAfQB/wEIAcoB9AH/ARQBoQHuAf8CLwHj
Af8CLwHjAf8CLwHjAf8CqQHvAf8CNgHjAf8CLwHjAf8CLwHjAf8CVgFYAbkDCgEOAxEBFwMAAQE4AANS
AakwAANSAakTAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/DAADFQEdAz0BaQM6
AWIBXAJgAdQBDQHLAfUB/wENAcsB9QH/AQ0BywH1Af8BGwGgAfAB/wI2AeYB/wI2AeYB/wI2AeYB/wLC
AfYB/wJOAegB/wI2AeYB/wI2AeYB/wJXAVkBvwNSAfQDAAH/Az4BbAMOARMDQgF2A0MBdwNDAXcDQwF3
AWIBXAJgAdQBCQHLAfUB/wEJAcsB9QH/AQkBywH1Af8BFwGgAfAB/wIyAeYB/wIyAeYB/wIyAeYB/wLC
AfYB/wJKAegB/wIyAeYB/wIyAeYB/wJXAVkBvwNSAfQDAAH/Az4BbAMOARMDQgF2A0MBdwNDAXcDQwF3
A0MBdwNDAXcDQwF3A0MBdwNDAXcDQwF3A0IBdgMUARsEAANSAakDIgEyA1IBqQNSAakDUgGpA1IBqQNS
AakDUgGpA1IBqQNSAakDUgGpA1IBqQMiATIDUgGpEwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMA
Af8DAAH/AwAB/wwAAUsCTAGQAQ4BywH2Af8BDgHLAfYB/wEOAcsB9gH/AQ4BywH2Af8BKQGSAaQB+gND
AXgDIgEyAksBogH7AjkB6QH/AjkB6QH/As0B+AH/Al0B7QH/AjkB6QH/AjkB6QH/A1ABngMAAf4DAAH/
Af8DAAH/AwAB/wwAAUsCTAGQAQoBywH2Af8BCgHLAfYB/wEKAcsB9gH/AQoBywH2Af8BKQGGAZwB+gND
AXgDIgEyAksBmAH7AjUB6QH/AjUB6QH/As0B+AH/AlkB7QH/AjUB6QH/AjUB6QH/A1ABngMAAf4DAAH/
A0MBdwMeASsDVwHFA1kBxwNZAccDWQHHA1kBxwNZAccDWQHHA1kBxwNZAccDWQHHA1gBxgMmATkEAANS
AakDNAFVAzQBVSAAAzQBVQM0AVUDUgGpEwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/
AwAB/wwAA1EBoAEQAcwB9wH/ARABzAH3Af8BEAHMAfcB/wEQAcwB9wH/A0MBdwgAA0oBjQI8AewB/wI8
AewB/wJYAe8B/wJAAewB/wI8AewB/wE4AUkB7QH/AVICUwGoAzMBUwM8AWcDFAEcOAADUgGpAzQBVQM0
AwAB/wwAA1EBoAEMAcwB9wH/AQwBzAH3Af8BDAHMAfcB/wEMAcwB9wH/A0MBdwgAA0oBjQI4AewB/wI4
AewB/wJUAe8B/wI8AewB/wI4AewB/wE0AUUB7QH/AVICUwGoAzMBUwM8AWcDFAEcOAADUgGpAzQBVQM0
AVUDRgGAA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA0UBfwM0AVUDNAFVA1IBqRMAAf8DAAH/AwAB/wMA
Af8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8PAAEBAT8CQAFvAT4BiwGYAfgBEQHNAfcB/wERAc0B9wH/
AxIBGAgAAwEBAgNGAX4CUgFsAfACPwHuAf8BPwFAAe4B/wFAAVIBvgH9AUUCRgF+AwMBBAMzAVMDPAFn
Af8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8PAAEBAT8CQAFvAT4BfwGQAfgBDQHNAfcB/wENAc0B9wH/
AxIBGAgAAwEBAgNGAX4CUgFnAfACOwHuAf8BOwE8Ae4B/wFAAU4BugH9AUUCRgF+AwMBBAMzAVMDPAFn
AxQBHDgAA1IBqQM0AVUDNAFVAz8BbgMyAVAQAAMnATsDRAF8AzQBVQM0AVUDUgGpEwAB/wMAAf8DAAH/
AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/w8AAQEBPwJAAW8BPgGLAZgB+AESAc4B+AH/ARIBzgH4
Af8DEgEYEAADFwEgARkBvAH3Af8BFgHEAfcB/wE2AbIBwgH9AUUCRgF+AwMBBAMAAf4DAAH/A0MBdwMf
AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/w8AAQEBPwJAAW8BPgF/AZAB+AEOAc4B+AH/AQ4BzgH4
Af8DEgEYEAADFwEgARUBvAH3Af8BEgHEAfcB/wE6Aa4BvAH9AUUCRgF+AwMBBAMAAf4DAAH/A0MBdwMf
ASwDVwHFA1kBxwNZAccDWQHHA1kBxwNZAccDWQHHA1kBxwNZAccDWQHHA1gBxgMmATkEAANSAakDNAFV
AzQBVQMFAQcDVQG1AxEBFwNSAakDKQE+BAADUAGfAxEBFwM0AVUDNAFVA1IBqRMAAf8DAAH/AwAB/wMA
Af8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8MAANRAaABFAHOAfgB/wEUAc8B+QH/ARQBzwH5Af8BFAHP
AfkB/wNDAXcQAANEAXoBFAHPAfkB/wEUAc8B+QH/ARQBzwH5Af8BFAHOAfgB/wFSAlMBqANSAfQDAAH/
Af8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8MAANRAaABEAHOAfgB/wEQAc8B+QH/ARABzwH5Af8BEAHP
AfkB/wNDAXcQAANEAXoBEAHPAfkB/wEQAc8B+QH/ARABzwH5Af8BEAHOAfgB/wFSAlMBqANSAfQDAAH/
Az4BbAMOARMDQgF1A0MBdwNDAXcDQwF3A0MBdwNDAXcDQwF3A0MBdwNDAXcDQwF3A0MBdwMUARsEAANS
AakDNAFVAzQBVQQAAzwBaANWAb4DIwE0A1UBtQMSARkDUQGgBAADNAFVAzQBVQNSAakTAAH/AwAB/wMA
Af8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DXAHfDAABSwJMAZABFQHQAfoB/wEVAdAB+gH/ARUB0AH6
Af8BFQHQAfoB/wEpAZIBpAH6A0MBeAMSARkDEwEaA0QBegEoAZUBqwH7ARUB0AH6Af8BFQHQAfoB/wEV
AdAB+gH/ARUB0AH6Af8DSgGMAwoBDgMRARcDAAEBOAADUgGpAzQBVQM0AVUDAAEBAy0BRgMKAQ4EAAM5
Af8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DXAHfDAABSwJMAZABEQHQAfoB/wERAdAB+gH/AREB0AH6
Af8BEQHQAfoB/wEpAYYBnAH6A0MBeAMSARkDEwEaA0QBegEoAZEBnQH7AREB0AH6Af8BEQHQAfoB/wER
AdAB+gH/AREB0AH6Af8DSgGMAwoBDgMRARcDAAEBOAADUgGpAzQBVQM0AVUDAAEBAy0BRgMKAQ4EAAM5
AV8DXAHOAygBPAQAAzQBVQM0AVUDUgGpEwAB/wOCAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DXAHf
AxcBIAwAAxUBHQM9AWkDOgFiAVwCYAHUARYB0QH6Af8BFgHRAfoB/wEWAdAB+gH/ARYBywHzAf8BFgHL
AfMB/wEWAdAB+gH/ARYB0QH6Af8BFgHRAfoB/wFdAmEB4gM6AWIDPQFpAxQBHANRAaIDVgG2AyoBQAQA
AxcBIAwAAxUBHQM9AWkDOgFiAVwCYAHUARIB0QH6Af8BEgHRAfoB/wESAdAB+gH/ARIBywHzAf8BEgHL
AfMB/wESAdAB+gH/ARIB0QH6Af8BEgHRAfoB/wFdAmEB4gM6AWIDPQFpAxQBHANRAaIDVgG2AyoBQAQA
AxABFQMRARcDEQEXAxEBFwMRARcDEQEXAxEBFwMRARcDEQEXAxEBFwMQARYIAANSAakDNAFVAzQBVQMz
AVMDUgGmA0oBjAcAAQEDRwGDCAADNAFVAzQBVQNSAakTAAH/A5kB/wOFAf8DAAH/AwAB/wMAAf8DAAH/
A1wB3wMXASAYAAMHAQoBUwFyAXkB8gEYAdIB+wH/ARgB0gH7Af8BGAHSAfsB/wEYAdIB+wH/ARgB0gH7
Af8BGAHSAfsB/wEYAdIB+wH/ARgB0gH7Af8BKwGWAasB+wMRARcLAAH/AwAB/wNDAXcDKQE+AwAB/wMA
A1wB3wMXASAYAAMHAQoBWAFpAW8B8gEUAdIB+wH/ARQB0gH7Af8BFAHSAfsB/wEUAdIB+wH/ARQB0gH7
Af8BFAHSAfsB/wEUAdIB+wH/ARQB0gH7Af8BKwGSAZ0B+wMRARcLAAH/AwAB/wNDAXcDKQE+AwAB/wMA
Af8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DMgFRBAADUgGpAzQBVQM0AVUDEQEX
A1ABngMkATYUAAM0AVUDNAFVA1IBqRAAA1AB+wMAAf8DAAH/AwAB/wMAAf8DAAH/A1wB3wMXASAcAAEw
AjEBTQEZAdIB/AH/ARkB0gH8Af8BWQFoAWoB6wFbAl4B2QEZAdIB/AH/ARkB0gH8Af8BWwJhAeEBXQJh
AeIBGQHSAfwB/wEZAdIB/AH/AzgBXggAA1UBtANZAccDLwFJAwABAQMbASYDHAEnAxwBJwMcAScDHAEn
AjEBTQEVAdIB/AH/ARUB0gH8Af8BWQFjAWYB6wFbAl4B2QEVAdIB/AH/ARUB0gH8Af8BWwJhAeEBXQJh
AeIBFQHSAfwB/wEVAdIB/AH/AzgBXggAA1UBtANZAccDLwFJAwABAQMbASYDHAEnAxwBJwMcAScDHAEn
AxwBJwMcAScDHAEnAxwBJwMcAScDHAEnAwIBAwQAA1IBqQMiATIDUgGpA1IBqQNSAakDUgGpA1IBqQNS
AakDUgGpA1IBqQNSAakDUgGpAyIBMgNSAakQAAMgAS4DKQE/AykBPwMpAT8DKQE/AykBPwMRARcgAAMF
AQcDTAGSAVYCWAHBAxUBHQM9AWkBGgHTAfwB/wEaAdMB/AH/AUUCRgF/AxABFQNWAbMBSwJMAY8DBAEG
AQcDTAGSAVYCWAHBAxUBHQM9AWkBFgHTAfwB/wEWAdMB/AH/AUUCRgF/AxABFQNWAbMBSwJMAY8DBAEG
TAADUAGjA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1ABo1wA
AxUBHQFCAXsBhAH1AUoBiQGWAfcDIAEvGAABQgFNAT4HAAE+AwABKAMAAUADAAEgAwABAQEAAQEGAAEB
AxUBHQFCAW8BewH1AVEBhQGKAfcDIAEvGAABQgFNAT4HAAE+AwABKAMAAUADAAEgAwABAQEAAQEGAAEB
FgAD/4EAAv8BgAEBAv8B/AEBAgABvwH9AeABBwHAAwABoAEdAeABBwHAAQABEAEBAaEB/QHgAQcBwAEA
AR8B/wG/Af0B4AEHBAABgAEBAeABBwQAAY8B8QHgAQcBAwEAAR8B/wGAAQEB4AEHAQMBAAEfAf8BgwHB
AeABBwEDAcACAAGAAUEB4AEHAQMBwAIAAYgBEQHgAQcCAAEfAf8BgQERAeABBwIAARABAQGBATEB4AEP
AcABAwIAAYEB8QHgAR8BwAEDAgABgAEBAeABPwHAAQMC/wGAAQEC/wH8AT8L
</value>
</data>
<metadata name="tsThumbnails.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>291, 17</value>
</metadata>
<metadata name="tsProperties.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>649, 17</value>
</metadata>
<metadata name="tsGCode.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>551, 17</value>
</metadata>
<metadata name="tsIssues.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>765, 17</value>
</metadata>
<metadata name="toolTipInformation.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>863, 17</value>
</metadata>
<metadata name="toolTipInformation.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>863, 17</value>
</metadata>
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.5.1.3")]
[assembly: AssemblyFileVersion("0.5.1.3")]
[assembly: AssemblyVersion("0.5.2.0")]
[assembly: AssemblyFileVersion("0.5.2.0")]
+15 -1
View File
@@ -9,6 +9,7 @@ using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
@@ -70,7 +71,18 @@ namespace UVtools.Parser
/// <summary>
/// Gets the number of pixels on this issue
/// </summary>
public uint Size => (uint) (Pixels?.Length ?? 0);
public uint Size {
get
{
if (Type == IssueType.ResinTrap && !BoundingRectangle.IsEmpty)
{
return (uint) (BoundingRectangle.Width * BoundingRectangle.Height);
}
if (ReferenceEquals(Pixels, null)) return 0;
return (uint) Pixels.Length;
}
}
/// <summary>
/// Check if this issue have a valid start point to show
@@ -125,6 +137,8 @@ namespace UVtools.Parser
public AreaType Type { get; set; } = AreaType.Unknown;
public bool Processed { get; set; }
#region Indexers
public Point this[uint index]
{
+3 -3
View File
@@ -7,9 +7,9 @@
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
<PackageIcon></PackageIcon>
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<AssemblyVersion>0.5.1.3</AssemblyVersion>
<FileVersion>0.5.1.3</FileVersion>
<Version>0.5.1.3</Version>
<AssemblyVersion>0.5.2.0</AssemblyVersion>
<FileVersion>0.5.2.0</FileVersion>
<Version>0.5.2</Version>
<Description>MSLA/DLP, file analysis, repair, conversion and manipulation</Description>
<PackageId>UVtoolsParser</PackageId>
<PackageLicenseFile>LICENSE</PackageLicenseFile>