Commit ac3dd85c authored by sumpfralle's avatar sumpfralle

separated collision detection functions for later re-use


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@356 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent c6e15d92
...@@ -24,7 +24,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>. ...@@ -24,7 +24,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
from pycam.PathProcessors import * from pycam.PathProcessors import *
from pycam.Geometry import * from pycam.Geometry import *
from pycam.Geometry.utils import * from pycam.Geometry.utils import *
import pycam.PathGenerators from pycam.PathGenerators import drop_cutter_test, get_free_horizontal_paths_ode
from pycam.Exporters.SVGExporter import SVGExporter from pycam.Exporters.SVGExporter import SVGExporter
import math import math
...@@ -138,66 +138,6 @@ class PushCutter: ...@@ -138,66 +138,6 @@ class PushCutter:
return paths return paths
def get_free_paths_ode(self, minx, maxx, miny, maxy, z, depth=8):
""" Recursive function for splitting a line (usually along x or y) into
small pieces to gather connected paths for the PushCutter.
Strategy: check if the whole line is free (without collisions). Do a
recursive call (for the first and second half), if there was a
collision.
Usually either minx/maxx or miny/maxy should be equal, unless you want
to do a diagonal cut.
@param minx: lower limit of x
@type minx: float
@param maxx: upper limit of x; should equal minx for a cut along the x axis
@type maxx: float
@param miny: lower limit of y
@type miny: float
@param maxy: upper limit of y; should equal miny for a cut along the y axis
@type maxy: float
@param z: the fixed z level
@type z: float
@param depth: number of splits to be calculated via recursive calls; the
accuracy can be calculated as (maxx-minx)/(2^depth)
@type depth: int
@returns: a list of points that describe the tool path of the PushCutter;
each pair of points defines a collision-free path
@rtype: list(pycam.Geometry.Point.Point)
"""
points = []
# "resize" the drill along the while x/y range and check for a collision
self.physics.extend_drill(maxx-minx, maxy-miny, 0.0)
self.physics.set_drill_position((minx, miny, z))
if self.physics.check_collision():
# collision detected
if depth > 0:
middle_x = (minx + maxx)/2.0
middle_y = (miny + maxy)/2.0
group1 = self.get_free_paths_ode(minx, middle_x, miny, middle_y, z, depth-1)
group2 = self.get_free_paths_ode(middle_x, maxx, middle_y, maxy, z, depth-1)
if group1 and group2 and (group1[-1].x == group2[0].x) and (group1[-1].y == group2[0].y):
# the last couple of the first group ends where the first couple of the second group starts
# we will combine them into one couple
last = group1[-2]
first = group2[1]
combined = [last, first]
points.extend(group1[:-2])
points.extend(combined)
points.extend(group2[2:])
else:
# the two groups are not connected - just add both
points.extend(group1)
points.extend(group2)
else:
# no points to be added
pass
else:
# no collision - the line is free
points.append(Point(minx, miny, z))
points.append(Point(maxx, maxy, z))
self.physics.reset_drill()
return points
def GenerateToolPathSlice_ode(self, minx, maxx, miny, maxy, z, dx, dy, def GenerateToolPathSlice_ode(self, minx, maxx, miny, maxy, z, dx, dy,
draw_callback=None, progress_counter=None): draw_callback=None, progress_counter=None):
""" only dx or (exclusive!) dy may be bigger than zero """ only dx or (exclusive!) dy may be bigger than zero
...@@ -224,9 +164,9 @@ class PushCutter: ...@@ -224,9 +164,9 @@ class PushCutter:
self.pa.new_scanline() self.pa.new_scanline()
if dx > 0: if dx > 0:
points = self.get_free_paths_ode(x, x, miny, maxy, z, depth=depth_x) points = get_free_horizontal_paths_ode(self.physics, x, x, miny, maxy, z, depth=depth_x)
else: else:
points = self.get_free_paths_ode(minx, maxx, y, y, z, depth=depth_y) points = get_free_horizontal_paths_ode(self.physics, minx, maxx, y, y, z, depth=depth_y)
for p in points: for p in points:
self.pa.append(p) self.pa.append(p)
...@@ -254,19 +194,6 @@ class PushCutter: ...@@ -254,19 +194,6 @@ class PushCutter:
draw_callback(percent=progress_counter.get_percent()) draw_callback(percent=progress_counter.get_percent())
def DropCutterTest(self, point, model):
zmax = -INFINITE
tmax = None
c = self.cutter
c.moveto(point)
for t in model.triangles():
if t.normal().z < 0: continue
cl = c.drop(t)
if cl and cl.z > zmax and cl.z < INFINITE:
zmax = cl.z
tmax = t
return (zmax, tmax)
def GenerateToolPathSlice_triangles(self, minx, maxx, miny, maxy, z, dx, dy, def GenerateToolPathSlice_triangles(self, minx, maxx, miny, maxy, z, dx, dy,
draw_callback=None, progress_counter=None): draw_callback=None, progress_counter=None):
global DEBUG_PUSHCUTTER, DEBUG_PUSHCUTTER2, DEBUG_PUSHCUTTER3 global DEBUG_PUSHCUTTER, DEBUG_PUSHCUTTER2, DEBUG_PUSHCUTTER3
...@@ -379,7 +306,7 @@ class PushCutter: ...@@ -379,7 +306,7 @@ class PushCutter:
# determine height at each interesting point # determine height at each interesting point
for h in hits: for h in hits:
(zmax, tmax) = self.DropCutterTest(h.cl, model) (zmax, tmax) = drop_cutter_test(self.cutter, h.cl, model)
h.z = zmax h.z = zmax
if DEBUG_PUSHCUTTER: print "@ cl=",h.cl,",d=",h.d,",z=",h.z if DEBUG_PUSHCUTTER: print "@ cl=",h.cl,",d=",h.d,",z=",h.z
if DEBUG_PUSHCUTTER3: self.svg.fill("blue"); self.svg.AddDot(h.cl.x, h.z) if DEBUG_PUSHCUTTER3: self.svg.fill("blue"); self.svg.AddDot(h.cl.x, h.z)
......
...@@ -20,9 +20,84 @@ You should have received a copy of the GNU General Public License ...@@ -20,9 +20,84 @@ You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>. along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
""" """
list = ["DropCutter", "PushCutter"] __all__ = ["DropCutter", "PushCutter"]
__all__ = list
from DropCutter import DropCutter from pycam.Geometry.utils import INFINITE
from PushCutter import PushCutter from pycam.Geometry import Point
def get_free_horizontal_paths_ode(physics, minx, maxx, miny, maxy, z, depth=8):
""" Recursive function for splitting a line (usually along x or y) into
small pieces to gather connected paths for the PushCutter.
Strategy: check if the whole line is free (without collisions). Do a
recursive call (for the first and second half), if there was a
collision.
Usually either minx/maxx or miny/maxy should be equal, unless you want
to do a diagonal cut.
@param minx: lower limit of x
@type minx: float
@param maxx: upper limit of x; should equal minx for a cut along the x axis
@type maxx: float
@param miny: lower limit of y
@type miny: float
@param maxy: upper limit of y; should equal miny for a cut along the y axis
@type maxy: float
@param z: the fixed z level
@type z: float
@param depth: number of splits to be calculated via recursive calls; the
accuracy can be calculated as (maxx-minx)/(2^depth)
@type depth: int
@returns: a list of points that describe the tool path of the PushCutter;
each pair of points defines a collision-free path
@rtype: list(pycam.Geometry.Point.Point)
"""
points = []
# "resize" the drill along the while x/y range and check for a collision
physics.extend_drill(maxx-minx, maxy-miny, 0.0)
physics.set_drill_position((minx, miny, z))
if physics.check_collision():
# collision detected
if depth > 0:
middle_x = (minx + maxx)/2.0
middle_y = (miny + maxy)/2.0
group1 = get_free_horizontal_paths_ode(physics, minx, middle_x,
miny, middle_y, z, depth-1)
group2 = get_free_horizontal_paths_ode(physics, middle_x, maxx,
middle_y, maxy, z, depth-1)
if group1 and group2 and (group1[-1].x == group2[0].x) and (group1[-1].y == group2[0].y):
# the last couple of the first group ends where the first couple of the second group starts
# we will combine them into one couple
last = group1[-2]
first = group2[1]
combined = [last, first]
points.extend(group1[:-2])
points.extend(combined)
points.extend(group2[2:])
else:
# the two groups are not connected - just add both
points.extend(group1)
points.extend(group2)
else:
# no points to be added
pass
else:
# no collision - the line is free
points.append(Point(minx, miny, z))
points.append(Point(maxx, maxy, z))
physics.reset_drill()
return points
def drop_cutter_test(cutter, point, model):
zmax = -INFINITE
tmax = None
c = cutter
c.moveto(point)
for t in model.triangles():
if t.normal().z < 0: continue
cl = c.drop(t)
if cl and cl.z > zmax and cl.z < INFINITE:
zmax = cl.z
tmax = t
return (zmax, tmax)
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