- modified the Cutout Tool to generate multi-geo objects therefore the set geometry parameters will populate the Geometry Object UI

- modified the Panelize Tool to optimize the output from Cutout Tool such that there are no longer overlapping cuts
- some string corrections
This commit is contained in:
Marius Stanciu 2020-05-02 15:56:30 +03:00 committed by Marius
parent 48b3f8d65a
commit ada271cbd6
23 changed files with 238 additions and 137 deletions

View File

@ -14,6 +14,9 @@ CHANGELOG for FlatCAM beta
- fixed bug in Gerber Editor in which the units conversion wasn't calculated correct
- fixed bug in Gerber Editor in which the QThread that is started on object edit was not stopped at clean up stage
- fixed bug in Gerber Editor that kept all the apertures (including the geometry) of a previously edited object that was not saved after edit
- modified the Cutout Tool to generate multi-geo objects therefore the set geometry parameters will populate the Geometry Object UI
- modified the Panelize Tool to optimize the output from Cutout Tool such that there are no longer overlapping cuts
- some string corrections
01.05.2020

View File

@ -4111,9 +4111,11 @@ class App(QtCore.QObject):
obj.multigeo = True
for tooluid, dict_value in obj.tools.items():
dict_value['solid_geometry'] = deepcopy(obj.solid_geometry)
if not isinstance(obj.solid_geometry, list):
obj.solid_geometry = [obj.solid_geometry]
obj.solid_geometry[:] = []
# obj.solid_geometry[:] = []
obj.plot()
self.should_we_save = True
@ -5024,7 +5026,7 @@ class App(QtCore.QObject):
self.paste_tool.on_add_tool_by_key()
# It's meant to delete tools in tool tables via a 'Delete' shortcut key but only if certain conditions are met
# See description bellow.
# See description below.
def on_delete_keypress(self):
notebook_widget_name = self.ui.notebook.currentWidget().objectName()

View File

@ -3226,7 +3226,7 @@ class FlatCAMExcEditor(QtCore.QObject):
spec = {"C": float(tool_dia[0])}
self.new_tools[name] = spec
# add in self.tools the 'solid_geometry' key, the value (a list) is populated bellow
# add in self.tools the 'solid_geometry' key, the value (a list) is populated below
self.new_tools[name]['solid_geometry'] = []
# create the self.drills for the new Excellon object (the one with edited content)
@ -3258,7 +3258,7 @@ class FlatCAMExcEditor(QtCore.QObject):
spec = {"C": float(tool_dia[0])}
self.new_tools[name] = spec
# add in self.tools the 'solid_geometry' key, the value (a list) is populated bellow
# add in self.tools the 'solid_geometry' key, the value (a list) is populated below
self.new_tools[name]['solid_geometry'] = []
# create the self.slots for the new Excellon object (the one with edited content)

View File

@ -3232,7 +3232,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
else:
self.app.collection.set_active(names_list[active_index-1])
# Select the object in the Tree bellow the current one
# Select the object in the Tree below the current one
if key == QtCore.Qt.Key_Down:
# make sure it works only for the Project Tab who is an instance of KeySensitiveListView
focused_wdg = QtWidgets.QApplication.focusWidget()

View File

