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()
# We need to use a global function here - otherwise it does not work with
# the multiprocessing Pool.
def _process_one_triangle(obj, triangle, z):
def _process_one_triangle(model, cutter, up_vector, triangle, z):
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
if triangle.maxz < z:
# Case 1a
return result
return result, None
# 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
return result
edge_collisions = obj.get_collision_waterline_of_triangle(triangle, z)
if not edge_collisions:
return result
return result, None
edge_collisions = get_collision_waterline_of_triangle(model, cutter, up_vector, triangle, z)
if edge_collisions is None:
# 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:
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 _DEBUG_DISBALE_WATERLINE_SHIFT:
result.append((edge, edge))
else:
result.append((edge, shifted_edge))
return result
return result, None
class CollisionPaths:
......@@ -286,9 +287,13 @@ class ContourFollow:
projected_waterlines = []
triangles = self.model.triangles(minx=minx, miny=miny, maxx=maxx,
maxy=maxy)
results_iter = run_in_parallel(_process_one_triangle,
[(self, t, z) for t in triangles], unordered=True)
for result in results_iter:
args = [(self.model, self.cutter, self._up_vector, t, z)
for t in triangles if not id(t) in self._processed_triangles]
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:
waterline_triangles.add(edge, shifted_edge)
if (not progress_counter is None) \
......@@ -304,18 +309,10 @@ class ContourFollow:
result.append(cropped_line)
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"
plane = Plane(Point(0, 0, z), self._up_vector)
plane = Plane(Point(0, 0, z), up_vector)
if triangle.minz >= z:
# no point of the triangle is below z
# try all edges
......@@ -330,13 +327,13 @@ class ContourFollow:
for index in range(3):
edge = Line(proj_points[index - 1], proj_points[index])
# 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)
edges.append((edge, proj_points[index - 2]))
outer_edges = []
for edge, other_point in edges:
# 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)
if len(outer_edges) == 0:
# the points seem to be an one line
......@@ -348,7 +345,7 @@ class ContourFollow:
outer_edges = [long_edge]
else:
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)
outer_edges = [edge]
else:
......@@ -383,7 +380,7 @@ class ContourFollow:
outer_edges = [waterline]
elif len(points_above) == 1:
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:
# Case (2b)
outer_edges = [waterline]
......@@ -394,7 +391,7 @@ class ContourFollow:
edges.append(Line(waterline.p2, other_point))
outer_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))
else:
outer_edges.append(edge)
......@@ -407,14 +404,14 @@ class ContourFollow:
edges.append(Line(waterline.p2, other_point))
edges.sort(key=lambda x: x.len)
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)]
else:
outer_edges = [edge]
else:
# two points above
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:
# Case (2b)
# the other two points are on the right side
......@@ -422,7 +419,7 @@ class ContourFollow:
elif dot < 0:
# Case (3a)
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)]
else:
outer_edges = [edge]
......@@ -438,16 +435,21 @@ class ContourFollow:
edges.append(Line(p1, p2))
edges.sort(key=lambda x: x.len)
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)]
else:
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 = []
for edge in outer_edges:
direction = self._up_vector.cross(edge.dir).normalized()
direction = up_vector.cross(edge.dir).normalized()
if direction is None:
continue
direction = direction.mul(self.get_max_length())
direction = direction.mul(max_length)
edge_dir = edge.p2.sub(edge.p1)
# 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
......@@ -456,7 +458,7 @@ class ContourFollow:
start = edge.p1.add(edge_dir.mul(factor))
# We need to use the triangle collision algorithm here - because we
# 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)
for index, coll in enumerate(collisions):
if (index % 2 == 0) and (not coll[1] is None) \
......@@ -479,14 +481,15 @@ class ContourFollow:
# Don't check triangles again that are completely above the z level and
# did not return any collisions.
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
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.
# This is necessary for calculating the horizontal distance between the
# 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)
if wl_proj.len < epsilon:
return None
......
......@@ -254,7 +254,6 @@ def run_in_parallel_remote(func, args_list, unordered=False,
results_queue = __manager.results()
remote_cache = __manager.cache()
stats = __manager.statistics()
local_cache = {}
for args in args_list:
start_time = time.time()
result_args = []
......@@ -262,12 +261,8 @@ def run_in_parallel_remote(func, args_list, unordered=False,
# add the argument to the cache if possible
if hasattr(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):
log.debug("Adding cache item for job %s: %s - %s" % (job_id, arg.uuid, arg.__class__))
remote_cache.add(data_uuid, arg)
result_args.append(data_uuid)
else:
......@@ -404,6 +399,7 @@ class ProcessStatistics(object):
self.queues[name].transfer_time += amount
# TODO: implement an expiry time for cache items
class ProcessDataCache(object):
def __init__(self):
......@@ -417,7 +413,6 @@ class ProcessDataCache(object):
def add(self, name, value):
if isinstance(name, ProcessDataCacheItemID):
name = name.value
log.debug("Added cache item: %s - %s" % (name, type(value)))
self.cache[name] = value
def get(self, name):
......@@ -428,7 +423,6 @@ class ProcessDataCache(object):
def remove(self, name):
if isinstance(name, ProcessDataCacheItemID):
name = name.value
log.debug("Removed cache item: %s - %s" % (name, type(value)))
if name in self.cache:
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