mirror of
https://github.com/riegera2412/UVtools.git
synced 2026-07-08 17:42:31 +02:00
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
This commit is contained in:
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
|
||||
Generated
+5
-3
@@ -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
@@ -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
@@ -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>
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -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]
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user