Commit 85c63cb1 authored by sumpfralle's avatar sumpfralle

added a Lock to prevent parallel access to the cutter's "moveto" function...

added a Lock to prevent parallel access to the cutter's "moveto" function (this would cause problems with the collision detection)
fixed a weird namespace issue in the startup script


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@729 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 02ce4015
...@@ -22,6 +22,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>. ...@@ -22,6 +22,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
""" """
import pycam.Utils.threading
from pycam.Geometry.Point import Point from pycam.Geometry.Point import Point
from pycam.Geometry.utils import number, INFINITE, epsilon from pycam.Geometry.utils import number, INFINITE, epsilon
from pycam.Geometry.intersection import intersect_circle_point, \ from pycam.Geometry.intersection import intersect_circle_point, \
...@@ -91,10 +92,15 @@ class BaseCutter(object): ...@@ -91,10 +92,15 @@ class BaseCutter(object):
def get_required_distance(self): def get_required_distance(self):
return self.required_distance return self.required_distance
def moveto(self, location): def moveto(self, location, keep_lock=False):
# "moveto" is used for collision detection calculation.
# We need to prevent multiple changes during one calculation.
pycam.Utils.threading.acquire_lock()
self.location = location self.location = location
for shape, set_pos_func in self.shape.values(): for shape, set_pos_func in self.shape.values():
set_pos_func(location.x, location.y, location.z) set_pos_func(location.x, location.y, location.z)
if not keep_lock:
pycam.Utils.threading.release_lock()
def intersect(self, direction, triangle): def intersect(self, direction, triangle):
raise NotImplementedError("Inherited class of BaseCutter does not " \ raise NotImplementedError("Inherited class of BaseCutter does not " \
......
...@@ -129,8 +129,8 @@ class CylindricalCutter(BaseCutter): ...@@ -129,8 +129,8 @@ class CylindricalCutter(BaseCutter):
GLU.gluDisk(self._disk, 0, self.radius, 10, 10) GLU.gluDisk(self._disk, 0, self.radius, 10, 10)
GL.glPopMatrix() GL.glPopMatrix()
def moveto(self, location): def moveto(self, location, **kwargs):
BaseCutter.moveto(self, location) BaseCutter.moveto(self, location, **kwargs)
self.center = Point(location.x, location.y, location.z - self.get_required_distance()) self.center = Point(location.x, location.y, location.z - self.get_required_distance())
def intersect_circle_plane(self, direction, triangle): def intersect_circle_plane(self, direction, triangle):
......
...@@ -137,8 +137,8 @@ class SphericalCutter(BaseCutter): ...@@ -137,8 +137,8 @@ class SphericalCutter(BaseCutter):
10, 10) 10, 10)
GL.glPopMatrix() GL.glPopMatrix()
def moveto(self, location): def moveto(self, location, **kwargs):
BaseCutter.moveto(self, location) BaseCutter.moveto(self, location, **kwargs)
self.center = Point(location.x, location.y, location.z + self.radius) self.center = Point(location.x, location.y, location.z + self.radius)
def intersect_sphere_plane(self, direction, triangle): def intersect_sphere_plane(self, direction, triangle):
......
...@@ -111,8 +111,8 @@ class ToroidalCutter(BaseCutter): ...@@ -111,8 +111,8 @@ class ToroidalCutter(BaseCutter):
GLU.gluDisk(self._disk, 0, self.majorradius, 20, 10) GLU.gluDisk(self._disk, 0, self.majorradius, 20, 10)
GL.glPopMatrix() GL.glPopMatrix()
def moveto(self, location): def moveto(self, location, **kwargs):
BaseCutter.moveto(self, location) BaseCutter.moveto(self, location, **kwargs)
self.center = Point(location.x, location.y, location.z+self.minorradius) self.center = Point(location.x, location.y, location.z+self.minorradius)
def intersect_torus_plane(self, direction, triangle): def intersect_torus_plane(self, direction, triangle):
......
...@@ -264,7 +264,6 @@ class ContourFollow: ...@@ -264,7 +264,6 @@ class ContourFollow:
self.pa.new_scanline() self.pa.new_scanline()
for p in points: for p in points:
self.pa.append(p) self.pa.append(p)
self.cutter.moveto(p)
if draw_callback: if draw_callback:
draw_callback(tool_position=p, toolpath=self.pa.paths) draw_callback(tool_position=p, toolpath=self.pa.paths)
last_position = p last_position = p
......
...@@ -151,7 +151,6 @@ class DropCutter: ...@@ -151,7 +151,6 @@ class DropCutter:
for p in points: for p in points:
self.pa.append(p) self.pa.append(p)
self.cutter.moveto(p)
# "draw_callback" returns true, if the user requested to quit # "draw_callback" returns true, if the user requested to quit
# via the GUI. # via the GUI.
# The progress counter may return True, if cancel was requested. # The progress counter may return True, if cancel was requested.
......
...@@ -162,7 +162,6 @@ class EngraveCutter: ...@@ -162,7 +162,6 @@ class EngraveCutter:
if points: if points:
for p in points: for p in points:
pa.append(p) pa.append(p)
self.cutter.moveto(p)
if draw_callback: if draw_callback:
draw_callback(tool_position=p, toolpath=pa.paths) draw_callback(tool_position=p, toolpath=pa.paths)
...@@ -206,7 +205,6 @@ class EngraveCutter: ...@@ -206,7 +205,6 @@ class EngraveCutter:
+ "of the boundary box: using a safe height " \ + "of the boundary box: using a safe height " \
+ "instead. This warning is reported only once.") + "instead. This warning is reported only once.")
self._boundary_warning_already_shown = True self._boundary_warning_already_shown = True
self.cutter.moveto(p)
# "draw_callback" returns true, if the user requested quitting via # "draw_callback" returns true, if the user requested quitting via
# the GUI. # the GUI.
if draw_callback \ if draw_callback \
......
...@@ -145,7 +145,6 @@ class PushCutter: ...@@ -145,7 +145,6 @@ class PushCutter:
self.pa.new_scanline() self.pa.new_scanline()
for p in points: for p in points:
self.pa.append(p) self.pa.append(p)
self.cutter.moveto(p)
if draw_callback: if draw_callback:
draw_callback(tool_position=p, toolpath=self.pa.paths) draw_callback(tool_position=p, toolpath=self.pa.paths)
self.pa.end_scanline() self.pa.end_scanline()
......
...@@ -25,6 +25,7 @@ __all__ = ["DropCutter", "PushCutter", "EngraveCutter", "ContourFollow"] ...@@ -25,6 +25,7 @@ __all__ = ["DropCutter", "PushCutter", "EngraveCutter", "ContourFollow"]
from pycam.Geometry.utils import INFINITE, epsilon, sqrt from pycam.Geometry.utils import INFINITE, epsilon, sqrt
from pycam.Geometry.Point import Point from pycam.Geometry.Point import Point
import pycam.Utils.threading
class Hit: class Hit:
...@@ -59,13 +60,14 @@ def get_free_paths_triangles(model, cutter, p1, p2, return_triangles=False): ...@@ -59,13 +60,14 @@ def get_free_paths_triangles(model, cutter, p1, p2, return_triangles=False):
maxy + cutter.distance_radius, INFINITE) maxy + cutter.distance_radius, INFINITE)
for t in triangles: for t in triangles:
cutter.moveto(p1) cutter.moveto(p1, keep_lock=True)
(cl, d, cp) = cutter.intersect(backward, t) (cl1, d1, cp1) = cutter.intersect(backward, t)
if cl: (cl2, d2, cp2) = cutter.intersect(forward, t)
hits.append(Hit(cl, cp, t, -d, backward)) pycam.Utils.threading.release_lock()
(cl, d, cp) = cutter.intersect(forward, t) if cl1:
if cl: hits.append(Hit(cl1, cp1, t, -d1, backward))
hits.append(Hit(cl, cp, t, d, forward)) if cl2:
hits.append(Hit(cl2, cp2, t, d2, forward))
# sort along the scan direction # sort along the scan direction
hits.sort(key=lambda h: h.d) hits.sort(key=lambda h: h.d)
...@@ -211,7 +213,6 @@ def get_max_height_triangles(model, cutter, x, y, minz, maxz, order=None, ...@@ -211,7 +213,6 @@ def get_max_height_triangles(model, cutter, x, y, minz, maxz, order=None,
height_max = None height_max = None
cut_max = None cut_max = None
triangle_max = None triangle_max = None
cutter.moveto(p)
box_x_min = cutter.minx box_x_min = cutter.minx
box_x_max = cutter.maxx box_x_max = cutter.maxx
box_y_min = cutter.miny box_y_min = cutter.miny
...@@ -220,12 +221,14 @@ def get_max_height_triangles(model, cutter, x, y, minz, maxz, order=None, ...@@ -220,12 +221,14 @@ def get_max_height_triangles(model, cutter, x, y, minz, maxz, order=None,
box_z_max = maxz box_z_max = maxz
triangles = model.triangles(box_x_min, box_y_min, box_z_min, box_x_max, triangles = model.triangles(box_x_min, box_y_min, box_z_min, box_x_max,
box_y_max, box_z_max) box_y_max, box_z_max)
cutter.moveto(p, keep_lock=True)
for t in triangles: for t in triangles:
cut = cutter.drop(t) cut = cutter.drop(t)
if cut and ((height_max is None) or (cut.z > height_max)): if cut and ((height_max is None) or (cut.z > height_max)):
height_max = cut.z height_max = cut.z
cut_max = cut cut_max = cut
triangle_max = t triangle_max = t
pycam.Utils.threading.release_lock()
# don't do a complete boundary check for the height # don't do a complete boundary check for the height
# this avoids zero-cuts for models that exceed the bounding box height # this avoids zero-cuts for models that exceed the bounding box height
if not cut_max or cut_max.z < minz + epsilon: if not cut_max or cut_max.z < minz + epsilon:
......
...@@ -21,6 +21,9 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>. ...@@ -21,6 +21,9 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
""" """
import pycam.Utils.log import pycam.Utils.log
# multiprocessing is imported later
#import multiprocessing
log = pycam.Utils.log.get_logger() log = pycam.Utils.log.get_logger()
...@@ -34,9 +37,11 @@ __multiprocessing = None ...@@ -34,9 +37,11 @@ __multiprocessing = None
# needs to be initialized, if multiprocessing is enabled # needs to be initialized, if multiprocessing is enabled
__num_of_processes = None __num_of_processes = None
__lock = None
def init_threading(number_of_processes=None): def init_threading(number_of_processes=None):
global __multiprocessing, __num_of_processes global __multiprocessing, __num_of_processes, __lock
try: try:
import multiprocessing import multiprocessing
mp_is_available = True mp_is_available = True
...@@ -62,6 +67,7 @@ def init_threading(number_of_processes=None): ...@@ -62,6 +67,7 @@ def init_threading(number_of_processes=None):
if __multiprocessing is False: if __multiprocessing is False:
log.info("Disabled multi-threading") log.info("Disabled multi-threading")
else: else:
__lock = multiprocessing.Lock()
log.info("Enabled multi-threading with %d parallel processes" % __num_of_processes) log.info("Enabled multi-threading with %d parallel processes" % __num_of_processes)
...@@ -86,3 +92,11 @@ def run_in_parallel(func, args, unordered=False, disable_multiprocessing=False): ...@@ -86,3 +92,11 @@ def run_in_parallel(func, args, unordered=False, disable_multiprocessing=False):
for arg in args: for arg in args:
yield func(arg) yield func(arg)
def acquire_lock():
if __multiprocessing:
__lock.acquire()
def release_lock():
if __multiprocessing:
__lock.release()
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