Merge remote-tracking branch 'remotes/jpcgt/flatcam/Beta' into Beta

This commit is contained in:
camellan 2019-06-08 23:16:41 +04:00
commit 70e939ca36
68 changed files with 8057 additions and 7048 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,11 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 #
# MIT Licence #
############################################################
# ########################################################## ##
class LoudDict(dict):
"""

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 #
# MIT Licence #
############################################################
# ########################################################## ##
import copy
import inspect # TODO: For debugging only.
@ -35,9 +35,9 @@ class ValidationError(Exception):
self.errors = errors
# #######################################
# # FlatCAMObj ##
# #######################################
# ##################################### ##
# # FlatCAMObj # ##
# ##################################### ##
class FlatCAMObj(QtCore.QObject):
@ -90,6 +90,8 @@ class FlatCAMObj(QtCore.QObject):
self.isHovering = False
self.notHovering = True
self.units = 'IN'
# assert isinstance(self.ui, ObjectUI)
# self.ui.name_entry.returnPressed.connect(self.on_name_activate)
# self.ui.offset_button.clicked.connect(self.on_offset_button_click)
@ -135,8 +137,7 @@ class FlatCAMObj(QtCore.QObject):
if key == 'plot':
self.visible = self.options['plot']
# self.emit(QtCore.SIGNAL("optionChanged"), key)
self.optionChanged.emit(key)
# self.optionChanged.emit(key)
def set_ui(self, ui):
self.ui = ui
@ -296,8 +297,6 @@ class FlatCAMObj(QtCore.QObject):
return False
self.clear()
return True
def serialize(self):
@ -340,13 +339,18 @@ class FlatCAMObj(QtCore.QObject):
@visible.setter
def visible(self, value):
self.shapes.visible = value
log.debug("FlatCAMObj.visible()")
# Not all object types has annotations
try:
self.annotation.visible = value
except AttributeError:
pass
def worker_task(app_obj):
app_obj.shapes.visible = value
# Not all object types has annotations
try:
app_obj.annotation.visible = value
except Exception as e:
pass
self.app.worker_task.emit({'fcn': worker_task, 'params': [self]})
@property
def drawing_tolerance(self):
@ -365,12 +369,6 @@ class FlatCAMObj(QtCore.QObject):
except AttributeError:
pass
# Not all object types have mark_shapes
# try:
# self.mark_shapes.clear(update)
# except AttributeError:
# pass
def delete(self):
# Free resources
del self.ui
@ -1053,7 +1051,6 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
:param kwargs: color and face_color
:return:
"""
FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + " --> FlatCAMGerber.plot()")
# Does all the required setup and returns False
@ -1065,6 +1062,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
color = kwargs['color']
else:
color = self.app.defaults['global_plot_line']
if 'face_color' in kwargs:
face_color = kwargs['face_color']
else:
@ -1078,7 +1076,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
# Make sure geometry is iterable.
try:
_ = iter(geometry)
__ = iter(geometry)
except TypeError:
geometry = [geometry]
@ -2342,7 +2340,7 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
"Initializer expected a FlatCAMGeometry, got %s" % type(geo_obj)
app_obj.progress.emit(20)
### Add properties to the object
# ## Add properties to the object
# get the tool_table items in a list of row items
tool_table_items = self.get_selected_tools_table_items()
@ -2436,7 +2434,7 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
"Initializer expected a FlatCAMGeometry, got %s" % type(geo_obj)
app_obj.progress.emit(20)
### Add properties to the object
# ## Add properties to the object
# get the tool_table items in a list of row items
tool_table_items = self.get_selected_tools_table_items()
@ -2561,7 +2559,7 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
# insert an information only element in the front
tool_table_items.insert(0, [_("Tool_nr"), _("Diameter"), _("Drills_Nr"), _("Slots_Nr")])
### Add properties to the object
# ## Add properties to the object
job_obj.origin_kind = 'excellon'
@ -2795,7 +2793,7 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
# this stays for compatibility reasons, in case we try to open old projects
try:
_ = iter(self.solid_geometry)
__ = iter(self.solid_geometry)
except TypeError:
self.solid_geometry = [self.solid_geometry]
@ -2932,18 +2930,18 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
"""
pts = []
## Iterable: descend into each item.
# Iterable: descend into each item.
try:
for subo in o:
pts += FlatCAMGeometry.get_pts(subo)
## Non-iterable
# Non-iterable
except TypeError:
if o is not None:
if type(o) == MultiPolygon:
for poly in o:
pts += FlatCAMGeometry.get_pts(poly)
## Descend into .exerior and .interiors
# ## Descend into .exerior and .interiors
elif type(o) == Polygon:
pts += FlatCAMGeometry.get_pts(o.exterior)
for i in o.interiors:
@ -2951,7 +2949,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
elif type(o) == MultiLineString:
for line in o:
pts += FlatCAMGeometry.get_pts(line)
## Has .coords: list them.
# ## Has .coords: list them.
else:
pts += list(o.coords)
else:
@ -3033,6 +3031,12 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
# engine of FlatCAM. Most likely are generated by some of tools and are special cases of geometries.
self. special_group = None
self.old_pp_state = ''
self.old_toolchangeg_state = ''
# store here the default data for Geometry Data
self.default_data = {}
# Attributes to be included in serialization
# Always append to it because it carries contents
# from predecessors.
@ -3101,7 +3105,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
self.ui.geo_tools_table.setCellWidget(row_no, 3, type_item)
self.ui.geo_tools_table.setCellWidget(row_no, 4, tool_type_item)
### REMEMBER: THIS COLUMN IS HIDDEN IN OBJECTUI.PY ###
# ## REMEMBER: THIS COLUMN IS HIDDEN IN OBJECTUI.PY # ##
self.ui.geo_tools_table.setItem(row_no, 5, tool_uid_item) # Tool unique ID
self.ui.geo_tools_table.setCellWidget(row_no, 6, plot_item)
@ -3391,11 +3395,11 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
try:
# works for CheckBoxes
self.ui.grid3.itemAt(i).widget().stateChanged.connect(self.gui_form_to_storage)
except:
except Exception as e:
# works for ComboBoxes
try:
self.ui.grid3.itemAt(i).widget().currentIndexChanged.connect(self.gui_form_to_storage)
except:
except Exception as e2:
# works for Entry
try:
self.ui.grid3.itemAt(i).widget().editingFinished.connect(self.gui_form_to_storage)
@ -3492,13 +3496,6 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
def on_tool_add(self, dia=None):
self.ui_disconnect()
last_offset = None
last_offset_value = None
last_type = None
last_tool_type = None
last_data = None
last_solid_geometry = []
# if a Tool diameter entered is a char instead a number the final message of Tool adding is changed
# because the Default value for Tool is used.
change_message = False
@ -3547,7 +3544,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
self.tools.update({
self.tooluid: {
'tooldia': tooldia,
'offset': ('Path'),
'offset': 'Path',
'offset_value': 0.0,
'type': _('Rough'),
'tool_type': 'C1',
@ -3556,7 +3553,6 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
}
})
else:
# print("LAST", self.tools[maxuid])
last_data = self.tools[max_uid]['data']
last_offset = self.tools[max_uid]['offset']
last_offset_value = self.tools[max_uid]['offset_value']
@ -3580,7 +3576,6 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
'solid_geometry': deepcopy(last_solid_geometry)
}
})
# print("CURRENT", self.tools[-1])
self.ui.tool_offset_entry.hide()
self.ui.tool_offset_lbl.hide()
@ -4277,6 +4272,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
# Object initialization function for app.new_object()
# RUNNING ON SEPARATE THREAD!
def job_init_single_geometry(job_obj, app_obj):
log.debug("Creating a CNCJob out of a single-geometry")
assert isinstance(job_obj, FlatCAMCNCjob), \
"Initializer expected a FlatCAMCNCjob, got %s" % type(job_obj)
@ -4451,8 +4448,9 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
app_obj.progress.emit(40)
tol = float(self.app.defaults['global_tolerance'])
res = job_obj.generate_from_geometry_2(
self, tooldia=tooldia_val, offset=tool_offset, tolerance=0.0005,
self, tooldia=tooldia_val, offset=tool_offset, tolerance=tol,
z_cut=z_cut, z_move=z_move,
feedrate=feedrate, feedrate_z=feedrate_z, feedrate_rapid=feedrate_rapid,
spindlespeed=spindlespeed, spindledir=spindledir, dwell=dwell, dwelltime=dwelltime,
@ -4488,6 +4486,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
# Object initialization function for app.new_object()
# RUNNING ON SEPARATE THREAD!
def job_init_multi_geometry(job_obj, app_obj):
log.debug("Creating a CNCJob out of a multi-geometry")
assert isinstance(job_obj, FlatCAMCNCjob), \
"Initializer expected a FlatCAMCNCjob, got %s" % type(job_obj)
@ -4682,9 +4682,10 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
spindledir = self.app.defaults['geometry_spindledir']
tool_solid_geometry = self.tools[current_uid]['solid_geometry']
tol = float(self.app.defaults['global_tolerance'])
res = job_obj.generate_from_multitool_geometry(
tool_solid_geometry, tooldia=tooldia_val, offset=tool_offset,
tolerance=0.0005, z_cut=z_cut, z_move=z_move,
tolerance=tol, z_cut=z_cut, z_move=z_move,
feedrate=feedrate, feedrate_z=feedrate_z, feedrate_rapid=feedrate_rapid,
spindlespeed=spindlespeed, spindledir=spindledir, dwell=dwell, dwelltime=dwelltime,
multidepth=multidepth, depthpercut=depthpercut,
@ -4741,7 +4742,6 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
else:
self.app.new_object("cncjob", outname, job_init_multi_geometry)
def generatecncjob(self, outname=None,
tooldia=None, offset=None,
z_cut=None, z_move=None,
@ -4850,8 +4850,13 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
'or self.options["feedrate_probe"]'
))
# TODO: The tolerance should not be hard coded. Just for testing.
job_obj.generate_from_geometry_2(self, tooldia=tooldia, offset=offset, tolerance=0.0005,
job_obj.options['xmin'] = self.options['xmin']
job_obj.options['ymin'] = self.options['ymin']
job_obj.options['xmax'] = self.options['xmax']
job_obj.options['ymax'] = self.options['ymax']
tol = float(self.app.defaults['global_tolerance'])
job_obj.generate_from_geometry_2(self, tooldia=tooldia, offset=offset, tolerance=tol,
z_cut=z_cut, z_move=z_move,
feedrate=feedrate, feedrate_z=feedrate_z, feedrate_rapid=feedrate_rapid,
spindlespeed=spindlespeed, dwell=dwell, dwelltime=dwelltime,
@ -5379,7 +5384,7 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
self.ui.cnc_tools_table.setItem(row_no, 3, type_item) # Toolpath Type
self.ui.cnc_tools_table.setItem(row_no, 4, tool_type_item) # Tool Type
### REMEMBER: THIS COLUMN IS HIDDEN IN OBJECTUI.PY ###
# ## REMEMBER: THIS COLUMN IS HIDDEN IN OBJECTUI.PY # ##
self.ui.cnc_tools_table.setItem(row_no, 5, tool_uid_item) # Tool unique ID)
self.ui.cnc_tools_table.setCellWidget(row_no, 6, plot_item)
@ -5464,6 +5469,15 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
# set the kind of geometries are plotted by default with plot2() from camlib.CNCJob
self.ui.cncplot_method_combo.set_value(self.app.defaults["cncjob_plot_kind"])
try:
self.ui.annotation_cb.stateChanged.disconnect(self.on_annotation_change)
except:
pass
self.ui.annotation_cb.stateChanged.connect(self.on_annotation_change)
# set if to display text annotations
self.ui.annotation_cb.set_value(self.app.defaults["cncjob_annotation"])
# Show/Hide Advanced Options
if self.app.defaults["global_app_level"] == 'b':
self.ui.level.setText(_(
@ -5913,6 +5927,14 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
self.shapes.clear(update=True)
self.annotation.clear(update=True)
def on_annotation_change(self):
if self.ui.annotation_cb.get_value():
self.app.plotcanvas.text_collection.enabled = True
else:
self.app.plotcanvas.text_collection.enabled = False
kind = self.ui.cncplot_method_combo.get_value()
self.plot(kind=kind)
def convert_units(self, units):
factor = CNCjob.convert_units(self, units)
FlatCAMApp.App.log.debug("FlatCAMCNCjob.convert_units()")

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Matthieu Berthomé #
# Date: 5/26/2017 #
# MIT Licence #
############################################################
# ########################################################## ##
from importlib.machinery import SourceFileLoader
import os

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 #
# MIT Licence #
############################################################
# ########################################################## ##
from flatcamGUI.FlatCAMGUI import FlatCAMActivityView
from PyQt5 import QtCore

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 #
# MIT Licence #
############################################################
# ########################################################## ##
from PyQt5 import QtGui, QtCore, QtWidgets, QtWidgets
from PyQt5.QtCore import Qt

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
import os
import sys

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 #
# MIT Licence #
############################################################
# ########################################################## ##
from PyQt5 import QtCore

View File

@ -1,14 +1,14 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 #
# MIT Licence #
############################################################
# ########################################################## ##
############################################################
# ########################################################## ##
# File modified by: Dennis Hayrullin #
############################################################
# ########################################################## ##
# from PyQt5.QtCore import QModelIndex
from FlatCAMObj import *
@ -20,9 +20,9 @@ from PyQt5.QtCore import Qt
import gettext
import FlatCAMTranslation as fcTranslate
import builtins
fcTranslate.apply_language('strings')
import builtins
if '_' not in builtins.__dict__:
_ = gettext.gettext
@ -210,7 +210,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
QtCore.QAbstractItemModel.__init__(self)
### Icons for the list view
# ## Icons for the list view
self.icons = {}
for kind in ObjectCollection.icon_files:
self.icons[kind] = QtGui.QPixmap(ObjectCollection.icon_files[kind])
@ -230,7 +230,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
# print i.data(0)
# i.append_child(TreeItem(["empty"]))
### Data ###
# ## Data # ##
self.checked_indexes = []
# Names of objects that are expected to become available.
@ -245,7 +245,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
self.app = app
### View
# ## View
self.view = KeySensitiveListView(app)
self.view.setModel(self)
@ -261,7 +261,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
font.setFamily("Seagoe UI")
self.view.setFont(font)
## GUI Events
# ## GUI Events
self.view.selectionModel().selectionChanged.connect(self.on_list_selection_change)
self.view.activated.connect(self.on_item_activated)
# self.view.keyPressed.connect(self.on_key)
@ -399,11 +399,11 @@ class ObjectCollection(QtCore.QAbstractItemModel):
if index.isValid():
obj = index.internalPointer().obj
if obj:
old_name = str(obj.options['name'])
old_name = obj.options['name']
new_name = str(data)
if old_name != new_name and new_name != '':
# rename the object
obj.options["name"] = str(data)
obj.options["name"] = deepcopy(data)
# update the SHELL auto-completer model data
try:
@ -411,11 +411,12 @@ class ObjectCollection(QtCore.QAbstractItemModel):
self.app.myKeywords.append(new_name)
self.app.shell._edit.set_model_data(self.app.myKeywords)
self.app.ui.code_editor.set_model_data(self.app.myKeywords)
except:
except Exception as e:
log.debug(
"setData() --> Could not remove the old object name from auto-completer model list")
"setData() --> Could not remove the old object name from auto-completer model list. %s" %
str(e))
obj.build_ui()
# obj.build_ui()
self.app.inform.emit(_("Object renamed from <b>{old}</b> to <b>{new}</b>").format(old=old_name,
new=new_name))
@ -452,7 +453,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
# Prevent same name
while name in self.get_names():
## Create a new name
# ## Create a new name
# Ends with number?
FlatCAMApp.App.log.debug("new_object(): Object name (%s) exists, changing." % name)
match = re.search(r'(.*[^\d])?(\d+)$', name)
@ -525,8 +526,8 @@ class ObjectCollection(QtCore.QAbstractItemModel):
ymin = min([ymin, gymin])
xmax = max([xmax, gxmax])
ymax = max([ymax, gymax])
except:
FlatCAMApp.App.log.warning("DEV WARNING: Tried to get bounds of empty geometry.")
except Exception as e:
FlatCAMApp.App.log.warning("DEV WARNING: Tried to get bounds of empty geometry. %s" % str(e))
return [xmin, ymin, xmax, ymax]
@ -536,12 +537,12 @@ class ObjectCollection(QtCore.QAbstractItemModel):
:param name: The name of the object.
:type name: str
:param isCaseSensitive: whether searching of the object is done by name where the name is case sensitive
:return: The requested object or None if no such object.
:rtype: FlatCAMObj or None
"""
FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.get_by_name()")
if isCaseSensitive is None or isCaseSensitive is True:
for obj in self.get_list():
if obj.options['name'] == name:
@ -569,10 +570,9 @@ class ObjectCollection(QtCore.QAbstractItemModel):
self.app.myKeywords.remove(name)
self.app.shell._edit.set_model_data(self.app.myKeywords)
self.app.ui.code_editor.set_model_data(self.app.myKeywords)
except:
except Exception as e:
log.debug(
"delete_active() --> Could not remove the old object name from auto-completer model list")
"delete_active() --> Could not remove the old object name from auto-completer model list. %s" % str(e))
self.beginRemoveRows(self.index(group.row(), 0, QtCore.QModelIndex()), active.row(), active.row())
@ -649,12 +649,12 @@ class ObjectCollection(QtCore.QAbstractItemModel):
:return: List of objects
"""
l = self.get_list()
obj_list = self.get_list()
for sel in self.get_selected():
l.remove(sel)
obj_list.remove(sel)
return l
return obj_list
def set_active(self, name):
"""
@ -731,8 +731,8 @@ class ObjectCollection(QtCore.QAbstractItemModel):
self.app.inform.emit('')
try:
self.app.ui.selected_scroll_area.takeWidget()
except:
FlatCAMApp.App.log.debug("Nothing to remove")
except Exception as e:
FlatCAMApp.App.log.debug("Nothing to remove. %s" % str(e))
self.app.setup_component_editor()
return

