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
along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
import pycam.PathProcessors.PathAccumulator
from pycam.Geometry import Point
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
import math
import sys
class EngraveCutter:
......@@ -33,11 +35,16 @@ class EngraveCutter:
self.cutter = cutter
self.model = 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.safety_height = safety_height
self._boundary_warning_already_shown = False
def GenerateToolPath(self, minz, maxz, horiz_step, dz, draw_callback=None):
quit_requested = False
# calculate the number of steps
num_of_layers = 1 + int(math.ceil(abs(maxz - minz) / dz))
if num_of_layers > 1:
......@@ -51,10 +58,12 @@ class EngraveCutter:
paths = []
current_layer = 0
lines = self.contour_model.get_lines()
progress_counter = ProgressCounter(len(z_steps) * len(lines),
num_of_lines = len(self.contour_model.get_lines())
progress_counter = ProgressCounter(len(z_steps) * num_of_lines,
draw_callback)
line_groups = self.contour_model.get_line_groups()
# push slices for all layers above ground
for z in z_steps[:-1]:
# update the progress bar and check, if we should cancel the process
......@@ -63,37 +72,61 @@ class EngraveCutter:
# cancel immediately
break
for line in lines:
self.GenerateToolPathLinePush(line, z)
progress_counter.increment()
self.pa.finish()
for line_group in line_groups:
for line in line_group:
self.GenerateToolPathLinePush(self.pa_push, line, z)
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
if self.pa.paths:
paths += self.pa.paths
if self.pa_push.paths:
paths += self.pa_push.paths
# break the outer loop if requested
if quit_requested:
break
current_layer += 1
if quit_requested:
return paths
if draw_callback:
draw_callback(text="Engrave: processing layer %d/%d" \
% (current_layer, num_of_layers))
# process the final layer with a drop cutter
for line in lines:
self.GenerateToolPathLineDrop(line, minz, maxz, horiz_step,
draw_callback=draw_callback)
progress_counter.increment()
self.pa.finish()
for line_group in self.contour_model.get_line_groups():
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)
if progress_counter.increment():
# 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
if self.pa.paths:
paths += self.pa.paths
if self.pa_drop.paths:
paths += self.pa_drop.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)
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]
elif self.physics:
points = get_free_horizontal_paths_ode(self.physics, p1.x, p2.x,
......@@ -103,18 +136,21 @@ class EngraveCutter:
self.cutter, p1.x, p2.x, p1.y, p2.y, z)
if points:
for p in points:
self.pa.append(p)
pa.append(p)
self.cutter.moveto(p)
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):
pa.new_direction(0)
pa.new_scanline()
p1 = Point(line.p1.x, line.p1.y, minz)
p2 = Point(line.p2.x, line.p2.y, minz)
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
x_step = (p2.x - p1.x) / (num_of_steps - 1)
y_step = (p2.y - p1.y) / (num_of_steps - 1)
......@@ -126,7 +162,8 @@ class EngraveCutter:
for x, y in step_coords:
if not self.model:
points = [p1, p2]
# no obstacle -> minimum height
points = [Point(x, y, minz)]
elif self.physics:
points = get_max_height_ode(self.physics, x, y, minz, maxz)
else:
......@@ -135,10 +172,10 @@ class EngraveCutter:
if points:
for p in points:
self.pa.append(p)
pa.append(p)
else:
p = Point(x, y, self.safety_height)
self.pa.append(p)
pa.append(p)
if not self._boundary_warning_already_shown:
print >>sys.stderr, "WARNING: DropCutter exceed the height" \
+ " of the boundary box: using a safe height " \
......@@ -147,7 +184,7 @@ class EngraveCutter:
self.cutter.moveto(p)
# "draw_callback" returns true, if the user requested quitting via the GUI
if draw_callback and draw_callback(tool_position=p):
#print "Quit requested?"
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