Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/sn4k3/UVtools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'PrusaSL1Viewer/FrmMain.cs')
-rw-r--r--PrusaSL1Viewer/FrmMain.cs474
1 files changed, 422 insertions, 52 deletions
diff --git a/PrusaSL1Viewer/FrmMain.cs b/PrusaSL1Viewer/FrmMain.cs
index a4126af..7918c9d 100644
--- a/PrusaSL1Viewer/FrmMain.cs
+++ b/PrusaSL1Viewer/FrmMain.cs
@@ -86,6 +86,7 @@ namespace PrusaSL1Viewer
public FrmLoading FrmLoading { get; }
+
public static FileFormat SlicerFile
{
get => Program.SlicerFile;
@@ -93,8 +94,13 @@ namespace PrusaSL1Viewer
}
public uint ActualLayer => (uint)(sbLayers.Maximum - sbLayers.Value);
+
public Image<L8> ActualLayerImage { get; private set; }
+ public Dictionary<uint, List<LayerIsland>> Islands { get; set; }
+
+ public uint TotalIslands { get; set; }
+
#endregion
#region Constructors
@@ -416,6 +422,80 @@ namespace PrusaSL1Viewer
// View
+ // Tools
+ if (ReferenceEquals(sender, menuToolsRepairLayers))
+ {
+ uint layerStart;
+ uint layerEnd;
+ uint closingIterations;
+ uint openingIterations;
+ using (var frmRepairLayers = new FrmRepairLayers(2))
+ {
+ if (frmRepairLayers.ShowDialog() != DialogResult.OK) return;
+
+ layerStart = frmRepairLayers.LayerRangeStart;
+ layerEnd = frmRepairLayers.LayerRangeEnd;
+ closingIterations = frmRepairLayers.ClosingIterations;
+ openingIterations = frmRepairLayers.OpeningIterations;
+ }
+
+ DisableGUI();
+ FrmLoading.SetDescription("Reparing Layers");
+
+ Task<bool> task = Task<bool>.Factory.StartNew(() =>
+ {
+ bool result = false;
+ try
+ {
+
+ Parallel.For(layerStart, layerEnd + 1, i =>
+ {
+ Layer layer = SlicerFile[i];
+ var image = layer.Image;
+ var imageEgmu = image.ToEmguImage();
+
+ 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;
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ finally
+ {
+ Invoke((MethodInvoker)delegate {
+ // Running on the UI thread
+ EnableGUI(true);
+ });
+ }
+
+ return result;
+ });
+
+ FrmLoading.ShowDialog();
+
+ ShowLayer(ActualLayer);
+
+ ComputeIslands();
+
+ menuFileSave.Enabled =
+ menuFileSaveAs.Enabled = true;
+ return;
+ }
// About
if (ReferenceEquals(sender, menuHelpAbout))
@@ -653,6 +733,87 @@ namespace PrusaSL1Viewer
}
/************************
+ * Islands Menu *
+ ***********************/
+ if(ReferenceEquals(sender, tsIslandsRefresh))
+ {
+ if (MessageBox.Show("Are you sure you want to compute islands?", "Islands Compute",
+ MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) return;
+
+ ComputeIslands();
+
+ return;
+ }
+
+ if (ReferenceEquals(sender, tsIslandsNext))
+ {
+ if (!tsIslandsNext.Enabled) return;
+ int index = Convert.ToInt32(tsIslandsCount.Tag);
+ lvIslands.SelectedItems.Clear();
+ lvIslands.Items[++index].Selected = true;
+ lvIslands_ItemActivate(lvIslands, null);
+ return;
+ }
+
+ if (ReferenceEquals(sender, tsIslandsPrevious))
+ {
+ if (!tsIslandsPrevious.Enabled) return;
+ int index = Convert.ToInt32(tsIslandsCount.Tag);
+ lvIslands.SelectedItems.Clear();
+ lvIslands.Items[--index].Selected = true;
+ lvIslands_ItemActivate(lvIslands, null);
+ return;
+ }
+
+ if (ReferenceEquals(sender, tsIslandsRemove))
+ {
+ if (!tsIslandsRemove.Enabled || ReferenceEquals(Islands, null)) return;
+
+ if (MessageBox.Show("Are you sure you want to remove all selected islands from image?\n" +
+ "Warning: Removing a island can cause another island 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?",
+ MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) return;
+
+ foreach (ListViewItem item in lvIslands.SelectedItems)
+ {
+ if(!(item.Tag is LayerIsland island)) continue;
+
+ var image = ActualLayer == island.Owner.Index ? ActualLayerImage : island.Owner.Image;
+
+ foreach (var pixel in island)
+ {
+ image[pixel.X, pixel.Y] = Helpers.L8Black;
+ if (ActualLayer == island.Owner.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);
+ }
+ }
+
+ if (ActualLayer == island.Owner.Index) pbLayer.Invalidate();
+
+ island.Owner.Image = image;
+ Islands[island.Owner.Index].Remove(island);
+ TotalIslands--;
+ item.Remove();
+ }
+
+ UpdateIslandsInfo();
+ menuFileSave.Enabled =
+ menuFileSaveAs.Enabled = true;
+
+ return;
+ }
+
+ /************************
* Layer Menu *
***********************/
if (ReferenceEquals(sender, tsLayerImageRotate) || ReferenceEquals(sender, tsLayerImageLayerDifference) || ReferenceEquals(sender, tsLayerImageLayerOutline))
@@ -757,6 +918,92 @@ namespace PrusaSL1Viewer
}
}
+
+ private void pbLayer_Zoomed(object sender, Cyotek.Windows.Forms.ImageBoxZoomEventArgs e)
+ {
+ tsLayerImageZoom.Text = $"Zoom: {e.NewZoom}% ({e.NewZoom/100f}x)";
+ }
+
+ private void pbLayer_MouseUp(object sender, MouseEventArgs e)
+ {
+ if (!tsLayerImagePixelEdit.Checked || (e.Button & MouseButtons.Right) == 0) return;
+ if (!pbLayer.IsPointInImage(e.Location)) return;
+ var location = pbLayer.PointToImage(e.Location);
+
+ if (Control.ModifierKeys == Keys.Shift)
+ {
+ DrawPixel(false, location);
+ }
+ else
+ {
+ DrawPixel(true, location);
+ }
+
+ SlicerFile[ActualLayer].Image = ActualLayerImage;
+ }
+
+ private void pbLayer_MouseMove(object sender, MouseEventArgs e)
+ {
+ if (!pbLayer.IsPointInImage(e.Location)) return;
+ var location = pbLayer.PointToImage(e.Location);
+
+ int x = location.X;
+ int y = location.Y;
+
+ if (tsLayerImageRotate.Checked)
+ {
+ x = location.Y;
+ y = ActualLayerImage.Height - 1 - location.X;
+ }
+
+ tsLayerImageMouseLocation.Text = $"{{X={x}, Y={y}, B={ActualLayerImage[x,y].PackedValue}}}";
+
+ if (!tsLayerImagePixelEdit.Checked || (e.Button & MouseButtons.Right) == 0) return;
+ if (!pbLayer.IsPointInImage(e.Location)) return;
+
+ if (Control.ModifierKeys == Keys.Shift)
+ {
+ DrawPixel(false, location);
+ return;
+ }
+
+ DrawPixel(true, location);
+ }
+
+ private void lvIslands_ItemActivate(object sender, EventArgs e)
+ {
+ if (lvIslands.SelectedItems.Count == 0) return;
+ var item = lvIslands.SelectedItems[0];
+
+ if (!(item.Tag is LayerIsland island)) return;
+ if (island.Owner.Index != ActualLayer)
+ {
+ sbLayers.Value = (int)(SlicerFile.LayerCount - island.Owner.Index - 1);
+ //ShowLayer(island.Owner.Index);
+ }
+
+ uint x = island.X;
+ uint y = island.Y;
+
+ if (tsLayerImageRotate.Checked)
+ {
+ //x = island.Y;
+ //y = SlicerFile.ResolutionX - 1 - island.X;
+
+ //x = SlicerFile.ResolutionY - 1 - y;
+ //y = x;
+
+ x = (uint) (ActualLayerImage.Height - 1 - island.Y);
+ y = island.X;
+ }
+
+ //pbLayer.Zoom = 1200;
+ pbLayer.ZoomToRegion(x, y, 5, 5);
+ pbLayer.ZoomOut(true);
+
+ tsIslandsCount.Tag = lvIslands.SelectedIndices[0];
+ UpdateIslandsInfo();
+ }
#endregion
#region Methods
@@ -775,6 +1022,15 @@ namespace PrusaSL1Viewer
pbLayer.Image = null;
pbThumbnail.Image = null;
tbGCode.Clear();
+
+ Islands = null;
+ TotalIslands = 0;
+ lvIslands.BeginUpdate();
+ lvIslands.Items.Clear();
+ lvIslands.Groups.Clear();
+ lvIslands.EndUpdate();
+ UpdateIslandsInfo();
+
lbLayers.Text = "Layers";
lvProperties.BeginUpdate();
lvProperties.Items.Clear();
@@ -792,6 +1048,11 @@ namespace PrusaSL1Viewer
item.Enabled = false;
}
+ foreach (ToolStripItem item in menuTools.DropDownItems)
+ {
+ item.Enabled = false;
+ }
+
foreach (ToolStripItem item in tsThumbnails.Items)
{
item.Enabled = false;
@@ -804,6 +1065,10 @@ namespace PrusaSL1Viewer
{
item.Enabled = false;
}
+ foreach (ToolStripItem item in tsIslands.Items)
+ {
+ item.Enabled = false;
+ }
tsThumbnailsResolution.Text =
tsLayerPreviewTime.Text =
@@ -822,13 +1087,15 @@ namespace PrusaSL1Viewer
pbLayers.Enabled =
menuEdit.Enabled =
menuMutate.Enabled =
+ menuTools.Enabled =
false;
tsThumbnailsCount.Text = "0/0";
tsThumbnailsCount.Tag = null;
- tabControlLeft.TabPages.Remove(tbpGCode);
+ tabControlLeft.TabPages.Remove(tabPageGCode);
+ tabControlLeft.TabPages.Remove(tabPageIslands);
tabControlLeft.SelectedIndex = 0;
}
@@ -947,6 +1214,10 @@ namespace PrusaSL1Viewer
{
item.Enabled = true;
}
+ foreach (ToolStripItem item in menuTools.DropDownItems)
+ {
+ item.Enabled = true;
+ }
foreach (ToolStripItem item in tsLayer.Items)
{
item.Enabled = true;
@@ -966,12 +1237,16 @@ namespace PrusaSL1Viewer
pbLayers.Enabled =
menuEdit.Enabled =
menuMutate.Enabled =
+ menuTools.Enabled =
+
+ tsIslandsRefresh.Enabled =
true;
if (!ReferenceEquals(SlicerFile.GCode, null))
{
- tabControlLeft.TabPages.Add(tbpGCode);
+ tabControlLeft.TabPages.Add(tabPageGCode);
}
+ tabControlLeft.TabPages.Add(tabPageIslands);
//ShowLayer(0);
@@ -1081,7 +1356,7 @@ namespace PrusaSL1Viewer
if (tsLayerImageLayerOutline.Checked)
{
- Emgu.CV.Image<Gray, byte> grayscale = image.ToEmguImage();
+ Image<Gray, byte> grayscale = image.ToEmguImage();
grayscale = grayscale.Canny(100, 200, 3, true);
image = grayscale.ToImageSharpL8();
grayscale.Dispose();
@@ -1126,7 +1401,8 @@ namespace PrusaSL1Viewer
}
//watch.Restart();
- pbLayer.Image = image.ToBitmap();
+ var imageBmp = image.ToBitmap();
+ pbLayer.Image = imageBmp;
pbLayer.Image.Tag = image;
//Debug.WriteLine(watch.ElapsedMilliseconds);
@@ -1157,17 +1433,49 @@ namespace PrusaSL1Viewer
byte percent = (byte)((layerNum + 1) * 100 / SlicerFile.LayerCount);
+ //var islands = SlicerFile.LayerManager.GetAllIslands();
+ //Debug.WriteLine(islands.Length);
+
+ if (!ReferenceEquals(Islands, null) && Islands.Count > ActualLayer)
+ {
+ var islands = Islands[ActualLayer];
+
+ foreach (var island in islands)
+ {
+ if(ReferenceEquals(island, null)) continue; // Removed islands
+ foreach (var pixel in island)
+ {
+ int x = pixel.X;
+ int y = pixel.Y;
+
+ if (tsLayerImageRotate.Checked)
+ {
+ x = ActualLayerImage.Height - 1 - pixel.Y;
+ y = pixel.X;
+ }
+
+ if(ActualLayerImage[pixel.X, pixel.Y].PackedValue == 0) continue;
+ imageBmp.SetPixel(x, y, Color.Yellow);
+ }
+
+ }
+
+
+ }
watch.Stop();
tsLayerPreviewTime.Text = $"{watch.ElapsedMilliseconds}ms";
- lbLayers.Text = $"{SlicerFile.GetHeightFromLayer((uint)layerNum + 1)} / {SlicerFile.TotalHeight}mm\n{layerNum} / {SlicerFile.LayerCount-1}\n{percent}%";
+ lbLayers.Text = $"{SlicerFile.GetHeightFromLayer(layerNum)} / {SlicerFile.TotalHeight}mm\n{layerNum} / {SlicerFile.LayerCount-1}\n{percent}%";
pbLayers.Value = percent;
+
+
}
catch (Exception e)
{
Debug.WriteLine(e);
}
+
}
void AddStatusBarItem(string name, object item, string extraText = "")
@@ -1185,36 +1493,40 @@ namespace PrusaSL1Viewer
}
#endregion
- private void pbLayer_Zoomed(object sender, Cyotek.Windows.Forms.ImageBoxZoomEventArgs e)
- {
- tsLayerImageZoomValueLabel.Text = $"{e.NewZoom} %";
- }
+
- void DrawPixel(bool isAdd, Point location, Color color, L8 pixelL8)
+ void DrawPixel(bool isAdd, Point location)
{
- var point = pbLayer.PointToImage(location);
- int x = point.X;
- int y = point.Y;
+ //var point = pbLayer.PointToImage(location);
+ int x = location.X;
+ int y = location.Y;
if (tsLayerImageRotate.Checked)
{
- x = point.Y;
- y = ActualLayerImage.Height - 1 - point.X;
+ x = location.Y;
+ y = ActualLayerImage.Height - 1 - location.X;
}
+ Color color;
+ L8 pixelL8;
- if (isAdd && ActualLayerImage[x, y].PackedValue > byte.MaxValue / 2)
+ if (isAdd)
{
- return;
+ if (ActualLayerImage[x, y].PackedValue > 200) return;
+ color = Color.Green;
+ pixelL8 = Helpers.L8White;
}
- if (!isAdd && ActualLayerImage[x, y].PackedValue < byte.MaxValue / 2)
+ else
{
- return;
+ if (ActualLayerImage[x, y].PackedValue == 0) return;
+ color = Color.DarkRed;
+ pixelL8 = Helpers.L8Black;
}
+
ActualLayerImage[x, y] = pixelL8;
Bitmap bmp = pbLayer.Image as Bitmap;
- bmp.SetPixel(point.X, point.Y, color);
+ bmp.SetPixel(location.X, location.Y, color);
/*if (bmp.GetPixel(point.X, point.Y).GetBrightness() == returnif) return;
bmp.SetPixel(point.X, point.Y, color);
@@ -1229,37 +1541,7 @@ namespace PrusaSL1Viewer
menuFileSave.Enabled = menuFileSaveAs.Enabled = true;
}
- private void pbLayer_MouseUp(object sender, MouseEventArgs e)
- {
- if (!tsLayerImagePixelEdit.Checked || (e.Button & MouseButtons.Right) == 0) return;
- if (!pbLayer.IsPointInImage(e.Location)) return;
-
-
- if (Control.ModifierKeys == Keys.Shift)
- {
- DrawPixel(false, e.Location, Color.DarkRed, Helpers.L8Black);
- }
- else
- {
- DrawPixel(true, e.Location, Color.Green, Helpers.L8White);
- }
-
- SlicerFile[ActualLayer].Image = ActualLayerImage;
- }
-
- private void pbLayer_MouseMove(object sender, MouseEventArgs e)
- {
- if (!tsLayerImagePixelEdit.Checked || (e.Button & MouseButtons.Right) == 0) return;
- if (!pbLayer.IsPointInImage(e.Location)) return;
-
- if (Control.ModifierKeys == Keys.Shift)
- {
- DrawPixel(false, e.Location, Color.DarkRed, Helpers.L8Black);
- return;
- }
-
- DrawPixel(true, e.Location, Color.Green, Helpers.L8White);
- }
+
public void MutateLayers(Mutation.Mutates type)
{
@@ -1308,7 +1590,7 @@ namespace PrusaSL1Viewer
iterations = Math.Min(Math.Max(1, iterations), maxIteration);
//Debug.WriteLine($"A Layer: {i} = {iterations}");
}
- LayerManager.Layer layer = SlicerFile[i];
+ Layer layer = SlicerFile[i];
var image = layer.Image;
var imageEgmu = image.ToEmguImage();
switch (type)
@@ -1380,5 +1662,93 @@ namespace PrusaSL1Viewer
menuFileSave.Enabled =
menuFileSaveAs.Enabled = true;
}
+
+ private void UpdateIslandsInfo()
+ {
+ if (TotalIslands == 0)
+ {
+ tsIslandsPrevious.Enabled =
+ tsIslandsCount.Enabled =
+ tsIslandsNext.Enabled = false;
+
+ tsIslandsCount.Text = "0/0";
+ tsIslandsCount.Tag = -1;
+ }
+ else
+ {
+ int currentIslandSelected = Convert.ToInt32(tsIslandsCount.Tag);
+ tsIslandsCount.Enabled = true;
+ tsIslandsCount.Text = $"{currentIslandSelected+1}/{TotalIslands}";
+
+ tsIslandsPrevious.Enabled = currentIslandSelected > 0;
+ tsIslandsNext.Enabled = currentIslandSelected+1 < TotalIslands;
+ }
+
+ }
+
+ private void ComputeIslands()
+ {
+ TotalIslands = 0;
+ lvIslands.BeginUpdate();
+ lvIslands.Items.Clear();
+ lvIslands.Groups.Clear();
+ lvIslands.EndUpdate();
+ UpdateIslandsInfo();
+
+ DisableGUI();
+ FrmLoading.SetDescription("Computing Islands");
+
+ Task<bool> task = Task<bool>.Factory.StartNew(() =>
+ {
+ bool result = false;
+ try
+ {
+ Islands = SlicerFile.LayerManager.GetAllIslands();
+ result = true;
+ }
+ catch (Exception)
+ {
+ }
+ finally
+ {
+ Invoke((MethodInvoker)delegate {
+ // Running on the UI thread
+ EnableGUI(true);
+ });
+ }
+
+ return result;
+ });
+
+ FrmLoading.ShowDialog();
+
+ lvIslands.BeginUpdate();
+ uint count = 0;
+ for (uint layerIndex = 0; layerIndex < SlicerFile.LayerCount; layerIndex++)
+ {
+ ListViewGroup group = new ListViewGroup($"Layer {layerIndex} - {Islands[layerIndex].Count} Islands");
+ for (var i = 0; i < Islands[layerIndex].Count; i++)
+ {
+ count++;
+ var island = Islands[layerIndex][i];
+ TotalIslands++;
+ ListViewItem item = new ListViewItem(group) {Text = count.ToString()};
+ item.SubItems.Add((i + 1).ToString());
+ item.SubItems.Add($"{island.X}, {island.Y}");
+ item.SubItems.Add(island.Size.ToString());
+ item.Tag = island;
+ lvIslands.Groups.Add(group);
+ lvIslands.Items.Add(item);
+ }
+ }
+ lvIslands.EndUpdate();
+
+ UpdateIslandsInfo();
+ }
+
+ private void lvIslands_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ tsIslandsRemove.Enabled = lvIslands.SelectedIndices.Count > 0;
+ }
}
}