- added a new Tcl command: buffer which will buffer the geometry of an object or will scale individually each geometry sub element

- fixed the buffer() method for the Excellon objects (the resulting tool diameters were calculated less than the what was expected)
This commit is contained in:
Marius Stanciu
2022-01-21 02:37:34 +02:00
committed by Marius
parent ba8b16e54f
commit b0db73029d
8 changed files with 176 additions and 77 deletions

View File

@@ -9,7 +9,7 @@
from camlib import Geometry, grace
import shapely.affinity as affinity
from shapely.geometry import Point, LineString
from shapely.geometry import Point, LineString, LinearRing, MultiLineString, MultiPolygon
import numpy as np
import re
@@ -1559,13 +1559,14 @@ class Excellon(Geometry):
self.create_geometry()
self.app.proc_container.new_text = ''
def buffer(self, distance, join, factor):
def buffer(self, distance, join, factor, only_exterior=False):
"""
:param distance: if 'factor' is True then distance is the factor
:param factor: True or False (None)
:param join: The type of line joint used by the shapely buffer method: round, square, bevel
:return: None
:param distance: if 'factor' is True then distance is the factor
:param factor: True or False (None)
:param join: The type of line joint used by the shapely buffer method: round, square, bevel
:param only_exterior: Bool. If True, the LineStrings are buffered only on the outside
:return: None
"""
self.app.log.debug("appParsers.ParseExcellon.Excellon.buffer()")
@@ -1573,19 +1574,22 @@ class Excellon(Geometry):
return
def buffer_geom(obj):
new_obj = []
try:
new_obj = []
for g in obj:
work_geo = obj.geoms if isinstance(obj, (MultiPolygon, MultiLineString)) else obj
for g in work_geo:
new_obj.append(buffer_geom(g))
return new_obj
except TypeError:
try:
if factor is None:
return obj.buffer(distance, resolution=self.excellon_circle_steps)
new_obj = obj.buffer(distance, resolution=self.excellon_circle_steps)
if isinstance(obj, (LinearRing, LineString)) and only_exterior is True:
new_obj = new_obj.exterior
else:
return affinity.scale(obj, xfact=distance, yfact=distance, origin='center')
new_obj = affinity.scale(obj, xfact=distance, yfact=distance, origin='center')
except AttributeError:
return obj
new_obj = obj
return new_obj
# buffer solid_geometry
for tool, tool_dict in list(self.tools.items()):
@@ -1596,8 +1600,8 @@ class Excellon(Geometry):
except TypeError:
self.tools[tool]['solid_geometry'] = [res]
if factor is None:
self.tools[tool]['tooldia'] += distance
self.tools[tool]['tooldia'] += (distance * 2)
else:
self.tools[tool]['tooldia'] *= distance
self.tools[tool]['tooldia'] *= (distance * 2)
self.create_geometry()

View File

@@ -8,6 +8,7 @@ from copy import deepcopy
from shapely.ops import unary_union, linemerge
import shapely.affinity as affinity
from shapely.geometry import box as shply_box
from shapely.geometry import LinearRing, MultiLineString
from lxml import etree as ET
import ezdxf
@@ -2488,13 +2489,14 @@ class Gerber(Geometry):
self.app.inform.emit('[success] %s' % _("Done."))
self.app.proc_container.new_text = ''
def buffer(self, distance, join=2, factor=None):
def buffer(self, distance, join=2, factor=None, only_exterior=False):
"""
:param distance: If 'factor' is True then distance is the factor
:param join: The type of joining used by the Shapely buffer method. Can be: round, square and bevel
:param factor: True or False (None)
:return:
:param distance: If 'factor' is True then distance is the factor
:param join: The type of joining used by the Shapely buffer method. Can be: round, square and bevel
:param factor: True or False (None)
:param only_exterior: Bool. If True, the LineStrings are buffered only on the outside
:return: None
"""
self.app.log.debug("parseGerber.Gerber.buffer()")
@@ -2513,23 +2515,20 @@ class Gerber(Geometry):
if factor is None:
def buffer_geom(obj):
if type(obj) is list:
new_obj = []
for g in obj:
new_obj = []
try:
work_geo = obj.geoms if isinstance(obj, (MultiPolygon, MultiLineString)) else obj
for g in work_geo:
new_obj.append(buffer_geom(g))
return new_obj
else:
except TypeError:
try:
self.el_count += 1
disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 100]))
if self.old_disp_number < disp_number <= 100:
self.app.proc_container.update_view_text(' %d%%' % disp_number)
self.old_disp_number = disp_number
return obj.buffer(distance, resolution=int(self.steps_per_circle), join_style=join)
new_obj = obj.buffer(distance, resolution=self.steps_per_circle, join_style=join)
if isinstance(obj, (LinearRing, LineString)) and only_exterior is True:
new_obj = new_obj.exterior
except AttributeError:
return obj
new_obj = obj
return new_obj
self.solid_geometry = flatten_shapely_geometry(buffer_geom(self.solid_geometry))