Commit 3d95f0cb authored by sumpfralle's avatar sumpfralle

EngraveCutter now uses a separated PathProcessor for the last (drop) layer


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@380 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 2512b27b
...@@ -21,10 +21,12 @@ You should have received a copy of the GNU General Public License ...@@ -21,10 +21,12 @@ You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>. along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
""" """
import pycam.PathProcessors.PathAccumulator
from pycam.Geometry import Point from pycam.Geometry import Point
from pycam.Geometry.utils import INFINITE from pycam.Geometry.utils import INFINITE
from pycam.PathGenerators import get_max_height_triangles, get_max_height_ode, get_free_horizontal_paths_ode, get_free_horizontal_paths_triangles, ProgressCounter from pycam.PathGenerators import get_max_height_triangles, get_max_height_ode, get_free_horizontal_paths_ode, get_free_horizontal_paths_triangles, ProgressCounter
import math import math
import sys
class EngraveCutter: class EngraveCutter:
...@@ -33,11 +35,16 @@ class EngraveCutter: ...@@ -33,11 +35,16 @@ class EngraveCutter:
self.cutter = cutter self.cutter = cutter
self.model = model self.model = model
self.contour_model = contour_model self.contour_model = contour_model
self.pa = path_processor self.pa_push = path_processor
# We use a separated path processor for the last "drop" layer.
# This path processor does not need to be configurable.
self.pa_drop = pycam.PathProcessors.PathAccumulator()
self.physics = physics self.physics = physics
self.safety_height = safety_height self.safety_height = safety_height
self._boundary_warning_already_shown = False
def GenerateToolPath(self, minz, maxz, horiz_step, dz, draw_callback=None): def GenerateToolPath(self, minz, maxz, horiz_step, dz, draw_callback=None):
quit_requested = False
# calculate the number of steps # calculate the number of steps
num_of_layers = 1 + int(math.ceil(abs(maxz - minz) / dz)) num_of_layers = 1 + int(math.ceil(abs(maxz - minz) / dz))
if num_of_layers > 1: if num_of_layers > 1:
...@@ -51,10 +58,12 @@ class EngraveCutter: ...@@ -51,10 +58,12 @@ class EngraveCutter:
paths = [] paths = []
current_layer = 0 current_layer = 0
lines = self.contour_model.get_lines() num_of_lines = len(self.contour_model.get_lines())
progress_counter = ProgressCounter(len(z_steps) * len(lines), progress_counter = ProgressCounter(len(z_steps) * num_of_lines,
draw_callback) draw_callback)
line_groups = self.contour_model.get_line_groups()
# push slices for all layers above ground # push slices for all layers above ground
for z in z_steps[:-1]: for z in z_steps[:-1]:
# update the progress bar and check, if we should cancel the process # update the progress bar and check, if we should cancel the process
...@@ -63,37 +72,61 @@ class EngraveCutter: ...@@ -63,37 +72,61 @@ class EngraveCutter:
# cancel immediately # cancel immediately
break break
for line in lines: for line_group in line_groups:
self.GenerateToolPathLinePush(line, z) for line in line_group:
progress_counter.increment() self.GenerateToolPathLinePush(self.pa_push, line, z)
self.pa.finish() if progress_counter.increment():
# cancel requested
quit_requested = True
break
self.pa_push.finish()
# the path accumulator will be reset for each slice - we need to store the result # the path accumulator will be reset for each slice - we need to store the result
if self.pa.paths: if self.pa_push.paths:
paths += self.pa.paths paths += self.pa_push.paths
# break the outer loop if requested
if quit_requested:
break
current_layer += 1 current_layer += 1
if quit_requested:
return paths
if draw_callback: if draw_callback:
draw_callback(text="Engrave: processing layer %d/%d" \ draw_callback(text="Engrave: processing layer %d/%d" \
% (current_layer, num_of_layers)) % (current_layer, num_of_layers))
# process the final layer with a drop cutter # process the final layer with a drop cutter
for line in lines: for line_group in self.contour_model.get_line_groups():
self.GenerateToolPathLineDrop(line, minz, maxz, horiz_step, self.pa_drop.new_direction(0)
self.pa_drop.new_scanline()
for line in line_group:
self.GenerateToolPathLineDrop(self.pa_drop, line, minz, maxz, horiz_step,
draw_callback=draw_callback) draw_callback=draw_callback)
progress_counter.increment() if progress_counter.increment():
self.pa.finish() # quit requested
quit_requested = True
break
self.pa_drop.end_scanline()
self.pa_drop.end_direction()
# break the outer loop if requested
if quit_requested:
break
self.pa_drop.finish()
# the path accumulator will be reset for each slice - we need to store the result # the path accumulator will be reset for each slice - we need to store the result
if self.pa.paths: if self.pa_drop.paths:
paths += self.pa.paths paths += self.pa_drop.paths
return paths return paths
def GenerateToolPathLinePush(self, line, z, draw_callback=None): def GenerateToolPathLinePush(self, pa, line, z, draw_callback=None):
p1 = Point(line.p1.x, line.p1.y, z) p1 = Point(line.p1.x, line.p1.y, z)
p2 = Point(line.p2.x, line.p2.y, z) p2 = Point(line.p2.x, line.p2.y, z)
if not self.model: # no model -> no possible obstacles
# model is completely below z (e.g. support bridges) -> no obstacles
if not self.model or (self.model.maxz < z):
points = [p1, p2] points = [p1, p2]
elif self.physics: elif self.physics:
points = get_free_horizontal_paths_ode(self.physics, p1.x, p2.x, points = get_free_horizontal_paths_ode(self.physics, p1.x, p2.x,
...@@ -103,18 +136,21 @@ class EngraveCutter: ...@@ -103,18 +136,21 @@ class EngraveCutter:
self.cutter, p1.x, p2.x, p1.y, p2.y, z) self.cutter, p1.x, p2.x, p1.y, p2.y, z)
if points: if points:
for p in points: for p in points:
self.pa.append(p) pa.append(p)
self.cutter.moveto(p) self.cutter.moveto(p)
if draw_callback: if draw_callback:
draw_callback(tool_position=p) draw_callback(tool_position=tool_position)
def GenerateToolPathLineDrop(self, line, minz, maxz, horiz_step, def GenerateToolPathLineDrop(self, pa, line, minz, maxz, horiz_step,
draw_callback=None): draw_callback=None):
pa.new_direction(0)
pa.new_scanline()
p1 = Point(line.p1.x, line.p1.y, minz) p1 = Point(line.p1.x, line.p1.y, minz)
p2 = Point(line.p2.x, line.p2.y, minz) p2 = Point(line.p2.x, line.p2.y, minz)
distance = line.len() distance = line.len()
num_of_steps = 1 + int(math.ceil(distance / horiz_step)) # we want to have at least five steps each
num_of_steps = max(5, 1 + int(math.ceil(distance / horiz_step)))
# steps may be negative # steps may be negative
x_step = (p2.x - p1.x) / (num_of_steps - 1) x_step = (p2.x - p1.x) / (num_of_steps - 1)
y_step = (p2.y - p1.y) / (num_of_steps - 1) y_step = (p2.y - p1.y) / (num_of_steps - 1)
...@@ -126,7 +162,8 @@ class EngraveCutter: ...@@ -126,7 +162,8 @@ class EngraveCutter:
for x, y in step_coords: for x, y in step_coords:
if not self.model: if not self.model:
points = [p1, p2] # no obstacle -> minimum height
points = [Point(x, y, minz)]
elif self.physics: elif self.physics:
points = get_max_height_ode(self.physics, x, y, minz, maxz) points = get_max_height_ode(self.physics, x, y, minz, maxz)
else: else:
...@@ -135,10 +172,10 @@ class EngraveCutter: ...@@ -135,10 +172,10 @@ class EngraveCutter:
if points: if points:
for p in points: for p in points:
self.pa.append(p) pa.append(p)
else: else:
p = Point(x, y, self.safety_height) p = Point(x, y, self.safety_height)
self.pa.append(p) pa.append(p)
if not self._boundary_warning_already_shown: if not self._boundary_warning_already_shown:
print >>sys.stderr, "WARNING: DropCutter exceed the height" \ print >>sys.stderr, "WARNING: DropCutter exceed the height" \
+ " of the boundary box: using a safe height " \ + " of the boundary box: using a safe height " \
...@@ -147,7 +184,7 @@ class EngraveCutter: ...@@ -147,7 +184,7 @@ class EngraveCutter:
self.cutter.moveto(p) self.cutter.moveto(p)
# "draw_callback" returns true, if the user requested quitting via the GUI # "draw_callback" returns true, if the user requested quitting via the GUI
if draw_callback and draw_callback(tool_position=p): if draw_callback and draw_callback(tool_position=p):
#print "Quit requested?"
break break
pa.end_scanline()
pa.end_direction()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment