First write (untested) of paint_connect.
This commit is contained in:
parent
a42c3f6e10
commit
9632d9a98f
167
camlib.py
167
camlib.py
@ -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:
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user