diff --git a/GUI/PathCAM.cs b/GUI/PathCAM.cs
index 720d922..3365b2e 100644
--- a/GUI/PathCAM.cs
+++ b/GUI/PathCAM.cs
@@ -149,7 +149,9 @@ void worker_LoadMesh(object sender, DoWorkEventArgs e)
e.Result = triangleMesh;
}
-
+ // For debugging, generate paths for the first loaded
+ // trianglemesh every frame (allows drawing code inside the generation)
+ //TriangleMeshGUI m = null;
void IOpenGLDrawable.Draw()
{
try
@@ -157,7 +159,15 @@ void IOpenGLDrawable.Draw()
foreach (var mesh in inProgressMeshes)
{
mesh.Draw();
+ //if (m == null)
+ //{
+ // m = mesh;
+ //}
}
+ //if (m != null)
+ //{
+ // PathPlanner.PlanPaths(m, m.Tabs.ConvertAll(tab => tab as Tabs), router);
+ //}
}
catch (Exception)
{
@@ -375,7 +385,7 @@ private void InitializeComponent()
//
this.showRobotFormCheckbox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.showRobotFormCheckbox.AutoSize = true;
- this.showRobotFormCheckbox.Location = new System.Drawing.Point(-1, 449);
+ this.showRobotFormCheckbox.Location = new System.Drawing.Point(-1, 549);
this.showRobotFormCheckbox.Name = "showRobotFormCheckbox";
this.showRobotFormCheckbox.Size = new System.Drawing.Size(15, 14);
this.showRobotFormCheckbox.TabIndex = 69;
@@ -395,7 +405,7 @@ private void InitializeComponent()
//
this.robotControl.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.robotControl.BackColor = System.Drawing.Color.Transparent;
- this.robotControl.Location = new System.Drawing.Point(-1, 327);
+ this.robotControl.Location = new System.Drawing.Point(-1, 427);
this.robotControl.Name = "robotControl";
this.robotControl.Size = new System.Drawing.Size(169, 136);
this.robotControl.TabIndex = 8;
@@ -414,7 +424,7 @@ private void InitializeComponent()
this.drawing3D.MinimumSize = new System.Drawing.Size(10, 10);
this.drawing3D.Name = "drawing3D";
this.drawing3D.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
- this.drawing3D.Size = new System.Drawing.Size(100, 98);
+ this.drawing3D.Size = new System.Drawing.Size(300, 198);
this.drawing3D.TabIndex = 68;
this.drawing3D.VSync = false;
//
@@ -422,7 +432,7 @@ private void InitializeComponent()
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(584, 462);
+ this.ClientSize = new System.Drawing.Size(784, 562);
this.Controls.Add(this.showRobotFormCheckbox);
this.Controls.Add(this.saveGcodeButton);
this.Controls.Add(this.button2);
diff --git a/Geometry/Slice.cs b/Geometry/Slice.cs
index 32d80dd..6f3ca51 100644
--- a/Geometry/Slice.cs
+++ b/Geometry/Slice.cs
@@ -85,7 +85,7 @@ public Slice(TriangleMesh mesh, Plane plane)
else
{
Slice s = new Slice(lineHandler.GetOuterLoops(), plane);
- this.Add(s);
+ this.Union(s);
}
}
//GL.End();
@@ -760,7 +760,7 @@ private Slice GetPairs(bool outside)
return s;
}
- public void Add(Slice other)
+ public void Union(Slice other)
{
Clipper c = new Clipper();
c.Clear();
diff --git a/Robot/Robot.cs b/Robot/Robot.cs
index 6aeea09..0541959 100644
--- a/Robot/Robot.cs
+++ b/Robot/Robot.cs
@@ -121,6 +121,7 @@ private void NewDataAvailable(SerialPortWrapper.SimpleSerialPacket packet)
{
lock (thisLock)
{
+ elapsedCounter = 0;
if (currentCommand == null)
{
Console.WriteLine("Error: Received data, but no command was sent!");
@@ -173,7 +174,7 @@ private void NewDataAvailable(SerialPortWrapper.SimpleSerialPacket packet)
currentCommand = GetNextCommand(locations);
- elapsedCounter = 0;
+
serial.Transmit(currentCommand.GenerateCommand(), 0x21);
}
else
diff --git a/Router/Paths/PathPlanner.cs b/Router/Paths/PathPlanner.cs
index 3640bba..3855dbe 100644
--- a/Router/Paths/PathPlanner.cs
+++ b/Router/Paths/PathPlanner.cs
@@ -30,20 +30,44 @@ namespace Router.Paths
public class PathPlanner
{
///
- /// Find a toolpath which will remove everything described in the slice.
+ /// Get slices from the top of the triangle mesh to the bottom, spaced no more than
+ /// the specified cut depth in router. The first slice is the highest.
///
- ///
- public static void PlanPaths(Slice slice)
+ ///
+ ///
+ ///
+ private static List GetSlices(TriangleMesh triangles, Router router)
{
- // 1. Get all small holes in the slice - rout them first
- // 2. Rout everything remaining in the slice from
+ float maxCutDepth = router.MaxCutDepth;
+ float minZ = triangles.MinPoint.Z;
+ float maxZ = triangles.MaxPoint.Z;
+
+ float skin = 0.002f; // Depth above the minpoint and below the maxpoint to slice.
+
+ // Figure out an even maximum cut depth
+ int layers = (int)((maxZ - minZ) / maxCutDepth + 0.95f);
+ float actualCutDepth = (maxZ - minZ - 2*skin) / layers;
+ actualCutDepth = Math.Min(maxZ - minZ - 2*skin, actualCutDepth);
+
+ List slices = new List();
+
+ for (float height = maxZ - skin; height > -actualCutDepth / 2.0f; height -= actualCutDepth)
+ {
+ var slice = new Slice(triangles, new Plane(Vector3.UnitZ, new Vector3(0, 0, height)));
+ foreach (var higherSlice in slices)
+ {
+ slice.Union(higherSlice);
+ }
+ slices.Add(slice);
+ }
+ return slices;
}
public static List PlanPaths(TriangleMesh triangles, List tabs, Router router)
{
List routs = new List();
- float toolRadius = router.ToolDiameter / 2.0f; // Router units are inches
+ float toolRadius = router.ToolDiameter / 2.0f;
float maxCutDepth = router.MaxCutDepth;
float lastPassHeight = router.LastPassHeight;
float cleanPassFactor = 0.90f; // 90% of the tool radius will be removed on the clean pass
@@ -51,17 +75,30 @@ public static List PlanPaths(TriangleMesh triangles, List tabs,
float minZ = triangles.MinPoint.Z;
float maxZ = triangles.MaxPoint.Z;
- Slice boundary = new Slice(triangles, new Plane(Vector3.UnitZ, new Vector3(0, 0, minZ)));
+ var slices = GetSlices(triangles, router);
+ //GL.PushMatrix();
+ //foreach (var s in slices)
+ //{
+ // GL.Translate(triangles.MaxPoint.X - triangles.MinPoint.X, 0, 0);
+ // DrawSlice(Color.Orange, Color.Black, s);
+ //}
+ //GL.PopMatrix();
+
+ Slice top = slices[0];
+ slices.RemoveAt(0);
+ Slice boundary = new Slice (slices[slices.Count - 1]);
+
boundary.Offset(toolRadius * (cleanPassFactor + 1.05f)); // Note: this is slightly larger to allow some polygon width to exist
+
+ // Enable complete removal of holes with no tabs
foreach (var tab in tabs)
{
if (tab.TabLocations.Count() == 0)
{
- boundary.Add(tab.Boundary);
+ boundary.Union(tab.Boundary);
}
}
- Slice top = new Slice(triangles, new Plane(Vector3.UnitZ, new Vector3(0, 0, maxZ)));
top.SubtractFrom(boundary);
//GL.PushMatrix();
@@ -70,7 +107,6 @@ public static List PlanPaths(TriangleMesh triangles, List tabs,
//GL.PopMatrix();
Slice holes = top.PolygonsWithoutHoles();
-
List holeRouts = new List();
foreach (var polygon in holes.IndividualPolygons())
@@ -78,21 +114,15 @@ public static List PlanPaths(TriangleMesh triangles, List tabs,
holeRouts.Add(new Hole(polygon, toolRadius, cleanPassFactor));
}
- // Figure out a nice even maximum cut depth
- int layers = (int)((maxZ - minZ) / maxCutDepth + 0.95f);
- float actualCutDepth = (maxZ - minZ) / layers;
-
- for (float height = minZ; height < maxZ; height += actualCutDepth)
+ foreach (Slice current in slices)
{
- Slice current = new Slice(triangles, new Plane(Vector3.UnitZ, new Vector3(0, 0, height)));
current.Offset(toolRadius);
- GL.PushMatrix();
- GL.Translate(0, 0, -0.001f);
- //DrawSlice(Color.Tan, Color.Gray, boundary);
- GL.PopMatrix();
- //DrawSlice(Color.Red, Color.Blue, current);
+ //GL.PushMatrix();
+ //GL.Translate(0, 0, -0.001f);
+ ////DrawSlice(Color.Tan, Color.Gray, boundary);
+ //GL.PopMatrix();
+ ////DrawSlice(Color.Red, Color.Blue, current);
-
Slice original = new Slice(current);
current.SubtractFrom(boundary);
@@ -123,20 +153,20 @@ public static List PlanPaths(TriangleMesh triangles, List tabs,
// Rout all outside paths. These will be done from top down, one layer at a time for structural reasons.
// For the top several layers, two paths could be combined...
- //var withHoles = outsidePairs.PolygonsWithHoles();
- var outsideRouts = RoutAreasWithHoles(outsidePairs, toolRadius, cleanPassFactor, tabs, false);
+ var outsideRouts = RoutAreasWithHoles(insidePairs.PolygonsWithHoles(), toolRadius, cleanPassFactor, tabs, true);
var newLines = new List();
foreach (var line in outsideRouts)
{
var r = new LineStrip();
r.AddRange(line.Vertices);
r.Append(line.Vertices[0]);
+ r.Vertices.Reverse();
newLines.Add(r);
}
- routs.InsertRange(0, newLines);
+ routs.AddRange(newLines);
- outsideRouts = RoutAreasWithHoles(insidePairs.PolygonsWithHoles(), toolRadius, cleanPassFactor, tabs, true);
+ outsideRouts = RoutAreasWithHoles(outsidePairs, toolRadius, cleanPassFactor, tabs, false);
newLines = new List();
foreach (var line in outsideRouts)
{
@@ -145,7 +175,7 @@ public static List PlanPaths(TriangleMesh triangles, List tabs,
r.Append(line.Vertices[0]);
newLines.Add(r);
}
- routs.InsertRange(0, newLines);
+ routs.AddRange(newLines);
}
foreach (var hole in holeRouts)
@@ -327,16 +357,16 @@ public List GetRouts()
GL.PushMatrix();
Slice lastPolygon = null;
- for (int i = polygons.Count - 1; i >= 0; i--)
+ foreach (var p in polygons)
{
- var p = polygons[i];
var routLast = p.GetLines(Slice.LineType.Outside).First(s => true);
routLast.Vertices.Add(routLast.Vertices[0]);
+ routLast.Vertices.Reverse();
Slice obliterate = new Slice(p);
obliterate.Offset(-toolRadius * cleanRoutFactor);
- var routFirst = PathTree.ObliterateSlice(obliterate, toolRadius * 2.0f);
+ var routFirst = PathTree.ObliterateSlice(obliterate, toolRadius * 2.0f, true);
if (lastPolygon == null)
{
@@ -429,6 +459,7 @@ private class PathTree
private Slice slice;
private List children = new List();
private List badTrees;
+ private bool reverse;
#region Public Methods
@@ -439,13 +470,13 @@ private class PathTree
///
/// maximum distance between disjoint paths
///
- public static List ObliterateSlice(Slice polygons, float maxShrink)
+ public static List ObliterateSlice(Slice polygons, float maxShrink, bool reverse = false)
{
List lines = new List();
foreach (Slice slice in polygons.IndividualPolygons())
{
- PathTree tree = new PathTree();
+ PathTree tree = new PathTree(reverse);
Slice inside = new Slice(slice.GetLines(Slice.LineType.Hole), slice.Plane);
Slice shrink = new Slice(slice);
while (shrink.Area() > 0)
@@ -474,21 +505,28 @@ public static List ObliterateSlice(Slice polygons, float maxShrink)
#region Private Methods
- private PathTree()
+ private PathTree(bool reverse)
{
slice = null;
badTrees = new List();
+ this.reverse = reverse;
}
private PathTree(Slice slice, PathTree parent)
{
this.badTrees = parent.badTrees;
this.slice = slice;
+ this.reverse = parent.reverse;
}
private LineStrip CreatePath()
{
- return slice.GetLines(Geometry.Slice.LineType.Outside).First(s => true);
+ var path = slice.GetLines(Geometry.Slice.LineType.Outside).First(s => true);
+ if (reverse)
+ {
+ path.Vertices.Reverse();
+ }
+ return path;
}
private void Draw(Color lineColor, Color planeColor)