Commit ef92a990 authored by sumpfralle's avatar sumpfralle

allow a stateless cutter intersection test with an optional position parameter


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@732 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 0e747819
......@@ -47,26 +47,28 @@ class BaseCutter(object):
self.required_distance = 0
self.distance_radius = self.radius
self.distance_radiussq = self.distance_radius ** 2
# self.minx, self.maxx, self.miny and self.maxy are defined as
# properties below
self.shape = {}
self.moveto(location)
def _get_minx(self):
def get_minx(self, start=None):
if start is None:
start = self.location
return self.location.x - self.distance_radius
minx = property(_get_minx)
def _get_maxx(self):
def get_maxx(self, start=None):
if start is None:
start = self.location
return self.location.x + self.distance_radius
maxx = property(_get_maxx)
def _get_miny(self):
def get_miny(self, start=None):
if start is None:
start = self.location
return self.location.y - self.distance_radius
miny = property(_get_miny)
def _get_maxy(self):
def get_maxy(self, start=None):
if start is None:
start = self.location
return self.location.y + self.distance_radius
maxy = property(_get_maxy)
def __repr__(self):
return "BaseCutter"
......@@ -102,24 +104,26 @@ class BaseCutter(object):
if not keep_lock:
pycam.Utils.threading.release_lock()
def intersect(self, direction, triangle):
def intersect(self, direction, triangle, start=None):
raise NotImplementedError("Inherited class of BaseCutter does not " \
+ "implement the required function 'intersect'.")
def drop(self, triangle):
def drop(self, triangle, start=None):
if start is None:
start = self.location
# check bounding box collision
if self.minx > triangle.maxx + epsilon:
if self.get_minx(start) > triangle.maxx + epsilon:
return None
if self.maxx < triangle.minx - epsilon:
if self.get_maxx(start) < triangle.minx - epsilon:
return None
if self.miny > triangle.maxy + epsilon:
if self.get_miny(start) > triangle.maxy + epsilon:
return None
if self.maxy < triangle.miny - epsilon:
if self.get_maxy(start) < triangle.miny - epsilon:
return None
# check bounding circle collision
c = triangle.middle
if (c.x - self.location.x) ** 2 + (c.y - self.location.y) ** 2 \
if (c.x - start.x) ** 2 + (c.y - start.y) ** 2 \
> (self.distance_radiussq + 2 * self.distance_radius \
* triangle.radius + triangle.radiussq) + epsilon:
return None
......@@ -127,18 +131,21 @@ class BaseCutter(object):
(cl, d, cp) = self.intersect(BaseCutter.vertical, triangle)
return cl
def intersect_circle_triangle(self, direction, triangle):
(cl, ccp, cp, d) = self.intersect_circle_plane(direction, triangle)
def intersect_circle_triangle(self, direction, triangle, start=None):
(cl, ccp, cp, d) = self.intersect_circle_plane(direction, triangle,
start=start)
if cp and triangle.is_point_inside(cp):
return (cl, d, cp)
return (None, INFINITE, None)
def intersect_circle_vertex(self, direction, point):
(cl, ccp, cp, l) = self.intersect_circle_point(direction, point)
def intersect_circle_vertex(self, direction, point, start=None):
(cl, ccp, cp, l) = self.intersect_circle_point(direction, point,
start=start)
return (cl, l, cp)
def intersect_circle_edge(self, direction, edge):
(cl, ccp, cp, l) = self.intersect_circle_line(direction, edge)
def intersect_circle_edge(self, direction, edge, start=None):
(cl, ccp, cp, l) = self.intersect_circle_line(direction, edge,
start=start)
if cp:
# check if the contact point is between the endpoints
m = cp.sub(edge.p1).dot(edge.dir)
......@@ -146,38 +153,50 @@ class BaseCutter(object):
return (None, INFINITE, cp)
return (cl, l, cp)
def intersect_cylinder_point(self, direction, point):
(ccp, cp, l) = intersect_cylinder_point(self.center, self.axis,
def intersect_cylinder_point(self, direction, point, start=None):
if start is None:
start = self.location
(ccp, cp, l) = intersect_cylinder_point(
start.sub(self.location).add(self.center), self.axis,
self.distance_radius, self.distance_radiussq, direction, point)
# offset intersection
if ccp:
cl = cp.add(self.location.sub(ccp))
cl = cp.add(start.sub(ccp))
return (cl, ccp, cp, l)
return (None, None, None, INFINITE)
def intersect_cylinder_vertex(self, direction, point):
(cl, ccp, cp, l) = self.intersect_cylinder_point(direction, point)
if ccp and ccp.z < self.center.z:
def intersect_cylinder_vertex(self, direction, point, start=None):
if start is None:
start = self.location
(cl, ccp, cp, l) = self.intersect_cylinder_point(direction, point,
start=start)
if ccp and ccp.z < start.sub(self.location).add(self.center).z:
return (None, INFINITE, None)
return (cl, l, cp)
def intersect_cylinder_line(self, direction, edge):
(ccp, cp, l) = intersect_cylinder_line(self.center, self.axis,
def intersect_cylinder_line(self, direction, edge, start=None):
if start is None:
start = self.location
(ccp, cp, l) = intersect_cylinder_line(
start.sub(self.location).add(self.center), self.axis,
self.distance_radius, self.distance_radiussq, direction, edge)
# offset intersection
if ccp:
cl = self.location.add(cp.sub(ccp))
cl = start.add(cp.sub(ccp))
return (cl, ccp, cp, l)
return (None, None, None, INFINITE)
def intersect_cylinder_edge(self, direction, edge):
(cl, ccp, cp, l) = self.intersect_cylinder_line(direction, edge)
def intersect_cylinder_edge(self, direction, edge, start=None):
if start is None:
start = self.location
(cl, ccp, cp, l) = self.intersect_cylinder_line(direction, edge,
start=start)
if not ccp:
return (None, INFINITE, None)
m = cp.sub(edge.p1).dot(edge.dir)
if (m < -epsilon) or (m > edge.len + epsilon):
return (None, INFINITE, None)
if ccp.z < self.center.z:
if ccp.z < start.sub(self.location).add(self.center).z:
return (None, INFINITE, None)
return (cl, l, cp)
......@@ -133,36 +133,46 @@ class CylindricalCutter(BaseCutter):
BaseCutter.moveto(self, location, **kwargs)
self.center = Point(location.x, location.y, location.z - self.get_required_distance())
def intersect_circle_plane(self, direction, triangle):
(ccp, cp, d) = intersect_circle_plane(self.center, self.distance_radius,
def intersect_circle_plane(self, direction, triangle, start=None):
if start is None:
start = self.location
(ccp, cp, d) = intersect_circle_plane(
start.sub(self.location).add(self.center), self.distance_radius,
direction, triangle)
if ccp and cp:
cl = cp.add(self.location.sub(ccp))
cl = cp.add(start.sub(ccp))
return (cl, ccp, cp, d)
return (None, None, None, INFINITE)
def intersect_circle_point(self, direction, point):
(ccp, cp, l) = intersect_circle_point(self.center, self.axis,
def intersect_circle_point(self, direction, point, start=None):
if start is None:
start = self.location
(ccp, cp, l) = intersect_circle_point(
start.sub(self.location).add(self.center), self.axis,
self.distance_radius, self.distance_radiussq, direction, point)
if ccp:
cl = cp.add(self.location.sub(ccp))
cl = cp.add(start.sub(ccp))
return (cl, ccp, cp, l)
return (None, None, None, INFINITE)
def intersect_circle_line(self, direction, edge):
(ccp, cp, l) = intersect_circle_line(self.center, self.axis,
def intersect_circle_line(self, direction, edge, start=None):
if start is None:
start = self.location
(ccp, cp, l) = intersect_circle_line(
start.sub(self.location).add(self.center), self.axis,
self.distance_radius, self.distance_radiussq, direction, edge)
if ccp:
cl = cp.add(self.location.sub(ccp))
cl = cp.add(start.sub(ccp))
return (cl, ccp, cp, l)
return (None, None, None, INFINITE)
def intersect_plane(self, direction, triangle):
def intersect_plane(self, direction, triangle, start=None):
# TODO: are "intersect_plane" and "self.intersect_circle_plane" obsolete?
return self.intersect_circle_plane(direction, triangle)
return self.intersect_circle_plane(direction, triangle, start=start)
def intersect(self, direction, triangle):
(cl_t, d_t, cp_t) = self.intersect_circle_triangle(direction, triangle)
def intersect(self, direction, triangle, start=None):
(cl_t, d_t, cp_t) = self.intersect_circle_triangle(direction, triangle,
start=start)
d = INFINITE
cl = None
cp = None
......@@ -172,9 +182,12 @@ class CylindricalCutter(BaseCutter):
cp = cp_t
if cl and (direction.x == 0) and (direction.y == 0):
return (cl, d, cp)
(cl_e1, d_e1, cp_e1) = self.intersect_circle_edge(direction, triangle.e1)
(cl_e2, d_e2, cp_e2) = self.intersect_circle_edge(direction, triangle.e2)
(cl_e3, d_e3, cp_e3) = self.intersect_circle_edge(direction, triangle.e3)
(cl_e1, d_e1, cp_e1) = self.intersect_circle_edge(direction,
triangle.e1, start=start)
(cl_e2, d_e2, cp_e2) = self.intersect_circle_edge(direction,
triangle.e2, start=start)
(cl_e3, d_e3, cp_e3) = self.intersect_circle_edge(direction,
triangle.e3, start=start)
if d_e1 < d:
d = d_e1
cl = cl_e1
......@@ -189,9 +202,12 @@ class CylindricalCutter(BaseCutter):
cp = cp_e3
if cl and (direction.x == 0) and (direction.y == 0):
return (cl, d, cp)
(cl_p1, d_p1, cp_p1) = self.intersect_circle_vertex(direction, triangle.p1)
(cl_p2, d_p2, cp_p2) = self.intersect_circle_vertex(direction, triangle.p2)
(cl_p3, d_p3, cp_p3) = self.intersect_circle_vertex(direction, triangle.p3)
(cl_p1, d_p1, cp_p1) = self.intersect_circle_vertex(direction,
triangle.p1, start=start)
(cl_p2, d_p2, cp_p2) = self.intersect_circle_vertex(direction,
triangle.p2, start=start)
(cl_p3, d_p3, cp_p3) = self.intersect_circle_vertex(direction,
triangle.p3, start=start)
if d_p1 < d:
d = d_p1
cl = cl_p1
......@@ -208,11 +224,11 @@ class CylindricalCutter(BaseCutter):
return (cl, d, cp)
if (direction.x != 0) or (direction.y != 0):
(cl_p1, d_p1, cp_p1) = self.intersect_cylinder_vertex(direction,
triangle.p1)
triangle.p1, start=start)
(cl_p2, d_p2, cp_p2) = self.intersect_cylinder_vertex(direction,
triangle.p2)
triangle.p2, start=start)
(cl_p3, d_p3, cp_p3) = self.intersect_cylinder_vertex(direction,
triangle.p3)
triangle.p3, start=start)
if d_p1 < d:
d = d_p1
cl = cl_p1
......@@ -225,9 +241,12 @@ class CylindricalCutter(BaseCutter):
d = d_p3
cl = cl_p3
cp = cp_p3
(cl_e1, d_e1, cp_e1) = self.intersect_cylinder_edge(direction, triangle.e1)
(cl_e2, d_e2, cp_e2) = self.intersect_cylinder_edge(direction, triangle.e2)
(cl_e3, d_e3, cp_e3) = self.intersect_cylinder_edge(direction, triangle.e3)
(cl_e1, d_e1, cp_e1) = self.intersect_cylinder_edge(direction,
triangle.e1, start=start)
(cl_e2, d_e2, cp_e2) = self.intersect_cylinder_edge(direction,
triangle.e2, start=start)
(cl_e3, d_e3, cp_e3) = self.intersect_cylinder_edge(direction,
triangle.e3, start=start)
if d_e1 < d:
d = d_e1
cl = cl_e1
......
......@@ -141,45 +141,57 @@ class SphericalCutter(BaseCutter):
BaseCutter.moveto(self, location, **kwargs)
self.center = Point(location.x, location.y, location.z + self.radius)
def intersect_sphere_plane(self, direction, triangle):
(ccp, cp, d) = intersect_sphere_plane(self.center, self.distance_radius,
def intersect_sphere_plane(self, direction, triangle, start=None):
if start is None:
start = self.location
(ccp, cp, d) = intersect_sphere_plane(
start.sub(self.location).add(self.center), self.distance_radius,
direction, triangle)
# offset intersection
if ccp:
cl = cp.add(self.location.sub(ccp))
cl = cp.add(start.sub(ccp))
return (cl, ccp, cp, d)
return (None, None, None, INFINITE)
def intersect_sphere_triangle(self, direction, triangle):
(cl, ccp, cp, d) = self.intersect_sphere_plane(direction, triangle)
def intersect_sphere_triangle(self, direction, triangle, start=None):
(cl, ccp, cp, d) = self.intersect_sphere_plane(direction, triangle,
start=start)
if cp and triangle.is_point_inside(cp):
return (cl, d, cp)
return (None, INFINITE, None)
def intersect_sphere_point(self, direction, point):
(ccp, cp, l) = intersect_sphere_point(self.center, self.distance_radius,
def intersect_sphere_point(self, direction, point, start=None):
if start is None:
start = self.location
(ccp, cp, l) = intersect_sphere_point(
start.sub(self.location).add(self.center), self.distance_radius,
self.distance_radiussq, direction, point)
# offset intersection
cl = None
if cp:
cl = self.location.add(direction.mul(l))
cl = start.add(direction.mul(l))
return (cl, ccp, cp, l)
def intersect_sphere_vertex(self, direction, point):
(cl, ccp, cp, l) = self.intersect_sphere_point(direction, point)
def intersect_sphere_vertex(self, direction, point, start=None):
(cl, ccp, cp, l) = self.intersect_sphere_point(direction, point,
start=start)
return (cl, l, cp)
def intersect_sphere_line(self, direction, edge):
(ccp, cp, l) = intersect_sphere_line(self.center, self.distance_radius,
def intersect_sphere_line(self, direction, edge, start=None):
if start is None:
start = self.location
(ccp, cp, l) = intersect_sphere_line(
start.sub(self.location).add(self.center), self.distance_radius,
self.distance_radiussq, direction, edge)
# offset intersection
if ccp:
cl = cp.sub(ccp.sub(self.location))
cl = cp.sub(ccp.sub(start))
return (cl, ccp, cp, l)
return (None, None, None, INFINITE)
def intersect_sphere_edge(self, direction, edge):
(cl, ccp, cp, l) = self.intersect_sphere_line(direction, edge)
def intersect_sphere_edge(self, direction, edge, start=None):
(cl, ccp, cp, l) = self.intersect_sphere_line(direction, edge,
start=start)
if cp:
# check if the contact point is between the endpoints
d = edge.p2.sub(edge.p1)
......@@ -188,12 +200,13 @@ class SphericalCutter(BaseCutter):
return (None, INFINITE, None)
return (cl, l, cp)
def intersect_point(self, direction, point):
def intersect_point(self, direction, point, start=None):
# TODO: probably obsolete?
return self.intersect_sphere_point(direction, point)
return self.intersect_sphere_point(direction, point, start=start)
def intersect(self, direction, triangle):
(cl_t, d_t, cp_t) = self.intersect_sphere_triangle(direction, triangle)
def intersect(self, direction, triangle, start=None):
(cl_t, d_t, cp_t) = self.intersect_sphere_triangle(direction, triangle,
start=start)
d = INFINITE
cl = None
cp = None
......@@ -203,9 +216,12 @@ class SphericalCutter(BaseCutter):
cp = cp_t
if cl and (direction.x == 0) and (direction.y == 0):
return (cl, d, cp)
(cl_e1, d_e1, cp_e1) = self.intersect_sphere_edge(direction, triangle.e1)
(cl_e2, d_e2, cp_e2) = self.intersect_sphere_edge(direction, triangle.e2)
(cl_e3, d_e3, cp_e3) = self.intersect_sphere_edge(direction, triangle.e3)
(cl_e1, d_e1, cp_e1) = self.intersect_sphere_edge(direction,
triangle.e1, start=start)
(cl_e2, d_e2, cp_e2) = self.intersect_sphere_edge(direction,
triangle.e2, start=start)
(cl_e3, d_e3, cp_e3) = self.intersect_sphere_edge(direction,
triangle.e3, start=start)
if d_e1 < d:
d = d_e1
cl = cl_e1
......@@ -220,9 +236,12 @@ class SphericalCutter(BaseCutter):
cp = cp_e3
if cl and (direction.x == 0) and (direction.y == 0):
return (cl, d, cp)
(cl_p1, d_p1, cp_p1) = self.intersect_sphere_vertex(direction, triangle.p1)
(cl_p2, d_p2, cp_p2) = self.intersect_sphere_vertex(direction, triangle.p2)
(cl_p3, d_p3, cp_p3) = self.intersect_sphere_vertex(direction, triangle.p3)
(cl_p1, d_p1, cp_p1) = self.intersect_sphere_vertex(direction,
triangle.p1, start=start)
(cl_p2, d_p2, cp_p2) = self.intersect_sphere_vertex(direction,
triangle.p2, start=start)
(cl_p3, d_p3, cp_p3) = self.intersect_sphere_vertex(direction,
triangle.p3, start=start)
if d_p1 < d:
d = d_p1
cl = cl_p1
......@@ -239,11 +258,11 @@ class SphericalCutter(BaseCutter):
return (cl, d, cp)
if (direction.x != 0) or (direction.y != 0):
(cl_p1, d_p1, cp_p1) = self.intersect_cylinder_vertex(direction,
triangle.p1)
triangle.p1, start=start)
(cl_p2, d_p2, cp_p2) = self.intersect_cylinder_vertex(direction,
triangle.p2)
triangle.p2, start=start)
(cl_p3, d_p3, cp_p3) = self.intersect_cylinder_vertex(direction,
triangle.p3)
triangle.p3, start=start)
if d_p1 < d:
d = d_p1
cl = cl_p1
......@@ -256,9 +275,12 @@ class SphericalCutter(BaseCutter):
d = d_p3
cl = cl_p3
cp = cp_p3
(cl_e1, d_e1, cp_e1) = self.intersect_cylinder_edge(direction, triangle.e1)
(cl_e2, d_e2, cp_e2) = self.intersect_cylinder_edge(direction, triangle.e2)
(cl_e3, d_e3, cp_e3) = self.intersect_cylinder_edge(direction, triangle.e3)
(cl_e1, d_e1, cp_e1) = self.intersect_cylinder_edge(direction,
triangle.e1, start=start)
(cl_e2, d_e2, cp_e2) = self.intersect_cylinder_edge(direction,
triangle.e2, start=start)
(cl_e3, d_e3, cp_e3) = self.intersect_cylinder_edge(direction,
triangle.e3, start=start)
if d_e1 < d:
d = d_e1
cl = cl_e1
......
This diff is collapsed.
......@@ -213,10 +213,10 @@ def get_max_height_triangles(model, cutter, x, y, minz, maxz, order=None,
height_max = None
cut_max = None
triangle_max = None
box_x_min = cutter.minx
box_x_max = cutter.maxx
box_y_min = cutter.miny
box_y_max = cutter.maxy
box_x_min = cutter.get_minx(p)
box_x_max = cutter.get_maxx(p)
box_y_min = cutter.get_miny(p)
box_y_max = cutter.get_maxy(p)
box_z_min = minz
box_z_max = maxz
triangles = model.triangles(box_x_min, box_y_min, box_z_min, box_x_max,
......
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