diff --git a/LaserGRBL/GrblFile.cs b/LaserGRBL/GrblFile.cs index aaf0fa414..888f8e513 100644 --- a/LaserGRBL/GrblFile.cs +++ b/LaserGRBL/GrblFile.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; +using System.Linq; namespace LaserGRBL { @@ -181,7 +182,7 @@ public override bool IsSeparator - public void LoadImagePotrace(Bitmap bmp, string filename, bool UseSpotRemoval, int SpotRemoval, bool UseSmoothing, decimal Smoothing, bool UseOptimize, decimal Optimize, L2LConf c) + public void LoadImagePotrace(Bitmap bmp, string filename, bool UseSpotRemoval, int SpotRemoval, bool UseSmoothing, decimal Smoothing, bool UseOptimize, decimal Optimize, bool useOptimizeFast, L2LConf c) { bmp.RotateFlip(RotateFlipType.RotateNoneFlipY); long start = Tools.HiResTimer.TotalMilliseconds; @@ -231,8 +232,12 @@ public void LoadImagePotrace(Bitmap bmp, string filename, bool UseSpotRemoval, i } } - //absolute - list.Add(new GrblCommand("G90")); + //Optimize fast movement + if(useOptimizeFast) + plist = OptimizePaths(plist); + + //absolute + list.Add(new GrblCommand("G90")); //move fast to offset list.Add(new GrblCommand(String.Format("G0 X{0} Y{1}", formatnumber(c.oX), formatnumber(c.oY)))); //laser off and power to maxPower @@ -558,8 +563,72 @@ private void ExtractSegment(Bitmap image, int x, int y, bool reverse, ref int le prevCol = col; } - - private int GetColor(Bitmap I, int X, int Y, int min, int max, bool pwm) + private List> OptimizePaths(List> list) + { + //Order all paths in list to reduce travel distance + //Calculate and store all distances in a matrix + var distances = new double[list.Count, list.Count]; + for (int p1 = 0; p1 < list.Count; p1++) + { + for (int p2 = 0; p2 < list.Count; p2++) + { + var dx = list[p1][0].A.X - list[p2][0].A.X; + var dy = list[p1][0].A.Y - list[p2][0].A.Y; + if (p1 != p2) + distances[p1, p2] = Math.Sqrt((dx * dx) + (dy * dy)); + else + distances[p1, p2] = double.MaxValue; + } + } + + List> best = new List>(); + var bestTotDistance = double.MaxValue; + + //Test all possibile starting shape + for (int first = 0; first < list.Count; first++) + { + //Create a list of unvisited places + List unvisited = Enumerable.Range(0, list.Count).ToList(); + + //Pick nearest points + List> nearest = new List>(); + + //Save starting point index + var lastIndex = first; + var totDistance = 0.0; + while (unvisited.Count > 0) + { + var bestIndex = 0; + var bestDistance = double.MaxValue; + foreach (var nextIndex in unvisited) + { + var dist = distances[nextIndex, lastIndex]; + if (dist < bestDistance) + { + bestIndex = nextIndex; + bestDistance = dist; + } + } + + //Save nearest point + lastIndex = bestIndex; + nearest.Add(list[lastIndex]); + unvisited.Remove(lastIndex); + totDistance += bestDistance; + } + + //Count traveled distance + if (totDistance < bestTotDistance) + { + bestTotDistance = totDistance; + //Save best list + best = nearest; + } + } + return best; + } + + private int GetColor(Bitmap I, int X, int Y, int min, int max, bool pwm) { Color C = I.GetPixel(X, Y); int rv = (255 - C.R) * C.A / 255; diff --git a/LaserGRBL/RasterConverter/ImageProcessor.cs b/LaserGRBL/RasterConverter/ImageProcessor.cs index cf75a7585..5be59f3f1 100644 --- a/LaserGRBL/RasterConverter/ImageProcessor.cs +++ b/LaserGRBL/RasterConverter/ImageProcessor.cs @@ -51,6 +51,7 @@ public class ImageProcessor : ICloneable private bool mUseSmootihing; private decimal mDownSampling; private bool mUseDownSampling; + private bool mOptimizeFast; private Direction mDirection; private Direction mFillingDirection; private ImageTransform.DitheringMode mDithering; @@ -516,6 +517,19 @@ public decimal DownSampling } } + public bool OptimizeFast + { + get { return mOptimizeFast; } + set + { + if (value != mOptimizeFast) + { + mOptimizeFast = value; + Refresh(); + } + } + } + public bool UseSmoothing { get { return mUseSmootihing; } @@ -726,7 +740,7 @@ void DoTrueWork() if (SelectedTool == ImageProcessor.Tool.Line2Line || SelectedTool == ImageProcessor.Tool.Dithering) mCore.LoadedFile.LoadImageL2L(bmp, mFileName, conf); else if (SelectedTool == ImageProcessor.Tool.Vectorize) - mCore.LoadedFile.LoadImagePotrace(bmp, mFileName, UseSpotRemoval, (int)SpotRemoval, UseSmoothing, Smoothing, UseOptimize, Optimize, conf); + mCore.LoadedFile.LoadImagePotrace(bmp, mFileName, UseSpotRemoval, (int)SpotRemoval, UseSmoothing, Smoothing, UseOptimize, Optimize, OptimizeFast, conf); } if (GenerationComplete != null) diff --git a/LaserGRBL/RasterConverter/RasterToLaserForm.Designer.cs b/LaserGRBL/RasterConverter/RasterToLaserForm.Designer.cs index f2be2c783..7dbc63927 100644 --- a/LaserGRBL/RasterConverter/RasterToLaserForm.Designer.cs +++ b/LaserGRBL/RasterConverter/RasterToLaserForm.Designer.cs @@ -64,6 +64,8 @@ private void InitializeComponent() this.UDDownSample = new System.Windows.Forms.NumericUpDown(); this.label1 = new System.Windows.Forms.Label(); this.CbDownSample = new System.Windows.Forms.CheckBox(); + this.lOptimizeFast = new System.Windows.Forms.Label(); + this.CbOptimizeFast = new System.Windows.Forms.CheckBox(); this.BtnFillingQualityInfo = new LaserGRBL.UserControls.ImageButton(); this.GbParameters = new System.Windows.Forms.GroupBox(); this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); @@ -331,15 +333,17 @@ private void InitializeComponent() this.tableLayoutPanel5.Controls.Add(this.UDSmoothing, 1, 1); this.tableLayoutPanel5.Controls.Add(this.CbOptimize, 2, 2); this.tableLayoutPanel5.Controls.Add(this.CbSmoothing, 2, 1); - this.tableLayoutPanel5.Controls.Add(this.label14, 0, 4); - this.tableLayoutPanel5.Controls.Add(this.CbFillingDirection, 1, 4); - this.tableLayoutPanel5.Controls.Add(this.LblFillingQuality, 0, 5); - this.tableLayoutPanel5.Controls.Add(this.UDFillingQuality, 1, 5); - this.tableLayoutPanel5.Controls.Add(this.LblFillingLineLbl, 2, 5); + this.tableLayoutPanel5.Controls.Add(this.label14, 0, 5); + this.tableLayoutPanel5.Controls.Add(this.CbFillingDirection, 1, 5); + this.tableLayoutPanel5.Controls.Add(this.LblFillingQuality, 0, 6); + this.tableLayoutPanel5.Controls.Add(this.UDFillingQuality, 1, 6); + this.tableLayoutPanel5.Controls.Add(this.LblFillingLineLbl, 2, 6); this.tableLayoutPanel5.Controls.Add(this.UDDownSample, 1, 3); this.tableLayoutPanel5.Controls.Add(this.label1, 0, 3); this.tableLayoutPanel5.Controls.Add(this.CbDownSample, 2, 3); - this.tableLayoutPanel5.Controls.Add(this.BtnFillingQualityInfo, 3, 5); + this.tableLayoutPanel5.Controls.Add(this.lOptimizeFast, 0, 4); + this.tableLayoutPanel5.Controls.Add(this.CbOptimizeFast, 2, 4); + this.tableLayoutPanel5.Controls.Add(this.BtnFillingQualityInfo, 3, 6); this.tableLayoutPanel5.Name = "tableLayoutPanel5"; this.TT.SetToolTip(this.tableLayoutPanel5, resources.GetString("tableLayoutPanel5.ToolTip")); // @@ -541,6 +545,18 @@ private void InitializeComponent() this.TT.SetToolTip(this.CbDownSample, resources.GetString("CbDownSample.ToolTip")); this.CbDownSample.UseVisualStyleBackColor = true; this.CbDownSample.CheckedChanged += new System.EventHandler(this.CbDownSample_CheckedChanged); + // + // lOptimizeFast + // + this.lOptimizeFast.Name = "lOptimizeFast"; + this.lOptimizeFast.Text = "Optimize Fast"; + this.lOptimizeFast.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // CbOptimizeFast + // + this.CbOptimizeFast.Name = "CbDownSample"; + this.CbOptimizeFast.UseVisualStyleBackColor = true; + this.CbOptimizeFast.CheckedChanged += new System.EventHandler(this.CbOptimizeFast_CheckedChanged); // // BtnFillingQualityInfo // @@ -1120,5 +1136,7 @@ private void InitializeComponent() private UserControls.ImageButton BtnFillingQualityInfo; private UserControls.ColorSlider TBWhiteClip; private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label lOptimizeFast; + private System.Windows.Forms.CheckBox CbOptimizeFast; } } \ No newline at end of file diff --git a/LaserGRBL/RasterConverter/RasterToLaserForm.cs b/LaserGRBL/RasterConverter/RasterToLaserForm.cs index 4f19a9489..0b5e7ea22 100644 --- a/LaserGRBL/RasterConverter/RasterToLaserForm.cs +++ b/LaserGRBL/RasterConverter/RasterToLaserForm.cs @@ -192,6 +192,7 @@ private void StoreSettings() // Settings.SetObject("GrayScaleConversion.VectorizeOptions.ShowImage.Enabled", CbShowImage.Checked); Settings.SetObject("GrayScaleConversion.VectorizeOptions.FillingDirection", (ImageProcessor.Direction)CbFillingDirection.SelectedItem); Settings.SetObject("GrayScaleConversion.VectorizeOptions.FillingQuality", UDFillingQuality.Value); + Settings.SetObject("GrayScaleConversion.VectorizeOptions.OptimizeFast.Enabled", CbOptimizeFast.Checked); Settings.SetObject("GrayScaleConversion.DitheringOptions.DitheringMode", (ImageTransform.DitheringMode)CbDither.SelectedItem); @@ -244,6 +245,7 @@ private void LoadSettings() UDOptimize.Value = IP.Optimize = (decimal)Settings.GetObject("GrayScaleConversion.VectorizeOptions.Optimize.Value", 0.2m); CbDownSample.Checked = IP.UseDownSampling = (bool)Settings.GetObject("GrayScaleConversion.VectorizeOptions.DownSample.Enabled", false); UDDownSample.Value = IP.DownSampling = (decimal)Settings.GetObject("GrayScaleConversion.VectorizeOptions.DownSample.Value", 2.0m); + CbOptimizeFast.Checked = IP.OptimizeFast = (bool) Settings.GetObject("GrayScaleConversion.VectorizeOptions.OptimizeFast.Enabled", false); //CbShowDots.Checked = IP.ShowDots = (bool)Settings.GetObject("GrayScaleConversion.VectorizeOptions.ShowDots.Enabled", false); //CbShowImage.Checked = IP.ShowImage = (bool)Settings.GetObject("GrayScaleConversion.VectorizeOptions.ShowImage.Enabled", true); @@ -593,6 +595,14 @@ private void UDDownSample_ValueChanged(object sender, EventArgs e) IP.DownSampling = UDDownSample.Value; } + private void CbOptimizeFast_CheckedChanged(object sender, EventArgs e) + { + if (IP != null) + { + IP.OptimizeFast = CbOptimizeFast.Checked; + } + } + private void PbConverted_Resize(object sender, EventArgs e) { if (IP != null) diff --git a/LaserGRBL/RasterConverter/RasterToLaserForm.resx b/LaserGRBL/RasterConverter/RasterToLaserForm.resx index 4324dde6b..60bcbcb21 100644 --- a/LaserGRBL/RasterConverter/RasterToLaserForm.resx +++ b/LaserGRBL/RasterConverter/RasterToLaserForm.resx @@ -496,7 +496,7 @@ System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - 6 + 7 2