diff options
author | Tiago Conceição <Tiago_caza@hotmail.com> | 2020-06-20 01:52:08 +0300 |
---|---|---|
committer | Tiago Conceição <Tiago_caza@hotmail.com> | 2020-06-20 01:52:08 +0300 |
commit | fc73f2ff7546f3f66ec4ada7b975534487001fac (patch) | |
tree | 2a1364c37afda2251d84b3695aaa6a1eb403042c | |
parent | 93e548c7de7611ae2bd34f36a7be6d596558fe90 (diff) |
v0.5.2v0.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
-rw-r--r-- | CHANGELOG.md | 8 | ||||
-rw-r--r-- | UVtools.GUI/Forms/FrmRepairLayers.Designer.cs | 60 | ||||
-rw-r--r-- | UVtools.GUI/Forms/FrmRepairLayers.cs | 13 | ||||
-rw-r--r-- | UVtools.GUI/Forms/FrmRepairLayers.resx | 3 | ||||
-rw-r--r-- | UVtools.GUI/FrmMain.Designer.cs | 8 | ||||
-rw-r--r-- | UVtools.GUI/FrmMain.cs | 432 | ||||
-rw-r--r-- | UVtools.GUI/FrmMain.resx | 83 | ||||
-rw-r--r-- | UVtools.GUI/Properties/AssemblyInfo.cs | 4 | ||||
-rw-r--r-- | UVtools.Parser/LayerManager.cs | 16 | ||||
-rw-r--r-- | UVtools.Parser/UVtools.Parser.csproj | 6 |
10 files changed, 345 insertions, 288 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index a448e8b..b2e9d83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/UVtools.GUI/Forms/FrmRepairLayers.Designer.cs b/UVtools.GUI/Forms/FrmRepairLayers.Designer.cs index d5227c9..e9a4e0f 100644 --- a/UVtools.GUI/Forms/FrmRepairLayers.Designer.cs +++ b/UVtools.GUI/Forms/FrmRepairLayers.Designer.cs @@ -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; } }
\ No newline at end of file diff --git a/UVtools.GUI/Forms/FrmRepairLayers.cs b/UVtools.GUI/Forms/FrmRepairLayers.cs index e065d1a..3e197e0 100644 --- a/UVtools.GUI/Forms/FrmRepairLayers.cs +++ b/UVtools.GUI/Forms/FrmRepairLayers.cs @@ -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) { diff --git a/UVtools.GUI/Forms/FrmRepairLayers.resx b/UVtools.GUI/Forms/FrmRepairLayers.resx index b58bc91..8d221ec 100644 --- a/UVtools.GUI/Forms/FrmRepairLayers.resx +++ b/UVtools.GUI/Forms/FrmRepairLayers.resx @@ -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. diff --git a/UVtools.GUI/FrmMain.Designer.cs b/UVtools.GUI/FrmMain.Designer.cs index 17f2258..f9513c9 100644 --- a/UVtools.GUI/FrmMain.Designer.cs +++ b/UVtools.GUI/FrmMain.Designer.cs @@ -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 diff --git a/UVtools.GUI/FrmMain.cs b/UVtools.GUI/FrmMain.cs index 7905296..3cc5222 100644 --- a/UVtools.GUI/FrmMain.cs +++ b/UVtools.GUI/FrmMain.cs @@ -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); + } + } + } + + 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(); + 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 (!processIssues.TryGetValue(issue.Layer.Index, out var issueList)) + { + issueList = new List<LayerIssue>(); + processIssues.Add(issue.Layer.Index, issueList); + } - if(!issue.HaveValidPoint) continue; - - foreach (var pixel in issue) + issueList.Add(issue); + } + + + DisableGUI(); + FrmLoading.SetDescription("Removing selected issues"); + + Task<bool> task = Task<bool>.Factory.StartNew(() => + { + bool result = false; + try { - image[pixel.X, pixel.Y] = Helpers.L8Black; - if (ActualLayer == issue.Layer.Index) + Parallel.ForEach(processIssues, layerIssues => { - int x = pixel.X; - int y = pixel.Y; - - if (tsLayerImageRotate.Checked) + using (var image = SlicerFile[layerIssues.Key].Image) { - x = ActualLayerImage.Height - 1 - pixel.Y; - y = pixel.X; - } + using (var imageEmgu = image.ToEmguImage()) + { + var data = imageEmgu.Data; - ((Bitmap) pbLayer.Image).SetPixel(x, y, Color.DarkRed); - } + 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 (ActualLayer == issue.Layer.Index) pbLayer.Invalidate(); + 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; - issue.Layer.Image = image; Issues[issue.Layer.Index].Remove(issue); - TotalIssues--; 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)) + var issues = SlicerFile.LayerManager.GetAllIssues(); + Issues = new Dictionary<uint, List<LayerIssue>>(); + + for (uint i = 0; i < SlicerFile.LayerCount; i++) { - Issues.Add(i, list); + 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 + { + 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 { - 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; - } + 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) diff --git a/UVtools.GUI/FrmMain.resx b/UVtools.GUI/FrmMain.resx index fb7b729..a2492a8 100644 --- a/UVtools.GUI/FrmMain.resx +++ b/UVtools.GUI/FrmMain.resx @@ -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> diff --git a/UVtools.GUI/Properties/AssemblyInfo.cs b/UVtools.GUI/Properties/AssemblyInfo.cs index 04bc2a1..2e37d79 100644 --- a/UVtools.GUI/Properties/AssemblyInfo.cs +++ b/UVtools.GUI/Properties/AssemblyInfo.cs @@ -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")] diff --git a/UVtools.Parser/LayerManager.cs b/UVtools.Parser/LayerManager.cs index 0403e49..9f84489 100644 --- a/UVtools.Parser/LayerManager.cs +++ b/UVtools.Parser/LayerManager.cs @@ -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] { diff --git a/UVtools.Parser/UVtools.Parser.csproj b/UVtools.Parser/UVtools.Parser.csproj index 752f6d5..b23027e 100644 --- a/UVtools.Parser/UVtools.Parser.csproj +++ b/UVtools.Parser/UVtools.Parser.csproj @@ -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> |