Commit 6ed95bf7 authored by sumpfralle's avatar sumpfralle

removed useless local cache for the process pusher

adjusted the ContourFollow strategy to use caching properly


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@747 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 198a3ab2
...@@ -45,30 +45,31 @@ log = pycam.Utils.log.get_logger() ...@@ -45,30 +45,31 @@ log = pycam.Utils.log.get_logger()
# We need to use a global function here - otherwise it does not work with # We need to use a global function here - otherwise it does not work with
# the multiprocessing Pool. # the multiprocessing Pool.
def _process_one_triangle(obj, triangle, z): def _process_one_triangle(model, cutter, up_vector, triangle, z):
result = [] result = []
if id(triangle) in obj._processed_triangles:
# skip triangles that are known to cause no collision
return result
# ignore triangles below the z level # ignore triangles below the z level
if triangle.maxz < z: if triangle.maxz < z:
# Case 1a # Case 1a
return result return result, None
# ignore triangles pointing upwards or downwards # ignore triangles pointing upwards or downwards
if triangle.normal.cross(obj._up_vector).norm == 0: if triangle.normal.cross(up_vector).norm == 0:
# Case 1b # Case 1b
return result return result, None
edge_collisions = obj.get_collision_waterline_of_triangle(triangle, z) edge_collisions = get_collision_waterline_of_triangle(model, cutter, up_vector, triangle, z)
if not edge_collisions: if edge_collisions is None:
return result # don't try to use this edge again
return result, [id(triangle)]
elif len(edge_collisions) == 0:
return result, None
else:
for cutter_location, edge in edge_collisions: for cutter_location, edge in edge_collisions:
shifted_edge = obj.get_shifted_waterline(edge, cutter_location) shifted_edge = get_shifted_waterline(up_vector, edge, cutter_location)
if not shifted_edge is None: if not shifted_edge is None:
if _DEBUG_DISBALE_WATERLINE_SHIFT: if _DEBUG_DISBALE_WATERLINE_SHIFT:
result.append((edge, edge)) result.append((edge, edge))
else: else:
result.append((edge, shifted_edge)) result.append((edge, shifted_edge))
return result return result, None
class CollisionPaths: class CollisionPaths:
...@@ -286,9 +287,13 @@ class ContourFollow: ...@@ -286,9 +287,13 @@ class ContourFollow:
projected_waterlines = [] projected_waterlines = []
triangles = self.model.triangles(minx=minx, miny=miny, maxx=maxx, triangles = self.model.triangles(minx=minx, miny=miny, maxx=maxx,
maxy=maxy) maxy=maxy)
results_iter = run_in_parallel(_process_one_triangle, args = [(self.model, self.cutter, self._up_vector, t, z)
[(self, t, z) for t in triangles], unordered=True) for t in triangles if not id(t) in self._processed_triangles]
for result in results_iter: results_iter = run_in_parallel(_process_one_triangle, args,
unordered=True)
for result, ignore_triangle_id_list in results_iter:
if ignore_triangle_id_list:
self._processed_triangles.extend(ignore_triangle_id_list)
for edge, shifted_edge in result: for edge, shifted_edge in result:
waterline_triangles.add(edge, shifted_edge) waterline_triangles.add(edge, shifted_edge)
if (not progress_counter is None) \ if (not progress_counter is None) \
...@@ -304,18 +309,10 @@ class ContourFollow: ...@@ -304,18 +309,10 @@ class ContourFollow:
result.append(cropped_line) result.append(cropped_line)
return result return result
def get_max_length(self):
if not hasattr(self, "_max_length_cache"):
# update the cache
x_dim = abs(self.model.maxx - self.model.minx)
y_dim = abs(self.model.maxy - self.model.miny)
z_dim = abs(self.model.maxz - self.model.minz)
self._max_length_cache = sqrt(x_dim ** 2 + y_dim ** 2 + z_dim ** 2)
return self._max_length_cache
def get_collision_waterline_of_triangle(self, triangle, z): def get_collision_waterline_of_triangle(model, cutter, up_vector, triangle, z):
# TODO: there are problems with "material allowance > 0" # TODO: there are problems with "material allowance > 0"
plane = Plane(Point(0, 0, z), self._up_vector) plane = Plane(Point(0, 0, z), up_vector)
if triangle.minz >= z: if triangle.minz >= z:
# no point of the triangle is below z # no point of the triangle is below z
# try all edges # try all edges
...@@ -330,13 +327,13 @@ class ContourFollow: ...@@ -330,13 +327,13 @@ class ContourFollow:
for index in range(3): for index in range(3):
edge = Line(proj_points[index - 1], proj_points[index]) edge = Line(proj_points[index - 1], proj_points[index])
# the edge should be clockwise around the model # the edge should be clockwise around the model
if edge.dir.cross(triangle.normal).dot(self._up_vector) < 0: if edge.dir.cross(triangle.normal).dot(up_vector) < 0:
edge = Line(edge.p2, edge.p1) edge = Line(edge.p2, edge.p1)
edges.append((edge, proj_points[index - 2])) edges.append((edge, proj_points[index - 2]))
outer_edges = [] outer_edges = []
for edge, other_point in edges: for edge, other_point in edges:
# pick only edges, where the other point is on the right side # pick only edges, where the other point is on the right side
if other_point.sub(edge.p1).cross(edge.dir).dot(self._up_vector) > 0: if other_point.sub(edge.p1).cross(edge.dir).dot(up_vector) > 0:
outer_edges.append(edge) outer_edges.append(edge)
if len(outer_edges) == 0: if len(outer_edges) == 0:
# the points seem to be an one line # the points seem to be an one line
...@@ -348,7 +345,7 @@ class ContourFollow: ...@@ -348,7 +345,7 @@ class ContourFollow:
outer_edges = [long_edge] outer_edges = [long_edge]
else: else:
edge = Line(proj_points[0], proj_points[1]) edge = Line(proj_points[0], proj_points[1])
if edge.dir.cross(triangle.normal).dot(self._up_vector) < 0: if edge.dir.cross(triangle.normal).dot(up_vector) < 0:
edge = Line(edge.p2, edge.p1) edge = Line(edge.p2, edge.p1)
outer_edges = [edge] outer_edges = [edge]
else: else:
...@@ -383,7 +380,7 @@ class ContourFollow: ...@@ -383,7 +380,7 @@ class ContourFollow:
outer_edges = [waterline] outer_edges = [waterline]
elif len(points_above) == 1: elif len(points_above) == 1:
other_point = points_above[0] other_point = points_above[0]
dot = other_point.sub(waterline.p1).cross(waterline.dir).dot(self._up_vector) dot = other_point.sub(waterline.p1).cross(waterline.dir).dot(up_vector)
if dot > 0: if dot > 0:
# Case (2b) # Case (2b)
outer_edges = [waterline] outer_edges = [waterline]
...@@ -394,7 +391,7 @@ class ContourFollow: ...@@ -394,7 +391,7 @@ class ContourFollow:
edges.append(Line(waterline.p2, other_point)) edges.append(Line(waterline.p2, other_point))
outer_edges = [] outer_edges = []
for edge in edges: for edge in edges:
if edge.dir.cross(triangle.normal).dot(self._up_vector) < 0: if edge.dir.cross(triangle.normal).dot(up_vector) < 0:
outer_edges.append(Line(edge.p2, edge.p1)) outer_edges.append(Line(edge.p2, edge.p1))
else: else:
outer_edges.append(edge) outer_edges.append(edge)
...@@ -407,14 +404,14 @@ class ContourFollow: ...@@ -407,14 +404,14 @@ class ContourFollow:
edges.append(Line(waterline.p2, other_point)) edges.append(Line(waterline.p2, other_point))
edges.sort(key=lambda x: x.len) edges.sort(key=lambda x: x.len)
edge = edges[-1] edge = edges[-1]
if edge.dir.cross(triangle.normal).dot(self._up_vector) < 0: if edge.dir.cross(triangle.normal).dot(up_vector) < 0:
outer_edges = [Line(edge.p2, edge.p1)] outer_edges = [Line(edge.p2, edge.p1)]
else: else:
outer_edges = [edge] outer_edges = [edge]
else: else:
# two points above # two points above
other_point = points_above[0] other_point = points_above[0]
dot = other_point.sub(waterline.p1).cross(waterline.dir).dot(self._up_vector) dot = other_point.sub(waterline.p1).cross(waterline.dir).dot(up_vector)
if dot > 0: if dot > 0:
# Case (2b) # Case (2b)
# the other two points are on the right side # the other two points are on the right side
...@@ -422,7 +419,7 @@ class ContourFollow: ...@@ -422,7 +419,7 @@ class ContourFollow:
elif dot < 0: elif dot < 0:
# Case (3a) # Case (3a)
edge = Line(points_above[0], points_above[1]) edge = Line(points_above[0], points_above[1])
if edge.dir.cross(triangle.normal).dot(self._up_vector) < 0: if edge.dir.cross(triangle.normal).dot(up_vector) < 0:
outer_edges = [Line(edge.p2, edge.p1)] outer_edges = [Line(edge.p2, edge.p1)]
else: else:
outer_edges = [edge] outer_edges = [edge]
...@@ -438,16 +435,21 @@ class ContourFollow: ...@@ -438,16 +435,21 @@ class ContourFollow:
edges.append(Line(p1, p2)) edges.append(Line(p1, p2))
edges.sort(key=lambda x: x.len) edges.sort(key=lambda x: x.len)
edge = edges[-1] edge = edges[-1]
if edge.dir.cross(triangle.normal).dot(self._up_vector) < 0: if edge.dir.cross(triangle.normal).dot(up_vector) < 0:
outer_edges = [Line(edge.p2, edge.p1)] outer_edges = [Line(edge.p2, edge.p1)]
else: else:
outer_edges = [edge] outer_edges = [edge]
# calculate the maximum diagonal length within the model
x_dim = abs(model.maxx - model.minx)
y_dim = abs(model.maxy - model.miny)
z_dim = abs(model.maxz - model.minz)
max_length = sqrt(x_dim ** 2 + y_dim ** 2 + z_dim ** 2)
result = [] result = []
for edge in outer_edges: for edge in outer_edges:
direction = self._up_vector.cross(edge.dir).normalized() direction = up_vector.cross(edge.dir).normalized()
if direction is None: if direction is None:
continue continue
direction = direction.mul(self.get_max_length()) direction = direction.mul(max_length)
edge_dir = edge.p2.sub(edge.p1) edge_dir = edge.p2.sub(edge.p1)
# TODO: adapt the number of potential starting positions to the length of the line # TODO: adapt the number of potential starting positions to the length of the line
# Don't use 0.0 and 1.0 - this could result in ambiguous collisions # Don't use 0.0 and 1.0 - this could result in ambiguous collisions
...@@ -456,7 +458,7 @@ class ContourFollow: ...@@ -456,7 +458,7 @@ class ContourFollow:
start = edge.p1.add(edge_dir.mul(factor)) start = edge.p1.add(edge_dir.mul(factor))
# We need to use the triangle collision algorithm here - because we # We need to use the triangle collision algorithm here - because we
# need the point of collision in the triangle. # need the point of collision in the triangle.
collisions = get_free_paths_triangles(self.model, self.cutter, start, collisions = get_free_paths_triangles(model, cutter, start,
start.add(direction), return_triangles=True) start.add(direction), return_triangles=True)
for index, coll in enumerate(collisions): for index, coll in enumerate(collisions):
if (index % 2 == 0) and (not coll[1] is None) \ if (index % 2 == 0) and (not coll[1] is None) \
...@@ -479,14 +481,15 @@ class ContourFollow: ...@@ -479,14 +481,15 @@ class ContourFollow:
# Don't check triangles again that are completely above the z level and # Don't check triangles again that are completely above the z level and
# did not return any collisions. # did not return any collisions.
if (len(result) == 0) and (triangle.minz > z): if (len(result) == 0) and (triangle.minz > z):
self._processed_triangles.append(id(triangle)) # a return value None indicates that the triangle needs no further evaluation
return None
return result return result
def get_shifted_waterline(self, waterline, cutter_location): def get_shifted_waterline(up_vector, waterline, cutter_location):
# Project the waterline and the cutter location down to the slice plane. # Project the waterline and the cutter location down to the slice plane.
# This is necessary for calculating the horizontal distance between the # This is necessary for calculating the horizontal distance between the
# cutter and the triangle waterline. # cutter and the triangle waterline.
plane = Plane(cutter_location, self._up_vector) plane = Plane(cutter_location, up_vector)
wl_proj = plane.get_line_projection(waterline) wl_proj = plane.get_line_projection(waterline)
if wl_proj.len < epsilon: if wl_proj.len < epsilon:
return None return None
......
...@@ -254,7 +254,6 @@ def run_in_parallel_remote(func, args_list, unordered=False, ...@@ -254,7 +254,6 @@ def run_in_parallel_remote(func, args_list, unordered=False,
results_queue = __manager.results() results_queue = __manager.results()
remote_cache = __manager.cache() remote_cache = __manager.cache()
stats = __manager.statistics() stats = __manager.statistics()
local_cache = {}
for args in args_list: for args in args_list:
start_time = time.time() start_time = time.time()
result_args = [] result_args = []
...@@ -262,12 +261,8 @@ def run_in_parallel_remote(func, args_list, unordered=False, ...@@ -262,12 +261,8 @@ def run_in_parallel_remote(func, args_list, unordered=False,
# add the argument to the cache if possible # add the argument to the cache if possible
if hasattr(arg, "uuid"): if hasattr(arg, "uuid"):
data_uuid = ProcessDataCacheItemID(arg.uuid) data_uuid = ProcessDataCacheItemID(arg.uuid)
if not data_uuid in local_cache.keys():
local_cache[data_uuid] = arg
log.debug("Adding item to manager's local cache " \
+ "(job: %s): %s - %s" \
% (job_id, arg.uuid, arg.__class__))
if not remote_cache.contains(data_uuid): if not remote_cache.contains(data_uuid):
log.debug("Adding cache item for job %s: %s - %s" % (job_id, arg.uuid, arg.__class__))
remote_cache.add(data_uuid, arg) remote_cache.add(data_uuid, arg)
result_args.append(data_uuid) result_args.append(data_uuid)
else: else:
...@@ -404,6 +399,7 @@ class ProcessStatistics(object): ...@@ -404,6 +399,7 @@ class ProcessStatistics(object):
self.queues[name].transfer_time += amount self.queues[name].transfer_time += amount
# TODO: implement an expiry time for cache items
class ProcessDataCache(object): class ProcessDataCache(object):
def __init__(self): def __init__(self):
...@@ -417,7 +413,6 @@ class ProcessDataCache(object): ...@@ -417,7 +413,6 @@ class ProcessDataCache(object):
def add(self, name, value): def add(self, name, value):
if isinstance(name, ProcessDataCacheItemID): if isinstance(name, ProcessDataCacheItemID):
name = name.value name = name.value
log.debug("Added cache item: %s - %s" % (name, type(value)))
self.cache[name] = value self.cache[name] = value
def get(self, name): def get(self, name):
...@@ -428,7 +423,6 @@ class ProcessDataCache(object): ...@@ -428,7 +423,6 @@ class ProcessDataCache(object):
def remove(self, name): def remove(self, name):
if isinstance(name, ProcessDataCacheItemID): if isinstance(name, ProcessDataCacheItemID):
name = name.value name = name.value
log.debug("Removed cache item: %s - %s" % (name, type(value)))
if name in self.cache: if name in self.cache:
del self.cache[name] del self.cache[name]
......
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