diff --git a/OpenNest.Core/Splitting/SpikeGrooveSplit.cs b/OpenNest.Core/Splitting/SpikeGrooveSplit.cs index fa91f63..cbbdc52 100644 --- a/OpenNest.Core/Splitting/SpikeGrooveSplit.cs +++ b/OpenNest.Core/Splitting/SpikeGrooveSplit.cs @@ -16,9 +16,12 @@ public class SpikeGrooveSplit : ISplitFeature { var extent = extentEnd - extentStart; var pairCount = parameters.SpikePairCount; - var depth = parameters.SpikeDepth; + var spikeDepth = parameters.SpikeDepth; + var grooveDepth = parameters.GrooveDepth; + var weldGap = parameters.SpikeWeldGap; var angleRad = OpenNest.Math.Angle.ToRadians(parameters.SpikeAngle / 2); - var halfWidth = depth * System.Math.Tan(angleRad); + var spikeHalfWidth = spikeDepth * System.Math.Tan(angleRad); + var grooveHalfWidth = grooveDepth * System.Math.Tan(angleRad); var isVertical = line.Axis == CutOffAxis.Vertical; var pos = line.Position; @@ -37,8 +40,10 @@ public class SpikeGrooveSplit : ISplitFeature pairPositions.Add(extentStart + margin + usable * i / (pairCount - 1)); } - var negEntities = BuildGrooveSide(pairPositions, halfWidth, depth, extentStart, extentEnd, pos, isVertical); - var posEntities = BuildSpikeSide(pairPositions, halfWidth, depth, extentStart, extentEnd, pos, isVertical); + // Groove side: V-groove cut deeper than the spike so the spike fits inside + var negEntities = BuildGrooveSide(pairPositions, grooveHalfWidth, grooveDepth, extentStart, extentEnd, pos, isVertical); + // Spike side: spike protrudes but stops short of the split line by weldGap + var posEntities = BuildSpikeSide(pairPositions, spikeHalfWidth, spikeDepth, weldGap, extentStart, extentEnd, pos, isVertical); return new SplitFeatureResult(negEntities, posEntities); } @@ -70,8 +75,10 @@ public class SpikeGrooveSplit : ISplitFeature } private static List BuildSpikeSide(List pairPositions, double halfWidth, double depth, - double extentStart, double extentEnd, double pos, bool isVertical) + double weldGap, double extentStart, double extentEnd, double pos, bool isVertical) { + // Spike tip stops short of the split line by weldGap + var tipDepth = depth - weldGap; var entities = new List(); var cursor = extentEnd; @@ -84,8 +91,8 @@ public class SpikeGrooveSplit : ISplitFeature if (cursor > spikeEnd + OpenNest.Math.Tolerance.Epsilon) entities.Add(MakeLine(pos, cursor, pos, spikeEnd, isVertical)); - entities.Add(MakeLine(pos, spikeEnd, pos - depth, center, isVertical)); - entities.Add(MakeLine(pos - depth, center, pos, spikeStart, isVertical)); + entities.Add(MakeLine(pos, spikeEnd, pos - tipDepth, center, isVertical)); + entities.Add(MakeLine(pos - tipDepth, center, pos, spikeStart, isVertical)); cursor = spikeStart; } diff --git a/OpenNest.Core/Splitting/SplitParameters.cs b/OpenNest.Core/Splitting/SplitParameters.cs index d2f25b6..cf4a62f 100644 --- a/OpenNest.Core/Splitting/SplitParameters.cs +++ b/OpenNest.Core/Splitting/SplitParameters.cs @@ -18,6 +18,8 @@ public class SplitParameters // Spike/Groove parameters public double SpikeDepth { get; set; } = 0.5; + public double GrooveDepth { get; set; } = 0.625; + public double SpikeWeldGap { get; set; } = 0.125; public double SpikeAngle { get; set; } = 60.0; // degrees public int SpikePairCount { get; set; } = 2; @@ -27,7 +29,7 @@ public class SplitParameters public double FeatureOverhang => Type switch { SplitType.WeldGapTabs => TabHeight, - SplitType.SpikeGroove => SpikeDepth, + SplitType.SpikeGroove => System.Math.Max(SpikeDepth, GrooveDepth), _ => 0 }; } diff --git a/OpenNest/Forms/SplitDrawingForm.Designer.cs b/OpenNest/Forms/SplitDrawingForm.Designer.cs index 5460de4..2e3f3ca 100644 --- a/OpenNest/Forms/SplitDrawingForm.Designer.cs +++ b/OpenNest/Forms/SplitDrawingForm.Designer.cs @@ -84,6 +84,10 @@ namespace OpenNest.Forms this.nudSpikeAngle = new System.Windows.Forms.NumericUpDown(); this.lblSpikePairCount = new System.Windows.Forms.Label(); this.nudSpikePairCount = new System.Windows.Forms.NumericUpDown(); + this.lblGrooveDepth = new System.Windows.Forms.Label(); + this.nudGrooveDepth = new System.Windows.Forms.NumericUpDown(); + this.lblSpikeWeldGap = new System.Windows.Forms.Label(); + this.nudSpikeWeldGap = new System.Windows.Forms.NumericUpDown(); // OK/Cancel buttons this.btnOK = new System.Windows.Forms.Button(); @@ -101,6 +105,8 @@ namespace OpenNest.Forms ((System.ComponentModel.ISupportInitialize)(this.nudSpikeDepth)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.nudSpikeAngle)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.nudSpikePairCount)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nudGrooveDepth)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nudSpikeWeldGap)).BeginInit(); this.pnlSettings.SuspendLayout(); this.grpMethod.SuspendLayout(); this.grpAutoFit.SuspendLayout(); @@ -464,13 +470,17 @@ namespace OpenNest.Forms this.grpSpikeParams.Dock = System.Windows.Forms.DockStyle.Top; this.grpSpikeParams.Location = new System.Drawing.Point(6, 484); this.grpSpikeParams.Name = "grpSpikeParams"; - this.grpSpikeParams.Size = new System.Drawing.Size(208, 105); + this.grpSpikeParams.Size = new System.Drawing.Size(208, 159); this.grpSpikeParams.TabIndex = 5; this.grpSpikeParams.TabStop = false; this.grpSpikeParams.Text = "Spike Parameters"; this.grpSpikeParams.Visible = false; this.grpSpikeParams.Controls.Add(this.nudSpikePairCount); this.grpSpikeParams.Controls.Add(this.lblSpikePairCount); + this.grpSpikeParams.Controls.Add(this.nudSpikeWeldGap); + this.grpSpikeParams.Controls.Add(this.lblSpikeWeldGap); + this.grpSpikeParams.Controls.Add(this.nudGrooveDepth); + this.grpSpikeParams.Controls.Add(this.lblGrooveDepth); this.grpSpikeParams.Controls.Add(this.nudSpikeAngle); this.grpSpikeParams.Controls.Add(this.lblSpikeAngle); this.grpSpikeParams.Controls.Add(this.nudSpikeDepth); @@ -493,38 +503,71 @@ namespace OpenNest.Forms this.nudSpikeDepth.TabIndex = 0; this.nudSpikeDepth.Value = new decimal(new int[] { 5, 0, 0, 65536 }); + // lblGrooveDepth + this.lblGrooveDepth.AutoSize = true; + this.lblGrooveDepth.Location = new System.Drawing.Point(10, 49); + this.lblGrooveDepth.Name = "lblGrooveDepth"; + this.lblGrooveDepth.Size = new System.Drawing.Size(84, 15); + this.lblGrooveDepth.Text = "Groove Depth:"; + + // nudGrooveDepth + this.nudGrooveDepth.DecimalPlaces = 3; + this.nudGrooveDepth.Location = new System.Drawing.Point(110, 47); + this.nudGrooveDepth.Maximum = new decimal(new int[] { 100, 0, 0, 0 }); + this.nudGrooveDepth.Minimum = new decimal(new int[] { 1, 0, 0, 131072 }); + this.nudGrooveDepth.Name = "nudGrooveDepth"; + this.nudGrooveDepth.Size = new System.Drawing.Size(88, 23); + this.nudGrooveDepth.TabIndex = 1; + this.nudGrooveDepth.Value = new decimal(new int[] { 625, 0, 0, 196608 }); + + // lblSpikeWeldGap + this.lblSpikeWeldGap.AutoSize = true; + this.lblSpikeWeldGap.Location = new System.Drawing.Point(10, 76); + this.lblSpikeWeldGap.Name = "lblSpikeWeldGap"; + this.lblSpikeWeldGap.Size = new System.Drawing.Size(64, 15); + this.lblSpikeWeldGap.Text = "Weld Gap:"; + + // nudSpikeWeldGap + this.nudSpikeWeldGap.DecimalPlaces = 3; + this.nudSpikeWeldGap.Location = new System.Drawing.Point(110, 74); + this.nudSpikeWeldGap.Maximum = new decimal(new int[] { 10, 0, 0, 0 }); + this.nudSpikeWeldGap.Name = "nudSpikeWeldGap"; + this.nudSpikeWeldGap.Size = new System.Drawing.Size(88, 23); + this.nudSpikeWeldGap.TabIndex = 2; + this.nudSpikeWeldGap.Value = new decimal(new int[] { 125, 0, 0, 196608 }); + // lblSpikeAngle this.lblSpikeAngle.AutoSize = true; - this.lblSpikeAngle.Location = new System.Drawing.Point(10, 49); + this.lblSpikeAngle.Location = new System.Drawing.Point(10, 103); this.lblSpikeAngle.Name = "lblSpikeAngle"; this.lblSpikeAngle.Size = new System.Drawing.Size(74, 15); this.lblSpikeAngle.Text = "Spike Angle:"; // nudSpikeAngle this.nudSpikeAngle.DecimalPlaces = 1; - this.nudSpikeAngle.Location = new System.Drawing.Point(110, 47); + this.nudSpikeAngle.Location = new System.Drawing.Point(110, 101); this.nudSpikeAngle.Maximum = new decimal(new int[] { 89, 0, 0, 0 }); this.nudSpikeAngle.Minimum = new decimal(new int[] { 10, 0, 0, 0 }); this.nudSpikeAngle.Name = "nudSpikeAngle"; this.nudSpikeAngle.Size = new System.Drawing.Size(88, 23); - this.nudSpikeAngle.TabIndex = 1; + this.nudSpikeAngle.TabIndex = 3; this.nudSpikeAngle.Value = new decimal(new int[] { 45, 0, 0, 0 }); // lblSpikePairCount this.lblSpikePairCount.AutoSize = true; - this.lblSpikePairCount.Location = new System.Drawing.Point(10, 76); + this.lblSpikePairCount.Location = new System.Drawing.Point(10, 130); this.lblSpikePairCount.Name = "lblSpikePairCount"; this.lblSpikePairCount.Size = new System.Drawing.Size(65, 15); this.lblSpikePairCount.Text = "Pair Count:"; // nudSpikePairCount - this.nudSpikePairCount.Location = new System.Drawing.Point(110, 74); + this.nudSpikePairCount.Location = new System.Drawing.Point(110, 128); this.nudSpikePairCount.Maximum = new decimal(new int[] { 50, 0, 0, 0 }); this.nudSpikePairCount.Minimum = new decimal(new int[] { 1, 0, 0, 0 }); this.nudSpikePairCount.Name = "nudSpikePairCount"; this.nudSpikePairCount.Size = new System.Drawing.Size(88, 23); - this.nudSpikePairCount.TabIndex = 2; - this.nudSpikePairCount.Value = new decimal(new int[] { 3, 0, 0, 0 }); + this.nudSpikePairCount.TabIndex = 4; + this.nudSpikePairCount.Value = new decimal(new int[] { 2, 0, 0, 0 }); // ---- OK / Cancel Buttons ---- this.btnOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); @@ -584,6 +627,8 @@ namespace OpenNest.Forms ((System.ComponentModel.ISupportInitialize)(this.nudSpikeDepth)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.nudSpikeAngle)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.nudSpikePairCount)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nudGrooveDepth)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nudSpikeWeldGap)).EndInit(); this.pnlSettings.ResumeLayout(false); this.grpMethod.ResumeLayout(false); this.grpMethod.PerformLayout(); @@ -657,6 +702,10 @@ namespace OpenNest.Forms private System.Windows.Forms.NumericUpDown nudSpikeAngle; private System.Windows.Forms.Label lblSpikePairCount; private System.Windows.Forms.NumericUpDown nudSpikePairCount; + private System.Windows.Forms.Label lblGrooveDepth; + private System.Windows.Forms.NumericUpDown nudGrooveDepth; + private System.Windows.Forms.Label lblSpikeWeldGap; + private System.Windows.Forms.NumericUpDown nudSpikeWeldGap; private System.Windows.Forms.Button btnOK; private System.Windows.Forms.Button btnCancel; diff --git a/OpenNest/Forms/SplitDrawingForm.cs b/OpenNest/Forms/SplitDrawingForm.cs index 44aefc5..94f4c9a 100644 --- a/OpenNest/Forms/SplitDrawingForm.cs +++ b/OpenNest/Forms/SplitDrawingForm.cs @@ -153,6 +153,8 @@ public partial class SplitDrawingForm : Form { p.Type = SplitType.SpikeGroove; p.SpikeDepth = (double)nudSpikeDepth.Value; + p.GrooveDepth = (double)nudGrooveDepth.Value; + p.SpikeWeldGap = (double)nudSpikeWeldGap.Value; p.SpikeAngle = (double)nudSpikeAngle.Value; p.SpikePairCount = (int)nudSpikePairCount.Value; }