- fixed some errors in the buffer and isolate Tcl commands
- updated the camlib.Geometry.buffer() method
This commit is contained in:
@@ -16,6 +16,8 @@ CHANGELOG for FlatCAM beta
|
|||||||
- fix the Transform plugin, buffer functionality for Geometry objects such that the buffer with negative values will work by crating a buffer toward the interior of that geometry
|
- fix the Transform plugin, buffer functionality for Geometry objects such that the buffer with negative values will work by crating a buffer toward the interior of that geometry
|
||||||
- minor changes
|
- minor changes
|
||||||
- modified the bounding box utility feature in the Gerber Object UI to work with negative margin values
|
- modified the bounding box utility feature in the Gerber Object UI to work with negative margin values
|
||||||
|
- fixed some errors in the `buffer` and `isolate` Tcl commands
|
||||||
|
- updated the camlib.Geometry.buffer() method
|
||||||
|
|
||||||
25.01.2022
|
25.01.2022
|
||||||
|
|
||||||
|
|||||||
38
camlib.py
38
camlib.py
@@ -933,7 +933,8 @@ class Geometry(object):
|
|||||||
|
|
||||||
# ## If iterable, expand recursively.
|
# ## If iterable, expand recursively.
|
||||||
try:
|
try:
|
||||||
for geo in geometry:
|
w_geo = geometry.geoms if isinstance(geometry, MultiPolygon) else geometry
|
||||||
|
for geo in w_geo:
|
||||||
exteriors.extend(self.get_exteriors(geometry=geo))
|
exteriors.extend(self.get_exteriors(geometry=geo))
|
||||||
|
|
||||||
# ## Not iterable, get the exterior if polygon.
|
# ## Not iterable, get the exterior if polygon.
|
||||||
@@ -2606,13 +2607,14 @@ class Geometry(object):
|
|||||||
# self.solid_geometry = affinity.skew(self.solid_geometry, angle_x, angle_y,
|
# self.solid_geometry = affinity.skew(self.solid_geometry, angle_x, angle_y,
|
||||||
# origin=(px, py))
|
# origin=(px, py))
|
||||||
|
|
||||||
def buffer(self, distance, join, factor, only_exterior=False):
|
def buffer(self, distance, join, factor, only_exterior=False, muted=False):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
:param distance: if 'factor' is True then distance is the scale factor for each geometric element
|
:param distance: if 'factor' is True then distance is the scale factor for each geometric element
|
||||||
:param join: The kind of join used by the shapely buffer method: round, square or bevel
|
:param join: The kind of join used by the shapely buffer method: round, square or bevel
|
||||||
:param factor: True or False (None)
|
:param factor: True or False (None)
|
||||||
:param only_exterior: Bool. If True, the LineStrings are buffered only on the outside
|
:param only_exterior: Bool. If True, the LineStrings are buffered only on the outside
|
||||||
|
:param muted: Bool. If True no messages are created.
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -2626,25 +2628,32 @@ class Geometry(object):
|
|||||||
try:
|
try:
|
||||||
work_geo = obj.geoms if isinstance(obj, (MultiPolygon, MultiLineString)) else obj
|
work_geo = obj.geoms if isinstance(obj, (MultiPolygon, MultiLineString)) else obj
|
||||||
for g in work_geo:
|
for g in work_geo:
|
||||||
new_obj.append(buffer_geom(g))
|
new_obj += buffer_geom(g)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
try:
|
try:
|
||||||
if factor is None or factor is False or factor == 0:
|
if factor is None or factor is False or factor == 0:
|
||||||
if distance >= 0:
|
if distance >= 0:
|
||||||
new_obj = obj.buffer(distance, resolution=self.geo_steps_per_circle, join_style=join)
|
new_obj = obj.buffer(distance, resolution=self.geo_steps_per_circle, join_style=join)
|
||||||
else:
|
|
||||||
new_obj = obj.buffer(abs(distance*2), resolution=self.geo_steps_per_circle, join_style=join)
|
|
||||||
new_obj = unary_union(new_obj.interiors)
|
|
||||||
new_obj = new_obj.buffer(-distance, resolution=self.geo_steps_per_circle, join_style=join)
|
|
||||||
new_obj = new_obj.exterior
|
|
||||||
if isinstance(obj, (LinearRing, LineString)) and only_exterior is True:
|
if isinstance(obj, (LinearRing, LineString)) and only_exterior is True:
|
||||||
new_obj = new_obj.exterior
|
new_obj = new_obj.exterior
|
||||||
|
else:
|
||||||
|
if isinstance(obj, LineString):
|
||||||
|
if not obj.is_closed:
|
||||||
|
obj = Polygon(obj).exterior
|
||||||
|
|
||||||
|
new_obj = obj.buffer(abs(distance*2), resolution=self.geo_steps_per_circle, join_style=join)
|
||||||
|
new_obj_ints = new_obj.interiors
|
||||||
|
new_obj_union = unary_union(new_obj_ints)
|
||||||
|
new_obj = new_obj_union.buffer(
|
||||||
|
abs(distance), resolution=self.geo_steps_per_circle, join_style=join).exterior
|
||||||
|
|
||||||
else:
|
else:
|
||||||
new_obj = affinity.scale(obj, xfact=distance, yfact=distance, origin='center')
|
new_obj = affinity.scale(obj, xfact=distance, yfact=distance, origin='center')
|
||||||
except AttributeError:
|
except Exception as err:
|
||||||
|
self.app.log.error("camlib.Geometry.buffer.buffer_geom() -> %s" % str(err))
|
||||||
new_obj = obj
|
new_obj = obj
|
||||||
|
|
||||||
return new_obj
|
return [new_obj]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if self.multigeo is True:
|
if self.multigeo is True:
|
||||||
@@ -2652,8 +2661,15 @@ class Geometry(object):
|
|||||||
res = buffer_geom(self.tools[tool]['solid_geometry'])
|
res = buffer_geom(self.tools[tool]['solid_geometry'])
|
||||||
self.tools[tool]['solid_geometry'] = flatten_shapely_geometry(res)
|
self.tools[tool]['solid_geometry'] = flatten_shapely_geometry(res)
|
||||||
|
|
||||||
self.solid_geometry = buffer_geom(self.solid_geometry)
|
buff_geo = flatten_shapely_geometry(buffer_geom(self.solid_geometry))
|
||||||
|
if buff_geo:
|
||||||
|
self.solid_geometry = buff_geo
|
||||||
|
if muted is False:
|
||||||
self.app.inform.emit('[success] %s...' % _('Object was buffered'))
|
self.app.inform.emit('[success] %s...' % _('Object was buffered'))
|
||||||
|
else:
|
||||||
|
if muted is False:
|
||||||
|
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed."))
|
||||||
|
self.app.log.error("camlib.Geometry.buffer() -> Failed.")
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s %s' % (_("Failed."), _("No object is selected.")))
|
self.app.inform.emit('[ERROR_NOTCL] %s %s' % (_("Failed."), _("No object is selected.")))
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class TclCommandBuffer(TclCommand):
|
|||||||
])
|
])
|
||||||
|
|
||||||
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
required = ['name', 'distance']
|
required = ['name', 'dist']
|
||||||
|
|
||||||
# structured help for current command, args needs to be ordered
|
# structured help for current command, args needs to be ordered
|
||||||
help = {
|
help = {
|
||||||
@@ -67,7 +67,7 @@ class TclCommandBuffer(TclCommand):
|
|||||||
'buffer my_geo -dist 4.2 -factor True',
|
'buffer my_geo -dist 4.2 -factor True',
|
||||||
'buffer my_geo -dist 4.2 -factor 1',
|
'buffer my_geo -dist 4.2 -factor 1',
|
||||||
'# scale each geo element by a factor of 4.2 in the my_geo Geometry obj and the join is 2 (square)',
|
'# scale each geo element by a factor of 4.2 in the my_geo Geometry obj and the join is 2 (square)',
|
||||||
'buffer my_geo -distance 4.2 -factor True -join 2'
|
'buffer my_geo -dist 4.2 -factor True -join 2'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class TclCommandIsolate(TclCommandSignaled):
|
|||||||
par = args['combine']
|
par = args['combine']
|
||||||
args['combine'] = bool(eval(par))
|
args['combine'] = bool(eval(par))
|
||||||
else:
|
else:
|
||||||
args['combine'] = bool(eval(self.app.defaults["tools_iso_combine_passes"]))
|
args['combine'] = bool(eval(str(self.app.defaults["tools_iso_combine_passes"])))
|
||||||
|
|
||||||
obj = self.app.collection.get_by_name(name)
|
obj = self.app.collection.get_by_name(name)
|
||||||
if obj is None:
|
if obj is None:
|
||||||
|
|||||||
Reference in New Issue
Block a user