Commit 659ece8a authored by sumpfralle's avatar sumpfralle

implemented cropping for contour models

 * now EngraveCutter respects the defined boundary box


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@529 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 3d1f8a86
...@@ -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/>.
from pycam.Geometry import TransformableContainer from pycam.Geometry import TransformableContainer
from pycam.Geometry.Point import Point from pycam.Geometry.Point import Point
from pycam.Geometry.Plane import Plane
from pycam.Geometry.utils import epsilon from pycam.Geometry.utils import epsilon
import pycam.Geometry.Matrix as Matrix import pycam.Geometry.Matrix as Matrix
import math import math
...@@ -196,6 +197,60 @@ class Line(TransformableContainer): ...@@ -196,6 +197,60 @@ class Line(TransformableContainer):
# intersection outside of the length of line(x1, x2) # intersection outside of the length of line(x1, x2)
return None return None
def get_cropped_line(self, minx, maxx, miny, maxy, minz, maxz):
if (minx <= self.minx() <= self.maxx() <= maxx) \
and (miny <= self.miny() <= self.maxy() <= maxy) \
and (minz <= self.minz() <= self.maxz() <= maxz):
return Line(line.p1, line.p2)
elif (maxx < self.minx()) or (self.maxx() < minx) \
or (maxy < self.miny()) or (self.maxy() < miny) \
or (maxz < self.minz()) or (self.maxz() < minz):
return None
else:
# the line needs to be cropped
# generate the six planes of the cube for possible intersections
minp = Point(minx, miny, minz)
maxp = Point(maxx, maxy, maxz)
planes = [
Plane(minp, Point(1, 0, 0)),
Plane(minp, Point(0, 1, 0)),
Plane(minp, Point(0, 0, 1)),
Plane(maxp, Point(1, 0, 0)),
Plane(maxp, Point(0, 1, 0)),
Plane(maxp, Point(0, 0, 1)),
]
# calculate all intersections
intersections = [plane.intersect_point(self.dir(), self.p1)
for plane in planes]
# remove all intersections outside the box and outside the line
valid_intersections = [(cp, dist) for cp, dist in intersections
if cp and (0 <= dist <= self.len()) \
and (minx <= cp.x <= maxx) \
and (miny <= cp.y <= maxy) \
and (minz <= cp.z <= maxz)]
# sort the intersections according to their distance to self.p1
valid_intersections.sort(
cmp=lambda (cp1, l1), (cp2, l2): cmp(l1, l2))
# Check if p1 is within the box - otherwise use the closest
# intersection.
if (minx <= self.p1.x <= maxx) and (miny <= self.p1.y <= maxy) \
and (minz <= self.p1.z <= maxz):
new_p1 = self.p1
else:
new_p1 = valid_intersections[0][0]
# Check if p2 is within the box - otherwise use the intersection
# most distant from p1.
if (minx <= self.p2.x <= maxx) and (miny <= self.p2.y <= maxy) \
and (minz <= self.p2.z <= maxz):
new_p2 = self.p2
else:
new_p2 = valid_intersections[-1][0]
if new_p1 == new_p2:
# no real line
return None
else:
return Line(new_p1, new_p2)
class LineGroup(TransformableContainer): class LineGroup(TransformableContainer):
...@@ -435,3 +490,41 @@ class LineGroup(TransformableContainer): ...@@ -435,3 +490,41 @@ class LineGroup(TransformableContainer):
group.append(line) group.append(line)
return group return group
def get_cropped_line_groups(self, minx, maxx, miny, maxy, minz, maxz):
""" crop a line group according to a 3d bounding box
The result is a list of LineGroups, since the bounding box can possibly
break the original line group into several non-connected pieces.
"""
new_groups = []
for line in self._lines:
new_line = None
if (minx <= line.minx() <= line.maxx() <= maxx) \
and (miny <= line.miny() <= line.maxy() <= maxy) \
and (minz <= line.minz() <= line.maxz() <= maxz):
new_line = line
else:
cropped_line = line.get_cropped_line(minx, maxx, miny, maxy,
minz, maxz)
if not cropped_line is None:
new_line = cropped_line
# add the new line to one of the line groups
if not new_line is None:
# try to find a suitable line group
for new_group in new_groups:
try:
new_group.append(new_line)
break
except ValueError:
# the line did not fit to this group (segment is broken)
pass
else:
# no suitable group was found - we create a new one
new_group = LineGroup(self.get_offset_matrix())
new_group.append(new_line)
new_groups.append(new_group)
if len(new_groups) > 0:
return new_groups
else:
return None
...@@ -231,6 +231,21 @@ class ContourModel(BaseModel): ...@@ -231,6 +231,21 @@ class ContourModel(BaseModel):
def get_line_groups(self): def get_line_groups(self):
return self._line_groups return self._line_groups
def get_cropped_model(self, minx, maxx, miny, maxy, minz, maxz):
new_line_groups = []
for group in self._line_groups:
new_groups = group.get_cropped_line_groups(minx, maxx, miny, maxy,
minz, maxz)
if not new_groups is None:
new_line_groups.extend(new_groups)
if len(new_line_groups) > 0:
result = ContourModel()
for group in new_line_groups:
result.append(group)
return result
else:
return None
def get_offset_model(self, offset, callback=None): def get_offset_model(self, offset, callback=None):
""" calculate a contour model that surrounds the current model with """ calculate a contour model that surrounds the current model with
a given offset. a given offset.
......
...@@ -185,6 +185,12 @@ def generate_toolpath(model, tool_settings=None, ...@@ -185,6 +185,12 @@ def generate_toolpath(model, tool_settings=None,
else: else:
# no collisions and no user interruption # no collisions and no user interruption
pass pass
# limit the contour model to the bounding box
if contour_model:
contour_model = contour_model.get_cropped_model(minx, maxx, miny, maxy,
minz, maxz)
if contour_model is None:
return "No part of the contour model is within the bounding box."
# Due to some weirdness the height of the drill must be bigger than the # Due to some weirdness the height of the drill must be bigger than the
# object's size. Otherwise some collisions are not detected. # object's size. Otherwise some collisions are not detected.
cutter_height = 4 * (maxy - miny) cutter_height = 4 * (maxy - miny)
......
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