First write (untested) of paint_connect.

This commit is contained in:
jpcaram 2015-01-22 21:23:10 -05:00
parent a42c3f6e10
commit 9632d9a98f

167
camlib.py
View File

@ -141,6 +141,36 @@ class Geometry(object):
else: else:
return self.solid_geometry.bounds return self.solid_geometry.bounds
def find_polygon(self, point, geoset=None):
"""
Find an object that object.contains(Point(point)) in
poly, which can can be iterable, contain iterable of, or
be itself an implementer of .contains().
:param poly: See description
:return: Polygon containing point or None.
"""
if geoset is None:
geoset = self.solid_geometry
try: # Iterable
for sub_geo in geoset:
p = self.find_polygon(point, geoset=sub_geo)
if p is not None:
return p
except TypeError: # Non-iterable
try: # Implements .contains()
if geoset.contains(Point(point)):
return geoset
except AttributeError: # Does not implement .contains()
return None
return None
def flatten(self, geometry=None, reset=True, pathonly=False): def flatten(self, geometry=None, reset=True, pathonly=False):
""" """
Creates a list of non-iterable linear geometry objects. Creates a list of non-iterable linear geometry objects.
@ -178,26 +208,26 @@ class Geometry(object):
return self.flat_geometry return self.flat_geometry
def make2Dstorage(self): # def make2Dstorage(self):
#
self.flatten() # self.flatten()
#
def get_pts(o): # def get_pts(o):
pts = [] # pts = []
if type(o) == Polygon: # if type(o) == Polygon:
g = o.exterior # g = o.exterior
pts += list(g.coords) # pts += list(g.coords)
for i in o.interiors: # for i in o.interiors:
pts += list(i.coords) # pts += list(i.coords)
else: # else:
pts += list(o.coords) # pts += list(o.coords)
return pts # return pts
#
storage = FlatCAMRTreeStorage() # storage = FlatCAMRTreeStorage()
storage.get_points = get_pts # storage.get_points = get_pts
for shape in self.flat_geometry: # for shape in self.flat_geometry:
storage.insert(shape) # storage.insert(shape)
return storage # return storage
# def flatten_to_paths(self, geometry=None, reset=True): # def flatten_to_paths(self, geometry=None, reset=True):
# """ # """
@ -298,9 +328,9 @@ class Geometry(object):
:param overlap: Overlap of toolpasses. :param overlap: Overlap of toolpasses.
:return: :return:
""" """
poly_cuts = [polygon.buffer(-tooldia/2.0)] poly_cuts = [polygon.buffer(-tooldia / 2.0)]
while True: while True:
polygon = poly_cuts[-1].buffer(-tooldia*(1-overlap)) polygon = poly_cuts[-1].buffer(-tooldia * (1 - overlap))
if polygon.area > 0: if polygon.area > 0:
poly_cuts.append(polygon) poly_cuts.append(polygon)
else: else:
@ -388,6 +418,69 @@ class Geometry(object):
""" """
return return
def paint_connect(self, geolist, boundary, tooldia):
"""
Connects paths that results in a connection segment that is
within the paint area. This avoids unnecessary tool lifting.
:return:
"""
# Assuming geolist is a flat list of flat elements
## Index first and last points in paths
def get_pts(o):
return [o.coords[0], o.coords[-1]]
storage = FlatCAMRTreeStorage()
storage.get_points = get_pts
for shape in geolist:
if shape is not None: # TODO: This shouldn't have happened.
storage.insert(shape)
## Iterate over geometry paths getting the nearest each time.
optimized_paths = []
temp_path = None
path_count = 0
current_pt = (0, 0)
pt, geo = storage.nearest(current_pt)
try:
while True:
path_count += 1
# Remove before modifying, otherwise
# deletion will fail.
storage.remove(geo)
# If last point in geometry is the nearest
# then reverse coordinates.
if list(pt) == list(geo.coords[-1]):
geo.coords = list(geo.coords)[::-1]
# Straight line from current_pt to pt.
# Is the toolpath inside the geometry?
jump = LineString([current_pt, pt]).buffer(tooldia / 2)
if jump.within(boundary):
# Completely inside. Append...
if temp_path is None:
temp_path = geo
else:
temp_path.coords = list(temp_path.coords) + list(geo.coords)
else:
# Have to lift tool. End path.
optimized_paths.append(temp_path)
temp_path = geo
current_pt = geo.coords[-1]
# Next
pt, geo = storage.nearest(current_pt)
except StopIteration: # Nothing found in storage.
if not temp_path.equals(optimized_paths[-1]):
optimized_paths.append(temp_path)
def path_connect(self): def path_connect(self):
""" """
Simplifies a list of paths by joining those whose ends touch. Simplifies a list of paths by joining those whose ends touch.
@ -533,36 +626,6 @@ class Geometry(object):
""" """
self.solid_geometry = [cascaded_union(self.solid_geometry)] self.solid_geometry = [cascaded_union(self.solid_geometry)]
def find_polygon(self, point, geoset=None):
"""
Find an object that object.contains(Point(point)) in
poly, which can can be iterable, contain iterable of, or
be itself an implementer of .contains().
:param poly: See description
:return: Polygon containing point or None.
"""
if geoset is None:
geoset = self.solid_geometry
try: # Iterable
for sub_geo in geoset:
p = self.find_polygon(point, geoset=sub_geo)
if p is not None:
return p
except TypeError: # Non-iterable
try: # Implements .contains()
if geoset.contains(Point(point)):
return geoset
except AttributeError: # Does not implement .contains()
return None
return None
class ApertureMacro: class ApertureMacro:
""" """