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): ...@@ -47,26 +47,28 @@ class BaseCutter(object):
self.required_distance = 0 self.required_distance = 0
self.distance_radius = self.radius self.distance_radius = self.radius
self.distance_radiussq = self.distance_radius ** 2 self.distance_radiussq = self.distance_radius ** 2
# self.minx, self.maxx, self.miny and self.maxy are defined as
# properties below
self.shape = {} self.shape = {}
self.moveto(location) 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 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 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 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 return self.location.y + self.distance_radius
maxy = property(_get_maxy)
def __repr__(self): def __repr__(self):
return "BaseCutter" return "BaseCutter"
...@@ -102,24 +104,26 @@ class BaseCutter(object): ...@@ -102,24 +104,26 @@ class BaseCutter(object):
if not keep_lock: if not keep_lock:
pycam.Utils.threading.release_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 " \ raise NotImplementedError("Inherited class of BaseCutter does not " \
+ "implement the required function 'intersect'.") + "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 # check bounding box collision
if self.minx > triangle.maxx + epsilon: if self.get_minx(start) > triangle.maxx + epsilon:
return None return None
if self.maxx < triangle.minx - epsilon: if self.get_maxx(start) < triangle.minx - epsilon:
return None return None
if self.miny > triangle.maxy + epsilon: if self.get_miny(start) > triangle.maxy + epsilon:
return None return None
if self.maxy < triangle.miny - epsilon: if self.get_maxy(start) < triangle.miny - epsilon:
return None return None
# check bounding circle collision # check bounding circle collision
c = triangle.middle 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 \ > (self.distance_radiussq + 2 * self.distance_radius \
* triangle.radius + triangle.radiussq) + epsilon: * triangle.radius + triangle.radiussq) + epsilon:
return None return None
...@@ -127,18 +131,21 @@ class BaseCutter(object): ...@@ -127,18 +131,21 @@ class BaseCutter(object):
(cl, d, cp) = self.intersect(BaseCutter.vertical, triangle) (cl, d, cp) = self.intersect(BaseCutter.vertical, triangle)
return cl return cl
def intersect_circle_triangle(self, direction, triangle): def intersect_circle_triangle(self, direction, triangle, start=None):
(cl, ccp, cp, d) = self.intersect_circle_plane(direction, triangle) (cl, ccp, cp, d) = self.intersect_circle_plane(direction, triangle,
start=start)
if cp and triangle.is_point_inside(cp): if cp and triangle.is_point_inside(cp):
return (cl, d, cp) return (cl, d, cp)
return (None, INFINITE, None) return (None, INFINITE, None)
def intersect_circle_vertex(self, direction, point): def intersect_circle_vertex(self, direction, point, start=None):
(cl, ccp, cp, l) = self.intersect_circle_point(direction, point) (cl, ccp, cp, l) = self.intersect_circle_point(direction, point,
start=start)
return (cl, l, cp) return (cl, l, cp)
def intersect_circle_edge(self, direction, edge): def intersect_circle_edge(self, direction, edge, start=None):
(cl, ccp, cp, l) = self.intersect_circle_line(direction, edge) (cl, ccp, cp, l) = self.intersect_circle_line(direction, edge,
start=start)
if cp: if cp:
# check if the contact point is between the endpoints # check if the contact point is between the endpoints
m = cp.sub(edge.p1).dot(edge.dir) m = cp.sub(edge.p1).dot(edge.dir)
...@@ -146,38 +153,50 @@ class BaseCutter(object): ...@@ -146,38 +153,50 @@ class BaseCutter(object):
return (None, INFINITE, cp) return (None, INFINITE, cp)
return (cl, l, cp) return (cl, l, cp)
def intersect_cylinder_point(self, direction, point): def intersect_cylinder_point(self, direction, point, start=None):
(ccp, cp, l) = intersect_cylinder_point(self.center, self.axis, 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) self.distance_radius, self.distance_radiussq, direction, point)
# offset intersection # offset intersection
if ccp: if ccp:
cl = cp.add(self.location.sub(ccp)) cl = cp.add(start.sub(ccp))
return (cl, ccp, cp, l) return (cl, ccp, cp, l)
return (None, None, None, INFINITE) return (None, None, None, INFINITE)
def intersect_cylinder_vertex(self, direction, point): def intersect_cylinder_vertex(self, direction, point, start=None):
(cl, ccp, cp, l) = self.intersect_cylinder_point(direction, point) if start is None:
if ccp and ccp.z < self.center.z: 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 (None, INFINITE, None)
return (cl, l, cp) return (cl, l, cp)
def intersect_cylinder_line(self, direction, edge): def intersect_cylinder_line(self, direction, edge, start=None):
(ccp, cp, l) = intersect_cylinder_line(self.center, self.axis, 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) self.distance_radius, self.distance_radiussq, direction, edge)
# offset intersection # offset intersection
if ccp: if ccp:
cl = self.location.add(cp.sub(ccp)) cl = start.add(cp.sub(ccp))
return (cl, ccp, cp, l) return (cl, ccp, cp, l)
return (None, None, None, INFINITE) return (None, None, None, INFINITE)
def intersect_cylinder_edge(self, direction, edge): def intersect_cylinder_edge(self, direction, edge, start=None):
(cl, ccp, cp, l) = self.intersect_cylinder_line(direction, edge) if start is None:
start = self.location
(cl, ccp, cp, l) = self.intersect_cylinder_line(direction, edge,
start=start)
if not ccp: if not ccp:
return (None, INFINITE, None) return (None, INFINITE, None)
m = cp.sub(edge.p1).dot(edge.dir) m = cp.sub(edge.p1).dot(edge.dir)
if (m < -epsilon) or (m > edge.len + epsilon): if (m < -epsilon) or (m > edge.len + epsilon):
return (None, INFINITE, None) 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 (None, INFINITE, None)
return (cl, l, cp) return (cl, l, cp)
...@@ -133,36 +133,46 @@ class CylindricalCutter(BaseCutter): ...@@ -133,36 +133,46 @@ class CylindricalCutter(BaseCutter):
BaseCutter.moveto(self, location, **kwargs) 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, start=None):
(ccp, cp, d) = intersect_circle_plane(self.center, self.distance_radius, 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) direction, triangle)
if ccp and cp: if ccp and cp:
cl = cp.add(self.location.sub(ccp)) cl = cp.add(start.sub(ccp))
return (cl, ccp, cp, d) return (cl, ccp, cp, d)
return (None, None, None, INFINITE) return (None, None, None, INFINITE)
def intersect_circle_point(self, direction, point): def intersect_circle_point(self, direction, point, start=None):
(ccp, cp, l) = intersect_circle_point(self.center, self.axis, 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) self.distance_radius, self.distance_radiussq, direction, point)
if ccp: if ccp:
cl = cp.add(self.location.sub(ccp)) cl = cp.add(start.sub(ccp))
return (cl, ccp, cp, l) return (cl, ccp, cp, l)
return (None, None, None, INFINITE) return (None, None, None, INFINITE)
def intersect_circle_line(self, direction, edge): def intersect_circle_line(self, direction, edge, start=None):
(ccp, cp, l) = intersect_circle_line(self.center, self.axis, 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) self.distance_radius, self.distance_radiussq, direction, edge)
if ccp: if ccp:
cl = cp.add(self.location.sub(ccp)) cl = cp.add(start.sub(ccp))
return (cl, ccp, cp, l) return (cl, ccp, cp, l)
return (None, None, None, INFINITE) 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? # 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): def intersect(self, direction, triangle, start=None):
(cl_t, d_t, cp_t) = self.intersect_circle_triangle(direction, triangle) (cl_t, d_t, cp_t) = self.intersect_circle_triangle(direction, triangle,
start=start)
d = INFINITE d = INFINITE
cl = None cl = None
cp = None cp = None
...@@ -172,9 +182,12 @@ class CylindricalCutter(BaseCutter): ...@@ -172,9 +182,12 @@ class CylindricalCutter(BaseCutter):
cp = cp_t cp = cp_t
if cl and (direction.x == 0) and (direction.y == 0): if cl and (direction.x == 0) and (direction.y == 0):
return (cl, d, cp) return (cl, d, cp)
(cl_e1, d_e1, cp_e1) = self.intersect_circle_edge(direction, triangle.e1) (cl_e1, d_e1, cp_e1) = self.intersect_circle_edge(direction,
(cl_e2, d_e2, cp_e2) = self.intersect_circle_edge(direction, triangle.e2) triangle.e1, start=start)
(cl_e3, d_e3, cp_e3) = self.intersect_circle_edge(direction, triangle.e3) (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: if d_e1 < d:
d = d_e1 d = d_e1
cl = cl_e1 cl = cl_e1
...@@ -189,9 +202,12 @@ class CylindricalCutter(BaseCutter): ...@@ -189,9 +202,12 @@ class CylindricalCutter(BaseCutter):
cp = cp_e3 cp = cp_e3
if cl and (direction.x == 0) and (direction.y == 0): if cl and (direction.x == 0) and (direction.y == 0):
return (cl, d, cp) return (cl, d, cp)
(cl_p1, d_p1, cp_p1) = self.intersect_circle_vertex(direction, triangle.p1) (cl_p1, d_p1, cp_p1) = self.intersect_circle_vertex(direction,
(cl_p2, d_p2, cp_p2) = self.intersect_circle_vertex(direction, triangle.p2) triangle.p1, start=start)
(cl_p3, d_p3, cp_p3) = self.intersect_circle_vertex(direction, triangle.p3) (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: if d_p1 < d:
d = d_p1 d = d_p1
cl = cl_p1 cl = cl_p1
...@@ -208,11 +224,11 @@ class CylindricalCutter(BaseCutter): ...@@ -208,11 +224,11 @@ class CylindricalCutter(BaseCutter):
return (cl, d, cp) return (cl, d, cp)
if (direction.x != 0) or (direction.y != 0): if (direction.x != 0) or (direction.y != 0):
(cl_p1, d_p1, cp_p1) = self.intersect_cylinder_vertex(direction, (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, (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, (cl_p3, d_p3, cp_p3) = self.intersect_cylinder_vertex(direction,
triangle.p3) triangle.p3, start=start)
if d_p1 < d: if d_p1 < d:
d = d_p1 d = d_p1
cl = cl_p1 cl = cl_p1
...@@ -225,9 +241,12 @@ class CylindricalCutter(BaseCutter): ...@@ -225,9 +241,12 @@ class CylindricalCutter(BaseCutter):
d = d_p3 d = d_p3
cl = cl_p3 cl = cl_p3
cp = cp_p3 cp = cp_p3
(cl_e1, d_e1, cp_e1) = self.intersect_cylinder_edge(direction, triangle.e1) (cl_e1, d_e1, cp_e1) = self.intersect_cylinder_edge(direction,
(cl_e2, d_e2, cp_e2) = self.intersect_cylinder_edge(direction, triangle.e2) triangle.e1, start=start)
(cl_e3, d_e3, cp_e3) = self.intersect_cylinder_edge(direction, triangle.e3) (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: if d_e1 < d:
d = d_e1 d = d_e1
cl = cl_e1 cl = cl_e1
......
...@@ -141,45 +141,57 @@ class SphericalCutter(BaseCutter): ...@@ -141,45 +141,57 @@ class SphericalCutter(BaseCutter):
BaseCutter.moveto(self, location, **kwargs) 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, start=None):
(ccp, cp, d) = intersect_sphere_plane(self.center, self.distance_radius, 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) direction, triangle)
# offset intersection # offset intersection
if ccp: if ccp:
cl = cp.add(self.location.sub(ccp)) cl = cp.add(start.sub(ccp))
return (cl, ccp, cp, d) return (cl, ccp, cp, d)
return (None, None, None, INFINITE) return (None, None, None, INFINITE)
def intersect_sphere_triangle(self, direction, triangle): def intersect_sphere_triangle(self, direction, triangle, start=None):
(cl, ccp, cp, d) = self.intersect_sphere_plane(direction, triangle) (cl, ccp, cp, d) = self.intersect_sphere_plane(direction, triangle,
start=start)
if cp and triangle.is_point_inside(cp): if cp and triangle.is_point_inside(cp):
return (cl, d, cp) return (cl, d, cp)
return (None, INFINITE, None) return (None, INFINITE, None)
def intersect_sphere_point(self, direction, point): def intersect_sphere_point(self, direction, point, start=None):
(ccp, cp, l) = intersect_sphere_point(self.center, self.distance_radius, 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) self.distance_radiussq, direction, point)
# offset intersection # offset intersection
cl = None cl = None
if cp: if cp:
cl = self.location.add(direction.mul(l)) cl = start.add(direction.mul(l))
return (cl, ccp, cp, l) return (cl, ccp, cp, l)
def intersect_sphere_vertex(self, direction, point): def intersect_sphere_vertex(self, direction, point, start=None):
(cl, ccp, cp, l) = self.intersect_sphere_point(direction, point) (cl, ccp, cp, l) = self.intersect_sphere_point(direction, point,
start=start)
return (cl, l, cp) return (cl, l, cp)
def intersect_sphere_line(self, direction, edge): def intersect_sphere_line(self, direction, edge, start=None):
(ccp, cp, l) = intersect_sphere_line(self.center, self.distance_radius, 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) self.distance_radiussq, direction, edge)
# offset intersection # offset intersection
if ccp: if ccp:
cl = cp.sub(ccp.sub(self.location)) cl = cp.sub(ccp.sub(start))
return (cl, ccp, cp, l) return (cl, ccp, cp, l)
return (None, None, None, INFINITE) return (None, None, None, INFINITE)
def intersect_sphere_edge(self, direction, edge): def intersect_sphere_edge(self, direction, edge, start=None):
(cl, ccp, cp, l) = self.intersect_sphere_line(direction, edge) (cl, ccp, cp, l) = self.intersect_sphere_line(direction, edge,
start=start)
if cp: if cp:
# check if the contact point is between the endpoints # check if the contact point is between the endpoints
d = edge.p2.sub(edge.p1) d = edge.p2.sub(edge.p1)
...@@ -188,12 +200,13 @@ class SphericalCutter(BaseCutter): ...@@ -188,12 +200,13 @@ class SphericalCutter(BaseCutter):
return (None, INFINITE, None) return (None, INFINITE, None)
return (cl, l, cp) return (cl, l, cp)
def intersect_point(self, direction, point): def intersect_point(self, direction, point, start=None):
# TODO: probably obsolete? # TODO: probably obsolete?
return self.intersect_sphere_point(direction, point) return self.intersect_sphere_point(direction, point, start=start)
def intersect(self, direction, triangle): def intersect(self, direction, triangle, start=None):
(cl_t, d_t, cp_t) = self.intersect_sphere_triangle(direction, triangle) (cl_t, d_t, cp_t) = self.intersect_sphere_triangle(direction, triangle,
start=start)
d = INFINITE d = INFINITE
cl = None cl = None
cp = None cp = None
...@@ -203,9 +216,12 @@ class SphericalCutter(BaseCutter): ...@@ -203,9 +216,12 @@ class SphericalCutter(BaseCutter):
cp = cp_t cp = cp_t
if cl and (direction.x == 0) and (direction.y == 0): if cl and (direction.x == 0) and (direction.y == 0):
return (cl, d, cp) return (cl, d, cp)
(cl_e1, d_e1, cp_e1) = self.intersect_sphere_edge(direction, triangle.e1) (cl_e1, d_e1, cp_e1) = self.intersect_sphere_edge(direction,
(cl_e2, d_e2, cp_e2) = self.intersect_sphere_edge(direction, triangle.e2) triangle.e1, start=start)
(cl_e3, d_e3, cp_e3) = self.intersect_sphere_edge(direction, triangle.e3) (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: if d_e1 < d:
d = d_e1 d = d_e1
cl = cl_e1 cl = cl_e1
...@@ -220,9 +236,12 @@ class SphericalCutter(BaseCutter): ...@@ -220,9 +236,12 @@ class SphericalCutter(BaseCutter):
cp = cp_e3 cp = cp_e3
if cl and (direction.x == 0) and (direction.y == 0): if cl and (direction.x == 0) and (direction.y == 0):
return (cl, d, cp) return (cl, d, cp)
(cl_p1, d_p1, cp_p1) = self.intersect_sphere_vertex(direction, triangle.p1) (cl_p1, d_p1, cp_p1) = self.intersect_sphere_vertex(direction,
(cl_p2, d_p2, cp_p2) = self.intersect_sphere_vertex(direction, triangle.p2) triangle.p1, start=start)
(cl_p3, d_p3, cp_p3) = self.intersect_sphere_vertex(direction, triangle.p3) (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: if d_p1 < d:
d = d_p1 d = d_p1
cl = cl_p1 cl = cl_p1
...@@ -239,11 +258,11 @@ class SphericalCutter(BaseCutter): ...@@ -239,11 +258,11 @@ class SphericalCutter(BaseCutter):
return (cl, d, cp) return (cl, d, cp)
if (direction.x != 0) or (direction.y != 0): if (direction.x != 0) or (direction.y != 0):
(cl_p1, d_p1, cp_p1) = self.intersect_cylinder_vertex(direction, (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, (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, (cl_p3, d_p3, cp_p3) = self.intersect_cylinder_vertex(direction,
triangle.p3) triangle.p3, start=start)
if d_p1 < d: if d_p1 < d:
d = d_p1 d = d_p1
cl = cl_p1 cl = cl_p1
...@@ -256,9 +275,12 @@ class SphericalCutter(BaseCutter): ...@@ -256,9 +275,12 @@ class SphericalCutter(BaseCutter):
d = d_p3 d = d_p3
cl = cl_p3 cl = cl_p3
cp = cp_p3 cp = cp_p3
(cl_e1, d_e1, cp_e1) = self.intersect_cylinder_edge(direction, triangle.e1) (cl_e1, d_e1, cp_e1) = self.intersect_cylinder_edge(direction,
(cl_e2, d_e2, cp_e2) = self.intersect_cylinder_edge(direction, triangle.e2) triangle.e1, start=start)
(cl_e3, d_e3, cp_e3) = self.intersect_cylinder_edge(direction, triangle.e3) (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: if d_e1 < d:
d = d_e1 d = d_e1
cl = cl_e1 cl = cl_e1
......
...@@ -115,36 +115,43 @@ class ToroidalCutter(BaseCutter): ...@@ -115,36 +115,43 @@ class ToroidalCutter(BaseCutter):
BaseCutter.moveto(self, location, **kwargs) 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, start=None):
(ccp, cp, l) = intersect_torus_plane(self.center, self.axis, if start is None:
start = self.location
(ccp, cp, l) = intersect_torus_plane(
start.sub(self.location).add(self.center), self.axis,
self.distance_majorradius, self.distance_minorradius, direction, self.distance_majorradius, self.distance_minorradius, direction,
triangle) triangle)
if cp: if cp:
cl = cp.add(self.location.sub(ccp)) cl = cp.add(start.sub(ccp))
return (cl, ccp, cp, l) return (cl, ccp, cp, l)
return (None, None, None, INFINITE) return (None, None, None, INFINITE)
def intersect_torus_triangle(self, direction, triangle): def intersect_torus_triangle(self, direction, triangle, start=None):
(cl, ccp, cp, d) = self.intersect_torus_plane(direction, triangle) (cl, ccp, cp, d) = self.intersect_torus_plane(direction, triangle, start=start)
if cp and triangle.is_point_inside(cp): if cp and triangle.is_point_inside(cp):
return (cl, d, cp) return (cl, d, cp)
return (None, INFINITE, None) return (None, INFINITE, None)
def intersect_torus_point(self, direction, point): def intersect_torus_point(self, direction, point, start=None):
(ccp, cp, l) = intersect_torus_point(self.center, self.axis, if start is None:
start = self.location
(ccp, cp, l) = intersect_torus_point(
start.sub(self.location).add(self.center), self.axis,
self.distance_majorradius, self.distance_minorradius, self.distance_majorradius, self.distance_minorradius,
self.distance_majorradiussq, self.distance_minorradiussq, self.distance_majorradiussq, self.distance_minorradiussq,
direction, point) direction, point)
if ccp: if ccp:
cl = point.add(self.location.sub(ccp)) cl = point.add(start.sub(ccp))
return (cl, ccp, point, l) return (cl, ccp, point, l)
return (None, None, None, INFINITE) return (None, None, None, INFINITE)
def intersect_torus_vertex(self, direction, point): def intersect_torus_vertex(self, direction, point, start=None):
(cl, ccp, cp, l) = self.intersect_torus_point(direction, point) (cl, ccp, cp, l) = self.intersect_torus_point(direction, point,
start=start)
return (cl, l, cp) return (cl, l, cp)
def intersect_torus_edge(self, direction, edge): def intersect_torus_edge(self, direction, edge, start=None):
# TODO: calculate "optimal" scale: # TODO: calculate "optimal" scale:
# max(dir.dot(axis)/minor,dir.dot(dir.cross(axis).normalized())/major) # max(dir.dot(axis)/minor,dir.dot(dir.cross(axis).normalized())/major)
# "When in doubt, use brute force." Ken Thompson # "When in doubt, use brute force." Ken Thompson
...@@ -156,7 +163,8 @@ class ToroidalCutter(BaseCutter): ...@@ -156,7 +163,8 @@ class ToroidalCutter(BaseCutter):
for i in range(scale + 1): for i in range(scale + 1):
m = float(i) / scale m = float(i) / scale
p = edge.point_with_length_multiply(m) p = edge.point_with_length_multiply(m)
(cl, ccp, cp, l) = self.intersect_torus_point(direction, p) (cl, ccp, cp, l) = self.intersect_torus_point(direction, p,
start=start)
if not cl: if not cl:
continue continue
if l < min_l: if l < min_l:
...@@ -172,7 +180,8 @@ class ToroidalCutter(BaseCutter): ...@@ -172,7 +180,8 @@ class ToroidalCutter(BaseCutter):
if (m < -epsilon) or (m > 1 + epsilon): if (m < -epsilon) or (m > 1 + epsilon):
continue continue
p = edge.point_with_length_multiply(m) p = edge.point_with_length_multiply(m)
(cl, ccp, cp, l) = self.intersect_torus_point(direction, p) (cl, ccp, cp, l) = self.intersect_torus_point(direction, p,
start=None)
if not cl: if not cl:
continue continue
if l < min_l: if l < min_l:
...@@ -181,26 +190,33 @@ class ToroidalCutter(BaseCutter): ...@@ -181,26 +190,33 @@ class ToroidalCutter(BaseCutter):
min_cp = cp min_cp = cp
return (min_cl, min_l, min_cp) return (min_cl, min_l, min_cp)
def intersect_cylinder_point(self, direction, point): def intersect_cylinder_point(self, direction, point, start=None):
(ccp, cp, l) = intersect_cylinder_point(self.center, self.axis, 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) self.distance_radius, self.distance_radiussq, direction, point)
# offset intersection # offset intersection
if ccp: if ccp:
cl = self.location.add(direction.mul(l)) cl = start.add(direction.mul(l))
return (cl, ccp, cp, l) return (cl, ccp, cp, l)
return (None, None, None, INFINITE) return (None, None, None, INFINITE)
def intersect_cylinder_line(self, direction, edge): def intersect_cylinder_line(self, direction, edge, start=None):
(ccp, cp, l) = intersect_cylinder_line(self.center, self.axis, 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) self.distance_radius, self.distance_radiussq, direction, edge)
# offset intersection # offset intersection
if ccp: if ccp:
cl = self.location.add(cp.sub(ccp)) cl = start.add(cp.sub(ccp))
return (cl, ccp, cp, l) return (cl, ccp, cp, l)
return (None, None, None, INFINITE) return (None, None, None, INFINITE)
def intersect_cylinder_edge(self, direction, edge): def intersect_cylinder_edge(self, direction, edge, start=None):
(cl, ccp, cp, l) = self.intersect_cylinder_line(direction, edge) (cl, ccp, cp, l) = self.intersect_cylinder_line(direction, edge,
start=start)
if ccp and ccp.z < self.center.z: if ccp and ccp.z < self.center.z:
return (None, INFINITE, None) return (None, INFINITE, None)
if ccp: if ccp:
...@@ -209,35 +225,42 @@ class ToroidalCutter(BaseCutter): ...@@ -209,35 +225,42 @@ class ToroidalCutter(BaseCutter):
return (None, INFINITE, None) return (None, INFINITE, None)
return (cl, l, cp) return (cl, l, cp)
def intersect_circle_plane(self, direction, triangle): def intersect_circle_plane(self, direction, triangle, start=None):
(ccp, cp, l) = intersect_circle_plane(self.location, if start is None:
start = self.location
(ccp, cp, l) = intersect_circle_plane(start,
self.distance_majorradius, direction, triangle) self.distance_majorradius, direction, triangle)
# offset intersection # offset intersection
if ccp: if ccp:
cl = cp.sub(ccp.sub(self.location)) cl = cp.sub(ccp.sub(start))
return (cl, ccp, cp, l) return (cl, ccp, cp, l)
return (None, None, None, INFINITE) return (None, None, None, INFINITE)
def intersect_circle_point(self, direction, point): def intersect_circle_point(self, direction, point, start=None):
(ccp, cp, l) = intersect_circle_point(self.location, self.axis, if start is None:
start = self.location
(ccp, cp, l) = intersect_circle_point(start, self.axis,
self.distance_majorradius, self.distance_majorradiussq, self.distance_majorradius, self.distance_majorradiussq,
direction, point) direction, point)
if ccp: if ccp:
cl = cp.sub(ccp.sub(self.location)) cl = cp.sub(ccp.sub(start))
return (cl, ccp, point, l) return (cl, ccp, point, l)
return (None, None, None, INFINITE) return (None, None, None, INFINITE)
def intersect_circle_line(self, direction, edge): def intersect_circle_line(self, direction, edge, start=None):
(ccp, cp, l) = intersect_circle_line(self.location, self.axis, if start is None:
start = self.location
(ccp, cp, l) = intersect_circle_line(start, self.axis,
self.distance_majorradius, self.distance_majorradiussq, self.distance_majorradius, self.distance_majorradiussq,
direction, edge) direction, edge)
if ccp: if ccp:
cl = cp.sub(ccp.sub(self.location)) cl = cp.sub(ccp.sub(start))
return (cl, ccp, cp, l) return (cl, ccp, cp, l)
return (None, None, None, INFINITE) return (None, None, None, INFINITE)
def intersect(self, direction, triangle): def intersect(self, direction, triangle, start=None):
(cl_t, d_t, cp_t) = self.intersect_torus_triangle(direction, triangle) (cl_t, d_t, cp_t) = self.intersect_torus_triangle(direction, triangle,
start=start)
d = INFINITE d = INFINITE
cl = None cl = None
cp = None cp = None
...@@ -245,9 +268,12 @@ class ToroidalCutter(BaseCutter): ...@@ -245,9 +268,12 @@ class ToroidalCutter(BaseCutter):
d = d_t d = d_t
cl = cl_t cl = cl_t
cp = cp_t cp = cp_t
(cl_e1, d_e1, cp_e1) = self.intersect_torus_edge(direction, triangle.e1) (cl_e1, d_e1, cp_e1) = self.intersect_torus_edge(direction, triangle.e1,
(cl_e2, d_e2, cp_e2) = self.intersect_torus_edge(direction, triangle.e2) start=start)
(cl_e3, d_e3, cp_e3) = self.intersect_torus_edge(direction, triangle.e3) (cl_e2, d_e2, cp_e2) = self.intersect_torus_edge(direction, triangle.e2,
start=start)
(cl_e3, d_e3, cp_e3) = self.intersect_torus_edge(direction, triangle.e3,
start=start)
if d_e1 < d: if d_e1 < d:
d = d_e1 d = d_e1
cl = cl_e1 cl = cl_e1
...@@ -260,9 +286,12 @@ class ToroidalCutter(BaseCutter): ...@@ -260,9 +286,12 @@ class ToroidalCutter(BaseCutter):
d = d_e3 d = d_e3
cl = cl_e3 cl = cl_e3
cp = cp_e3 cp = cp_e3
(cl_p1, d_p1, cp_p1) = self.intersect_torus_vertex(direction, triangle.p1) (cl_p1, d_p1, cp_p1) = self.intersect_torus_vertex(direction,
(cl_p2, d_p2, cp_p2) = self.intersect_torus_vertex(direction, triangle.p2) triangle.p1, start=start)
(cl_p3, d_p3, cp_p3) = self.intersect_torus_vertex(direction, triangle.p3) (cl_p2, d_p2, cp_p2) = self.intersect_torus_vertex(direction,
triangle.p2, start=start)
(cl_p3, d_p3, cp_p3) = self.intersect_torus_vertex(direction,
triangle.p3, start=start)
if d_p1 < d: if d_p1 < d:
d = d_p1 d = d_p1
cl = cl_p1 cl = cl_p1
...@@ -275,14 +304,18 @@ class ToroidalCutter(BaseCutter): ...@@ -275,14 +304,18 @@ class ToroidalCutter(BaseCutter):
d = d_p3 d = d_p3
cl = cl_p3 cl = cl_p3
cp = cp_p3 cp = cp_p3
(cl_t, d_t, cp_t) = self.intersect_circle_triangle(direction, triangle) (cl_t, d_t, cp_t) = self.intersect_circle_triangle(direction, triangle,
start=start)
if d_t < d: if d_t < d:
d = d_t d = d_t
cl = cl_t cl = cl_t
cp = cp_t cp = cp_t
(cl_p1, d_p1, cp_p1) = self.intersect_circle_vertex(direction, triangle.p1) (cl_p1, d_p1, cp_p1) = self.intersect_circle_vertex(direction,
(cl_p2, d_p2, cp_p2) = self.intersect_circle_vertex(direction, triangle.p2) triangle.p1, start=start)
(cl_p3, d_p3, cp_p3) = self.intersect_circle_vertex(direction, triangle.p3) (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: if d_p1 < d:
d = d_p1 d = d_p1
cl = cl_p1 cl = cl_p1
...@@ -295,9 +328,12 @@ class ToroidalCutter(BaseCutter): ...@@ -295,9 +328,12 @@ class ToroidalCutter(BaseCutter):
d = d_p3 d = d_p3
cl = cl_p3 cl = cl_p3
cp = cp_p3 cp = cp_p3
(cl_e1, d_e1, cp_e1) = self.intersect_circle_edge(direction, triangle.e1) (cl_e1, d_e1, cp_e1) = self.intersect_circle_edge(direction,
(cl_e2, d_e2, cp_e2) = self.intersect_circle_edge(direction, triangle.e2) triangle.e1, start=start)
(cl_e3, d_e3, cp_e3) = self.intersect_circle_edge(direction, triangle.e3) (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: if d_e1 < d:
d = d_e1 d = d_e1
cl = cl_e1 cl = cl_e1
...@@ -312,11 +348,11 @@ class ToroidalCutter(BaseCutter): ...@@ -312,11 +348,11 @@ class ToroidalCutter(BaseCutter):
cp = cp_e3 cp = cp_e3
if direction.x != 0 or direction.y != 0: if direction.x != 0 or direction.y != 0:
(cl_p1, d_p1, cp_p1) = self.intersect_cylinder_vertex(direction, (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, (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, (cl_p3, d_p3, cp_p3) = self.intersect_cylinder_vertex(direction,
triangle.p3) triangle.p3, start=start)
if d_p1 < d: if d_p1 < d:
d = d_p1 d = d_p1
cl = cl_p1 cl = cl_p1
...@@ -329,9 +365,12 @@ class ToroidalCutter(BaseCutter): ...@@ -329,9 +365,12 @@ class ToroidalCutter(BaseCutter):
d = d_p3 d = d_p3
cl = cl_p3 cl = cl_p3
cp = cp_p3 cp = cp_p3
(cl_e1, d_e1, cp_e1) = self.intersect_cylinder_edge(direction, triangle.e1) (cl_e1, d_e1, cp_e1) = self.intersect_cylinder_edge(direction,
(cl_e2, d_e2, cp_e2) = self.intersect_cylinder_edge(direction, triangle.e2) triangle.e1, start=start)
(cl_e3, d_e3, cp_e3) = self.intersect_cylinder_edge(direction, triangle.e3) (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: if d_e1 < d:
d = d_e1 d = d_e1
cl = cl_e1 cl = cl_e1
......
...@@ -213,10 +213,10 @@ def get_max_height_triangles(model, cutter, x, y, minz, maxz, order=None, ...@@ -213,10 +213,10 @@ 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
box_x_min = cutter.minx box_x_min = cutter.get_minx(p)
box_x_max = cutter.maxx box_x_max = cutter.get_maxx(p)
box_y_min = cutter.miny box_y_min = cutter.get_miny(p)
box_y_max = cutter.maxy box_y_max = cutter.get_maxy(p)
box_z_min = minz box_z_min = minz
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,
......
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