View File

@ -9,12 +9,77 @@ CAD program, and create G-Code for Isolation routing.
=================================================
7.06.2019
- fixed bug in ToolCutout where creating a cutout object geometry from another external isolation geometry failed
- fixed bug in cncjob TclCommand where the gcode could not be correctly generated due of missing bounds params in obj.options dict
- fixed a hardcoded tolerance in FlatCAMGeometry.generatecncjob() and in FlatCAMGeometry.mtool_gen_cncjob() to use the parameter from Preferences
- updated translations
- RELEASE 8.918
5.06.2019
- updated translations
- some layout changes in Edit -> Preferences such that the German translation (longer words than English) to fit correctly
- after editing an parameter the focus is lost so the user knows that something happened
4.06.2019
- PEP8 updates in FlatCAMExcEditor.py
- added the Excellon Editor parameters to the Edit -> Preferences -> Excellon GUI
- fixed a small bug in Excellon Editor
- PEP8 cleanup in FlatCAMGui
- finished adding the Excellon Editor parameters into the app logic and added a selection limit within Excellon Editor just like in the other editors
3.06.2019
- TclCommand Geocutout is now creating a new geometry object when working on a geometry, preserving also the origin object
- added a new parameter in Edit -> Preferences -> CNCJob named Annotation Color; it controls the color of the font used for annotations
- added a new parameter in Edit -> Preferences -> CNCJob named Annotation Size; it controls the size of the font used for annotations
- made visibility change threaded in FlatCAMObj()
2.06.2019
- fixed issue with geometry name not being updated immediately after change while doing geocutout TclCommand
- some changes to enable/disable project context menu entry handlers
1.06.2019
- fixed text annotation for CNC job so there are no overlapping numbers when 2 lines meet on the same point
- fixed issue in CNC job plotting where some of the isolation polygons are painted incorrectly
- fixed issue in CNCJob where the set circle steps is not used
31.05.2019
- added the possibility to display text annotation for the CNC travel lines. The setting is both in Preferences and in the CNC object properties
30.05.2019
- editing a multi geometry will no longer pop-up a Tcl window
- solved issue #292 where a new geometry renamed with many underscores failed to store the name in a saved project
- the name for the saved projects are updated to the current time and not to the time of the app startup
- some PEP8 changes related to comments starting with only one '#' symbol
- more PEP8 cleanup
- solved issue where after the opening of an object the file path is not saved for further open operations
24.05.2019
- added a toggle Grid button to the canvas context menu in the Grids submenu
- added a toggle left panel button to the canvas context menu
23.05.2019
- fixed bug in Gerber editor FCDisk and FCSemiDisc that the resulting geometry was not stored into the '0' aperture where all the solids are stored
- fixed minor issue in Gerber Editor where apertures were included in the saved object even if there was no geometric data for that aperture
- some PEP8 cleanup in FlatCAMApp.py
22.05.2019
- Geo Editor - added a new editor tool, Eraser
- some PEP8 cleanup of the Geo Editor
- fixed some selection issues in the new tool Eraser in Geometry Editor
- updated the translation files
- RELEASE 8.917
21.05.2019

360
camlib.py

File diff suppressed because it is too large Load Diff

View File

