Commit 67639b45 authored by sumpfralle's avatar sumpfralle

fixed motion grid generation for 2D model tracing

cleaned up Toolpath class


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@1154 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 55911430
...@@ -233,15 +233,18 @@ def get_lines_layer(lines, z, last_z=None, step_width=None, ...@@ -233,15 +233,18 @@ def get_lines_layer(lines, z, last_z=None, step_width=None,
# process all projected lines # process all projected lines
for line in projected_lines: for line in projected_lines:
if step_width is None: if step_width is None:
yield line.p1 yield (line.p1, line.p2)
yield line.p2
else: else:
if isiterable(step_width): if isiterable(step_width):
steps = step_width steps = step_width
else: else:
steps = floatrange(0.0, line.len, inc=step_width) steps = floatrange(0.0, line.len, inc=step_width)
prior = None
for step in steps: for step in steps:
yield line.p1.add(line.dir.mul(step)) next_point = line.p1.add(line.dir.mul(step))
if not prior is None:
yield (prior, next_point)
prior = next_point
def _get_sorted_polygons(models, callback=None): def _get_sorted_polygons(models, callback=None):
# Sort the polygons according to their directions (first inside, then # Sort the polygons according to their directions (first inside, then
...@@ -266,17 +269,18 @@ def get_lines_grid(models, bounds, layer_distance, line_distance=None, ...@@ -266,17 +269,18 @@ def get_lines_grid(models, bounds, layer_distance, line_distance=None,
low, high = bounds.get_absolute_limits() low, high = bounds.get_absolute_limits()
else: else:
low, high = bounds low, high = bounds
# the lower limit is never below the model
polygons = _get_sorted_polygons(models, callback=callback)
low_limit_lines = min([polygon.minz for polygon in polygons])
low[2] = max(low[2], low_limit_lines)
lines = [] lines = []
for polygon in _get_sorted_polygons(models, callback=callback): for polygon in polygons:
if polygon.is_closed and \ if polygon.is_closed and \
(milling_style == MILLING_STYLE_CONVENTIONAL): (milling_style == MILLING_STYLE_CONVENTIONAL):
polygon = polygon.copy() polygon = polygon.copy()
polygon.reverse() polygon.reverse()
for line in polygon.get_lines(): for line in polygon.get_lines():
lines.append(line) lines.append(line)
# the lower limit is never below the model
low_limit_lines = min([line.minz for line in lines])
low[2] = max(low[2], low_limit_lines)
if isiterable(layer_distance): if isiterable(layer_distance):
layers = layer_distance layers = layer_distance
elif layer_distance is None: elif layer_distance is None:
...@@ -291,8 +295,8 @@ def get_lines_grid(models, bounds, layer_distance, line_distance=None, ...@@ -291,8 +295,8 @@ def get_lines_grid(models, bounds, layer_distance, line_distance=None,
if layers: if layers:
# the upper layers are used for PushCutter operations # the upper layers are used for PushCutter operations
for z in layers[:-1]: for z in layers[:-1]:
yield get_lines_layer(lines, z, last_z=last_z, yield get_lines_layer(lines, z, last_z=last_z, step_width=None,
step_width=None, milling_style=milling_style) milling_style=milling_style)
last_z = z last_z = z
# the last layer is used for a DropCutter operation # the last layer is used for a DropCutter operation
yield get_lines_layer(lines, layers[-1], last_z=last_z, yield get_lines_layer(lines, layers[-1], last_z=last_z,
......
...@@ -60,74 +60,55 @@ def simplify_toolpath(path): ...@@ -60,74 +60,55 @@ def simplify_toolpath(path):
index += 1 index += 1
class ToolpathList(list):
def add_toolpath(self, toolpath, name, toolpath_settings):
self.append(Toolpath(toolpath, name, toolpath_settings))
class Toolpath(object): class Toolpath(object):
def __init__(self, toolpath, name, toolpath_settings): def __init__(self, paths, max_safe_distance=0, feedrate=300):
self.toolpath = toolpath self.paths = paths
self.name = name self._max_safe_distance = max_safe_distance
self.toolpath_settings = toolpath_settings self._feedrate = feedrate
self.visible = True
self.color = None def get_params(self):
# generate random color return {"max_safe_distance": self._max_safe_distance,
self.set_color() "feedrate": self._feedrate,
}
def _get_limit_generic(self, attr, func): def _get_limit_generic(self, attr, func):
path_min = [] path_min = []
for path in self.get_paths(): for path in self.paths:
if path.points: if path.points:
path_min.append(func([getattr(p, attr) for p in path.points])) path_min.append(func([getattr(p, attr) for p in path.points]))
return func(path_min) return func(path_min)
@property
def minx(self): def minx(self):
return self._get_limit_generic("x", min) return self._get_limit_generic("x", min)
@property
def maxx(self): def maxx(self):
return self._get_limit_generic("x", max) return self._get_limit_generic("x", max)
@property
def miny(self): def miny(self):
return self._get_limit_generic("y", min) return self._get_limit_generic("y", min)
@property
def maxy(self): def maxy(self):
return self._get_limit_generic("y", max) return self._get_limit_generic("y", max)
@property
def minz(self): def minz(self):
return self._get_limit_generic("z", min) return self._get_limit_generic("z", min)
@property
def maxz(self): def maxz(self):
return self._get_limit_generic("z", max) return self._get_limit_generic("z", max)
def get_paths(self):
return self.toolpath
def get_bounding_box(self):
box = self.toolpath_settings.get_bounds()
(minx, miny, minz), (maxx, maxy, maxz) = box.get_bounds()
return (minx, maxx, miny, maxy, minz, maxz)
def get_tool_settings(self):
return self.toolpath_settings.get_tool_settings()
def get_toolpath_settings(self):
return self.toolpath_settings
def get_meta_data(self): def get_meta_data(self):
meta = self.toolpath_settings.get_string() meta = self.toolpath_settings.get_string()
start_marker = self.toolpath_settings.META_MARKER_START start_marker = self.toolpath_settings.META_MARKER_START
end_marker = self.toolpath_settings.META_MARKER_END end_marker = self.toolpath_settings.META_MARKER_END
return os.linesep.join((start_marker, meta, end_marker)) return os.linesep.join((start_marker, meta, end_marker))
def set_color(self, color=None):
if color is None:
self.color = (random.random(), random.random(), random.random())
else:
self.color = color
def get_moves(self, safety_height, max_movement=None): def get_moves(self, safety_height, max_movement=None):
class MoveContainer(object): class MoveContainer(object):
def __init__(self, max_movement): def __init__(self, max_movement):
...@@ -165,10 +146,8 @@ class Toolpath(object): ...@@ -165,10 +146,8 @@ class Toolpath(object):
self.moves.append((new_position, rapid)) self.moves.append((new_position, rapid))
return True return True
p_last = None p_last = None
max_safe_distance = 2 * self.toolpath_settings.get_tool().radius \
+ epsilon
result = MoveContainer(max_movement) result = MoveContainer(max_movement)
for path in self.get_paths(): for path in self.paths:
if not path: if not path:
# ignore empty paths # ignore empty paths
continue continue
...@@ -182,7 +161,8 @@ class Toolpath(object): ...@@ -182,7 +161,8 @@ class Toolpath(object):
# Draw the connection between the last and the next path. # Draw the connection between the last and the next path.
# Respect the safety height. # Respect the safety height.
if (abs(p_last.z - p_next.z) > epsilon) \ if (abs(p_last.z - p_next.z) > epsilon) \
or (p_last.sub(p_next).norm > max_safe_distance): or (p_last.sub(p_next).norm > \
self._max_safe_distance + epsilon):
# The distance between these two points is too far. # The distance between these two points is too far.
# This condition helps to prevent moves up/down for # This condition helps to prevent moves up/down for
# adjacent lines. # adjacent lines.
...@@ -211,14 +191,12 @@ class Toolpath(object): ...@@ -211,14 +191,12 @@ class Toolpath(object):
@returns: the machine time used for processing the toolpath in minutes @returns: the machine time used for processing the toolpath in minutes
""" """
result = 0 result = 0
feedrate = self.toolpath_settings.get_tool_settings()["feedrate"]
feedrate = number(feedrate)
safety_height = number(safety_height) safety_height = number(safety_height)
current_position = None current_position = None
# go through all points of the path # go through all points of the path
for new_pos, rapid in self.get_moves(safety_height): for new_pos, rapid in self.get_moves(safety_height):
if not current_position is None: if not current_position is None:
result += new_pos.sub(current_position).norm / feedrate result += new_pos.sub(current_position).norm / self._feedrate
current_position = new_pos current_position = new_pos
return result return result
...@@ -236,22 +214,20 @@ class Toolpath(object): ...@@ -236,22 +214,20 @@ class Toolpath(object):
def get_cropped_copy(self, polygons, callback=None): def get_cropped_copy(self, polygons, callback=None):
# create a deep copy of the current toolpath # create a deep copy of the current toolpath
new_paths = [] new_paths = []
for path in self.toolpath: for path in self.paths:
if path: if path:
new_path = Path() new_path = Path()
for point in path.points: for point in path.points:
new_path.append(point) new_path.append(point)
new_paths.append(new_path) new_paths.append(new_path)
tp = Toolpath(new_paths, "%s (cropped)" % self.name, tp = Toolpath(new_paths, **self.get_params())
self.toolpath_settings)
tp.visible = self.visible
tp.crop(polygons, callback=callback) tp.crop(polygons, callback=callback)
return tp return tp
def crop(self, polygons, callback=None): def crop(self, polygons, callback=None):
# collect all existing toolpath lines # collect all existing toolpath lines
open_lines = [] open_lines = []
for path in self.toolpath: for path in self.paths:
if path: if path:
for index in range(len(path.points) - 1): for index in range(len(path.points) - 1):
open_lines.append(Line(path.points[index], open_lines.append(Line(path.points[index],
...@@ -268,7 +244,7 @@ class Toolpath(object): ...@@ -268,7 +244,7 @@ class Toolpath(object):
inner_lines.extend(inner) inner_lines.extend(inner)
new_open_lines.extend(outer) new_open_lines.extend(outer)
open_lines = new_open_lines open_lines = new_open_lines
# turn all "inner_lines" into toolpath movements # turn all "inner_lines" into toolpath moves
new_paths = [] new_paths = []
current_path = Path() current_path = Path()
if inner_lines: if inner_lines:
...@@ -293,7 +269,7 @@ class Toolpath(object): ...@@ -293,7 +269,7 @@ class Toolpath(object):
current_path.append(line.p2) current_path.append(line.p2)
if current_path.points: if current_path.points:
new_paths.append(current_path) new_paths.append(current_path)
self.toolpath = new_paths self.paths = new_paths
class Bounds(object): class Bounds(object):
......
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