Trouble sequencing slices into paths

One quick fix, I think, to what you’ve described is to start clearing with the smallest (usually centermost) polygon regardless of whether that’s the closest next poly to clear. The current strategy incorrectly optimizes for overall path length and fewest moves.

Disabling “depth first” eliminates the code that has had potential crashes in the past.

Um. Actually, starting with small/center first is a (lesser) problem that I propose is a bug, and suggest the climb-right/conv-left scheme as a “quick” fix. Making some assumptions along the way.

I’ve been beating on depth-first roughing for a few days. Today I’ve thought myself into thinking of solving depth-first by way of first improving non-depth-first roughing.

Below there is a feature request for non-depth-first roughing and a couple of idea for the depth-first algorithm.

I’m struggling with vocabulary. So I’ll use:

  • path: ambiguous, meaning from context
  • loop: one closed circuit
  • nest: a sequence of adjacent loops each directly offset from one of its neighbors
  • (linked) group (of loops): all or part of a nest with stepover moves linking the member loops

Please let me know what you call these things.

Here’s a non-depth-first layer:

In the center there are two groups and a single loop. Around the outside are six round nests each including a linked group of two and a single loop. Between those are six trapezoid-ish (trapezoidoidal?) nests of two loops, one of which is linked.

Here’s the same with moves:

The resulting tool path

  1. starts with the innermost loop
  2. takes a lap around all six inner trapezoids, linking only the last to its nestmate
  3. takes a lap around all six inner linked groups of round loops
  4. goes back to the center the linked group around the first loop
  5. takes an out-of-order tour of the five remaining trapezoidish loops
  6. takes another lap around all six single round loops
  7. goes back a third time to finish the center nest
  8. finishes the three nests that enclose the inner island

That a lot of extra moves, each of which either adds two slow Z moves or plows through the layer at G1 speed. (or crashes trying to G0 without lifting but that’s a bug vs non-optimal function)

S.l.o.w. Hence my interest in depth-first.

Here’s the same slicing again, previewing the beginning of a depth-first path:

While it got ahead of itself with the outer roundy bits, within this layer it’s done some things right:

  • linked up all the nests
  • linked groups all run cw or ccw correctly for up/down milling preference
  • (not clear in this pic) nests around islands inside pockets link into two linked groups of opposite direction.

In my experience so far, the depth-first code always gets those things right within each layer.

What remains ambiguous is the direction of the stepover moves - which manifests as groups running inward or outward. Because the code already has cw/ccw right, and knows climb/conventional preference, I think it looks like stepover direction can be determined directly:

  • climb milling clockwise loops: start with outside loop and step in
  • climb ccw: start in step out
  • conv. cw: start in step out
  • conv. ccw: start out step in

(More succinctly: climb=step right; conv.=step left. But I don’t assume that right and left are easily determined in the code)

So…

Feature/function Request

…how about doing just that much “depth-first” path sorting within each layer of non-depth-first roughing?

That would hugely improve non-depth-first roughing!

Better non-depth-first roughing would take pressure off the depth-first problem.

And today I started thinking that would also simplify solving depth-first.

Idea 1

It looks like the depth-first code already links up these linked groups within each layer and keeps them together, so I assume they are somehow identified as units in the code.

For each such unit, the perimeter(s) of cut area can be determined by a tool radius offset outward from the outermost loop - and inward from the inside loop if it’s not a terminal inner loop. (orthogonal to the large offset/inside corner problem).

Testing for overlap of whole areas should avoid precision problems, no? (assuming your polygon library does that) If potential overlap at edges of two areas is ambiguous within small uncertainty, then it’s probably harmless. Alternative to that assumption, two areas could be determined: one slightly oversize for comparing required area upward and one slightly undersize for comparing safe area downward. Optimistically, the extra polys won’t hurt because there will be fewer “units” than loops.

Idea 2

It seems like that could simplify sorting groups into a depth-first toolpath.

Also a safe/conservative half-way depth-first proposal:

  • Do the layer-at-a-time loop group linking per current code, making linked-loop-group “units” explicit if not already so.
  • Extend each “unit” to include
    • unit area poly(s)
    • reference to one unit below, or none.
    • a flag
  • For each layer from the top down
    • For each unit which is a closed area (no hole) and not flagged
      • If the area entirely overlaps any closed areas in the layer below
        • choose one
        • set it’s flag
        • reference it as the unit below the current unit
  • For each layer from the top down
    • Link up a path through all unflagged units on the layer per current code, except:
      • when a unit references a unit below, recursively insert the unit(s) below into the path after the referencing unit.

I think that would safely snag some low-hanging fruit for constructing a depth-seeking tool path.

About that example

The example figure, by the way, is a 3Dified interpretation of the logo of the amazing “hackerspace” Pumping Station: One in Chicago that I made up (the figure) as a demo for this somewhat silly project. (in a nutshell) That spawned a follow-on project which is exceeding my expectations apart from documentation. Maybe I’ll post those under Showcase.

1 Like

Ah. Found the depth-firsting code. That should cut down on the speculating.

Something is obviously flawed in the non-depth-first code. Probably broke a while back and I never noticed. Should be easy to find and fix.

Related, in the FDM code I just patched up what’s called “thin-wall” detection. The same helper code I wrote to make that work will also detect CNC uncut regions from tool offsets > 50%.

found and fixed. pushed to the dev branch.

Got it. Will have a look.

…meanwhile…

This looks suspect:

It appears to return true if both polygons wind clockwise.

/**
* @returns {boolean} true if both polygons wind the same way
*/
PRO.sameWindings = function(poly) {
return this.isClockwise() === poly.isClockwise();
};

returns true if the windings of both polygons match, as designed

Oh yeah - that’s a big step in the right direction.

…in fact that is, in CAMotics, <1% slower than depth-first. Win.

Will pick nits later.

1 Like

You get a super like for your very well formatted and organized post:

:heart: :clap:

Of course. I should have gone to bed.

Golly. Glad you liked it.

@pmc can you check out today’s 2.3.D1 release and see if it handles roughing sequencing better? The path algorithm as well as the collision detection were both totally rewritten.

Over here:

(20 chars)