@ -16,9 +16,9 @@ from copy import copy, deepcopy
import gettext
import FlatCAMTranslation as fcTranslate
import builtins
fcTranslate.apply_language('strings')
import builtins
if '_' not in builtins.__dict__:
_ = gettext.gettext
@ -34,9 +34,9 @@ class FCDrillAdd(FCShapeTool):
self.selected_dia = None
try:
self.draw_app.app.inform.emit(self.start_msg)
# self.selected_dia = self.draw_app.tool2tooldia[self.draw_app.tools_table_exc.currentRow() + 1]
self.draw_app.app.inform.emit(_("Click to place ..."))
self.selected_dia = self.draw_app.tool2tooldia[self.draw_app.last_tool_selected]
# as a visual marker, select again in tooltable the actual tool that we are using
# remember that it was deselected when clicking on canvas
item = self.draw_app.tools_table_exc.item((self.draw_app.last_tool_selected - 1), 1)
@ -140,7 +140,7 @@ class FCDrillArray(FCShapeTool):
self.pt = []
try:
self.draw_app.app.inform.emit(self.start_msg)
self.draw_app.app.inform.emit(_("Click to place ..."))
self.selected_dia = self.draw_app.tool2tooldia[self.draw_app.last_tool_selected]
# as a visual marker, select again in tooltable the actual tool that we are using
# remember that it was deselected when clicking on canvas
@ -204,7 +204,7 @@ class FCDrillArray(FCShapeTool):
_("[ERROR_NOTCL] The value is not Float. Check for comma instead of dot separator."))
return
except Exception as e:
self.draw_app.app.inform.emit(_("[ERROR_NOTCL] The value is mistyped. Check the value."))
self.draw_app.app.inform.emit(_("[ERROR_NOTCL] The value is mistyped. Check the value. %s") % str(e))
return
if self.drill_array == 'Linear':
@ -350,7 +350,9 @@ class FCDrillResize(FCShapeTool):
try:
new_dia = self.draw_app.resdrill_entry.get_value()
except:
self.draw_app.app.inform.emit(_("[ERROR_NOTCL] Resize drill(s) failed. Please enter a diameter for resize."))
self.draw_app.app.inform.emit(
_("[ERROR_NOTCL] Resize drill(s) failed. Please enter a diameter for resize.")
)
return
if new_dia not in self.draw_app.olddia_newdia:
@ -406,7 +408,7 @@ class FCDrillResize(FCShapeTool):
if new_dia not in self.draw_app.points_edit:
self.draw_app.points_edit[new_dia] = [(0, 0)]
else:
self.draw_app.points_edit[new_dia].append((0,0))
self.draw_app.points_edit[new_dia].append((0, 0))
self.geometry = []
# if following the resize of the drills there will be no more drills for the selected tool then
@ -416,7 +418,6 @@ class FCDrillResize(FCShapeTool):
for shp in sel_shapes_to_be_deleted:
self.draw_app.selected.remove(shp)
sel_shapes_to_be_deleted = []
self.draw_app.build_ui()
self.draw_app.replot()
@ -440,6 +441,8 @@ class FCDrillMove(FCShapeTool):
# self.shape_buffer = self.draw_app.shape_buffer
self.origin = None
self.destination = None
self.sel_limit = self.draw_app.app.defaults["excellon_editor_sel_limit"]
self.selection_shape = self.selection_bbox()
self.selected_dia_list = []
if self.draw_app.launched_from_shortcuts is True:
@ -503,6 +506,25 @@ class FCDrillMove(FCShapeTool):
self.draw_app.build_ui()
self.draw_app.app.inform.emit(_("[success] Done. Drill(s) Move completed."))
def selection_bbox(self):
geo_list = []
for select_shape in self.draw_app.get_selected():
geometric_data = select_shape.geo
try:
for g in geometric_data:
geo_list.append(g)
except TypeError:
geo_list.append(geometric_data)
xmin, ymin, xmax, ymax = get_shapely_list_bounds(geo_list)
pt1 = (xmin, ymin)
pt2 = (xmax, ymin)
pt3 = (xmax, ymax)
pt4 = (xmin, ymax)
return Polygon([pt1, pt2, pt3, pt4])
def utility_geometry(self, data=None):
"""
Temporary geometry on screen while using this tool.
@ -520,9 +542,22 @@ class FCDrillMove(FCShapeTool):
dx = data[0] - self.origin[0]
dy = data[1] - self.origin[1]
for geom in self.draw_app.get_selected():
geo_list.append(affinity.translate(geom.geo, xoff=dx, yoff=dy))
return DrawToolUtilityShape(geo_list)
if len(self.draw_app.get_selected()) <= self.sel_limit:
try:
for geom in self.draw_app.get_selected():
geo_list.append(affinity.translate(geom.geo, xoff=dx, yoff=dy))
except AttributeError:
self.draw_app.select_tool('drill_select')
self.draw_app.selected = []
return
return DrawToolUtilityShape(geo_list)
else:
try:
ss_el = affinity.translate(self.selection_shape, xoff=dx, yoff=dy)
except ValueError:
ss_el = None
return DrawToolUtilityShape(ss_el)
class FCDrillCopy(FCDrillMove):
@ -595,8 +630,8 @@ class FCDrillSelect(DrawTool):
try:
for storage in self.exc_editor_app.storage_dict:
for shape in self.exc_editor_app.storage_dict[storage].get_objects():
self.sel_storage.insert(shape)
for sh in self.exc_editor_app.storage_dict[storage].get_objects():
self.sel_storage.insert(sh)
_, closest_shape = self.sel_storage.nearest(pos)
@ -718,19 +753,18 @@ class FlatCAMExcEditor(QtCore.QObject):
draw_shape_idx = -1
def __init__(self, app):
assert isinstance(app, FlatCAMApp.App), \
"Expected the app to be a FlatCAMApp.App, got %s" % type(app)
assert isinstance(app, FlatCAMApp.App), "Expected the app to be a FlatCAMApp.App, got %s" % type(app)
super(FlatCAMExcEditor, self).__init__()
self.app = app
self.canvas = self.app.plotcanvas
## Current application units in Upper Case
# ## Current application units in Upper Case
self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
self.exc_edit_widget = QtWidgets.QWidget()
## Box for custom widgets
# ## Box for custom widgets
# This gets populated in offspring implementations.
layout = QtWidgets.QVBoxLayout()
self.exc_edit_widget.setLayout(layout)
@ -744,22 +778,22 @@ class FlatCAMExcEditor(QtCore.QObject):
self.tools_box.setContentsMargins(0, 0, 0, 0)
self.drills_frame.setLayout(self.tools_box)
## Page Title box (spacing between children)
# ## Page Title box (spacing between children)
self.title_box = QtWidgets.QHBoxLayout()
self.tools_box.addLayout(self.title_box)
## Page Title icon
# ## Page Title icon
pixmap = QtGui.QPixmap('share/flatcam_icon32.png')
self.icon = QtWidgets.QLabel()
self.icon.setPixmap(pixmap)
self.title_box.addWidget(self.icon, stretch=0)
## Title label
# ## Title label
self.title_label = QtWidgets.QLabel("<font size=5><b>%s</b></font>" % _('Excellon Editor'))
self.title_label.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
self.title_box.addWidget(self.title_label, stretch=1)
## Object name
# ## Object name
self.name_box = QtWidgets.QHBoxLayout()
self.tools_box.addLayout(self.name_box)
name_label = QtWidgets.QLabel(_("Name:"))
@ -767,11 +801,11 @@ class FlatCAMExcEditor(QtCore.QObject):
self.name_entry = FCEntry()
self.name_box.addWidget(self.name_entry)
#### Tools Drills ####
# ### Tools Drills ## ##
self.tools_table_label = QtWidgets.QLabel("<b>%s</b>" % _('Tools Table'))
self.tools_table_label.setToolTip(
_( "Tools in this Excellon object\n"
"when are used for drilling.")
_("Tools in this Excellon object\n"
"when are used for drilling.")
)
self.tools_box.addWidget(self.tools_table_label)
@ -789,11 +823,11 @@ class FlatCAMExcEditor(QtCore.QObject):
self.empty_label = QtWidgets.QLabel('')
self.tools_box.addWidget(self.empty_label)
#### Add a new Tool ####
# ### Add a new Tool ## ##
self.addtool_label = QtWidgets.QLabel('<b>%s</b>' % _('Add/Delete Tool'))
self.addtool_label.setToolTip(
_("Add/Delete a tool to the tool list\n"
"for this Excellon object.")
"for this Excellon object.")
)
self.tools_box.addWidget(self.addtool_label)
@ -802,9 +836,8 @@ class FlatCAMExcEditor(QtCore.QObject):
addtool_entry_lbl = QtWidgets.QLabel(_('Tool Dia:'))
addtool_entry_lbl.setToolTip(
_("Diameter for the new tool")
_("Diameter for the new tool")
)
grid1.addWidget(addtool_entry_lbl, 0, 0)
hlay = QtWidgets.QHBoxLayout()
self.addtool_entry = FCEntry()
@ -813,11 +846,13 @@ class FlatCAMExcEditor(QtCore.QObject):
self.addtool_btn = QtWidgets.QPushButton(_('Add Tool'))
self.addtool_btn.setToolTip(
_( "Add a new tool to the tool list\n"
"with the diameter specified above.")
_("Add a new tool to the tool list\n"
"with the diameter specified above.")
)
self.addtool_btn.setFixedWidth(80)
hlay.addWidget(self.addtool_btn)
grid1.addWidget(addtool_entry_lbl, 0, 0)
grid1.addLayout(hlay, 0, 1)
grid2 = QtWidgets.QGridLayout()
@ -825,8 +860,8 @@ class FlatCAMExcEditor(QtCore.QObject):
self.deltool_btn = QtWidgets.QPushButton(_('Delete Tool'))
self.deltool_btn.setToolTip(
_( "Delete a tool in the tool list\n"
"by selecting a row in the tool table.")
_("Delete a tool in the tool list\n"
"by selecting a row in the tool table.")
)
grid2.addWidget(self.deltool_btn, 0, 1)
@ -839,7 +874,7 @@ class FlatCAMExcEditor(QtCore.QObject):
self.resize_box.setContentsMargins(0, 0, 0, 0)
self.resize_frame.setLayout(self.resize_box)
#### Resize a drill ####
# ### Resize a drill ## ##
self.emptyresize_label = QtWidgets.QLabel('')
self.resize_box.addWidget(self.emptyresize_label)
@ -882,7 +917,7 @@ class FlatCAMExcEditor(QtCore.QObject):
self.array_box.setContentsMargins(0, 0, 0, 0)
self.array_frame.setLayout(self.array_box)
#### Add DRILL Array ####
# ### Add DRILL Array ## ##
self.emptyarray_label = QtWidgets.QLabel('')
self.array_box.addWidget(self.emptyarray_label)
@ -895,7 +930,7 @@ class FlatCAMExcEditor(QtCore.QObject):
self.array_type_combo = FCComboBox()
self.array_type_combo.setToolTip(
_( "Select the type of drills array to create.\n"
"It can be Linear X(Y) or Circular")
"It can be Linear X(Y) or Circular")
)
self.array_type_combo.addItem(_("Linear"))
self.array_type_combo.addItem(_("Circular"))
@ -905,6 +940,7 @@ class FlatCAMExcEditor(QtCore.QObject):
self.array_form = QtWidgets.QFormLayout()
self.array_box.addLayout(self.array_form)
# Set the number of drill holes in the drill array
self.drill_array_size_label = QtWidgets.QLabel(_('Nr of drills:'))
self.drill_array_size_label.setToolTip(
_("Specify how many drills to be in the array.")
@ -924,21 +960,22 @@ class FlatCAMExcEditor(QtCore.QObject):
self.linear_form = QtWidgets.QFormLayout()
self.linear_box.addLayout(self.linear_form)
# Linear Drill Array direction
self.drill_axis_label = QtWidgets.QLabel(_('Direction:'))
self.drill_axis_label.setToolTip(
_("Direction on which the linear array is oriented:\n"
"- 'X' - horizontal axis \n"
"- 'Y' - vertical axis or \n"
"- 'Angle' - a custom angle for the array inclination")
"- 'X' - horizontal axis \n"
"- 'Y' - vertical axis or \n"
"- 'Angle' - a custom angle for the array inclination")
)
self.drill_axis_label.setFixedWidth(100)
self.drill_axis_radio = RadioSet([{'label': 'X', 'value': 'X'},
{'label': 'Y', 'value': 'Y'},
{'label': 'Angle', 'value': 'A'}])
self.drill_axis_radio.set_value('X')
self.linear_form.addRow(self.drill_axis_label, self.drill_axis_radio)
# Linear Drill Array pitch distance
self.drill_pitch_label = QtWidgets.QLabel(_('Pitch:'))
self.drill_pitch_label.setToolTip(
_("Pitch = Distance between elements of the array.")
@ -948,12 +985,13 @@ class FlatCAMExcEditor(QtCore.QObject):
self.drill_pitch_entry = LengthEntry()
self.linear_form.addRow(self.drill_pitch_label, self.drill_pitch_entry)
# Linear Drill Array angle
self.linear_angle_label = QtWidgets.QLabel(_('Angle:'))
self.linear_angle_label.setToolTip(
_( "Angle at which the linear array is placed.\n"
"The precision is of max 2 decimals.\n"
"Min value is: -359.99 degrees.\n"
"Max value is: 360.00 degrees.")
"The precision is of max 2 decimals.\n"
"Min value is: -359.99 degrees.\n"
"Max value is: 360.00 degrees.")
)
self.linear_angle_label.setFixedWidth(100)
@ -972,7 +1010,7 @@ class FlatCAMExcEditor(QtCore.QObject):
self.drill_direction_label = QtWidgets.QLabel(_('Direction:'))
self.drill_direction_label.setToolTip(
_( "Direction for circular array."
"Can be CW = clockwise or CCW = counter clockwise.")
"Can be CW = clockwise or CCW = counter clockwise.")
)
self.drill_direction_label.setFixedWidth(100)
@ -981,7 +1019,6 @@ class FlatCAMExcEditor(QtCore.QObject):
self.drill_direction_radio = RadioSet([{'label': 'CW', 'value': 'CW'},
{'label': 'CCW.', 'value': 'CCW'}])
self.drill_direction_radio.set_value('CW')
self.circular_form.addRow(self.drill_direction_label, self.drill_direction_radio)
self.drill_angle_label = QtWidgets.QLabel(_('Angle:'))
@ -1001,23 +1038,23 @@ class FlatCAMExcEditor(QtCore.QObject):
self.array_frame.hide()
self.tools_box.addStretch()
## Toolbar events and properties
# ## Toolbar events and properties
self.tools_exc = {
"drill_select": {"button": self.app.ui.select_drill_btn,
"constructor": FCDrillSelect},
"constructor": FCDrillSelect},
"drill_add": {"button": self.app.ui.add_drill_btn,
"constructor": FCDrillAdd},
"constructor": FCDrillAdd},
"drill_array": {"button": self.app.ui.add_drill_array_btn,
"constructor": FCDrillArray},
"constructor": FCDrillArray},
"drill_resize": {"button": self.app.ui.resize_drill_btn,
"constructor": FCDrillResize},
"constructor": FCDrillResize},
"drill_copy": {"button": self.app.ui.copy_drill_btn,
"constructor": FCDrillCopy},
"constructor": FCDrillCopy},
"drill_move": {"button": self.app.ui.move_drill_btn,
"constructor": FCDrillMove},
"constructor": FCDrillMove},
}
### Data
# ## Data
self.active_tool = None
self.in_action = False
@ -1073,12 +1110,6 @@ class FlatCAMExcEditor(QtCore.QObject):
self.app.ui.exc_move_drill_menuitem.triggered.connect(self.exc_move_drills)
# Init GUI
self.drill_array_size_entry.set_value(5)
self.drill_pitch_entry.set_value(2.54)
self.drill_angle_entry.set_value(12)
self.drill_direction_radio.set_value('CW')
self.drill_axis_radio.set_value('X')
self.exc_obj = None
# VisPy Visuals
@ -1090,7 +1121,7 @@ class FlatCAMExcEditor(QtCore.QObject):
self.shapes.enabled = False
self.tool_shape.enabled = False
## List of selected shapes.
# ## List of selected shapes.
self.selected = []
self.move_timer = QtCore.QTimer()
@ -1105,6 +1136,8 @@ class FlatCAMExcEditor(QtCore.QObject):
self.snap_y = None
self.pos = None
self.complete = False
def make_callback(thetool):
def f():
self.on_tool_select(thetool)
@ -1159,15 +1192,13 @@ class FlatCAMExcEditor(QtCore.QObject):
@staticmethod
def make_storage():
## Shape storage.
# ## Shape storage.
storage = FlatCAMRTreeStorage()
storage.get_points = DrawToolShape.get_pts
return storage
def set_ui(self):
# updated units
self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
@ -1186,6 +1217,7 @@ class FlatCAMExcEditor(QtCore.QObject):
self.points_edit[tool_dia].append(drill['point'])
except KeyError:
self.points_edit[tool_dia] = [drill['point']]
# update the olddia_newdia dict to make sure we have an updated state of the tool_table
for key in self.points_edit:
self.olddia_newdia[key] = key
@ -1211,6 +1243,15 @@ class FlatCAMExcEditor(QtCore.QObject):
tool_dia = float('%.2f' % v['C'])
self.tool2tooldia[int(k)] = tool_dia
# Init GUI
self.addtool_entry.set_value(float(self.app.defaults['excellon_editor_newdia']))
self.drill_array_size_entry.set_value(int(self.app.defaults['excellon_editor_array_size']))
self.drill_axis_radio.set_value(self.app.defaults['excellon_editor_lin_dir'])
self.drill_pitch_entry.set_value(float(self.app.defaults['excellon_editor_lin_pitch']))
self.linear_angle_spinner.set_value(float(self.app.defaults['excellon_editor_lin_angle']))
self.drill_direction_radio.set_value(self.app.defaults['excellon_editor_circ_dir'])
self.drill_angle_entry.set_value(float(self.app.defaults['excellon_editor_circ_angle']))
def build_ui(self, first_run=None):
try:
@ -1231,11 +1272,6 @@ class FlatCAMExcEditor(QtCore.QObject):
self.edited_obj_name = self.exc_obj.options['name']
self.name_entry.set_value(self.edited_obj_name)
if self.units == "IN":
self.addtool_entry.set_value(0.039)
else:
self.addtool_entry.set_value(1.00)
sort_temp = []
for diam in self.olddia_newdia:
@ -1278,9 +1314,9 @@ class FlatCAMExcEditor(QtCore.QObject):
# slot editing not implemented
pass
id = QtWidgets.QTableWidgetItem('%d' % int(tool_id))
id.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
self.tools_table_exc.setItem(self.tool_row, 0, id) # Tool name/id
idd = QtWidgets.QTableWidgetItem('%d' % int(tool_id))
idd.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
self.tools_table_exc.setItem(self.tool_row, 0, idd) # Tool name/id
# Make sure that the drill diameter when in MM is with no more than 2 decimals
# There are no drill bits in MM with more than 3 decimals diameter
@ -1375,7 +1411,6 @@ class FlatCAMExcEditor(QtCore.QObject):
self.tools_table_exc.item(self.tool_row, kl).setFont(font)
self.tools_table_exc.item(self.tool_row, kl).setForeground(QtGui.QColor(0, 70, 255))
# all the tools are selected by default
self.tools_table_exc.selectColumn(0)
#
@ -1458,7 +1493,8 @@ class FlatCAMExcEditor(QtCore.QObject):
# we add a new entry in the tool2tooldia dict
self.tool2tooldia[len(self.olddia_newdia)] = tool_dia
self.app.inform.emit(_("[success] Added new tool with dia: {dia} {units}").format(dia=str(tool_dia), units=str(self.units)))
self.app.inform.emit(_("[success] Added new tool with dia: {dia} {units}").format(dia=str(tool_dia),
units=str(self.units)))
self.build_ui()
@ -1475,7 +1511,6 @@ class FlatCAMExcEditor(QtCore.QObject):
def on_tool_delete(self, dia=None):
self.is_modified = True
deleted_tool_dia_list = []
deleted_tool_offset_list = []
try:
if dia is None or dia is False:
@ -1516,14 +1551,15 @@ class FlatCAMExcEditor(QtCore.QObject):
# delete the tool
self.tool2tooldia.pop(tool_to_be_deleted, None)
# delete also the drills from points_edit dict just in case we add the tool again, we don't want to show the
# number of drills from before was deleter
# delete also the drills from points_edit dict just in case we add the tool again,
# we don't want to show the number of drills from before was deleter
self.points_edit[deleted_tool_dia] = []
flag_del = []
self.olddia_newdia.pop(deleted_tool_dia, None)
self.app.inform.emit(_("[success] Deleted tool with dia: {del_dia} {units}").format(del_dia=str(deleted_tool_dia), units=str(self.units)))
self.app.inform.emit(_("[success] Deleted tool with dia: {del_dia} {units}").format(
del_dia=str(deleted_tool_dia),
units=str(self.units)))
self.replot()
# self.app.inform.emit("Could not delete selected tool")
@ -1539,7 +1575,6 @@ class FlatCAMExcEditor(QtCore.QObject):
# self.tools_table_exc.selectionModel().currentChanged.disconnect()
self.is_modified = True
geometry = []
current_table_dia_edited = None
if self.tools_table_exc.currentItem() is not None:
@ -1565,7 +1600,7 @@ class FlatCAMExcEditor(QtCore.QObject):
self.tool2tooldia[key_in_tool2tooldia] = current_table_dia_edited
# update the tool offset
modified_offset = self.exc_obj.tool_offset.pop(dia_changed ,None)
modified_offset = self.exc_obj.tool_offset.pop(dia_changed, None)
if modified_offset is not None:
self.exc_obj.tool_offset[current_table_dia_edited] = modified_offset
@ -1575,10 +1610,11 @@ class FlatCAMExcEditor(QtCore.QObject):
factor = current_table_dia_edited / dia_changed
geometry = []
for shape in self.storage_dict[dia_changed].get_objects():
geometry.append(DrawToolShape(
MultiLineString([affinity.scale(subgeo, xfact=factor, yfact=factor, origin='center')
for subgeo in shape.geo])))
for shape_exc in self.storage_dict[dia_changed].get_objects():
scaled_geo = MultiLineString(
[affinity.scale(subgeo, xfact=factor, yfact=factor, origin='center') for subgeo in shape_exc.geo]
)
geometry.append(DrawToolShape(scaled_geo))
# add bogus drill points (for total count of drills)
for k, v in self.olddia_newdia.items():
@ -1586,8 +1622,8 @@ class FlatCAMExcEditor(QtCore.QObject):
self.points_edit[k].append((0, 0))
break
# search for the oldia that correspond to the newdia and add the drills in it's storage
# everything will be sort out later, when the edited excellon is updated
# search for the old dia that correspond to the new dia and add the drills in it's storage
# everything will be sort out later, when the edited Excellon is updated
for k, v in self.olddia_newdia.items():
if v == current_table_dia_edited:
self.add_exc_shape(geometry, self.storage_dict[k])
@ -1739,7 +1775,7 @@ class FlatCAMExcEditor(QtCore.QObject):
self.drills_frame.hide()
def connect_canvas_event_handlers(self):
## Canvas events
# ## Canvas events
# first connect to new, then disconnect the old handlers
# don't ask why but if there is nothing connected I've seen issues
@ -1833,7 +1869,7 @@ class FlatCAMExcEditor(QtCore.QObject):
Imports the geometry from the given FlatCAM Excellon object
into the editor.
:param fcgeometry: FlatCAMExcellon
:param exc_obj: FlatCAMExcellon object
:return: None
"""
@ -1870,16 +1906,16 @@ class FlatCAMExcEditor(QtCore.QObject):
stop_hor_line = ((point.x + (tool_dia / 2)), point.y)
start_vert_line = (point.x, (point.y - (tool_dia / 2)))
stop_vert_line = (point.x, (point.y + (tool_dia / 2)))
shape = MultiLineString([(start_hor_line, stop_hor_line),(start_vert_line, stop_vert_line)])
if shape is not None:
self.add_exc_shape(DrawToolShape(shape), storage_elem)
shape_geo = MultiLineString([(start_hor_line, stop_hor_line), (start_vert_line, stop_vert_line)])
if shape_geo is not None:
self.add_exc_shape(DrawToolShape(shape_geo), storage_elem)
self.storage_dict[tool_dia] = storage_elem
self.replot()
# add a first tool in the Tool Table but only if the Excellon Object is empty
if not self.tool2tooldia:
self.on_tool_add(tooldia=1.00)
self.on_tool_add(tooldia=float(self.app.defaults['excellon_editor_newdia']))
def update_fcexcellon(self, exc_obj):
"""
@ -1907,7 +1943,7 @@ class FlatCAMExcEditor(QtCore.QObject):
# create a tuple with the coordinates (x, y) and add it to the list that is the value of the
# edited_points dictionary
point = (x_coord, y_coord)
if not storage_tooldia in edited_points:
if storage_tooldia not in edited_points:
edited_points[storage_tooldia] = [point]
else:
edited_points[storage_tooldia].append(point)
@ -1964,8 +2000,8 @@ class FlatCAMExcEditor(QtCore.QObject):
if self.is_modified is True:
if "_edit" in self.edited_obj_name:
try:
id = int(self.edited_obj_name[-1]) + 1
self.edited_obj_name = self.edited_obj_name[:-1] + str(id)
idd = int(self.edited_obj_name[-1]) + 1
self.edited_obj_name = self.edited_obj_name[:-1] + str(idd)
except ValueError:
self.edited_obj_name += "_1"
else:
@ -2035,7 +2071,7 @@ class FlatCAMExcEditor(QtCore.QObject):
excellon_obj.create_geometry()
except KeyError:
self.app.inform.emit(
_( "[ERROR_NOTCL] There are no Tools definitions in the file. Aborting Excellon creation.")
_("[ERROR_NOTCL] There are no Tools definitions in the file. Aborting Excellon creation.")
)
except:
msg = _("[ERROR] An internal error has ocurred. See shell.\n")
@ -2116,7 +2152,7 @@ class FlatCAMExcEditor(QtCore.QObject):
def toolbar_tool_toggle(self, key):
self.options[key] = self.sender().isChecked()
if self.options[key] == True:
if self.options[key] is True:
return 1
else:
return 0
@ -2151,7 +2187,7 @@ class FlatCAMExcEditor(QtCore.QObject):
if self.active_tool is not None and event.button is 1:
# Dispatch event to active_tool
# msg = self.active_tool.click(self.app.geo_editor.snap(event.xdata, event.ydata))
msg = self.active_tool.click(self.app.geo_editor.snap(self.pos[0], self.pos[1]))
self.active_tool.click(self.app.geo_editor.snap(self.pos[0], self.pos[1]))
# If it is a shape generating tool
if isinstance(self.active_tool, FCShapeTool) and self.active_tool.complete:
@ -2207,6 +2243,7 @@ class FlatCAMExcEditor(QtCore.QObject):
:param shape: Shape to be added.
:type shape: DrawToolShape
:param storage: object where to store the shapes
:return: None
"""
# List of DrawToolShape?
@ -2221,8 +2258,7 @@ class FlatCAMExcEditor(QtCore.QObject):
assert shape.geo is not None, \
"Shape object has empty geometry (None)"
assert (isinstance(shape.geo, list) and len(shape.geo) > 0) or \
not isinstance(shape.geo, list), \
assert (isinstance(shape.geo, list) and len(shape.geo) > 0) or not isinstance(shape.geo, list), \
"Shape objects has empty geometry ([])"
if isinstance(shape, DrawToolUtilityShape):
@ -2251,8 +2287,7 @@ class FlatCAMExcEditor(QtCore.QObject):
assert shape.geo is not None, \
"Shape object has empty geometry (None)"
assert (isinstance(shape.geo, list) and len(shape.geo) > 0) or \
not isinstance(shape.geo, list), \
assert (isinstance(shape.geo, list) and len(shape.geo) > 0) or not isinstance(shape.geo, list), \
"Shape objects has empty geometry ([])"
if isinstance(shape, DrawToolUtilityShape):
@ -2318,14 +2353,15 @@ class FlatCAMExcEditor(QtCore.QObject):
log.warning("Error: %s" % str(e))
raise
def draw_selection_area_handler(self, start_pos, end_pos, sel_type):
def draw_selection_area_handler(self, start, end, sel_type):
"""
:param start_pos: mouse position when the selection LMB click was done
:param end_pos: mouse position when the left mouse button is released
:param sel_type: if True it's a left to right selection (enclosure), if False it's a 'touch' selection
:type Bool
:return:
"""
start_pos = (start[0], start[1])
end_pos = (end[0], end[1])
poly_selection = Polygon([start_pos, (end_pos[0], start_pos[1]), end_pos, (start_pos[0], end_pos[1])])
self.app.delete_selection_shape()
@ -2394,7 +2430,7 @@ class FlatCAMExcEditor(QtCore.QObject):
if self.active_tool is None:
return
### Snap coordinates
# ## Snap coordinates
if self.app.grid_status():
x, y = self.app.geo_editor.snap(x, y)
self.app.app_cursor.enabled = True
@ -2408,7 +2444,7 @@ class FlatCAMExcEditor(QtCore.QObject):
# update the position label in the infobar since the APP mouse event handlers are disconnected
self.app.ui.position_label.setText("&nbsp;&nbsp;&nbsp;&nbsp;<b>X</b>: %.4f&nbsp;&nbsp; "
"<b>Y</b>: %.4f" % (x, y))
"<b>Y</b>: %.4f" % (x, y))
if self.pos is None:
self.pos = (0, 0)
@ -2417,9 +2453,9 @@ class FlatCAMExcEditor(QtCore.QObject):
# update the reference position label in the infobar since the APP mouse event handlers are disconnected
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (dx, dy))
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (dx, dy))
### Utility geometry (animated)
# ## Utility geometry (animated)
geo = self.active_tool.utility_geometry(data=(x, y))
if isinstance(geo, DrawToolShape) and geo.geo is not None:
@ -2427,7 +2463,7 @@ class FlatCAMExcEditor(QtCore.QObject):
self.tool_shape.clear(update=True)
self.draw_utility_geometry(geo=geo)
### Selection area on canvas section ###
# ## Selection area on canvas section # ##
if event.is_dragging == 1 and event.button == 1:
# I make an exception for FCDrillAdd and FCDrillArray because clicking and dragging while making regions
# can create strange issues
@ -2437,12 +2473,12 @@ class FlatCAMExcEditor(QtCore.QObject):
dx = pos[0] - self.pos[0]
self.app.delete_selection_shape()
if dx < 0:
self.app.draw_moving_selection_shape((self.pos[0], self.pos[1]), (x,y),
color=self.app.defaults["global_alt_sel_line"],
face_color=self.app.defaults['global_alt_sel_fill'])
self.app.draw_moving_selection_shape((self.pos[0], self.pos[1]), (x, y),
color=self.app.defaults["global_alt_sel_line"],
face_color=self.app.defaults['global_alt_sel_fill'])
self.app.selection_type = False
else:
self.app.draw_moving_selection_shape((self.pos[0], self.pos[1]), (x,y))
self.app.draw_moving_selection_shape((self.pos[0], self.pos[1]), (x, y))
self.app.selection_type = True
else:
self.app.selection_type = None
@ -2454,43 +2490,41 @@ class FlatCAMExcEditor(QtCore.QObject):
self.key = None
def draw_utility_geometry(self, geo):
# Add the new utility shape
try:
# this case is for the Font Parse
for el in list(geo.geo):
if type(el) == MultiPolygon:
for poly in el:
self.tool_shape.add(
shape=poly,
color=(self.app.defaults["global_draw_color"] + '80'),
update=False,
layer=0,
tolerance=None
)
elif type(el) == MultiLineString:
for linestring in el:
self.tool_shape.add(
shape=linestring,
color=(self.app.defaults["global_draw_color"] + '80'),
update=False,
layer=0,
tolerance=None
)
else:
# Add the new utility shape
try:
# this case is for the Font Parse
for el in list(geo.geo):
if type(el) == MultiPolygon:
for poly in el:
self.tool_shape.add(
shape=el,
shape=poly,
color=(self.app.defaults["global_draw_color"] + '80'),
update=False,
layer=0,
tolerance=None
)
except TypeError:
self.tool_shape.add(
shape=geo.geo, color=(self.app.defaults["global_draw_color"] + '80'),
update=False, layer=0, tolerance=None)
self.tool_shape.redraw()
elif type(el) == MultiLineString:
for linestring in el:
self.tool_shape.add(
shape=linestring,
color=(self.app.defaults["global_draw_color"] + '80'),
update=False,
layer=0,
tolerance=None
)
else:
self.tool_shape.add(
shape=el,
color=(self.app.defaults["global_draw_color"] + '80'),
update=False,
layer=0,
tolerance=None
)
except TypeError:
self.tool_shape.add(
shape=geo.geo, color=(self.app.defaults["global_draw_color"] + '80'),
update=False, layer=0, tolerance=None)
self.tool_shape.redraw()
def replot(self):
self.plot_all()
@ -2526,10 +2560,8 @@ class FlatCAMExcEditor(QtCore.QObject):
#
# self.plot_shape(geometry=shape.geo, color=self.app.defaults['global_draw_color'])
for shape in self.utility:
self.plot_shape(geometry=shape.geo, linewidth=1)
for shape_form in self.utility:
self.plot_shape(geometry=shape_form.geo, linewidth=1)
continue
self.shapes.redraw()
@ -2553,13 +2585,13 @@ class FlatCAMExcEditor(QtCore.QObject):
for geo in geometry:
plot_elements += self.plot_shape(geometry=geo, color=color, linewidth=linewidth)
## Non-iterable
# ## Non-iterable
except TypeError:
## DrawToolShape
# ## DrawToolShape
if isinstance(geometry, DrawToolShape):
plot_elements += self.plot_shape(geometry=geometry.geo, color=color, linewidth=linewidth)
## Polygon: Descend into exterior and each interior.
# ## Polygon: Descend into exterior and each interior.
if type(geometry) == Polygon:
plot_elements += self.plot_shape(geometry=geometry.exterior, color=color, linewidth=linewidth)
plot_elements += self.plot_shape(geometry=geometry.interiors, color=color, linewidth=linewidth)
@ -2604,11 +2636,11 @@ class FlatCAMExcEditor(QtCore.QObject):
self.build_ui()
self.app.inform.emit(_("[success] Done. Drill(s) deleted."))
def delete_shape(self, shape):
def delete_shape(self, del_shape):
self.is_modified = True
if shape in self.utility:
self.utility.remove(shape)
if del_shape in self.utility:
self.utility.remove(del_shape)
return
for storage in self.storage_dict:
@ -2616,8 +2648,8 @@ class FlatCAMExcEditor(QtCore.QObject):
# self.storage_dict[storage].remove(shape)
# except:
# pass
if shape in self.storage_dict[storage].get_objects():
self.storage_dict[storage].remove(shape)
if del_shape in self.storage_dict[storage].get_objects():
self.storage_dict[storage].remove(del_shape)
# a hack to make the tool_table display less drills per diameter
# self.points_edit it's only useful first time when we load the data into the storage
# but is still used as referecen when building tool_table in self.build_ui()
@ -2625,15 +2657,13 @@ class FlatCAMExcEditor(QtCore.QObject):
# deleting self.points_edit elements (doesn't matter who but just the number) solved the display issue.
del self.points_edit[storage][0]
if shape in self.selected:
self.selected.remove(shape) # TODO: Check performance
if del_shape in self.selected:
self.selected.remove(del_shape) # TODO: Check performance
def delete_utility_geometry(self):
# for_deletion = [shape for shape in self.shape_buffer if shape.utility]
# for_deletion = [shape for shape in self.storage.get_objects() if shape.utility]
for_deletion = [shape for shape in self.utility]
for shape in for_deletion:
self.delete_shape(shape)
for_deletion = [util_shape for util_shape in self.utility]
for util_shape in for_deletion:
self.delete_shape(util_shape)
self.tool_shape.clear(update=True)
self.tool_shape.redraw()
@ -2652,17 +2682,17 @@ class FlatCAMExcEditor(QtCore.QObject):
self.tools_exc[toolname]["button"].setChecked(True)
self.on_tool_select(toolname)
def set_selected(self, shape):
def set_selected(self, sel_shape):
# Remove and add to the end.
if shape in self.selected:
self.selected.remove(shape)
if sel_shape in self.selected:
self.selected.remove(sel_shape)
self.selected.append(shape)
self.selected.append(sel_shape)
def set_unselected(self, shape):
if shape in self.selected:
self.selected.remove(shape)
def set_unselected(self, unsel_shape):
if unsel_shape in self.selected:
self.selected.remove(unsel_shape)
def on_array_type_combo(self):
if self.array_type_combo.currentIndex() == 0:
@ -2701,4 +2731,25 @@ class FlatCAMExcEditor(QtCore.QObject):
def exc_move_drills(self):
self.select_tool('drill_move')
return
return
def get_shapely_list_bounds(geometry_list):
xmin = Inf
ymin = Inf
xmax = -Inf
ymax = -Inf
for gs in geometry_list:
try:
gxmin, gymin, gxmax, gymax = gs.bounds
xmin = min([xmin, gxmin])
ymin = min([ymin, gymin])
xmax = max([xmax, gxmax])
ymax = max([ymax, gymax])
except Exception as e:
log.warning("DEVELOPMENT: Tried to get bounds of empty geometry. --> %s" % str(e))
return [xmin, ymin, xmax, ymax]
# EOF

