Commit 0385eb03 authored by sumpfralle's avatar sumpfralle

added proof-of-concept for automatic support grid positioning


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@622 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 2a4bdb52
Version 0.3.1 - UNRELEASED
* added automatic support grid positioning for contour models
Version 0.3.0 - 2010-08-16
* added support for importing contour paths from SVG files (requires Inkscape and pstoedit)
* added basic support for importing simple DXF contour files
......
This diff is collapsed.
......@@ -94,6 +94,9 @@ class Point:
def dot(self, p):
return self.x * p.x + self.y * p.y + self.z * p.z
def size(self):
return sqrt(self.dot(self))
def cross(self, p):
return Point(self.y * p.z - p.y * self.z, p.x * self.z - self.x * p.z,
self.x * p.y - p.x * self.y)
......
......@@ -36,7 +36,7 @@ class Polygon(TransformableContainer):
# TODO: derive the plane from the appended points
if plane is None:
plane = Plane(Point(0, 0, 0), Point(0, 0, 1))
self._plane = plane
self.plane = plane
self._points = []
self._is_closed = False
self.maxx = None
......@@ -102,10 +102,10 @@ class Polygon(TransformableContainer):
def next(self):
for point in self._points:
yield point
yield self._plane
yield self.plane
def get_children_count(self):
return len(self._points) + self._plane.get_children_count()
return len(self._points) + self.plane.get_children_count()
def get_area(self):
""" calculate the area covered by a line group
......@@ -126,6 +126,27 @@ class Polygon(TransformableContainer):
value += p1.x * p2.y - p2.x * p1.y
return value / 2
def get_length(self):
""" add the length of all lines within the polygon
"""
return sum(self.get_lengths())
def get_middle_of_line(self, index):
if (index >= len(self._points)) \
or (not self._is_closed and index == len(self._points) - 1):
return None
else:
return self._points[index].add(self._points[(index + 1) % len(self._points)]).div(2)
def get_lengths(self):
result = []
for index in range(len(self._points) - 1):
result.append(self._points[index + 1].sub(
self._points[index]).size())
if self._is_closed:
result.append(self._points[0].sub(self._points[-1]).size())
return result
def get_max_inside_distance(self):
""" calculate the maximum distance between two points of the polygon
"""
......@@ -243,10 +264,10 @@ class Polygon(TransformableContainer):
skel_dir = d1.add(d2).normalized()
if skel_dir is None:
# the two vectors pointed to opposite directions
skel_dir = d1.cross(self._plane.n).normalized()
skel_dir = d1.cross(self.plane.n).normalized()
else:
skel_up_vector = skel_dir.cross(p2.sub(p1))
offset_up_vector = self._plane.n
offset_up_vector = self.plane.n
# TODO: check for other axis as well
if offset_up_vector.z * skel_up_vector.z < 0:
# reverse the skeleton vector to point outwards
......@@ -257,7 +278,7 @@ class Polygon(TransformableContainer):
def get_shifted_vertex(index, offset):
p1 = self._points[index]
p2 = self._points[(index + 1) % len(self._points)]
cross_offset = p2.sub(p1).cross(self._plane.n).normalized()
cross_offset = p2.sub(p1).cross(self.plane.n).normalized()
bisector_normalized = self.get_bisector(index)
factor = cross_offset.dot(bisector_normalized)
if factor != 0:
......@@ -375,7 +396,7 @@ class Polygon(TransformableContainer):
self_is_outer = self.is_outer()
groups = []
for lines in cleaned_line_groups:
group = Polygon(self._plane)
group = Polygon(self.plane)
for line in lines:
group.append(line)
if group.is_outer() != self_is_outer:
......@@ -408,7 +429,7 @@ class Polygon(TransformableContainer):
if offset == 0:
return Line(line.p1, line.p2)
else:
cross_offset = line.dir.cross(self._plane.n).normalized().mul(offset)
cross_offset = line.dir.cross(self.plane.n).normalized().mul(offset)
# Prolong the line at the beginning and at the end - to allow
# overlaps. Use factor "2" to take care for star-like structure
# where a complete convex triangle would get cropped (two lines
......@@ -581,7 +602,7 @@ class Polygon(TransformableContainer):
self_is_outer = self.is_outer()
groups = []
for lines in cleaned_line_groups:
group = Polygon(self._plane)
group = Polygon(self.plane)
for line in lines:
group.append(line)
if group.is_outer() == self_is_outer:
......@@ -619,7 +640,7 @@ class Polygon(TransformableContainer):
pass
else:
# no suitable group was found - we create a new one
new_group = Polygon(self._plane)
new_group = Polygon(self.plane)
new_group.append(new_line)
new_groups.append(new_group)
if len(new_groups) > 0:
......
This diff is collapsed.
......@@ -20,13 +20,23 @@ You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
from pycam.Geometry.Point import Point
from pycam.Geometry.Point import Point, Vector
from pycam.Geometry.Line import Line
from pycam.Geometry.Triangle import Triangle
from pycam.Geometry.Model import Model
from pycam.Geometry.utils import number
def _add_pyramid_to_model(model, start, direction, height, width):
up = Vector(0, 0, 1)
top = start.add(direction).add(up.mul(height))
middle_end = start.add(direction)
end_right = middle_end.add(direction.cross(up).normalized().mul(width / 2))
end_left = middle_end.add(direction.cross(up).normalized().mul(-width / 2))
for points in ((start, top, end_right), (start, end_right, top),
(start, end_right, end_left), (top, end_left, end_right)):
model.append(Triangle(points[0], points[1], points[2]))
def _add_cuboid_to_model(minx, maxx, miny, maxy, minz, maxz):
def get_triangles_for_face(pts):
t1 = Triangle(pts[0], pts[1], pts[2], Line(pts[0], pts[1]),
......@@ -131,3 +141,38 @@ def get_support_grid(minx, maxx, miny, maxy, z_plane, dist_x, dist_y, thickness,
line_y + thick_half, z_plane, z_plane + height)
return grid_model
def get_distributed_support_bridges(model, z_plane, average_distance,
min_bridges_per_polygon, thickness, height):
result = Model()
for polygon in model.get_polygons():
if not polygon.is_outer():
continue
lines = polygon.get_lines()
poly_lengths = polygon.get_lengths()
num_of_bridges = max(min_bridges_per_polygon,
int(round(sum(poly_lengths) / average_distance)))
real_average_distance = sum(poly_lengths) / num_of_bridges
max_line_index = poly_lengths.index(max(poly_lengths))
positions = []
current_line_index = max_line_index
distance_processed = poly_lengths[current_line_index] / 2
positions.append(current_line_index)
while len(positions) < num_of_bridges:
current_line_index += 1
current_line_index %= len(poly_lengths)
while distance_processed + poly_lengths[current_line_index] < real_average_distance:
distance_processed += poly_lengths[current_line_index]
current_line_index += 1
current_line_index %= len(poly_lengths)
positions.append(current_line_index)
distance_processed += poly_lengths[current_line_index]
distance_processed %= real_average_distance
for line_index in positions:
bridge_dir = lines[line_index].dir.cross(polygon.plane.n)
# TODO: should we ask for a length?
length = average_distance / 4
_add_pyramid_to_model(result,
polygon.get_middle_of_line(line_index), bridge_dir,
height, thickness)
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