Commit 09ad8c60 authored by sumpfralle's avatar sumpfralle

separated the collision detection functions for DropCutter


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@362 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 322f3b37
......@@ -25,6 +25,7 @@ from pycam.PathProcessors import *
from pycam.Geometry import *
from pycam.Geometry.intersection import intersect_lines
from pycam.Geometry.utils import INFINITE
from pycam.PathGenerators import get_max_height_triangles, get_max_height_ode
import math
import sys
......@@ -67,9 +68,6 @@ class DropCutter:
self.processor = PathProcessor
self.physics = physics
self.safety_height = safety_height
# used for the non-ode code
self._triangle_last = None
self._cut_last = None
# remember if we already reported an invalid boundary
self._boundary_warning_already_shown = False
......@@ -109,8 +107,7 @@ class DropCutter:
finished_line = False
dims[0].set(dims[0].start)
pa.new_scanline()
self._triangle_last = None
self._cut_last = None
last_position = None
if draw_callback and draw_callback(text="DropCutter: processing line %d/%d" \
% (current_line, num_of_lines),
......@@ -120,9 +117,12 @@ class DropCutter:
while not finished_line:
if self.physics:
points = self.get_max_height_with_ode(dims[x].get(), dims[y].get(), minz, maxz, order=dim_attrs[:])
points = get_max_height_ode(self.physics, dims[x].get(),
dims[y].get(), minz, maxz, order=dim_attrs[:])
else:
points = self.get_max_height_manually(dims[x].get(), dims[y].get(), minz, maxz, order=dim_attrs[:])
points = get_max_height_triangles(self.model, self.cutter,
dims[x].get(), dims[y].get(), minz, maxz,
order=dim_attrs[:], last_pos=last_position)
if points:
for p in points:
......@@ -136,7 +136,7 @@ class DropCutter:
+ "instead. This warning is reported only once."
self._boundary_warning_already_shown = True
self.cutter.moveto(p)
# "draw_callback" returns true, if the user requested a break via the GUI
# "draw_callback" returns true, if the user requested quitting via the GUI
if draw_callback and draw_callback(tool_position=p):
finished_line = True
......@@ -169,111 +169,3 @@ class DropCutter:
pa.finish()
return pa.paths
def get_max_height_with_ode(self, x, y, minz, maxz, order=None):
low, high = minz, maxz
trip_start = 20
safe_z = None
# check if the full step-down would be ok
self.physics.set_drill_position((x, y, minz))
if self.physics.check_collision():
# there is an object between z1 and z0 - we need more=None loops
trips = trip_start
else:
# no need for further collision detection - we can go down the whole range z1..z0
trips = 0
safe_z = minz
while trips > 0:
current_z = (low + high) / 2.0
self.physics.set_drill_position((x, y, current_z))
if self.physics.check_collision():
low = current_z
else:
high = current_z
safe_z = current_z
trips -= 1
if safe_z is None:
# no safe position was found - let's check the upper bound
self.physics.set_drill_position((x, y, maxz))
if self.physics.check_collision():
# the object fills the whole range of z0..z1 -> no safe height
pass
else:
# at least the upper bound is collision free
safe_z = maxz
if safe_z is None:
return []
else:
return [Point(x, y, safe_z)]
def get_max_height_manually(self, x, y, minz, maxz, order=None):
result = []
if order is None:
order = ["x", "y"]
p = Point(x, y, maxz)
height_max = None
cut_max = None
triangle_max = None
self.cutter.moveto(p)
box_x_min = self.cutter.minx
box_x_max = self.cutter.maxx
box_y_min = self.cutter.miny
box_y_max = self.cutter.maxy
box_z_min = minz
box_z_max = self.safety_height
triangles = self.model.triangles(box_x_min, box_y_min, box_z_min, box_x_max, box_y_max, box_z_max)
for t in triangles:
if t.normal().z < 0: continue;
cut = self.cutter.drop(t)
if cut and (cut.z > height_max or height_max is None):
height_max = cut.z
cut_max = cut
triangle_max = t
# don't do a complete boundary check for the height
# this avoids zero-cuts for models that exceed the bounding box height
if not cut_max or cut_max.z < minz:
cut_max = Point(x, y, minz)
if self._cut_last and ((triangle_max and not self._triangle_last) or (self._triangle_last and not triangle_max)):
if minz <= self._cut_last.z <= maxz:
result.append(Point(self._cut_last.x, self._cut_last.y, cut_max.z))
else:
result.append(Point(cut_max.x, cut_max.y, self._cut_last.z))
elif (triangle_max and self._triangle_last and self._cut_last and cut_max) and (triangle_max != self._triangle_last):
nl = range(3)
nl[0] = -getattr(self._triangle_last.normal(), order[0])
nl[2] = self._triangle_last.normal().z
nm = range(3)
nm[0] = -getattr(triangle_max.normal(), order[0])
nm[2] = triangle_max.normal().z
last = range(3)
last[0] = getattr(self._cut_last, order[0])
last[2] = self._cut_last.z
mx = range(3)
mx[0] = getattr(cut_max, order[0])
mx[2] = cut_max.z
c = range(3)
(c[0], c[2]) = intersect_lines(last[0], last[2], nl[0], nl[2], mx[0], mx[2], nm[0], nm[2])
if c[0] and last[0] < c[0] and c[0] < mx[0] and (c[2] > last[2] or c[2] > mx[2]):
c[1] = getattr(self._cut_last, order[1])
if c[2]<minz-10 or c[2]>maxz+10:
print "^", "%sl=%s" % (order[0], last[0]), \
", %sl=%s" % ("z", last[2]), \
", n%sl=%s" % (order[0], nl[0]), \
", n%sl=%s" % ("z", nl[2]), \
", %s=%s" % (order[0].upper(), c[0]), \
", %s=%s" % ("z".upper(), c[2]), \
", %sm=%s" % (order[0], mx[0]), \
", %sm=%s" % ("z", mx[2]), \
", n%sm=%s" % (order[0], nm[0]), \
", n%sm=%s" % ("z", nm[2])
else:
if order[0] == "x":
result.append(Point(c[0], c[1], c[2]))
else:
result.append(Point(c[1], c[0], c[2]))
result.append(cut_max)
self._cut_last = cut_max
self._triangle_last = triangle_max
return result
......@@ -192,3 +192,118 @@ def drop_cutter_test(cutter, point, model):
tmax = t
return (zmax, tmax)
def get_max_height_ode(physics, x, y, minz, maxz, order=None):
low, high = minz, maxz
trip_start = 20
safe_z = None
# check if the full step-down would be ok
physics.set_drill_position((x, y, minz))
if physics.check_collision():
# there is an object between z1 and z0 - we need more=None loops
trips = trip_start
else:
# no need for further collision detection - we can go down the whole range z1..z0
trips = 0
safe_z = minz
while trips > 0:
current_z = (low + high) / 2.0
physics.set_drill_position((x, y, current_z))
if physics.check_collision():
low = current_z
else:
high = current_z
safe_z = current_z
trips -= 1
if safe_z is None:
# no safe position was found - let's check the upper bound
physics.set_drill_position((x, y, maxz))
if physics.check_collision():
# the object fills the whole range of z0..z1 -> no safe height
pass
else:
# at least the upper bound is collision free
safe_z = maxz
if safe_z is None:
return []
else:
return [Point(x, y, safe_z)]
def get_max_height_triangles(model, cutter, x, y, minz, maxz, order=None, last_pos=None):
result = []
if last_pos is None:
last_pos = {}
for key in ("triangle", "cut"):
if not key in last_pos:
last_pos[key] = None
if order is None:
order = ["x", "y"]
p = Point(x, y, maxz)
height_max = None
cut_max = None
triangle_max = None
cutter.moveto(p)
box_x_min = cutter.minx
box_x_max = cutter.maxx
box_y_min = cutter.miny
box_y_max = cutter.maxy
box_z_min = minz
box_z_max = maxz
triangles = model.triangles(box_x_min, box_y_min, box_z_min, box_x_max, box_y_max, box_z_max)
for t in triangles:
if t.normal().z < 0: continue;
cut = cutter.drop(t)
if cut and (cut.z > height_max or height_max is None):
height_max = cut.z
cut_max = cut
triangle_max = t
# don't do a complete boundary check for the height
# this avoids zero-cuts for models that exceed the bounding box height
if not cut_max or cut_max.z < minz:
cut_max = Point(x, y, minz)
if last_pos["cut"] and \
((triangle_max and not last_pos["triangle"]) \
or (last_pos["triangle"] and not triangle_max)):
if minz <= last_pos["cut"].z <= maxz:
result.append(Point(last_pos["cut"].x, last_pos["cut"].y, cut_max.z))
else:
result.append(Point(cut_max.x, cut_max.y, last_pos["cut"].z))
elif (triangle_max and last_pos["triangle"] and last_pos["cut"] and cut_max) and (triangle_max != last_pos["triangle"]):
nl = range(3)
nl[0] = -getattr(last_pos["triangle"].normal(), order[0])
nl[2] = last_pos["triangle"].normal().z
nm = range(3)
nm[0] = -getattr(triangle_max.normal(), order[0])
nm[2] = triangle_max.normal().z
last = range(3)
last[0] = getattr(last_pos["cut"], order[0])
last[2] = last_pos["cut"].z
mx = range(3)
mx[0] = getattr(cut_max, order[0])
mx[2] = cut_max.z
c = range(3)
(c[0], c[2]) = intersect_lines(last[0], last[2], nl[0], nl[2], mx[0], mx[2], nm[0], nm[2])
if c[0] and last[0] < c[0] and c[0] < mx[0] and (c[2] > last[2] or c[2] > mx[2]):
c[1] = getattr(last_pos["cut"], order[1])
if c[2]<minz-10 or c[2]>maxz+10:
print "^", "%sl=%s" % (order[0], last[0]), \
", %sl=%s" % ("z", last[2]), \
", n%sl=%s" % (order[0], nl[0]), \
", n%sl=%s" % ("z", nl[2]), \
", %s=%s" % (order[0].upper(), c[0]), \
", %s=%s" % ("z".upper(), c[2]), \
", %sm=%s" % (order[0], mx[0]), \
", %sm=%s" % ("z", mx[2]), \
", n%sm=%s" % (order[0], nm[0]), \
", n%sm=%s" % ("z", nm[2])
else:
if order[0] == "x":
result.append(Point(c[0], c[1], c[2]))
else:
result.append(Point(c[1], c[0], c[2]))
result.append(cut_max)
last_pos["cut"] = cut_max
last_pos["triangle"] = triangle_max
return result
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