@ -42,7 +42,7 @@ class PreferencesUIManager:
# if Preferences are changed in the Edit -> Preferences tab the value will be set to True
self.preferences_changed_flag = False
# when adding entries here read the comments in the method found bellow named:
# when adding entries here read the comments in the method found below named:
# def new_object(self, kind, name, initialize, active=True, fit=True, plot=True)
self.defaults_form_fields = {
# General App

View File

@ -364,7 +364,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
self.units_found = self.app.defaults['units']
# this signal has to be connected to it's slot before the defaults are populated
# the decision done in the slot has to override the default value set bellow
# the decision done in the slot has to override the default value set below
self.ui.toolchange_cb.toggled.connect(self.on_toolchange_custom_clicked)
self.form_fields.update({

View File

@ -426,7 +426,7 @@ class Excellon(Geometry):
# it's possible that tool definition has only tool number and no diameter info
# (those could be in another file like PCB Wizard do)
# then match.group(2) = None and float(None) will create the exception
# the bellow construction is so each tool will have a slightly different diameter
# the below construction is so each tool will have a slightly different diameter
# starting with a default value, to allow Excellon editing after that
self.diameterless = True
self.app.inform.emit('[WARNING] %s%s %s' %

View File

@ -293,12 +293,12 @@ class CutOut(FlatCAMTool):
font-weight: bold;
}
""")
self.layout.addWidget(self.rect_cutout_object_btn)
grid0.addWidget(self.rect_cutout_object_btn, 21, 0, 1, 2)
separator_line = QtWidgets.QFrame()
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
grid0.addWidget(separator_line, 21, 0, 1, 2)
grid0.addWidget(separator_line, 22, 0, 1, 2)
# Title5
title_manual_label = QtWidgets.QLabel("<font size=4><b>%s</b></font>" % _('B. Manual Bridge Gaps'))
@ -307,7 +307,7 @@ class CutOut(FlatCAMTool):
"This is done by mouse clicking on the perimeter of the\n"
"Geometry object that is used as a cutout object. ")
)
grid0.addWidget(title_manual_label, 22, 0, 1, 2)
grid0.addWidget(title_manual_label, 23, 0, 1, 2)
# Manual Geo Object
self.man_object_combo = FCComboBox()
@ -322,8 +322,8 @@ class CutOut(FlatCAMTool):
)
# self.man_object_label.setMinimumWidth(60)
grid0.addWidget(self.man_object_label, 23, 0, 1, 2)
grid0.addWidget(self.man_object_combo, 24, 0, 1, 2)
grid0.addWidget(self.man_object_label, 25, 0, 1, 2)
grid0.addWidget(self.man_object_combo, 26, 0, 1, 2)
self.man_geo_creation_btn = FCButton(_("Generate Manual Geometry"))
self.man_geo_creation_btn.setToolTip(
@ -338,7 +338,7 @@ class CutOut(FlatCAMTool):
font-weight: bold;
}
""")
grid0.addWidget(self.man_geo_creation_btn, 25, 0, 1, 2)
grid0.addWidget(self.man_geo_creation_btn, 28, 0, 1, 2)
self.man_gaps_creation_btn = FCButton(_("Manual Add Bridge Gaps"))
self.man_gaps_creation_btn.setToolTip(
@ -354,7 +354,7 @@ class CutOut(FlatCAMTool):
font-weight: bold;
}
""")
grid0.addWidget(self.man_gaps_creation_btn, 27, 0, 1, 2)
grid0.addWidget(self.man_gaps_creation_btn, 30, 0, 1, 2)
self.layout.addStretch()
@ -394,6 +394,9 @@ class CutOut(FlatCAMTool):
self.x_pos = None
self.y_pos = None
# store the default data for the resulting Geometry Object
self.default_data = {}
# Signals
self.ff_cutout_object_btn.clicked.connect(self.on_freeform_cutout)
self.rect_cutout_object_btn.clicked.connect(self.on_rectangular_cutout)
@ -454,6 +457,48 @@ class CutOut(FlatCAMTool):
self.convex_box.set_value(self.app.defaults['tools_cutout_convexshape'])
self.type_obj_radio.set_value('grb')
self.default_data.update({
"plot": True,
"cutz": float(self.app.defaults["geometry_cutz"]),
"multidepth": self.app.defaults["geometry_multidepth"],
"depthperpass": float(self.app.defaults["geometry_depthperpass"]),
"vtipdia": float(self.app.defaults["geometry_vtipdia"]),
"vtipangle": float(self.app.defaults["geometry_vtipangle"]),
"travelz": float(self.app.defaults["geometry_travelz"]),
"feedrate": float(self.app.defaults["geometry_feedrate"]),
"feedrate_z": float(self.app.defaults["geometry_feedrate_z"]),
"feedrate_rapid": float(self.app.defaults["geometry_feedrate_rapid"]),
"spindlespeed": self.app.defaults["geometry_spindlespeed"],
"dwell": self.app.defaults["geometry_dwell"],
"dwelltime": float(self.app.defaults["geometry_dwelltime"]),
"ppname_g": self.app.defaults["geometry_ppname_g"],
"extracut": self.app.defaults["geometry_extracut"],
"extracut_length": float(self.app.defaults["geometry_extracut_length"]),
"toolchange": self.app.defaults["geometry_toolchange"],
"toolchangexy": self.app.defaults["geometry_toolchangexy"],
"toolchangez": float(self.app.defaults["geometry_toolchangez"]),
"startz": self.app.defaults["geometry_startz"],
"endz": float(self.app.defaults["geometry_endz"]),
# NCC
"tools_nccoperation": self.app.defaults["tools_nccoperation"],
"tools_nccmilling_type": self.app.defaults["tools_nccmilling_type"],
"tools_nccoverlap": float(self.app.defaults["tools_nccoverlap"]),
"tools_nccmargin": float(self.app.defaults["tools_nccmargin"]),
"tools_nccmethod": self.app.defaults["tools_nccmethod"],
"tools_nccconnect": self.app.defaults["tools_nccconnect"],
"tools_ncccontour": self.app.defaults["tools_ncccontour"],
"tools_ncc_offset_choice": self.app.defaults["tools_ncc_offset_choice"],
"tools_ncc_offset_value": float(self.app.defaults["tools_ncc_offset_value"]),
# Paint
"tools_paintoverlap": float(self.app.defaults["tools_paintoverlap"]),
"tools_paintmargin": float(self.app.defaults["tools_paintmargin"]),
"tools_paintmethod": self.app.defaults["tools_paintmethod"],
"tools_pathconnect": self.app.defaults["tools_pathconnect"],
"tools_paintcontour": self.app.defaults["tools_paintcontour"],
})
def on_freeform_cutout(self):
log.debug("Cutout.on_freeform_cutout() was launched ...")
@ -622,8 +667,8 @@ class CutOut(FlatCAMTool):
solid_geo += cutout_handler(geom=geom_struct)
geo_obj.solid_geometry = deepcopy(solid_geo)
xmin, ymin, xmax, ymax = recursive_bounds(geo_obj.solid_geometry)
geo_obj.solid_geometry = deepcopy(solid_geo)
geo_obj.options['xmin'] = xmin
geo_obj.options['ymin'] = ymin
geo_obj.options['xmax'] = xmax
@ -633,6 +678,23 @@ class CutOut(FlatCAMTool):
geo_obj.options['multidepth'] = self.mpass_cb.get_value()
geo_obj.options['depthperpass'] = self.maxdepth_entry.get_value()
geo_obj.tools.update({
1: {
'tooldia': str(dia),
'offset': 'Path',
'offset_value': 0.0,
'type': _('Rough'),
'tool_type': 'C1',
'data': self.default_data,
'solid_geometry': geo_obj.solid_geometry
}
})
geo_obj.multigeo = True
geo_obj.tools[1]['data']['name'] = outname
geo_obj.tools[1]['data']['cutz'] = self.cutz_entry.get_value()
geo_obj.tools[1]['data']['multidepth'] = self.mpass_cb.get_value()
geo_obj.tools[1]['data']['depthperpass'] = self.maxdepth_entry.get_value()
outname = cutout_obj.options["name"] + "_cutout"
self.app.new_object('geometry', outname, geo_init)
@ -759,6 +821,7 @@ class CutOut(FlatCAMTool):
return proc_geometry
if kind == 'single':
# fuse the lines
object_geo = unary_union(object_geo)
xmin, ymin, xmax, ymax = object_geo.bounds
@ -805,11 +868,28 @@ class CutOut(FlatCAMTool):
_("Rectangular cutout with negative margin is not possible."))
return "fail"
geo_obj.solid_geometry = deepcopy(solid_geo)
geo_obj.options['cnctooldia'] = str(dia)
geo_obj.options['cutz'] = self.cutz_entry.get_value()
geo_obj.options['multidepth'] = self.mpass_cb.get_value()
geo_obj.options['depthperpass'] = self.maxdepth_entry.get_value()
geo_obj.solid_geometry = deepcopy(solid_geo)
geo_obj.tools.update({
1: {
'tooldia': str(dia),
'offset': 'Path',
'offset_value': 0.0,
'type': _('Rough'),
'tool_type': 'C1',
'data': self.default_data,
'solid_geometry': geo_obj.solid_geometry
}
})
geo_obj.multigeo = True
geo_obj.tools[1]['data']['name'] = outname
geo_obj.tools[1]['data']['cutz'] = self.cutz_entry.get_value()
geo_obj.tools[1]['data']['multidepth'] = self.mpass_cb.get_value()
geo_obj.tools[1]['data']['depthperpass'] = self.maxdepth_entry.get_value()
outname = cutout_obj.options["name"] + "_cutout"
ret = self.app.new_object('geometry', outname, geo_init)
@ -954,6 +1034,23 @@ class CutOut(FlatCAMTool):
geo_obj.options['multidepth'] = self.mpass_cb.get_value()
geo_obj.options['depthperpass'] = self.maxdepth_entry.get_value()
geo_obj.tools.update({
1: {
'tooldia': str(dia),
'offset': 'Path',
'offset_value': 0.0,
'type': _('Rough'),
'tool_type': 'C1',
'data': self.default_data,
'solid_geometry': geo_obj.solid_geometry
}
})
geo_obj.multigeo = True
geo_obj.tools[1]['data']['name'] = outname
geo_obj.tools[1]['data']['cutz'] = self.cutz_entry.get_value()
geo_obj.tools[1]['data']['multidepth'] = self.mpass_cb.get_value()
geo_obj.tools[1]['data']['depthperpass'] = self.maxdepth_entry.get_value()
outname = cutout_obj.options["name"] + "_cutout"
self.app.new_object('geometry', outname, geo_init)

View File

@ -14,6 +14,8 @@ from copy import deepcopy
import numpy as np
import shapely.affinity as affinity
from shapely.ops import unary_union
from shapely.geometry import LineString
import gettext
import FlatCAMTranslation as fcTranslate
@ -402,19 +404,18 @@ class Panelize(FlatCAMTool):
def on_panelize(self):
name = self.object_combo.currentText()
# Get source object.
# Get source object to be panelized.
try:
panel_obj = self.app.collection.get_by_name(str(name))
panel_source_obj = self.app.collection.get_by_name(str(name))
except Exception as e:
log.debug("Panelize.on_panelize() --> %s" % str(e))
self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
(_("Could not retrieve object"), name))
self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Could not retrieve object"), name))
return "Could not retrieve object: %s" % name
if panel_obj is None:
if panel_source_obj is None:
self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
(_("Object not found"), panel_obj))
return "Object not found: %s" % panel_obj
(_("Object not found"), panel_source_obj))
return "Object not found: %s" % panel_source_obj
boxname = self.box_combo.currentText()
@ -422,17 +423,15 @@ class Panelize(FlatCAMTool):
box = self.app.collection.get_by_name(boxname)
except Exception as e:
log.debug("Panelize.on_panelize() --> %s" % str(e))
self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
(_("Could not retrieve object"), boxname))
self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Could not retrieve object"), boxname))
return "Could not retrieve object: %s" % boxname
if box is None:
self.app.inform.emit('[WARNING_NOTCL]%s: %s' %
(_("No object Box. Using instead"), panel_obj))
self.app.inform.emit('[WARNING_NOTCL]%s: %s' % (_("No object Box. Using instead"), panel_source_obj))
self.reference_radio.set_value('bbox')
if self.reference_radio.get_value() == 'bbox':
box = panel_obj
box = panel_source_obj
self.outname = name + '_panelized'
@ -478,20 +477,20 @@ class Panelize(FlatCAMTool):
rows -= 1
panel_lengthy = ((ymax - ymin) * rows) + (spacing_rows * (rows - 1))
if panel_obj.kind == 'excellon' or panel_obj.kind == 'geometry':
if panel_source_obj.kind == 'excellon' or panel_source_obj.kind == 'geometry':
# make a copy of the panelized Excellon or Geometry tools
copied_tools = {}
for tt, tt_val in list(panel_obj.tools.items()):
for tt, tt_val in list(panel_source_obj.tools.items()):
copied_tools[tt] = deepcopy(tt_val)
if panel_obj.kind == 'gerber':
if panel_source_obj.kind == 'gerber':
# make a copy of the panelized Gerber apertures
copied_apertures = {}
for tt, tt_val in list(panel_obj.apertures.items()):
for tt, tt_val in list(panel_source_obj.apertures.items()):
copied_apertures[tt] = deepcopy(tt_val)
def panelize_2():
if panel_obj is not None:
def panelize_worker():
if panel_source_obj is not None:
self.app.inform.emit(_("Generating panel ... "))
def job_init_excellon(obj_fin, app_obj):
@ -501,15 +500,15 @@ class Panelize(FlatCAMTool):
obj_fin.slots = []
obj_fin.solid_geometry = []
for option in panel_obj.options:
for option in panel_source_obj.options:
if option != 'name':
try:
obj_fin.options[option] = panel_obj.options[option]
obj_fin.options[option] = panel_source_obj.options[option]
except KeyError:
log.warning("Failed to copy option. %s" % str(option))
geo_len_drills = len(panel_obj.drills) if panel_obj.drills else 0
geo_len_slots = len(panel_obj.slots) if panel_obj.slots else 0
geo_len_drills = len(panel_source_obj.drills) if panel_source_obj.drills else 0
geo_len_slots = len(panel_source_obj.slots) if panel_source_obj.slots else 0
element = 0
for row in range(rows):
@ -518,9 +517,9 @@ class Panelize(FlatCAMTool):
element += 1
old_disp_number = 0
if panel_obj.drills:
if panel_source_obj.drills:
drill_nr = 0
for tool_dict in panel_obj.drills:
for tool_dict in panel_source_obj.drills:
if self.app.abort_flag:
# graceful abort requested by the user
raise grace
@ -543,9 +542,9 @@ class Panelize(FlatCAMTool):
disp_number))
old_disp_number = disp_number
if panel_obj.slots:
if panel_source_obj.slots:
slot_nr = 0
for tool_dict in panel_obj.slots:
for tool_dict in panel_source_obj.slots:
if self.app.abort_flag:
# graceful abort requested by the user
raise grace
@ -574,8 +573,8 @@ class Panelize(FlatCAMTool):
currenty += lenghty
obj_fin.create_geometry()
obj_fin.zeros = panel_obj.zeros
obj_fin.units = panel_obj.units
obj_fin.zeros = panel_source_obj.zeros
obj_fin.units = panel_source_obj.units
self.app.proc_container.update_view_text('')
def job_init_geometry(obj_fin, app_obj):
@ -598,36 +597,36 @@ class Panelize(FlatCAMTool):
obj_fin.solid_geometry = []
# create the initial structure on which to create the panel
if panel_obj.kind == 'geometry':
obj_fin.multigeo = panel_obj.multigeo
if panel_source_obj.kind == 'geometry':
obj_fin.multigeo = panel_source_obj.multigeo
obj_fin.tools = copied_tools
if panel_obj.multigeo is True:
for tool in panel_obj.tools:
if panel_source_obj.multigeo is True:
for tool in panel_source_obj.tools:
obj_fin.tools[tool]['solid_geometry'][:] = []
elif panel_obj.kind == 'gerber':
elif panel_source_obj.kind == 'gerber':
obj_fin.apertures = copied_apertures
for ap in obj_fin.apertures:
obj_fin.apertures[ap]['geometry'] = []
# find the number of polygons in the source solid_geometry
geo_len = 0
if panel_obj.kind == 'geometry':
if panel_obj.multigeo is True:
for tool in panel_obj.tools:
if panel_source_obj.kind == 'geometry':
if panel_source_obj.multigeo is True:
for tool in panel_source_obj.tools:
try:
geo_len += len(panel_obj.tools[tool]['solid_geometry'])
geo_len += len(panel_source_obj.tools[tool]['solid_geometry'])
except TypeError:
geo_len += 1
else:
try:
geo_len = len(panel_obj.solid_geometry)
geo_len = len(panel_source_obj.solid_geometry)
except TypeError:
geo_len = 1
elif panel_obj.kind == 'gerber':
for ap in panel_obj.apertures:
if 'geometry' in panel_obj.apertures[ap]:
elif panel_source_obj.kind == 'gerber':
for ap in panel_source_obj.apertures:
if 'geometry' in panel_source_obj.apertures[ap]:
try:
geo_len += len(panel_obj.apertures[ap]['geometry'])
geo_len += len(panel_source_obj.apertures[ap]['geometry'])
except TypeError:
geo_len += 1
@ -639,29 +638,23 @@ class Panelize(FlatCAMTool):
element += 1
old_disp_number = 0
if panel_obj.kind == 'geometry':
if panel_obj.multigeo is True:
for tool in panel_obj.tools:
# Will panelize a Geometry Object
if panel_source_obj.kind == 'geometry':
if panel_source_obj.multigeo is True:
for tool in panel_source_obj.tools:
if self.app.abort_flag:
# graceful abort requested by the user
raise grace
# geo = translate_recursion(panel_obj.tools[tool]['solid_geometry'])
# if isinstance(geo, list):
# obj_fin.tools[tool]['solid_geometry'] += geo
# else:
# obj_fin.tools[tool]['solid_geometry'].append(geo)
# calculate the number of polygons
geo_len = len(panel_obj.tools[tool]['solid_geometry'])
geo_len = len(panel_source_obj.tools[tool]['solid_geometry'])
pol_nr = 0
for geo_el in panel_obj.tools[tool]['solid_geometry']:
for geo_el in panel_source_obj.tools[tool]['solid_geometry']:
trans_geo = translate_recursion(geo_el)
obj_fin.tools[tool]['solid_geometry'].append(trans_geo)
pol_nr += 1
disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
if old_disp_number < disp_number <= 100:
self.app.proc_container.update_view_text(' %s: %d %d%%' %
(_("Copy"),
@ -669,23 +662,18 @@ class Panelize(FlatCAMTool):
disp_number))
old_disp_number = disp_number
else:
# geo = translate_recursion(panel_obj.solid_geometry)
# if isinstance(geo, list):
# obj_fin.solid_geometry += geo
# else:
# obj_fin.solid_geometry.append(geo)
if self.app.abort_flag:
# graceful abort requested by the user
raise grace
try:
# calculate the number of polygons
geo_len = len(panel_obj.solid_geometry)
geo_len = len(panel_source_obj.solid_geometry)
except TypeError:
geo_len = 1
pol_nr = 0
try:
for geo_el in panel_obj.solid_geometry:
for geo_el in panel_source_obj.solid_geometry:
if self.app.abort_flag:
# graceful abort requested by the user
raise grace
@ -702,21 +690,18 @@ class Panelize(FlatCAMTool):
int(element),
disp_number))
old_disp_number = disp_number
except TypeError:
trans_geo = translate_recursion(panel_obj.solid_geometry)
trans_geo = translate_recursion(panel_source_obj.solid_geometry)
obj_fin.solid_geometry.append(trans_geo)
# Will panelize a Gerber Object
else:
# geo = translate_recursion(panel_obj.solid_geometry)
# if isinstance(geo, list):
# obj_fin.solid_geometry += geo
# else:
# obj_fin.solid_geometry.append(geo)
if self.app.abort_flag:
# graceful abort requested by the user
raise grace
try:
for geo_el in panel_obj.solid_geometry:
for geo_el in panel_source_obj.solid_geometry:
if self.app.abort_flag:
# graceful abort requested by the user
raise grace
@ -724,21 +709,21 @@ class Panelize(FlatCAMTool):
trans_geo = translate_recursion(geo_el)
obj_fin.solid_geometry.append(trans_geo)
except TypeError:
trans_geo = translate_recursion(panel_obj.solid_geometry)
trans_geo = translate_recursion(panel_source_obj.solid_geometry)
obj_fin.solid_geometry.append(trans_geo)
for apid in panel_obj.apertures:
for apid in panel_source_obj.apertures:
if self.app.abort_flag:
# graceful abort requested by the user
raise grace
if 'geometry' in panel_obj.apertures[apid]:
if 'geometry' in panel_source_obj.apertures[apid]:
try:
# calculate the number of polygons
geo_len = len(panel_obj.apertures[apid]['geometry'])
geo_len = len(panel_source_obj.apertures[apid]['geometry'])
except TypeError:
geo_len = 1
pol_nr = 0
for el in panel_obj.apertures[apid]['geometry']:
for el in panel_source_obj.apertures[apid]['geometry']:
if self.app.abort_flag:
# graceful abort requested by the user
raise grace
@ -771,20 +756,34 @@ class Panelize(FlatCAMTool):
currentx += lenghtx
currenty += lenghty
print("before", obj_fin.tools)
if panel_source_obj.kind == 'geometry' and panel_source_obj.multigeo is True:
# I'm going to do this only here as a fix for panelizing cutouts
# I'm going to separate linestrings out of the solid geometry from other
# possible type of elements and apply unary_union on them to fuse them
for tool in obj_fin.tools:
lines = []
other_geo = []
for geo in obj_fin.tools[tool]['solid_geometry']:
if isinstance(geo, LineString):
lines.append(geo)
else:
other_geo.append(geo)
fused_lines = list(unary_union(lines))
obj_fin.tools[tool]['solid_geometry'] = fused_lines + other_geo
print("after", obj_fin.tools)
if panel_type == 'gerber':
self.app.inform.emit('%s' % _("Generating panel ... Adding the Gerber code."))
obj_fin.source_file = self.app.export_gerber(obj_name=self.outname, filename=None,
local_use=obj_fin, use_thread=False)
# app_obj.log.debug("Found %s geometries. Creating a panel geometry cascaded union ..." %
# len(obj_fin.solid_geometry))
# obj_fin.solid_geometry = cascaded_union(obj_fin.solid_geometry)
# app_obj.log.debug("Finished creating a cascaded union for the panel.")
self.app.proc_container.update_view_text('')
self.app.inform.emit('%s: %d' % (_("Generating panel... Spawning copies"), (int(rows * columns))))
if panel_obj.kind == 'excellon':
if panel_source_obj.kind == 'excellon':
self.app.new_object("excellon", self.outname, job_init_excellon, plot=True, autoselected=True)
else:
self.app.new_object(panel_type, self.outname, job_init_geometry, plot=True, autoselected=True)
@ -801,7 +800,7 @@ class Panelize(FlatCAMTool):
def job_thread(app_obj):
try:
panelize_2()
panelize_worker()
self.app.inform.emit('[success] %s' % _("Panel created successfully."))
except Exception as ee:
proc.done()

View File

@ -155,7 +155,7 @@ class SolderPaste(FlatCAMTool):
step1_lbl = QtWidgets.QLabel("<b>%s:</b>" % _('STEP 1'))
step1_lbl.setToolTip(
_("First step is to select a number of nozzle tools for usage\n"
"and then optionally modify the GCode parameters bellow.")
"and then optionally modify the GCode parameters below.")
)
step1_description_lbl = QtWidgets.QLabel(_("Select tools.\n"
"Modify parameters."))

View File

@ -97,7 +97,7 @@ class ToolSub(FlatCAMTool):
form_layout.addRow(self.sub_gerber_label, self.sub_gerber_combo)
self.intersect_btn = FCButton(_('Substract Gerber'))
self.intersect_btn = FCButton(_('Subtract Gerber'))
self.intersect_btn.setToolTip(
_("Will remove the area occupied by the subtractor\n"
"Gerber from the Target Gerber.\n"

View File

@ -17325,7 +17325,7 @@ msgstr "SCHRITT 1"
#: flatcamTools/ToolSolderPaste.py:157
msgid ""
"First step is to select a number of nozzle tools for usage\n"
"and then optionally modify the GCode parameters bellow."
"and then optionally modify the GCode parameters below."
msgstr ""
"Zunächst müssen Sie eine Reihe von Düsenwerkzeugen auswählen\n"
"und ändern Sie dann optional die GCode-Parameter."
@ -17565,7 +17565,7 @@ msgstr ""
"vom Zielobjekt Gerber."
#: flatcamTools/ToolSub.py:100
msgid "Substract Gerber"
msgid "Subtract Gerber"
msgstr "Gerber abziehen"
#: flatcamTools/ToolSub.py:102
@ -20547,7 +20547,7 @@ msgstr ""
#~ msgid "[success] Paint Area Done."
#~ msgstr "[success] Lackierbereich fertig."
#~ msgid "...proccessing... [%s]"
#~ msgid "...processing... [%s]"
#~ msgstr "...wird bearbeitet...[%s]"
#~ msgid "Parsing aperture %s geometry ..."

View File

@ -16981,10 +16981,10 @@ msgstr "STEP 1"
#: flatcamTools/ToolSolderPaste.py:157
msgid ""
"First step is to select a number of nozzle tools for usage\n"
"and then optionally modify the GCode parameters bellow."
"and then optionally modify the GCode parameters below."
msgstr ""
"First step is to select a number of nozzle tools for usage\n"
"and then optionally modify the GCode parameters bellow."
"and then optionally modify the GCode parameters below."
#: flatcamTools/ToolSolderPaste.py:160
msgid ""
@ -17216,8 +17216,8 @@ msgstr ""
"from the target Gerber object."
#: flatcamTools/ToolSub.py:100
msgid "Substract Gerber"
msgstr "Substract Gerber"
msgid "Subtract Gerber"
msgstr "Subtract Gerber"
#: flatcamTools/ToolSub.py:102
msgid ""
@ -20512,8 +20512,8 @@ msgstr "No Geometry name in args. Provide a name and try again."
#~ msgid "Generating panel ... Please wait."
#~ msgstr "Generating panel ... Please wait."
#~ msgid "...proccessing... [%s]"
#~ msgstr "...proccessing... [%s]"
#~ msgid "...processing... [%s]"
#~ msgstr "...processing... [%s]"
#~ msgid "Parsing aperture %s geometry ..."
#~ msgstr "Parsing aperture %s geometry ..."

View File

@ -17257,7 +17257,7 @@ msgstr "PASO 1"
#: flatcamTools/ToolSolderPaste.py:157
msgid ""
"First step is to select a number of nozzle tools for usage\n"
"and then optionally modify the GCode parameters bellow."
"and then optionally modify the GCode parameters below."
msgstr ""
"El primer paso es seleccionar una serie de herramientas de boquillas para su "
"uso\n"
@ -17502,7 +17502,7 @@ msgstr ""
"del objeto objetivo de Gerber."
#: flatcamTools/ToolSub.py:100
msgid "Substract Gerber"
msgid "Subtract Gerber"
msgstr "Restar Gerber"
#: flatcamTools/ToolSub.py:102
@ -19224,7 +19224,7 @@ msgstr ""
#~ msgid "[success] Paint Area Done."
#~ msgstr "[éxito] Área de pintura realizada."
#~ msgid "...proccessing... [%s]"
#~ msgid "...processing... [%s]"
#~ msgstr "... procesando ... [% s]"
#~ msgid "Parsing aperture %s geometry ..."

View File

@ -17254,7 +17254,7 @@ msgstr "ÉTAPE 1"
#: flatcamTools/ToolSolderPaste.py:157
msgid ""
"First step is to select a number of nozzle tools for usage\n"
"and then optionally modify the GCode parameters bellow."
"and then optionally modify the GCode parameters below."
msgstr ""
"La première étape consiste à sélectionner un certain nombre doutils de buse "
"à utiliser.\n"
@ -17498,7 +17498,7 @@ msgstr ""
"à partir de l'objet Gerber cible."
#: flatcamTools/ToolSub.py:100
msgid "Substract Gerber"
msgid "Subtract Gerber"
msgstr "Soustraire Gerber"
#: flatcamTools/ToolSub.py:102

View File

@ -7235,11 +7235,11 @@ msgstr "Except"
#: flatcamGUI/ObjectUI.py:436
msgid ""
"When the isolation geometry is generated,\n"
"by checking this, the area of the object bellow\n"
"by checking this, the area of the object below\n"
"will be subtracted from the isolation geometry."
msgstr ""
"When the isolation geometry is generated,\n"
"by checking this, the area of the object bellow\n"
"by checking this, the area of the object below\n"
"will be subtracted from the isolation geometry."
#: flatcamGUI/ObjectUI.py:449 flatcamGUI/PreferencesUI.py:6527
@ -16986,10 +16986,10 @@ msgstr "STEP 1"
#: flatcamTools/ToolSolderPaste.py:157
msgid ""
"First step is to select a number of nozzle tools for usage\n"
"and then optionally modify the GCode parameters bellow."
"and then optionally modify the GCode parameters below."
msgstr ""
"First step is to select a number of nozzle tools for usage\n"
"and then optionally modify the GCode parameters bellow."
"and then optionally modify the GCode parameters below."
#: flatcamTools/ToolSolderPaste.py:160
msgid ""
@ -17221,8 +17221,8 @@ msgstr ""
"from the target Gerber object."
#: flatcamTools/ToolSub.py:100
msgid "Substract Gerber"
msgstr "Substract Gerber"
msgid "Subtract Gerber"
msgstr "Subtract Gerber"
#: flatcamTools/ToolSub.py:102
msgid ""
@ -20477,8 +20477,8 @@ msgstr "No Geometry name in args. Provide a name and try again."
#~ msgid "Generating panel ... Please wait."
#~ msgstr "Generating panel ... Please wait."
#~ msgid "...proccessing... [%s]"
#~ msgstr "...proccessing... [%s]"
#~ msgid "...processing... [%s]"
#~ msgstr "...processing... [%s]"
#~ msgid "Parsing aperture %s geometry ..."
#~ msgstr "Parsing aperture %s geometry ..."

View File

@ -6804,7 +6804,7 @@ msgstr ""
#: flatcamGUI/ObjectUI.py:431
msgid ""
"When the isolation geometry is generated,\n"
"by checking this, the area of the object bellow\n"
"by checking this, the area of the object below\n"
"will be subtracted from the isolation geometry."
msgstr ""
@ -14198,7 +14198,7 @@ msgid "Violations: There are no violations for the current rule."
msgstr ""
#: flatcamTools/ToolShell.py:70 flatcamTools/ToolShell.py:72
msgid "...proccessing..."
msgid "...processing..."
msgstr ""
#: flatcamTools/ToolSolderPaste.py:37
@ -14251,7 +14251,7 @@ msgstr ""
#: flatcamTools/ToolSolderPaste.py:156
msgid ""
"First step is to select a number of nozzle tools for usage\n"
"and then optionally modify the GCode parameters bellow."
"and then optionally modify the GCode parameters below."
msgstr ""
#: flatcamTools/ToolSolderPaste.py:159
@ -14452,7 +14452,7 @@ msgid ""
msgstr ""
#: flatcamTools/ToolSub.py:97
msgid "Substract Gerber"
msgid "Subtract Gerber"
msgstr ""
#: flatcamTools/ToolSub.py:99

View File

@ -17045,7 +17045,7 @@ msgstr "PASSO 1"
#: flatcamTools/ToolSolderPaste.py:157
msgid ""
"First step is to select a number of nozzle tools for usage\n"
"and then optionally modify the GCode parameters bellow."
"and then optionally modify the GCode parameters below."
msgstr ""
"O primeiro passo é selecionar um número de ferramentas de bico para usar,\n"
"e opcionalmente, modificar os parâmetros do G-Code abaixo."
@ -17286,7 +17286,7 @@ msgstr ""
"do objeto Gerber de destino."
#: flatcamTools/ToolSub.py:100
msgid "Substract Gerber"
msgid "Subtract Gerber"
msgstr "Subtrair Gerber"
#: flatcamTools/ToolSub.py:102
@ -20225,7 +20225,7 @@ msgstr "Nenhum nome de geometria nos argumentos. Altere e tente novamente."
#~ msgid "Generating panel ... Please wait."
#~ msgstr "Gerando painel ... Por favor, aguarde."
#~ msgid "...proccessing... [%s]"
#~ msgid "...processing... [%s]"
#~ msgstr "...processando... [%s]"
#~ msgid "Parsing aperture %s geometry ..."

View File

@ -17265,7 +17265,7 @@ msgstr "PAS 1"
#: flatcamTools/ToolSolderPaste.py:157
msgid ""
"First step is to select a number of nozzle tools for usage\n"
"and then optionally modify the GCode parameters bellow."
"and then optionally modify the GCode parameters below."
msgstr ""
"Primul pas este să se efectueza o selecţie de unelte Nozzl pt \n"
"utilizare și apoi in mod optional, să se modifice parametrii\n"
@ -17512,7 +17512,7 @@ msgstr ""
"obiectul Gerber tintă."
#: flatcamTools/ToolSub.py:100
msgid "Substract Gerber"
msgid "Subtract Gerber"
msgstr "Execută"
#: flatcamTools/ToolSub.py:102
@ -20553,7 +20553,7 @@ msgstr ""
#~ msgid "Generating panel ... Please wait."
#~ msgstr "Se generează panelul ... Va rugăm asteptati."
#~ msgid "...proccessing... [%s]"
#~ msgid "...processing... [%s]"
#~ msgstr "...in procesare... [%s]"
#~ msgid "Parsing aperture %s geometry ..."

View File

@ -17107,7 +17107,7 @@ msgstr "ШАГ 1"
#: flatcamTools/ToolSolderPaste.py:157
msgid ""
"First step is to select a number of nozzle tools for usage\n"
"and then optionally modify the GCode parameters bellow."
"and then optionally modify the GCode parameters below."
msgstr ""
"Первый шаг - выбрать несколько инструментов для использования насадок.\n"
"а затем при необходимости измените параметры кода G ниже."
@ -17349,7 +17349,7 @@ msgstr ""
"из целевого Gerber объекта."
#: flatcamTools/ToolSub.py:100
msgid "Substract Gerber"
msgid "Subtract Gerber"
msgstr "Вычесть Gerber"
#: flatcamTools/ToolSub.py:102
@ -20369,7 +20369,7 @@ msgstr "Нет имени геометрии в аргументах. Укажи
#~ msgid "Generating panel ... Please wait."
#~ msgstr "Выполняется панелизация ... Пожалуйста, подождите."
#~ msgid "...proccessing... [%s]"
#~ msgid "...processing... [%s]"
#~ msgstr "...обработка... [%s]"
#~ msgid "Parsing aperture %s geometry ..."

View File

@ -6789,7 +6789,7 @@ msgstr ""
#: flatcamGUI/ObjectUI.py:436
msgid ""
"When the isolation geometry is generated,\n"
"by checking this, the area of the object bellow\n"
"by checking this, the area of the object below\n"
"will be subtracted from the isolation geometry."
msgstr ""
@ -14604,7 +14604,7 @@ msgstr ""
#: flatcamTools/ToolSolderPaste.py:158
msgid ""
"First step is to select a number of nozzle tools for usage\n"
"and then optionally modify the GCode parameters bellow."
"and then optionally modify the GCode parameters below."
msgstr ""
#: flatcamTools/ToolSolderPaste.py:161
@ -14800,7 +14800,7 @@ msgid ""
msgstr ""
#: flatcamTools/ToolSub.py:100
msgid "Substract Gerber"
msgid "Subtract Gerber"
msgstr ""
#: flatcamTools/ToolSub.py:102

View File

@ -34,7 +34,7 @@ class TclCommandJoinExcellon(TclCommand):
help = {
'main': "Runs a merge operation (join) on the Excellon objects.\n"
"The names of the Excellon objects to be merged will be entered after the outname,\n"
"separated by spaces. See the example bellow.\n"
"separated by spaces. See the example below.\n"
"WARNING: if the name of an Excellon objects has spaces, enclose the name with quotes.",
'args': collections.OrderedDict([
('outname', 'Name of the new Excellon Object made by joining of other Excellon objects. Required'),

View File

@ -34,7 +34,7 @@ class TclCommandJoinGeometry(TclCommand):
help = {
'main': "Runs a merge operation (join) on the Geometry objects.\n"
"The names of the Geometry objects to be merged will be entered after the outname,\n"
"separated by spaces. See the example bellow.\n"
"separated by spaces. See the example below.\n"
"WARNING: if the name of an Geometry objects has spaces, enclose the name with quotes.",
'args': collections.OrderedDict([
('outname', 'Name of the new Geometry Object made by joining of other Geometry objects. Required'),