- Tool Cutout - more work in gaps thickness control feature

- Tool Cutout - added some icons to buttons
This commit is contained in:
Marius Stanciu 2020-08-05 11:46:56 +03:00
parent b26062c68a
commit b5f77eac1b
7 changed files with 171 additions and 84 deletions

View File

@ -7,11 +7,16 @@ CHANGELOG for FlatCAM beta
================================================= =================================================
5.08.2020
- Tool Cutout - more work in gaps thickness control feature
- Tool Cutout - added some icons to buttons
4.08.2020 4.08.2020
- removed the Toolchange Macro feature (in the future it will be replaced by full preprocessor customization) - removed the Toolchange Macro feature (in the future it will be replaced by full preprocessor customization)
- modified GUI in Preferences - modified GUI in Preferences
- Tool Cutout - working in adding gaps suppression feature; added the UI in the Tool - Tool Cutout - working in adding gaps thickness control feature; added the UI in the Tool
3.08.2020 3.08.2020

View File

@ -320,42 +320,54 @@ class CutOut(AppTool):
pass pass
else: else:
if gaps == '8' or gaps == '2LR': if gaps == '8' or gaps == '2LR':
geom = self.subtract_poly_from_geo(geom, points = (
xxmin - gapsize, # botleft_x xxmin - gapsize, # botleft_x
py - gapsize + leny / 4, # botleft_y py - gapsize + leny / 4, # botleft_y
xxmax + gapsize, # topright_x xxmax + gapsize, # topright_x
py + gapsize + leny / 4) # topright_y py + gapsize + leny / 4 # topright_y
geom = self.subtract_poly_from_geo(geom, )
xxmin - gapsize, geom = self.subtract_poly_from_geo(geom, points)
py - gapsize - leny / 4, points = (
xxmax + gapsize, xxmin - gapsize,
py + gapsize - leny / 4) py - gapsize - leny / 4,
xxmax + gapsize,
py + gapsize - leny / 4
)
geom = self.subtract_poly_from_geo(geom, points)
if gaps == '8' or gaps == '2TB': if gaps == '8' or gaps == '2TB':
geom = self.subtract_poly_from_geo(geom, points = (
px - gapsize + lenx / 4, px - gapsize + lenx / 4,
yymin - gapsize, yymin - gapsize,
px + gapsize + lenx / 4, px + gapsize + lenx / 4,
yymax + gapsize) yymax + gapsize
geom = self.subtract_poly_from_geo(geom, )
px - gapsize - lenx / 4, geom = self.subtract_poly_from_geo(geom, points)
yymin - gapsize, points = (
px + gapsize - lenx / 4, px - gapsize - lenx / 4,
yymax + gapsize) yymin - gapsize,
px + gapsize - lenx / 4,
yymax + gapsize
)
geom = self.subtract_poly_from_geo(geom, points)
if gaps == '4' or gaps == 'LR': if gaps == '4' or gaps == 'LR':
geom = self.subtract_poly_from_geo(geom, points = (
xxmin - gapsize, xxmin - gapsize,
py - gapsize, py - gapsize,
xxmax + gapsize, xxmax + gapsize,
py + gapsize) py + gapsize
)
geom = self.subtract_poly_from_geo(geom, points)
if gaps == '4' or gaps == 'TB': if gaps == '4' or gaps == 'TB':
geom = self.subtract_poly_from_geo(geom, points = (
px - gapsize, px - gapsize,
yymin - gapsize, yymin - gapsize,
px + gapsize, px + gapsize,
yymax + gapsize) yymax + gapsize
)
geom = self.subtract_poly_from_geo(geom, points)
try: try:
for g in geom: for g in geom:
@ -520,42 +532,55 @@ class CutOut(AppTool):
pass pass
else: else:
if gaps == '8' or gaps == '2LR': if gaps == '8' or gaps == '2LR':
geom = self.subtract_poly_from_geo(geom, points = (
xmin - gapsize, # botleft_x xmin - gapsize, # botleft_x
py - gapsize + leny / 4, # botleft_y py - gapsize + leny / 4, # botleft_y
xmax + gapsize, # topright_x xmax + gapsize, # topright_x
py + gapsize + leny / 4) # topright_y py + gapsize + leny / 4 # topright_y
geom = self.subtract_poly_from_geo(geom, )
xmin - gapsize, geom = self.subtract_poly_from_geo(geom, points)
py - gapsize - leny / 4, points = (
xmax + gapsize, xmin - gapsize,
py + gapsize - leny / 4) py - gapsize - leny / 4,
xmax + gapsize,
py + gapsize - leny / 4
)
geom = self.subtract_poly_from_geo(geom, points)
if gaps == '8' or gaps == '2TB': if gaps == '8' or gaps == '2TB':
geom = self.subtract_poly_from_geo(geom, points = (
px - gapsize + lenx / 4, px - gapsize + lenx / 4,
ymin - gapsize, ymin - gapsize,
px + gapsize + lenx / 4, px + gapsize + lenx / 4,
ymax + gapsize) ymax + gapsize
geom = self.subtract_poly_from_geo(geom, )
px - gapsize - lenx / 4, geom = self.subtract_poly_from_geo(geom, points)
ymin - gapsize, points = (
px + gapsize - lenx / 4, px - gapsize - lenx / 4,
ymax + gapsize) ymin - gapsize,
px + gapsize - lenx / 4,
ymax + gapsize
)
geom = self.subtract_poly_from_geo(geom, points)
if gaps == '4' or gaps == 'LR': if gaps == '4' or gaps == 'LR':
geom = self.subtract_poly_from_geo(geom, points = (
xmin - gapsize, xmin - gapsize,
py - gapsize, py - gapsize,
xmax + gapsize, xmax + gapsize,
py + gapsize) py + gapsize
)
geom = self.subtract_poly_from_geo(geom, points)
if gaps == '4' or gaps == 'TB': if gaps == '4' or gaps == 'TB':
geom = self.subtract_poly_from_geo(geom, points = (
px - gapsize, px - gapsize,
ymin - gapsize, ymin - gapsize,
px + gapsize, px + gapsize,
ymax + gapsize) ymax + gapsize
)
geom = self.subtract_poly_from_geo(geom, points)
try: try:
for g in geom: for g in geom:
proc_geometry.append(g) proc_geometry.append(g)
@ -1088,20 +1113,29 @@ class CutOut(AppTool):
self.draw_utility_geometry(geo=geo) self.draw_utility_geometry(geo=geo)
@staticmethod @staticmethod
def subtract_poly_from_geo(solid_geo, x0, y0, x1, y1): def subtract_poly_from_geo(solid_geo, pts):
""" """
Subtract polygon made from points from the given object. Subtract polygon made from points from the given object.
This only operates on the paths in the original geometry, This only operates on the paths in the original geometry,
i.e. it converts polygons into paths. i.e. it converts polygons into paths.
:param x0: x coord for lower left vertex of the polygon. :param solid_geo: Geometry from which to subtract.
:param y0: y coord for lower left vertex of the polygon. :param pts: a tuple of coordinates in format (x0, y0, x1, y1)
:param x1: x coord for upper right vertex of the polygon. :type pts: tuple
:param y1: y coord for upper right vertex of the polygon.
x0: x coord for lower left vertex of the polygon.
y0: y coord for lower left vertex of the polygon.
x1: x coord for upper right vertex of the polygon.
y1: y coord for upper right vertex of the polygon.
:param solid_geo: Geometry from which to substract. If none, use the solid_geomety property of the object
:return: none :return: none
""" """
x0 = pts[0]
y0 = pts[1]
x1 = pts[2]
y1 = pts[3]
points = [(x0, y0), (x1, y0), (x1, y1), (x0, y1)] points = [(x0, y0), (x1, y0), (x1, y1), (x0, y1)]
# pathonly should be allways True, otherwise polygons are not subtracted # pathonly should be allways True, otherwise polygons are not subtracted
@ -1120,6 +1154,50 @@ class CutOut(AppTool):
return unary_union(diffs) return unary_union(diffs)
@staticmethod
def intersect_poly_with_geo(solid_geo, pts, margin):
"""
Intersections with a polygon made from points from the given object.
This only operates on the paths in the original geometry,
i.e. it converts polygons into paths.
:param solid_geo: Geometry from which to get intersections.
:param pts: a tuple of coordinates in format (x0, y0, x1, y1)
:type pts: tuple
:param margin: a distance (buffer) applied to each solid_geo
x0: x coord for lower left vertex of the polygon.
y0: y coord for lower left vertex of the polygon.
x1: x coord for upper right vertex of the polygon.
y1: y coord for upper right vertex of the polygon.
:return: none
"""
x0 = pts[0]
y0 = pts[1]
x1 = pts[2]
y1 = pts[3]
points = [(x0, y0), (x1, y0), (x1, y1), (x0, y1)]
# pathonly should be allways True, otherwise polygons are not subtracted
flat_geometry = CutOut.flatten(geometry=solid_geo)
log.debug("%d paths" % len(flat_geometry))
polygon = Polygon(points)
toolgeo = cascaded_union(polygon)
intersects = []
for target in flat_geometry:
if type(target) == LineString or type(target) == LinearRing:
intersects.append(target.intersection(toolgeo))
else:
log.warning("Not implemented.")
return unary_union(intersects)
@staticmethod @staticmethod
def flatten(geometry): def flatten(geometry):
""" """
@ -1351,29 +1429,29 @@ class CutoutUI:
grid0.addWidget(self.mpass_cb, 10, 0) grid0.addWidget(self.mpass_cb, 10, 0)
grid0.addWidget(self.maxdepth_entry, 10, 1) grid0.addWidget(self.maxdepth_entry, 10, 1)
# Suppress gaps # Thin gaps
self.suppress_cb = FCCheckBox('%s:' % _("Suppress gaps")) self.thin_cb = FCCheckBox('%s:' % _("Thin gaps"))
self.suppress_cb.setToolTip( self.thin_cb.setToolTip(
_("Active only when multi depth is active.\n" _("Active only when multi depth is active.\n"
"If checked, the gaps will not be used until the specified depth.")) "If checked, the gaps will start at the specified depth."))
self.suppress_depth_entry = FCDoubleSpinner(callback=self.confirmation_message) self.thin_depth_entry = FCDoubleSpinner(callback=self.confirmation_message)
self.suppress_depth_entry.set_precision(self.decimals) self.thin_depth_entry.set_precision(self.decimals)
self.suppress_depth_entry.setRange(0, 9999.9999) self.thin_depth_entry.setRange(0, 9999.9999)
self.suppress_depth_entry.setSingleStep(0.1) self.thin_depth_entry.setSingleStep(0.1)
self.suppress_depth_entry.setToolTip( self.thin_depth_entry.setToolTip(
_("Active only when multi depth is active.\n" _("Active only when multi depth is active.\n"
"If checked, the gaps will not be used until the specified depth.")) "If checked, the gaps will start at the specified depth."))
grid0.addWidget(self.suppress_cb, 12, 0) grid0.addWidget(self.thin_cb, 12, 0)
grid0.addWidget(self.suppress_depth_entry, 12, 1) grid0.addWidget(self.thin_depth_entry, 12, 1)
self.ois_mpass_geo = OptionalInputSection(self.mpass_cb, self.ois_mpass_geo = OptionalInputSection(self.mpass_cb,
[ [
self.maxdepth_entry, self.maxdepth_entry,
self.suppress_cb, self.thin_cb,
self.suppress_depth_entry self.thin_depth_entry
]) ])
# Margin # Margin
@ -1461,7 +1539,8 @@ class CutoutUI:
grid0.addWidget(self.gaps, 26, 1) grid0.addWidget(self.gaps, 26, 1)
# Buttons # Buttons
self.ff_cutout_object_btn = FCButton(_("Generate Freeform Geometry")) self.ff_cutout_object_btn = FCButton(_("Generate Geometry"))
self.ff_cutout_object_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/irregular32.png'))
self.ff_cutout_object_btn.setToolTip( self.ff_cutout_object_btn.setToolTip(
_("Cutout the selected object.\n" _("Cutout the selected object.\n"
"The cutout shape can be of any shape.\n" "The cutout shape can be of any shape.\n"
@ -1475,7 +1554,8 @@ class CutoutUI:
""") """)
grid0.addWidget(self.ff_cutout_object_btn, 28, 0, 1, 2) grid0.addWidget(self.ff_cutout_object_btn, 28, 0, 1, 2)
self.rect_cutout_object_btn = FCButton(_("Generate Rectangular Geometry")) self.rect_cutout_object_btn = FCButton(_("Generate Geometry"))
self.rect_cutout_object_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/rectangle32.png'))
self.rect_cutout_object_btn.setToolTip( self.rect_cutout_object_btn.setToolTip(
_("Cutout the selected object.\n" _("Cutout the selected object.\n"
"The resulting cutout shape is\n" "The resulting cutout shape is\n"
@ -1517,6 +1597,7 @@ class CutoutUI:
# Generate a surrounding Geometry object # Generate a surrounding Geometry object
self.man_geo_creation_btn = FCButton(_("Generate Manual Geometry")) self.man_geo_creation_btn = FCButton(_("Generate Manual Geometry"))
self.man_geo_creation_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/rectangle32.png'))
self.man_geo_creation_btn.setToolTip( self.man_geo_creation_btn.setToolTip(
_("If the object to be cutout is a Gerber\n" _("If the object to be cutout is a Gerber\n"
"first create a Geometry that surrounds it,\n" "first create a Geometry that surrounds it,\n"
@ -1548,6 +1629,7 @@ class CutoutUI:
grid0.addWidget(self.man_object_combo, 44, 0, 1, 2) grid0.addWidget(self.man_object_combo, 44, 0, 1, 2)
self.man_gaps_creation_btn = FCButton(_("Manual Add Bridge Gaps")) self.man_gaps_creation_btn = FCButton(_("Manual Add Bridge Gaps"))
self.man_gaps_creation_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/gaps32.png'))
self.man_gaps_creation_btn.setToolTip( self.man_gaps_creation_btn.setToolTip(
_("Use the left mouse button (LMB) click\n" _("Use the left mouse button (LMB) click\n"
"to create a bridge gap to separate the PCB from\n" "to create a bridge gap to separate the PCB from\n"

View File

@ -2436,7 +2436,7 @@ class App(QtCore.QObject):
continue continue
else: else:
self.inform.emit('[WARNING_NOTCL] %s' % self.inform.emit('[WARNING_NOTCL] %s' %
_("Select a Gerber, Geometry, Excellon or CNCJobObject to update.")) _("Select a Gerber, Geometry, Excellon or CNCJob Object to update."))
return return
elif response == bt_cancel: elif response == bt_cancel:
return return

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 885 B

BIN
assets/resources/gaps32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 444 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 666 B