View File

@ -1,15 +1,15 @@
# ###########################################################
# ######################################################### ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 #
# MIT Licence #
# ###########################################################
# ######################################################### ##
# ########################################################### #
# File Modified: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# ###########################################################
# ######################################################### ##
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import Qt, QSettings
@ -629,7 +629,7 @@ class TransformEditorTool(FlatCAMTool):
self.transform_lay = QtWidgets.QVBoxLayout()
self.layout.addLayout(self.transform_lay)
## Title
# ## Title
title_label = QtWidgets.QLabel("%s" % (_('Editor %s') % self.toolName))
title_label.setStyleSheet("""
QLabel
@ -2917,9 +2917,9 @@ class FCTransform(FCShapeTool):
self.draw_app.transform_tool.run()
# #######################
# ## Main Application ###
# #######################
# ##################### ##
# # ## Main Application # ##
# ##################### ##
class FlatCAMGeoEditor(QtCore.QObject):
transform_complete = QtCore.pyqtSignal()
@ -2935,7 +2935,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.app = app
self.canvas = app.plotcanvas
## Toolbar events and properties
# ## Toolbar events and properties
self.tools = {
"select": {"button": self.app.ui.geo_select_btn,
"constructor": FCSelect},
@ -2965,7 +2965,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
"constructor": FCCopy}
}
# ## Data
# # ## Data
self.active_tool = None
self.storage = FlatCAMGeoEditor.make_storage()
@ -3373,10 +3373,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
def toolbar_tool_toggle(self, key):
self.options[key] = self.sender().isChecked()
if self.options[key] == True:
return 1
else:
return 0
return 1 if self.options[key] == True else 0
def clear(self):
self.active_tool = None
@ -3416,7 +3413,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
if multigeo_tool:
self.multigeo_tool = multigeo_tool
geo_to_edit = fcgeometry.flatten(geometry=fcgeometry.tools[self.multigeo_tool]['solid_geometry'])
self.app.inform.emit(_("[WARNING] Editing MultiGeo Geometry, tool: {tool} with diameter: {dia}").
self.app.inform.emit(_("[WARNING_NOTCL] Editing MultiGeo Geometry, tool: {tool} with diameter: {dia}").
format(tool=self.multigeo_tool, dia=fcgeometry.tools[self.multigeo_tool]['tooldia']))
else:
geo_to_edit = fcgeometry.flatten()
@ -3572,7 +3569,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
if self.active_tool is None:
return
# ## Snap coordinates
# # ## Snap coordinates
if self.app.grid_status():
x, y = self.snap(x, y)
self.app.app_cursor.enabled = True
@ -3600,14 +3597,14 @@ class FlatCAMGeoEditor(QtCore.QObject):
if event.button == 1 and event.is_dragging == 1 and isinstance(self.active_tool, FCEraser):
pass
else:
# ## Utility geometry (animated)
# # ## Utility geometry (animated)
geo = self.active_tool.utility_geometry(data=(x, y))
if isinstance(geo, DrawToolShape) and geo.geo is not None:
# Remove any previous utility shape
self.tool_shape.clear(update=True)
self.draw_utility_geometry(geo=geo)
# ## Selection area on canvas section ###
# # ## Selection area on canvas section # ##
dx = pos[0] - self.pos[0]
if event.is_dragging == 1 and event.button == 1:
self.app.delete_selection_shape()
@ -3941,9 +3938,9 @@ class FlatCAMGeoEditor(QtCore.QObject):
snap_x, snap_y = (x, y)
snap_distance = Inf
# ## Object (corner?) snap
# ## No need for the objects, just the coordinates
# ## in the index.
# # ## Object (corner?) snap
# # ## No need for the objects, just the coordinates
# # ## in the index.
if self.options["corner_snap"]:
try:
nearest_pt, shape = self.storage.nearest((x, y))
@ -3955,7 +3952,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
except (StopIteration, AssertionError):
pass
# ## Grid snap
# # ## Grid snap
if self.options["grid_snap"]:
if self.options["global_gridx"] != 0:
snap_x_ = round(x / self.options["global_gridx"]) * self.options['global_gridx']

View File

@ -52,7 +52,7 @@ class DrawToolShape(object):
"""
pts = []
## Iterable: descend into each item.
# ## Iterable: descend into each item.
try:
for sub_o in o:
pts += DrawToolShape.get_pts(sub_o)
@ -64,7 +64,7 @@ class DrawToolShape(object):
if isinstance(o, DrawToolShape):
pts += DrawToolShape.get_pts(o.geo)
## Descend into .exerior and .interiors
# ## Descend into .exerior and .interiors
elif type(o) == Polygon:
pts += DrawToolShape.get_pts(o.exterior)
for i in o.interiors:
@ -72,7 +72,7 @@ class DrawToolShape(object):
elif type(o) == MultiLineString:
for line in o:
pts += DrawToolShape.get_pts(line)
## Has .coords: list them.
# ## Has .coords: list them.
else:
if DrawToolShape.tolerance is not None:
pts += list(o.simplify(DrawToolShape.tolerance).coords)
@ -1349,7 +1349,14 @@ class FCDisc(FCShapeTool):
size_ap = float(self.draw_app.storage_dict[self.draw_app.last_aperture_selected]['size'])
self.buf_val = (size_ap / 2) if size_ap > 0 else 0.0000001
self.storage_obj = self.draw_app.storage_dict[self.draw_app.last_aperture_selected]['geometry']
if '0' in self.draw_app.storage_dict:
self.storage_obj = self.draw_app.storage_dict['0']['geometry']
else:
self.draw_app.storage_dict['0'] = dict()
self.draw_app.storage_dict['0']['type'] = 'C'
self.draw_app.storage_dict['0']['size'] = 0.0
self.draw_app.storage_dict['0']['geometry'] = list()
self.storage_obj = self.draw_app.storage_dict['0']['geometry']
self.draw_app.app.inform.emit(_("Click on Center point ..."))
@ -1436,7 +1443,14 @@ class FCSemiDisc(FCShapeTool):
size_ap = float(self.draw_app.storage_dict[self.draw_app.last_aperture_selected]['size'])
self.buf_val = (size_ap / 2) if size_ap > 0 else 0.0000001
self.storage_obj = self.draw_app.storage_dict[self.draw_app.last_aperture_selected]['geometry']
if '0' in self.draw_app.storage_dict:
self.storage_obj = self.draw_app.storage_dict['0']['geometry']
else:
self.draw_app.storage_dict['0'] = dict()
self.draw_app.storage_dict['0']['type'] = 'C'
self.draw_app.storage_dict['0']['size'] = 0.0
self.draw_app.storage_dict['0']['geometry'] = list()
self.storage_obj = self.draw_app.storage_dict['0']['geometry']
self.steps_per_circ = self.draw_app.app.defaults["gerber_circle_steps"]
@ -2050,7 +2064,9 @@ class FCEraser(FCShapeTool):
if 'solid' in geo_el.geo:
geometric_data = geo_el.geo['solid']
if eraser_sel_shapes.within(geometric_data) or eraser_sel_shapes.intersects(geometric_data):
geo_el.geo['solid'] = geometric_data.difference(eraser_sel_shapes)
geos = geometric_data.difference(eraser_sel_shapes)
geos = geos.buffer(0)
geo_el.geo['solid'] = deepcopy(geos)
except KeyError:
pass
@ -2258,7 +2274,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
layout.addLayout(self.custom_box)
# ### Gerber Apertures ####
# # ## Gerber Apertures ## ##
self.apertures_table_label = QtWidgets.QLabel(_('<b>Apertures:</b>'))
self.apertures_table_label.setToolTip(
_("Apertures Table for the Gerber Object.")
@ -2300,7 +2316,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.apertures_box.setContentsMargins(0, 0, 0, 0)
self.apertures_frame.setLayout(self.apertures_box)
# ### Add/Delete an new Aperture ####
# # ## Add/Delete an new Aperture ## ##
grid1 = QtWidgets.QGridLayout()
self.apertures_box.addLayout(grid1)
@ -2374,7 +2390,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
hlay_ad.addWidget(self.addaperture_btn)
hlay_ad.addWidget(self.delaperture_btn)
# ## BUFFER TOOL ###
# # ## BUFFER TOOL # ##
self.buffer_tool_frame = QtWidgets.QFrame()
self.buffer_tool_frame.setContentsMargins(0, 0, 0, 0)
@ -2418,7 +2434,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.buffer_button = QtWidgets.QPushButton(_("Buffer"))
hlay_buf.addWidget(self.buffer_button)
# ## SCALE TOOL ###
# # ## SCALE TOOL # ##
self.scale_tool_frame = QtWidgets.QFrame()
self.scale_tool_frame.setContentsMargins(0, 0, 0, 0)
@ -2465,7 +2481,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.array_box.setContentsMargins(0, 0, 0, 0)
self.array_frame.setLayout(self.array_box)
# ### Add Pad Array ####
# # ## Add Pad Array ## ##
self.emptyarray_label = QtWidgets.QLabel('')
self.array_box.addWidget(self.emptyarray_label)
@ -2617,7 +2633,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
"constructor": FCApertureMove},
}
# ## Data
# # ## Data
self.active_tool = None
self.storage_dict = {}
@ -3463,9 +3479,9 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.gerber_obj.apertures = conv_apertures
# ###############################################################
# ############################################################# ##
# APPLY CLEAR_GEOMETRY on the SOLID_GEOMETRY
# ###############################################################
# ############################################################# ##
# log.warning("Applying clear geometry in the apertures dict.")
# list of clear geos that are to be applied to the entire file
@ -3621,7 +3637,13 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.gerber_obj.options['name'].upper())
out_name = outname
local_storage_dict = deepcopy(self.storage_dict)
local_storage_dict = dict()
for aperture in self.storage_dict:
if 'geometry' in self.storage_dict[aperture]:
# add aperture only if it has geometry
if len(self.storage_dict[aperture]['geometry']) > 0:
local_storage_dict[aperture] = deepcopy(self.storage_dict[aperture])
# How the object should be initialized
def obj_init(grb_obj, app_obj):
@ -4057,7 +4079,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
if self.active_tool is None:
return
# ## Snap coordinates
# # ## Snap coordinates
if self.app.grid_status():
x, y = self.app.geo_editor.snap(x, y)
self.app.app_cursor.enabled = True
@ -4082,7 +4104,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (dx, dy))
# ## Utility geometry (animated)
# # ## Utility geometry (animated)
geo = self.active_tool.utility_geometry(data=(x, y))
if isinstance(geo, DrawToolShape) and geo.geo is not None:
@ -4090,7 +4112,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.tool_shape.clear(update=True)
self.draw_utility_geometry(geo=geo)
# ## Selection area on canvas section ###
# # ## Selection area on canvas section # ##
if event.is_dragging == 1 and event.button == 1:
# I make an exception for FCRegion and FCTrack because clicking and dragging while making regions can
# create strange issues like missing a point in a track/region

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,15 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 #
# MIT Licence #
############################################################
# ########################################################## ##
############################################################
# ########################################################## ##
# File Modified (major mod): Marius Adrian Stanciu #
# Date: 3/10/2019 #
############################################################
# ########################################################## ##
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
@ -159,6 +159,10 @@ class LengthEntry(QtWidgets.QLineEdit):
'MM': 1.0}
}
self.readyToEdit = True
self.editingFinished.connect(self.on_edit_finished)
def on_edit_finished(self):
self.clearFocus()
def mousePressEvent(self, e, Parent=None):
super(LengthEntry, self).mousePressEvent(e) # required to deselect on 2e click
@ -209,6 +213,10 @@ class FloatEntry(QtWidgets.QLineEdit):
def __init__(self, parent=None):
super(FloatEntry, self).__init__(parent)
self.readyToEdit = True
self.editingFinished.connect(self.on_edit_finished)
def on_edit_finished(self):
self.clearFocus()
def mousePressEvent(self, e, Parent=None):
super(FloatEntry, self).mousePressEvent(e) # required to deselect on 2e click
@ -256,6 +264,10 @@ class FloatEntry2(QtWidgets.QLineEdit):
def __init__(self, parent=None):
super(FloatEntry2, self).__init__(parent)
self.readyToEdit = True
self.editingFinished.connect(self.on_edit_finished)
def on_edit_finished(self):
self.clearFocus()
def mousePressEvent(self, e, Parent=None):
super(FloatEntry2, self).mousePressEvent(e) # required to deselect on 2e click
@ -295,6 +307,10 @@ class IntEntry(QtWidgets.QLineEdit):
self.allow_empty = allow_empty
self.empty_val = empty_val
self.readyToEdit = True
self.editingFinished.connect(self.on_edit_finished)
def on_edit_finished(self):
self.clearFocus()
def mousePressEvent(self, e, Parent=None):
super(IntEntry, self).mousePressEvent(e) # required to deselect on 2e click
@ -335,6 +351,10 @@ class FCEntry(QtWidgets.QLineEdit):
def __init__(self, parent=None):
super(FCEntry, self).__init__(parent)
self.readyToEdit = True
self.editingFinished.connect(self.on_edit_finished)
def on_edit_finished(self):
self.clearFocus()
def mousePressEvent(self, e, Parent=None):
super(FCEntry, self).mousePressEvent(e) # required to deselect on 2e click
@ -365,6 +385,10 @@ class FCEntry2(FCEntry):
def __init__(self, parent=None):
super(FCEntry2, self).__init__(parent)
self.readyToEdit = True
self.editingFinished.connect(self.on_edit_finished)
def on_edit_finished(self):
self.clearFocus()
def set_value(self, val):
try:
@ -378,6 +402,10 @@ class EvalEntry(QtWidgets.QLineEdit):
def __init__(self, parent=None):
super(EvalEntry, self).__init__(parent)
self.readyToEdit = True
self.editingFinished.connect(self.on_edit_finished)
def on_edit_finished(self):
self.clearFocus()
def mousePressEvent(self, e, Parent=None):
super(EvalEntry, self).mousePressEvent(e) # required to deselect on 2e click
@ -420,6 +448,10 @@ class EvalEntry2(QtWidgets.QLineEdit):
def __init__(self, parent=None):
super(EvalEntry2, self).__init__(parent)
self.readyToEdit = True
self.editingFinished.connect(self.on_edit_finished)
def on_edit_finished(self):
self.clearFocus()
def mousePressEvent(self, e, Parent=None):
super(EvalEntry2, self).mousePressEvent(e) # required to deselect on 2e click
@ -1462,6 +1494,10 @@ class FCSpinner(QtWidgets.QSpinBox):
def __init__(self, parent=None):
super(FCSpinner, self).__init__(parent)
self.readyToEdit = True
self.editingFinished.connect(self.on_edit_finished)
def on_edit_finished(self):
self.clearFocus()
def mousePressEvent(self, e, parent=None):
super(FCSpinner, self).mousePressEvent(e) # required to deselect on 2e click
@ -1497,6 +1533,10 @@ class FCDoubleSpinner(QtWidgets.QDoubleSpinBox):
def __init__(self, parent=None):
super(FCDoubleSpinner, self).__init__(parent)
self.readyToEdit = True
self.editingFinished.connect(self.on_edit_finished)
def on_edit_finished(self):
self.clearFocus()
def mousePressEvent(self, e, parent=None):
super(FCDoubleSpinner, self).mousePressEvent(e) # required to deselect on 2e click

View File

@ -1,15 +1,15 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 #
# MIT Licence #
############################################################
# ########################################################## ##
############################################################
# ########################################################## ##
# File Modified (major mod): Marius Adrian Stanciu #
# Date: 3/10/2019 #
############################################################
# ########################################################## ##
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import Qt
@ -36,22 +36,22 @@ class ObjectUI(QtWidgets.QWidget):
layout = QtWidgets.QVBoxLayout()
self.setLayout(layout)
## Page Title box (spacing between children)
# ## Page Title box (spacing between children)
self.title_box = QtWidgets.QHBoxLayout()
layout.addLayout(self.title_box)
## Page Title icon
# ## Page Title icon
pixmap = QtGui.QPixmap(icon_file)
self.icon = QtWidgets.QLabel()
self.icon.setPixmap(pixmap)
self.title_box.addWidget(self.icon, stretch=0)
## Title label
# ## Title label
self.title_label = QtWidgets.QLabel("<font size=5><b>%s</b></font>" % title)
self.title_label.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
self.title_box.addWidget(self.title_label, stretch=1)
## App Level label
# ## App Level label
self.level = QtWidgets.QLabel("")
self.level.setToolTip(
_(
@ -66,16 +66,16 @@ class ObjectUI(QtWidgets.QWidget):
self.level.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
self.title_box.addWidget(self.level)
## Box box for custom widgets
# ## Box box for custom widgets
# This gets populated in offspring implementations.
self.custom_box = QtWidgets.QVBoxLayout()
layout.addLayout(self.custom_box)
###########################
## Common to all objects ##
###########################
######################### ##
# ## Common to all objects # ##
######################### ##
#### Scale ####
#### Scale ## ##
self.scale_label = QtWidgets.QLabel(_('<b>Scale:</b>'))
self.scale_label.setToolTip(
_("Change the size of the object.")
@ -104,7 +104,7 @@ class ObjectUI(QtWidgets.QWidget):
self.scale_button.setFixedWidth(70)
self.scale_grid.addWidget(self.scale_button, 0, 2)
#### Offset ####
#### Offset ## ##
self.offset_label = QtWidgets.QLabel(_('<b>Offset:</b>'))
self.offset_label.setToolTip(
_("Change the position of this object.")
@ -176,7 +176,7 @@ class GerberObjectUI(ObjectUI):
self.plot_cb.setFixedWidth(59)
grid0.addWidget(self.plot_cb, 0, 3)
## Object name
# ## Object name
self.name_hlay = QtWidgets.QHBoxLayout()
self.custom_box.addLayout(self.name_hlay)
name_label = QtWidgets.QLabel(_("<b>Name:</b>"))
@ -188,7 +188,7 @@ class GerberObjectUI(ObjectUI):
hlay_plot = QtWidgets.QHBoxLayout()
self.custom_box.addLayout(hlay_plot)
#### Gerber Apertures ####
#### Gerber Apertures ## ##
self.apertures_table_label = QtWidgets.QLabel(_('<b>Apertures:</b>'))
self.apertures_table_label.setToolTip(
_("Apertures Table for the Gerber Object.")
@ -380,7 +380,7 @@ class GerberObjectUI(ObjectUI):
grid2 = QtWidgets.QGridLayout()
self.custom_box.addLayout(grid2)
## Clear non-copper regions
# ## Clear non-copper regions
self.clearcopper_label = QtWidgets.QLabel(_("<b>Clear N-copper:</b>"))
self.clearcopper_label.setToolTip(
_("Create a Geometry object with\n"
@ -396,7 +396,7 @@ class GerberObjectUI(ObjectUI):
)
grid2.addWidget(self.generate_ncc_button, 0, 1)
## Board cutout
# ## Board cutout
self.board_cutout_label = QtWidgets.QLabel(_("<b>Board cutout:</b>"))
self.board_cutout_label.setToolTip(
_("Create toolpaths to cut around\n"
@ -412,7 +412,7 @@ class GerberObjectUI(ObjectUI):
)
grid2.addWidget(self.generate_cutout_button, 1, 1)
## Non-copper regions
# ## Non-copper regions
self.noncopper_label = QtWidgets.QLabel(_("<b>Non-copper regions:</b>"))
self.noncopper_label.setToolTip(
_("Create polygons covering the\n"
@ -450,7 +450,7 @@ class GerberObjectUI(ObjectUI):
self.generate_noncopper_button = QtWidgets.QPushButton(_('Generate Geo'))
grid4.addWidget(self.generate_noncopper_button, 1, 1)
## Bounding box
# ## Bounding box
self.boundingbox_label = QtWidgets.QLabel(_('<b>Bounding Box:</b>'))
self.boundingbox_label.setToolTip(
_("Create a geometry surrounding the Gerber object.\n"
@ -498,7 +498,7 @@ class ExcellonObjectUI(ObjectUI):
icon_file='share/drill32.png',
parent=parent)
#### Plot options ####
#### Plot options ## ##
hlay_plot = QtWidgets.QHBoxLayout()
self.custom_box.addLayout(hlay_plot)
@ -511,7 +511,7 @@ class ExcellonObjectUI(ObjectUI):
hlay_plot.addStretch()
hlay_plot.addWidget(self.solid_cb)
## Object name
# ## Object name
self.name_hlay = QtWidgets.QHBoxLayout()
self.custom_box.addLayout(self.name_hlay)
name_label = QtWidgets.QLabel(_("<b>Name:</b>"))
@ -532,7 +532,7 @@ class ExcellonObjectUI(ObjectUI):
hlay_plot = QtWidgets.QHBoxLayout()
self.tools_box.addLayout(hlay_plot)
#### Tools Drills ####
#### Tools Drills ## ##
self.tools_table_label = QtWidgets.QLabel(_('<b>Tools Table</b>'))
self.tools_table_label.setToolTip(
_("Tools in this Excellon object\n"
@ -580,7 +580,7 @@ class ExcellonObjectUI(ObjectUI):
self.empty_label = QtWidgets.QLabel('')
self.tools_box.addWidget(self.empty_label)
#### Create CNC Job ####
#### Create CNC Job ## ##
self.cncjob_label = QtWidgets.QLabel(_('<b>Create CNC Job</b>'))
self.cncjob_label.setToolTip(
_("Create a CNC Job object\n"
@ -768,7 +768,7 @@ class ExcellonObjectUI(ObjectUI):
)
self.tools_box.addWidget(self.generate_cnc_button)
#### Milling Holes Drills####
#### Milling Holes Drills## ##
self.mill_hole_label = QtWidgets.QLabel(_('<b>Mill Holes</b>'))
self.mill_hole_label.setToolTip(
_("Create Geometry for milling holes.")
@ -833,7 +833,7 @@ class GeometryObjectUI(ObjectUI):
self.plot_options_label = QtWidgets.QLabel(_("<b>Plot Options:</b>"))
self.custom_box.addWidget(self.plot_options_label)
## Object name
# ## Object name
self.name_hlay = QtWidgets.QHBoxLayout()
self.custom_box.addLayout(self.name_hlay)
name_label = QtWidgets.QLabel(_("<b>Name:</b>"))
@ -854,7 +854,7 @@ class GeometryObjectUI(ObjectUI):
hlay_plot = QtWidgets.QHBoxLayout()
self.geo_tools_box.addLayout(hlay_plot)
#### Tools ####
#### Tools ## ##
self.tools_table_label = QtWidgets.QLabel(_('<b>Tools Table</b>'))
self.tools_table_label.setToolTip(
_("Tools in this Geometry object used for cutting.\n"
@ -964,7 +964,7 @@ class GeometryObjectUI(ObjectUI):
self.grid1.addWidget(self.tool_offset_entry, 0, 1)
self.grid1.addWidget(spacer_lbl, 0, 2)
#### Add a new Tool ####
#### Add a new Tool ## ##
hlay = QtWidgets.QHBoxLayout()
self.geo_tools_box.addLayout(hlay)
@ -1022,7 +1022,7 @@ class GeometryObjectUI(ObjectUI):
#-----------------------------------
# Create CNC Job
#-----------------------------------
#### Tools Data ####
#### Tools Data ## ##
self.tool_data_label = QtWidgets.QLabel(_('<b>Tool Data</b>'))
self.tool_data_label.setToolTip(
_(
@ -1346,7 +1346,7 @@ class CNCObjectUI(ObjectUI):
self.offset_label.hide()
self.offset_button.hide()
## Plot options
# ## Plot options
self.plot_options_label = QtWidgets.QLabel(_("<b>Plot Options:</b>"))
self.custom_box.addWidget(self.plot_options_label)
@ -1366,7 +1366,17 @@ class CNCObjectUI(ObjectUI):
{"label": "Cut", "value": "cut"}
], stretch=False)
## Object name
self.annotation_label = QtWidgets.QLabel(_("<b>Display Annotation:</b>"))
self.annotation_label.setToolTip(
_(
"This selects if to display text annotation on the plot.\n"
"When checked it will display numbers in order for each end\n"
"of a travel line."
)
)
self.annotation_cb = FCCheckBox()
# ## Object name
self.name_hlay = QtWidgets.QHBoxLayout()
self.custom_box.addLayout(self.name_hlay)
name_label = QtWidgets.QLabel(_("<b>Name:</b>"))
@ -1399,9 +1409,12 @@ class CNCObjectUI(ObjectUI):
f_lay.addWidget(self.cncplot_method_label, 0, 0)
f_lay.addWidget(self.cncplot_method_combo, 0, 1)
f_lay.addWidget(QtWidgets.QLabel(''), 0, 2)
f_lay.addWidget(self.t_distance_label, 1, 0)
f_lay.addWidget(self.t_distance_entry, 1, 1)
f_lay.addWidget(self.units_label, 1, 2)
f_lay.addWidget(self.annotation_label, 1, 0)
f_lay.addWidget(self.annotation_cb, 1, 1)
f_lay.addWidget(QtWidgets.QLabel(''), 1, 2)
f_lay.addWidget(self.t_distance_label, 2, 0)
f_lay.addWidget(self.t_distance_entry, 2, 1)
f_lay.addWidget(self.units_label, 2, 2)
self.t_distance_label.hide()
self.t_distance_entry.setVisible(False)
@ -1462,9 +1475,9 @@ class CNCObjectUI(ObjectUI):
)
self.custom_box.addWidget(self.updateplot_button)
##################
## Export G-Code
##################
################ ##
# ## Export G-Code
################ ##
self.export_gcode_label = QtWidgets.QLabel(_("<b>Export CNC Code:</b>"))
self.export_gcode_label.setToolTip(
_("Export and save G-Code to\n"

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://caram.cl/software/flatcam #
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 #
# MIT Licence #
############################################################
# ########################################################## ##
from PyQt5 import QtCore
@ -51,7 +51,7 @@ class PlotCanvas(QtCore.QObject):
self.vispy_canvas.native.setParent(self.app.ui)
self.container.addWidget(self.vispy_canvas.native)
### AXIS ###
# ## AXIS # ##
self.v_line = InfiniteLine(pos=0, color=(0.70, 0.3, 0.3, 1.0), vertical=True,
parent=self.vispy_canvas.view.scene)
@ -74,7 +74,7 @@ class PlotCanvas(QtCore.QObject):
self.text_collection = self.new_text_collection()
# TODO: Should be setting to show/hide CNC job annotations (global or per object)
self.text_collection.enabled = False
self.text_collection.enabled = True
# draw a rectangle made out of 4 lines on the canvas to serve as a hint for the work area
# all CNC have a limited workspace

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Dennis Hayrullin #
# Date: 2/5/2016 #
# MIT Licence #
############################################################
# ########################################################## ##
import numpy as np
from PyQt5.QtGui import QPalette

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Dennis Hayrullin #
# Date: 2/5/2016 #
# MIT Licence #
############################################################
# ########################################################## ##
from vispy.visuals import markers, LineVisual, InfiniteLineVisual
from vispy.visuals.axis import Ticker, _get_ticks_talbot

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Dennis Hayrullin #
# Date: 2/5/2016 #
# MIT Licence #
############################################################
# ########################################################## ##
from OpenGL import GLU

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Dennis Hayrullin #
# Date: 2/5/2016 #
# MIT Licence #
############################################################
# ########################################################## ##
from vispy.visuals import CompoundVisual, LineVisual, MeshVisual, TextVisual, MarkersVisual
from vispy.scene.visuals import VisualNode, generate_docstring, visuals
@ -456,20 +456,26 @@ class TextCollectionVisual(TextVisual):
self.data = {}
self.last_key = -1
self.lock = threading.Lock()
self.method = 'gpu'
super(TextCollectionVisual, self).__init__(**kwargs)
self.freeze()
def add(self, text, pos, visible=True, update=True):
def add(self, text, pos, visible=True, update=True, font_size=9, color='black'):
"""
Adds array of text to collection
:param text: list
Array of strings ['str1', 'str2', ... ]
:param pos: list
Array of string positions [(0, 0), (10, 10), ... ]
:param visible: bool
| Set True to make it visible
:param update: bool
Set True to redraw collection
:param font_size: int
Set font size to redraw collection
:param color: string
Set font color to redraw collection
:return: int
Index of array
"""
@ -480,7 +486,7 @@ class TextCollectionVisual(TextVisual):
self.lock.release()
# Prepare data for translation
self.data[key] = {'text': text, 'pos': pos, 'visible': visible}
self.data[key] = {'text': text, 'pos': pos, 'visible': visible,'font_size': font_size, 'color': color}
if update:
self.redraw()
@ -516,6 +522,8 @@ class TextCollectionVisual(TextVisual):
"""
labels = []
pos = []
font_s = 9
color = 'black'
# Merge buffers
for data in list(self.data.values()):
@ -523,6 +531,8 @@ class TextCollectionVisual(TextVisual):
try:
labels += data['text']
pos += data['pos']
font_s = data['font_size']
color = data['color']
except Exception as e:
print("Data error", e)
@ -530,6 +540,8 @@ class TextCollectionVisual(TextVisual):
if len(labels) > 0:
self.text = labels
self.pos = pos
self.font_size = font_s
self.color = color
else:
self.text = None
self.pos = (0, 0)

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from shapely.geometry import LineString
import logging

View File

@ -2,12 +2,12 @@
# Vasilis Vlachoudis
# Date: 20-Oct-2015
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File modified: Marius Adrian Stanciu #
# Date: 3/10/2019 #
############################################################
# ########################################################## ##
import math
import sys

View File

@ -1,15 +1,15 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
#########################################################################
### Borrowed code from 'https://github.com/gddc/ttfquery/blob/master/ ###
### and made it work with Python 3 #############
#########################################################################
# ####################################################################### ##
# ## Borrowed code from 'https://github.com/gddc/ttfquery/blob/master/ # ##
# ## and made it work with Python 3 ########### ##
# ####################################################################### ##
import re, os, sys, glob
import itertools

View File

@ -1,4 +1,4 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# Author: Juan Pablo Caram (c) #
@ -17,7 +17,7 @@
# * All transformations #
# #
# Reference: www.w3.org/TR/SVG/Overview.html #
############################################################
# ########################################################## ##
# import xml.etree.ElementTree as ET
from svg.path import Line, Arc, CubicBezier, QuadraticBezier, parse_path

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMTool import FlatCAMTool
from FlatCAMObj import *
@ -31,7 +31,7 @@ class ToolCalculator(FlatCAMTool):
self.app = app
## Title
# ## Title
title_label = QtWidgets.QLabel("%s" % self.toolName)
title_label.setStyleSheet("""
QLabel
@ -42,14 +42,14 @@ class ToolCalculator(FlatCAMTool):
""")
self.layout.addWidget(title_label)
######################
## Units Calculator ##
######################
#################### ##
# ## Units Calculator # ##
#################### ##
self.unists_spacer_label = QtWidgets.QLabel(" ")
self.layout.addWidget(self.unists_spacer_label)
## Title of the Units Calculator
# ## Title of the Units Calculator
units_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.unitsName)
self.layout.addWidget(units_label)
@ -76,18 +76,18 @@ class ToolCalculator(FlatCAMTool):
grid_units_layout.addWidget(self.inch_entry, 1, 1)
############################
## V-shape Tool Calculator ##
############################
########################## ##
# ## V-shape Tool Calculator # ##
########################## ##
self.v_shape_spacer_label = QtWidgets.QLabel(" ")
self.layout.addWidget(self.v_shape_spacer_label)
## Title of the V-shape Tools Calculator
# ## Title of the V-shape Tools Calculator
v_shape_title_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.v_shapeName)
self.layout.addWidget(v_shape_title_label)
## Form Layout
# ## Form Layout
form_layout = QtWidgets.QFormLayout()
self.layout.addLayout(form_layout)
@ -127,7 +127,7 @@ class ToolCalculator(FlatCAMTool):
form_layout.addRow(self.cutDepth_label, self.cutDepth_entry)
form_layout.addRow(self.effectiveToolDia_label, self.effectiveToolDia_entry)
## Buttons
# ## Buttons
self.calculate_vshape_button = QtWidgets.QPushButton(_("Calculate"))
# self.calculate_button.setFixedWidth(70)
self.calculate_vshape_button.setToolTip(
@ -139,14 +139,14 @@ class ToolCalculator(FlatCAMTool):
form_layout.addRow(self.empty_label, self.calculate_vshape_button)
####################################
## ElectroPlating Tool Calculator ##
####################################
################################## ##
# ## ElectroPlating Tool Calculator # ##
################################## ##
self.plate_spacer_label = QtWidgets.QLabel(" ")
self.layout.addWidget(self.plate_spacer_label)
## Title of the ElectroPlating Tools Calculator
# ## Title of the ElectroPlating Tools Calculator
plate_title_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.eplateName)
plate_title_label.setToolTip(
_("This calculator is useful for those who plate the via/pad/drill holes,\n"
@ -154,7 +154,7 @@ class ToolCalculator(FlatCAMTool):
)
self.layout.addWidget(plate_title_label)
## Plate Form Layout
# ## Plate Form Layout
plate_form_layout = QtWidgets.QFormLayout()
self.layout.addLayout(plate_form_layout)
@ -210,7 +210,7 @@ class ToolCalculator(FlatCAMTool):
plate_form_layout.addRow(self.cvaluelabel, self.cvalue_entry)
plate_form_layout.addRow(self.timelabel, self.time_entry)
## Buttons
# ## Buttons
self.calculate_plate_button = QtWidgets.QPushButton(_("Calculate"))
# self.calculate_button.setFixedWidth(70)
self.calculate_plate_button.setToolTip(
@ -223,7 +223,7 @@ class ToolCalculator(FlatCAMTool):
self.layout.addStretch()
## Signals
# ## Signals
self.cutDepth_entry.textChanged.connect(self.on_calculate_tool_dia)
self.cutDepth_entry.editingFinished.connect(self.on_calculate_tool_dia)
self.tipDia_entry.editingFinished.connect(self.on_calculate_tool_dia)
@ -264,7 +264,7 @@ class ToolCalculator(FlatCAMTool):
def set_tool_ui(self):
self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
## Initialize form
# ## Initialize form
self.mm_entry.set_value('0')
self.inch_entry.set_value('0')

View File

@ -415,7 +415,7 @@ class CutOut(FlatCAMTool):
object_geo = cutout_obj.solid_geometry
try:
_ = iter(object_geo)
__ = iter(object_geo)
except TypeError:
object_geo = [object_geo]
@ -424,7 +424,8 @@ class CutOut(FlatCAMTool):
geo = (geo.buffer(margin + abs(dia / 2))).exterior
# Get min and max data for each object as we just cut rectangles across X or Y
xmin, ymin, xmax, ymax = geo.bounds
xmin, ymin, xmax, ymax = recursive_bounds(geo)
px = 0.5 * (xmin + xmax) + margin
py = 0.5 * (ymin + ymax) + margin
lenx = (xmax - xmin) + (margin * 2)
@ -475,6 +476,11 @@ class CutOut(FlatCAMTool):
solid_geo.append(geo)
geo_obj.solid_geometry = deepcopy(solid_geo)
xmin, ymin, xmax, ymax = recursive_bounds(geo_obj.solid_geometry)
geo_obj.options['xmin'] = xmin
geo_obj.options['ymin'] = ymin
geo_obj.options['xmax'] = xmax
geo_obj.options['ymax'] = ymax
outname = cutout_obj.options["name"] + "_cutout"
self.app.new_object('geometry', outname, geo_init)
@ -565,7 +571,7 @@ class CutOut(FlatCAMTool):
object_geo = cutout_obj.solid_geometry
try:
_ = iter(object_geo)
__ = iter(object_geo)
except TypeError:
object_geo = [object_geo]

View File

@ -20,7 +20,7 @@ class DblSidedTool(FlatCAMTool):
def __init__(self, app):
FlatCAMTool.__init__(self, app)
## Title
# ## Title
title_label = QtWidgets.QLabel("%s" % self.toolName)
title_label.setStyleSheet("""
QLabel
@ -34,11 +34,11 @@ class DblSidedTool(FlatCAMTool):
self.empty_lb = QtWidgets.QLabel("")
self.layout.addWidget(self.empty_lb)
## Grid Layout
# ## Grid Layout
grid_lay = QtWidgets.QGridLayout()
self.layout.addLayout(grid_lay)
## Gerber Object to mirror
# ## Gerber Object to mirror
self.gerber_object_combo = QtWidgets.QComboBox()
self.gerber_object_combo.setModel(self.app.collection)
self.gerber_object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
@ -62,7 +62,7 @@ class DblSidedTool(FlatCAMTool):
grid_lay.addWidget(self.gerber_object_combo, 1, 0)
grid_lay.addWidget(self.mirror_gerber_button, 1, 1)
## Excellon Object to mirror
# ## Excellon Object to mirror
self.exc_object_combo = QtWidgets.QComboBox()
self.exc_object_combo.setModel(self.app.collection)
self.exc_object_combo.setRootModelIndex(self.app.collection.index(1, 0, QtCore.QModelIndex()))
@ -86,7 +86,7 @@ class DblSidedTool(FlatCAMTool):
grid_lay.addWidget(self.exc_object_combo, 3, 0)
grid_lay.addWidget(self.mirror_exc_button, 3, 1)
## Geometry Object to mirror
# ## Geometry Object to mirror
self.geo_object_combo = QtWidgets.QComboBox()
self.geo_object_combo.setModel(self.app.collection)
self.geo_object_combo.setRootModelIndex(self.app.collection.index(2, 0, QtCore.QModelIndex()))
@ -110,11 +110,11 @@ class DblSidedTool(FlatCAMTool):
grid_lay.addWidget(self.geo_object_combo, 5, 0)
grid_lay.addWidget(self.mirror_geo_button, 5, 1)
## Grid Layout
# ## Grid Layout
grid_lay1 = QtWidgets.QGridLayout()
self.layout.addLayout(grid_lay1)
## Axis
# ## Axis
self.mirror_axis = RadioSet([{'label': 'X', 'value': 'X'},
{'label': 'Y', 'value': 'Y'}])
self.mirax_label = QtWidgets.QLabel(_("Mirror Axis:"))
@ -127,7 +127,7 @@ class DblSidedTool(FlatCAMTool):
grid_lay1.addWidget(self.mirax_label, 7, 0)
grid_lay1.addWidget(self.mirror_axis, 7, 1)
## Axis Location
# ## Axis Location
self.axis_location = RadioSet([{'label': 'Point', 'value': 'point'},
{'label': 'Box', 'value': 'box'}])
self.axloc_label = QtWidgets.QLabel(_("Axis Ref:"))
@ -143,11 +143,11 @@ class DblSidedTool(FlatCAMTool):
self.empty_lb2 = QtWidgets.QLabel("")
grid_lay1.addWidget(self.empty_lb2, 9, 0)
## Grid Layout
# ## Grid Layout
grid_lay2 = QtWidgets.QGridLayout()
self.layout.addLayout(grid_lay2)
## Point/Box
# ## Point/Box
self.point_box_container = QtWidgets.QVBoxLayout()
self.pb_label = QtWidgets.QLabel("<b>%s</b>" % _('Point/Box Reference:'))
self.pb_label.setToolTip(
@ -189,7 +189,7 @@ class DblSidedTool(FlatCAMTool):
self.box_combo_type.hide()
## Alignment holes
# ## Alignment holes
self.ah_label = QtWidgets.QLabel("<b>%s</b>" % _('Alignment Drill Coordinates:'))
self.ah_label.setToolTip(
_( "Alignment holes (x1, y1), (x2, y2), ... "
@ -220,7 +220,7 @@ class DblSidedTool(FlatCAMTool):
grid_lay3.addWidget(self.alignment_holes, 0, 0)
grid_lay3.addWidget(self.add_drill_point_button, 0, 1)
## Drill diameter for alignment holes
# ## Drill diameter for alignment holes
self.dt_label = QtWidgets.QLabel("<b>%s</b>:" % _('Alignment Drill Diameter'))
self.dt_label.setToolTip(
_("Diameter of the drill for the "
@ -243,7 +243,7 @@ class DblSidedTool(FlatCAMTool):
hlay2 = QtWidgets.QHBoxLayout()
self.layout.addLayout(hlay2)
## Buttons
# ## Buttons
self.create_alignment_hole_button = QtWidgets.QPushButton(_("Create Excellon Object"))
self.create_alignment_hole_button.setToolTip(
_("Creates an Excellon Object containing the\n"
@ -261,7 +261,7 @@ class DblSidedTool(FlatCAMTool):
self.layout.addStretch()
## Signals
# ## Signals
self.create_alignment_hole_button.clicked.connect(self.on_create_alignment_holes)
self.mirror_gerber_button.clicked.connect(self.on_mirror_gerber)
self.mirror_exc_button.clicked.connect(self.on_mirror_exc)

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMTool import FlatCAMTool
@ -165,7 +165,7 @@ class Film(FlatCAMTool):
self.layout.addStretch()
## Signals
# ## Signals
self.film_object_button.clicked.connect(self.on_film_creation)
self.tf_type_obj_combo.currentIndexChanged.connect(self.on_type_obj_index_changed)
self.tf_type_box_combo.currentIndexChanged.connect(self.on_type_box_index_changed)

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMTool import FlatCAMTool
@ -144,7 +144,7 @@ class ToolImage(FlatCAMTool):
self.layout.addStretch()
## Signals
# ## Signals
self.import_button.clicked.connect(self.on_file_importimage)
def run(self, toggle=True):
@ -173,7 +173,7 @@ class ToolImage(FlatCAMTool):
FlatCAMTool.install(self, icon, separator, **kwargs)
def set_tool_ui(self):
## Initialize form
# ## Initialize form
self.dpi_entry.set_value(96)
self.image_type.set_value('black')
self.mask_bw_entry.set_value(250)

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMTool import FlatCAMTool
from FlatCAMObj import *
@ -32,11 +32,11 @@ class Measurement(FlatCAMTool):
self.canvas = self.app.plotcanvas
self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower()
## Title
# ## Title
title_label = QtWidgets.QLabel("<font size=4><b>%s</b></font><br>" % self.toolName)
self.layout.addWidget(title_label)
## Form Layout
# ## Form Layout
form_layout = QtWidgets.QFormLayout()
self.layout.addLayout(form_layout)

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMTool import FlatCAMTool
from FlatCAMObj import *

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Modified by: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMTool import FlatCAMTool
from copy import copy,deepcopy
@ -38,7 +38,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
self.tools_box.setContentsMargins(0, 0, 0, 0)
self.tools_frame.setLayout(self.tools_box)
## Title
# ## Title
title_label = QtWidgets.QLabel("%s" % self.toolName)
title_label.setStyleSheet("""
QLabel
@ -49,11 +49,11 @@ class NonCopperClear(FlatCAMTool, Gerber):
""")
self.tools_box.addWidget(title_label)
## Form Layout
# ## Form Layout
form_layout = QtWidgets.QFormLayout()
self.tools_box.addLayout(form_layout)
## Object
# ## Object
self.object_combo = QtWidgets.QComboBox()
self.object_combo.setModel(self.app.collection)
self.object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
@ -68,7 +68,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
form_layout.addRow(self.object_label, self.object_combo)
form_layout.addRow(e_lab_0)
#### Tools ####
#### Tools ## ##
self.tools_table_label = QtWidgets.QLabel('<b>%s</b>' % _('Tools Table'))
self.tools_table_label.setToolTip(
_("Tools pool from which the algorithm\n"
@ -113,7 +113,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
self.empty_label = QtWidgets.QLabel('')
self.tools_box.addWidget(self.empty_label)
#### Add a new Tool ####
#### Add a new Tool ## ##
hlay = QtWidgets.QHBoxLayout()
self.tools_box.addLayout(hlay)
@ -420,7 +420,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
self.tools_table.setItem(row_no, 1, dia) # Diameter
self.tools_table.setCellWidget(row_no, 2, tool_type_item)
### REMEMBER: THIS COLUMN IS HIDDEN IN OBJECTUI.PY ###
# ## REMEMBER: THIS COLUMN IS HIDDEN IN OBJECTUI.PY # ##
self.tools_table.setItem(row_no, 3, tool_uid_item) # Tool unique ID
# make the diameter column editable

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 4/23/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMTool import FlatCAMTool
from shapely.geometry import Point, Polygon, LineString
@ -1242,9 +1242,9 @@ class ToolPDF(FlatCAMTool):
new_el['follow'] = pdf_geo.exterior
apertures_dict[str(aperture)]['geometry'].append(deepcopy(new_el))
# ###############################################
# ############################################# ##
# store the found geometry for filling the path #
# ###############################################
# ############################################# ##
# in case that a color change to white (transparent) occurred
if flag_clear_geo is True:

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Modified: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMTool import FlatCAMTool
from copy import copy,deepcopy
@ -29,7 +29,7 @@ class ToolPaint(FlatCAMTool, Gerber):
FlatCAMTool.__init__(self, app)
Geometry.__init__(self, geo_steps_per_circle=self.app.defaults["geometry_circle_steps"])
## Title
# ## Title
title_label = QtWidgets.QLabel("%s" % self.toolName)
title_label.setStyleSheet("""
QLabel
@ -47,11 +47,11 @@ class ToolPaint(FlatCAMTool, Gerber):
self.tools_box.setContentsMargins(0, 0, 0, 0)
self.tools_frame.setLayout(self.tools_box)
## Form Layout
# ## Form Layout
form_layout = QtWidgets.QFormLayout()
self.tools_box.addLayout(form_layout)
## Object
# ## Object
self.object_combo = QtWidgets.QComboBox()
self.object_combo.setModel(self.app.collection)
self.object_combo.setRootModelIndex(self.app.collection.index(2, 0, QtCore.QModelIndex()))
@ -65,7 +65,7 @@ class ToolPaint(FlatCAMTool, Gerber):
form_layout.addRow(self.object_label, self.object_combo)
form_layout.addRow(e_lab_0)
#### Tools ####
#### Tools ## ##
self.tools_table_label = QtWidgets.QLabel('<b>%s</b>' % _('Tools Table'))
self.tools_table_label.setToolTip(
_("Tools pool from which the algorithm\n"
@ -110,7 +110,7 @@ class ToolPaint(FlatCAMTool, Gerber):
self.empty_label = QtWidgets.QLabel('')
self.tools_box.addWidget(self.empty_label)
#### Add a new Tool ####
#### Add a new Tool ## ##
hlay = QtWidgets.QHBoxLayout()
self.tools_box.addLayout(hlay)
@ -305,7 +305,7 @@ class ToolPaint(FlatCAMTool, Gerber):
self.tool_type_item_options = ["C1", "C2", "C3", "C4", "B", "V"]
## Signals
# ## Signals
self.addtool_btn.clicked.connect(self.on_tool_add)
self.addtool_entry.returnPressed.connect(self.on_tool_add)
# self.copytool_btn.clicked.connect(lambda: self.on_tool_copy())
@ -365,7 +365,7 @@ class ToolPaint(FlatCAMTool, Gerber):
self.tools_frame.show()
self.reset_fields()
## Init the GUI interface
# ## Init the GUI interface
self.paintmargin_entry.set_value(self.default_data["paintmargin"])
self.paintmethod_combo.set_value(self.default_data["paintmethod"])
self.selectmethod_combo.set_value(self.default_data["selectmethod"])
@ -484,7 +484,7 @@ class ToolPaint(FlatCAMTool, Gerber):
self.tools_table.setItem(row_no, 1, dia) # Diameter
self.tools_table.setCellWidget(row_no, 2, tool_type_item)
### REMEMBER: THIS COLUMN IS HIDDEN IN OBJECTUI.PY ###
# ## REMEMBER: THIS COLUMN IS HIDDEN IN OBJECTUI.PY # ##
self.tools_table.setItem(row_no, 3, tool_uid_item) # Tool unique ID
# make the diameter column editable
@ -1035,13 +1035,13 @@ class ToolPaint(FlatCAMTool, Gerber):
if reset:
self.flat_geometry = []
## If iterable, expand recursively.
# ## If iterable, expand recursively.
try:
for geo in geometry:
if geo is not None:
recurse(geometry=geo, reset=False)
## Not iterable, do the actual indexing and add.
# ## Not iterable, do the actual indexing and add.
except TypeError:
self.flat_geometry.append(geometry)

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMTool import FlatCAMTool
from copy import copy, deepcopy
@ -28,7 +28,7 @@ class Panelize(FlatCAMTool):
super(Panelize, self).__init__(self)
self.app = app
## Title
# ## Title
title_label = QtWidgets.QLabel("%s" % self.toolName)
title_label.setStyleSheet("""
QLabel

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 4/15/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMTool import FlatCAMTool
@ -152,7 +152,7 @@ class PcbWizard(FlatCAMTool):
self.modified_excellon_file = ''
## Signals
# ## Signals
self.excellon_brn.clicked.connect(self.on_load_excellon_click)
self.inf_btn.clicked.connect(self.on_load_inf_click)
self.import_button.clicked.connect(lambda: self.on_import_excellon(
@ -207,7 +207,7 @@ class PcbWizard(FlatCAMTool):
self.exc_file_content = None
self.tools_from_inf = {}
## Initialize form
# ## Initialize form
self.int_entry.set_value(self.integral)
self.frac_entry.set_value(self.fractional)
self.zeros_radio.set_value(self.zeros)

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import Qt
@ -37,7 +37,7 @@ class Properties(FlatCAMTool):
self.properties_box.setContentsMargins(0, 0, 0, 0)
self.properties_frame.setLayout(self.properties_box)
## Title
# ## Title
title_label = QtWidgets.QLabel("%s" % self.toolName)
title_label.setStyleSheet("""
QLabel

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 #
# MIT Licence #
############################################################
# ########################################################## ##
# from PyQt5.QtCore import pyqtSignal
from PyQt5.QtCore import Qt

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMTool import FlatCAMTool
from FlatCAMCommon import LoudDict
@ -39,7 +39,7 @@ class SolderPaste(FlatCAMTool):
def __init__(self, app):
FlatCAMTool.__init__(self, app)
## Title
# ## Title
title_label = QtWidgets.QLabel("%s" % self.toolName)
title_label.setStyleSheet("""
QLabel
@ -50,11 +50,11 @@ class SolderPaste(FlatCAMTool):
""")
self.layout.addWidget(title_label)
## Form Layout
# ## Form Layout
obj_form_layout = QtWidgets.QFormLayout()
self.layout.addLayout(obj_form_layout)
## Gerber Object to be used for solderpaste dispensing
# ## Gerber Object to be used for solderpaste dispensing
self.obj_combo = FCComboBox(callback=self.on_rmb_combo)
self.obj_combo.setModel(self.app.collection)
self.obj_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
@ -66,7 +66,7 @@ class SolderPaste(FlatCAMTool):
)
obj_form_layout.addRow(self.object_label, self.obj_combo)
#### Tools ####
#### Tools ## ##
self.tools_table_label = QtWidgets.QLabel('<b>%s</b>' % _('Tools Table'))
self.tools_table_label.setToolTip(
_("Tools pool from which the algorithm\n"
@ -94,7 +94,7 @@ class SolderPaste(FlatCAMTool):
_( "Nozzle tool Diameter. It's value (in current FlatCAM units)\n"
"is the width of the solder paste dispensed."))
#### Add a new Tool ####
#### Add a new Tool ## ##
hlay_tools = QtWidgets.QHBoxLayout()
self.layout.addLayout(hlay_tools)
@ -135,7 +135,7 @@ class SolderPaste(FlatCAMTool):
self.layout.addSpacing(10)
## Buttons
# ## Buttons
grid0_1 = QtWidgets.QGridLayout()
self.layout.addLayout(grid0_1)
@ -157,7 +157,7 @@ class SolderPaste(FlatCAMTool):
self.gcode_box.setContentsMargins(0, 0, 0, 0)
self.gcode_frame.setLayout(self.gcode_box)
## Form Layout
# ## Form Layout
self.gcode_form_layout = QtWidgets.QFormLayout()
self.gcode_box.addLayout(self.gcode_form_layout)
@ -283,7 +283,7 @@ class SolderPaste(FlatCAMTool):
self.pp_combo.setStyleSheet('background-color: rgb(255,255,255)')
self.gcode_form_layout.addRow(pp_label, self.pp_combo)
## Buttons
# ## Buttons
grid1 = QtWidgets.QGridLayout()
self.gcode_box.addLayout(grid1)
@ -301,7 +301,7 @@ class SolderPaste(FlatCAMTool):
self.generation_frame.setLayout(self.generation_box)
## Buttons
# ## Buttons
grid2 = QtWidgets.QGridLayout()
self.generation_box.addLayout(grid2)
@ -313,11 +313,11 @@ class SolderPaste(FlatCAMTool):
grid2.addWidget(step2_lbl, 0, 0)
grid2.addWidget(self.soldergeo_btn, 0, 2)
## Form Layout
# ## Form Layout
geo_form_layout = QtWidgets.QFormLayout()
self.generation_box.addLayout(geo_form_layout)
## Geometry Object to be used for solderpaste dispensing
# ## Geometry Object to be used for solderpaste dispensing
self.geo_obj_combo = FCComboBox(callback=self.on_rmb_combo)
self.geo_obj_combo.setModel(self.app.collection)
self.geo_obj_combo.setRootModelIndex(self.app.collection.index(2, 0, QtCore.QModelIndex()))
@ -346,11 +346,11 @@ class SolderPaste(FlatCAMTool):
grid3.addWidget(step3_lbl, 0, 0)
grid3.addWidget(self.solder_gcode_btn, 0, 2)
## Form Layout
# ## Form Layout
cnc_form_layout = QtWidgets.QFormLayout()
self.generation_box.addLayout(cnc_form_layout)
## Gerber Object to be used for solderpaste dispensing
# ## Gerber Object to be used for solderpaste dispensing
self.cnc_obj_combo = FCComboBox(callback=self.on_rmb_combo)
self.cnc_obj_combo.setModel(self.app.collection)
self.cnc_obj_combo.setRootModelIndex(self.app.collection.index(3, 0, QtCore.QModelIndex()))
@ -412,7 +412,7 @@ class SolderPaste(FlatCAMTool):
# action to be added in the combobox context menu
self.combo_context_del_action = QtWidgets.QAction(QtGui.QIcon('share/trash16.png'), _("Delete Object"))
## Signals
# ## Signals
self.combo_context_del_action.triggered.connect(self.on_delete_object)
self.addtool_btn.clicked.connect(self.on_tool_add)
self.addtool_entry.returnPressed.connect(self.on_tool_add)
@ -995,7 +995,7 @@ class SolderPaste(FlatCAMTool):
if reset:
self.flat_geometry = []
## If iterable, expand recursively.
# ## If iterable, expand recursively.
try:
for geo in geometry:
if geo is not None:
@ -1003,7 +1003,7 @@ class SolderPaste(FlatCAMTool):
reset=False,
pathonly=pathonly)
## Not iterable, do the actual indexing and add.
# ## Not iterable, do the actual indexing and add.
except TypeError:
if pathonly and type(geometry) == Polygon:
self.flat_geometry.append(geometry.exterior)
@ -1226,7 +1226,7 @@ class SolderPaste(FlatCAMTool):
job_obj.options["tooldia"] = tool_dia
job_obj.options['tool_dia'] = tool_dia
### CREATE GCODE ###
# ## CREATE GCODE # ##
res = job_obj.generate_gcode_from_solderpaste_geo(**tooluid_value)
if res == 'fail':
@ -1235,7 +1235,7 @@ class SolderPaste(FlatCAMTool):
else:
tool_cnc_dict['gcode'] = res
### PARSE GCODE ###
# ## PARSE GCODE # ##
tool_cnc_dict['gcode_parsed'] = job_obj.gcode_parse()
# TODO this serve for bounding box creation only; should be optimized
@ -1380,7 +1380,7 @@ class SolderPaste(FlatCAMTool):
gcode += obj.cnc_tools[tool]['gcode']
lines = StringIO(gcode)
## Write
# ## Write
if filename is not None:
try:
with open(filename, 'w') as f:

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 4/24/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMTool import FlatCAMTool

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMTool import FlatCAMTool
from FlatCAMObj import *
@ -32,7 +32,7 @@ class ToolTransform(FlatCAMTool):
self.transform_lay = QtWidgets.QVBoxLayout()
self.layout.addLayout(self.transform_lay)
## Title
# ## Title
title_label = QtWidgets.QLabel("%s" % self.toolName)
title_label.setStyleSheet("""
QLabel
@ -56,11 +56,11 @@ class ToolTransform(FlatCAMTool):
self.empty_label4.setFixedWidth(70)
self.transform_lay.addWidget(self.empty_label)
## Rotate Title
# ## Rotate Title
rotate_title_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.rotateName)
self.transform_lay.addWidget(rotate_title_label)
## Layout
# ## Layout
form_layout = QtWidgets.QFormLayout()
self.transform_lay.addLayout(form_layout)
form_child = QtWidgets.QHBoxLayout()
@ -94,11 +94,11 @@ class ToolTransform(FlatCAMTool):
self.transform_lay.addWidget(self.empty_label1)
## Skew Title
# ## Skew Title
skew_title_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.skewName)
self.transform_lay.addWidget(skew_title_label)
## Form Layout
# ## Form Layout
form1_layout = QtWidgets.QFormLayout()
self.transform_lay.addLayout(form1_layout)
form1_child_1 = QtWidgets.QHBoxLayout()
@ -151,11 +151,11 @@ class ToolTransform(FlatCAMTool):
self.transform_lay.addWidget(self.empty_label2)
## Scale Title
# ## Scale Title
scale_title_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.scaleName)
self.transform_lay.addWidget(scale_title_label)
## Form Layout
# ## Form Layout
form2_layout = QtWidgets.QFormLayout()
self.transform_lay.addLayout(form2_layout)
form2_child_1 = QtWidgets.QHBoxLayout()
@ -225,11 +225,11 @@ class ToolTransform(FlatCAMTool):
self.transform_lay.addWidget(self.empty_label3)
## Offset Title
# ## Offset Title
offset_title_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.offsetName)
self.transform_lay.addWidget(offset_title_label)
## Form Layout
# ## Form Layout
form3_layout = QtWidgets.QFormLayout()
self.transform_lay.addLayout(form3_layout)
form3_child_1 = QtWidgets.QHBoxLayout()
@ -280,11 +280,11 @@ class ToolTransform(FlatCAMTool):
self.transform_lay.addWidget(self.empty_label4)
## Flip Title
# ## Flip Title
flip_title_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.flipName)
self.transform_lay.addWidget(flip_title_label)
## Form Layout
# ## Form Layout
form4_layout = QtWidgets.QFormLayout()
form4_child_hlay = QtWidgets.QHBoxLayout()
self.transform_lay.addLayout(form4_child_hlay)
@ -355,7 +355,7 @@ class ToolTransform(FlatCAMTool):
self.transform_lay.addStretch()
## Signals
# ## Signals
self.rotate_button.clicked.connect(self.on_rotate)
self.skewx_button.clicked.connect(self.on_skewx)
self.skewy_button.clicked.connect(self.on_skewy)
@ -401,7 +401,7 @@ class ToolTransform(FlatCAMTool):
FlatCAMTool.install(self, icon, separator, shortcut='ALT+R', **kwargs)
def set_tool_ui(self):
## Initialize form
# ## Initialize form
if self.app.defaults["tools_transform_rotate"]:
self.rotate_entry.set_value(self.app.defaults["tools_transform_rotate"])
else:

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# Author: Juan Pablo Caram (c) #
@ -11,12 +11,12 @@
# This is not an aid to install FlatCAM from source on #
# Windows platforms. It is only useful when FlatCAM is up #
# and running and ready to be packaged. #
############################################################
# ########################################################## ##
############################################################
# ########################################################## ##
# File Modified (major mod): Marius Adrian Stanciu #
# Date: 3/10/2019 #
############################################################
# ########################################################## ##
# Files not needed: Qt, tk.dll, tcl.dll, tk/, tcl/, vtk/,

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMPostProc import *

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMPostProc import *

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMPostProc import *

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMPostProc import *

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMPostProc import *

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMPostProc import *

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Matthieu Berthomé #
# Date: 5/26/2017 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMPostProc import *

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Matthieu Berthomé #
# Date: 5/26/2017 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMPostProc import *

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Matthieu Berthomé #
# Date: 5/26/2017 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMPostProc import *

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMPostProc import *

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMPostProc import *

View File

@ -1,10 +1,10 @@
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Marius Adrian Stanciu (c) #
# Date: 3/10/2019 #
# MIT Licence #
############################################################
# ########################################################## ##
from FlatCAMPostProc import *

BIN
share/disable16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 B

BIN
share/disable32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 715 B

BIN
share/notebook16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

View File

@ -120,7 +120,7 @@ class TclCommandCutout(TclCommand):
geo_obj.solid_geometry = cascaded_union([LineString(segment) for segment in cuts])
try:
obj.app.new_object("geometry", name + "_cutout", geo_init_me)
self.app.new_object("geometry", name + "_cutout", geo_init_me)
self.app.inform.emit("[success] Rectangular-form Cutout operation finished.")
except Exception as e:
return "Operation failed: %s" % str(e)

View File

@ -165,6 +165,11 @@ class TclCommandGeoCutout(TclCommandSignaled):
# Get min and max data for each object as we just cut rectangles across X or Y
xmin, ymin, xmax, ymax = cutout_obj.bounds()
cutout_obj.options['xmin'] = xmin
cutout_obj.options['ymin'] = ymin
cutout_obj.options['xmax'] = xmax
cutout_obj.options['ymax'] = ymax
px = 0.5 * (xmin + xmax) + margin
py = 0.5 * (ymin + ymax) + margin
lenghtx = (xmax - xmin) + (margin * 2)
@ -179,48 +184,102 @@ class TclCommandGeoCutout(TclCommandSignaled):
if isinstance(cutout_obj, FlatCAMGeometry):
# rename the obj name so it can be identified as cutout
cutout_obj.options["name"] += "_cutout"
# cutout_obj.options["name"] += "_cutout"
if gaps_u == 8 or gaps_u == '2lr':
subtract_rectangle(cutout_obj,
xmin - gapsize, # botleft_x
py - gapsize + lenghty / 4, # botleft_y
xmax + gapsize, # topright_x
py + gapsize + lenghty / 4) # topright_y
subtract_rectangle(cutout_obj,
xmin - gapsize,
py - gapsize - lenghty / 4,
xmax + gapsize,
py + gapsize - lenghty / 4)
# if gaps_u == 8 or gaps_u == '2lr':
# subtract_rectangle(cutout_obj,
# xmin - gapsize, # botleft_x
# py - gapsize + lenghty / 4, # botleft_y
# xmax + gapsize, # topright_x
# py + gapsize + lenghty / 4) # topright_y
# subtract_rectangle(cutout_obj,
# xmin - gapsize,
# py - gapsize - lenghty / 4,
# xmax + gapsize,
# py + gapsize - lenghty / 4)
#
# if gaps_u == 8 or gaps_u == '2tb':
# subtract_rectangle(cutout_obj,
# px - gapsize + lenghtx / 4,
# ymin - gapsize,
# px + gapsize + lenghtx / 4,
# ymax + gapsize)
# subtract_rectangle(cutout_obj,
# px - gapsize - lenghtx / 4,
# ymin - gapsize,
# px + gapsize - lenghtx / 4,
# ymax + gapsize)
#
# if gaps_u == 4 or gaps_u == 'lr':
# subtract_rectangle(cutout_obj,
# xmin - gapsize,
# py - gapsize,
# xmax + gapsize,
# py + gapsize)
#
# if gaps_u == 4 or gaps_u == 'tb':
# subtract_rectangle(cutout_obj,
# px - gapsize,
# ymin - gapsize,
# px + gapsize,
# ymax + gapsize)
if gaps_u == 8 or gaps_u == '2tb':
subtract_rectangle(cutout_obj,
px - gapsize + lenghtx / 4,
ymin - gapsize,
px + gapsize + lenghtx / 4,
ymax + gapsize)
subtract_rectangle(cutout_obj,
px - gapsize - lenghtx / 4,
ymin - gapsize,
px + gapsize - lenghtx / 4,
ymax + gapsize)
def geo_init(geo_obj, app_obj):
geo = deepcopy(cutout_obj.solid_geometry)
if gaps_u == 4 or gaps_u == 'lr':
subtract_rectangle(cutout_obj,
xmin - gapsize,
py - gapsize,
xmax + gapsize,
py + gapsize)
if gaps_u == 8 or gaps_u == '2lr':
geo = substract_rectangle_geo(geo,
xmin - gapsize, # botleft_x
py - gapsize + lenghty / 4, # botleft_y
xmax + gapsize, # topright_x
py + gapsize + lenghty / 4) # topright_y
geo = substract_rectangle_geo(geo,
xmin - gapsize,
py - gapsize - lenghty / 4,
xmax + gapsize,
py + gapsize - lenghty / 4)
if gaps_u == 4 or gaps_u == 'tb':
subtract_rectangle(cutout_obj,
px - gapsize,
ymin - gapsize,
px + gapsize,
ymax + gapsize)
if gaps_u == 8 or gaps_u == '2tb':
geo = substract_rectangle_geo(geo,
px - gapsize + lenghtx / 4,
ymin - gapsize,
px + gapsize + lenghtx / 4,
ymax + gapsize)
geo = substract_rectangle_geo(geo,
px - gapsize - lenghtx / 4,
ymin - gapsize,
px + gapsize - lenghtx / 4,
ymax + gapsize)
cutout_obj.plot()
self.app.inform.emit("[success] Any-form Cutout operation finished.")
if gaps_u == 4 or gaps_u == 'lr':
geo = substract_rectangle_geo(geo,
xmin - gapsize,
py - gapsize,
xmax + gapsize,
py + gapsize)
if gaps_u == 4 or gaps_u == 'tb':
geo = substract_rectangle_geo(geo,
px - gapsize,
ymin - gapsize,
px + gapsize,
ymax + gapsize)
geo_obj.solid_geometry = deepcopy(geo)
geo_obj.options['xmin'] = cutout_obj.options['xmin']
geo_obj.options['ymin'] = cutout_obj.options['ymin']
geo_obj.options['xmax'] = cutout_obj.options['xmax']
geo_obj.options['ymax'] = cutout_obj.options['ymax']
app_obj.disable_plots(objects=[cutout_obj])
app_obj.inform.emit("[success] Any-form Cutout operation finished.")
outname = cutout_obj.options["name"] + "_cutout"
self.app.new_object('geometry', outname, geo_init)
# cutout_obj.plot()
# self.app.inform.emit("[success] Any-form Cutout operation finished.")
# self.app.plots_updated.emit()
elif isinstance(cutout_obj, FlatCAMGerber):
def geo_init(geo_obj, app_obj):
@ -267,7 +326,12 @@ class TclCommandGeoCutout(TclCommandSignaled):
ymin - gapsize,
px + gapsize,
ymax + gapsize)
geo_obj.solid_geometry = geo
geo_obj.solid_geometry = deepcopy(geo)
geo_obj.options['xmin'] = cutout_obj.options['xmin']
geo_obj.options['ymin'] = cutout_obj.options['ymin']
geo_obj.options['xmax'] = cutout_obj.options['xmax']
geo_obj.options['ymax'] = cutout_obj.options['ymax']
app_obj.inform.emit("[success] Any-form Cutout operation finished.")
outname = cutout_obj.options["name"] + "_cutout"
self.app.new_object('geometry', outname, geo_init)