Merged jpcgt/flatcam into master

This commit is contained in:
Kamil Sopko
2016-02-29 22:05:32 +01:00
4 changed files with 156 additions and 92 deletions

View File

@@ -2137,7 +2137,7 @@ class App(QtCore.QObject):
def geocutout(name, *args): def geocutout(name, *args):
""" """
cut gaps in current geometry subtract gaps from geometry, this will not create new object
:param name: :param name:
:param args: :param args:
@@ -2148,6 +2148,14 @@ class App(QtCore.QObject):
'gapsize': float, 'gapsize': float,
'gaps': str} 'gaps': str}
#way gaps wil be rendered:
# lr - left + right
# tb - top + bottom
# 4 - left + right +top + bottom
# 2lr - 2*left + 2*right
# 2tb - 2*top + 2*bottom
# 8 - 2*left + 2*right +2*top + 2*bottom
for key in kwa: for key in kwa:
if key not in types: if key not in types:
return 'Unknown parameter: %s' % key return 'Unknown parameter: %s' % key
@@ -2159,15 +2167,23 @@ class App(QtCore.QObject):
return "Could not retrieve object: %s" % name return "Could not retrieve object: %s" % name
#get min and max data for each object as we just cut rectangles across X or Y
xmin, ymin, xmax, ymax = obj.bounds() xmin, ymin, xmax, ymax = obj.bounds()
px = 0.5 * (xmin + xmax) px = 0.5 * (xmin + xmax)
py = 0.5 * (ymin + ymax) py = 0.5 * (ymin + ymax)
lenghtx = (xmax - xmin)
lenghty = (ymax - ymin)
gapsize = kwa['gapsize']+kwa['dia']/2 gapsize = kwa['gapsize']+kwa['dia']/2
if kwa['gaps'] == '8' or kwa['gaps']=='2lr':
subtract_rectangle(name,xmin-gapsize,py-gapsize+lenghty/4,xmax+gapsize,py+gapsize+lenghty/4)
subtract_rectangle(name,xmin-gapsize,py-gapsize-lenghty/4,xmax+gapsize,py+gapsize-lenghty/4)
if kwa['gaps'] == '8' or kwa['gaps']=='2tb':
subtract_rectangle(name,px-gapsize+lenghtx/4,ymin-gapsize,px+gapsize+lenghtx/4,ymax+gapsize)
subtract_rectangle(name,px-gapsize-lenghtx/4,ymin-gapsize,px+gapsize-lenghtx/4,ymax+gapsize)
if kwa['gaps'] == '4' or kwa['gaps']=='lr': if kwa['gaps'] == '4' or kwa['gaps']=='lr':
del_rectangle(name,xmin-gapsize,py-gapsize,xmax+gapsize,py+gapsize) subtract_rectangle(name,xmin-gapsize,py-gapsize,xmax+gapsize,py+gapsize)
if kwa['gaps'] == '4' or kwa['gaps']=='tb': if kwa['gaps'] == '4' or kwa['gaps']=='tb':
del_rectangle(name,px-gapsize,ymin-gapsize,px+gapsize,ymax+gapsize) subtract_rectangle(name,px-gapsize,ymin-gapsize,px+gapsize,ymax+gapsize)
return 'Ok' return 'Ok'
def mirror(name, *args): def mirror(name, *args):
@@ -2299,6 +2315,7 @@ class App(QtCore.QObject):
'axis': str, 'axis': str,
'holes': str, 'holes': str,
'grid': float, 'grid': float,
'minoffset': float,
'gridoffset': float, 'gridoffset': float,
'axisoffset': float, 'axisoffset': float,
'dia': float, 'dia': float,
@@ -2359,25 +2376,22 @@ class App(QtCore.QObject):
else: else:
axisoffset=0 axisoffset=0
#this will align hole to given aligngridoffset and minimal offset from pcb, based on selected axis
if axis == "X": if axis == "X":
firstpoint=-kwa['gridoffset']+xmin firstpoint=kwa['gridoffset']
#-5 while (xmin-kwa['minoffset'])<firstpoint:
minlenght=(xmax-xmin+2*kwa['gridoffset']) firstpoint=firstpoint-kwa['grid']
#57+10=67 lastpoint=kwa['gridoffset']
gridstripped=(minlenght//kwa['grid'])*kwa['grid'] while (xmax+kwa['minoffset'])>lastpoint:
#67//10=60 lastpoint=lastpoint+kwa['grid']
if (minlenght-gridstripped) >kwa['gridoffset']:
gridstripped=gridstripped+kwa['grid']
lastpoint=(firstpoint+gridstripped)
localHoles=(firstpoint,axisoffset),(lastpoint,axisoffset) localHoles=(firstpoint,axisoffset),(lastpoint,axisoffset)
else: else:
firstpoint=-kwa['gridoffset']+ymin firstpoint=kwa['gridoffset']
minlenght=(ymax-ymin+2*kwa['gridoffset']) while (ymin-kwa['minoffset'])<firstpoint:
gridstripped=minlenght//kwa['grid']*kwa['grid'] firstpoint=firstpoint-kwa['grid']
if (minlenght-gridstripped) >kwa['gridoffset']: lastpoint=kwa['gridoffset']
gridstripped=gridstripped+kwa['grid'] while (ymax+kwa['minoffset'])>lastpoint:
lastpoint=(firstpoint+gridstripped) lastpoint=lastpoint+kwa['grid']
localHoles=(axisoffset,firstpoint),(axisoffset,lastpoint) localHoles=(axisoffset,firstpoint),(axisoffset,lastpoint)
for hole in localHoles: for hole in localHoles:
@@ -2456,26 +2470,26 @@ class App(QtCore.QObject):
return "ERROR: Only Excellon objects can be drilled." return "ERROR: Only Excellon objects can be drilled."
try: try:
# Get the tools from the list # Get the tools from the list
job_name = kwa["outname"] job_name = kwa["outname"]
# Object initialization function for app.new_object() # Object initialization function for app.new_object()
def job_init(job_obj, app_obj): def job_init(job_obj, app_obj):
assert isinstance(job_obj, FlatCAMCNCjob), \ assert isinstance(job_obj, FlatCAMCNCjob), \
"Initializer expected FlatCAMCNCjob, got %s" % type(job_obj) "Initializer expected FlatCAMCNCjob, got %s" % type(job_obj)
job_obj.z_cut = kwa["drillz"] job_obj.z_cut = kwa["drillz"]
job_obj.z_move = kwa["travelz"] job_obj.z_move = kwa["travelz"]
job_obj.feedrate = kwa["feedrate"] job_obj.feedrate = kwa["feedrate"]
job_obj.spindlespeed = kwa["spindlespeed"] if "spindlespeed" in kwa else None job_obj.spindlespeed = kwa["spindlespeed"] if "spindlespeed" in kwa else None
toolchange = True if "toolchange" in kwa and kwa["toolchange"] == 1 else False toolchange = True if "toolchange" in kwa and kwa["toolchange"] == 1 else False
job_obj.generate_from_excellon_by_tool(obj, kwa["tools"], toolchange) job_obj.generate_from_excellon_by_tool(obj, kwa["tools"], toolchange)
job_obj.gcode_parse() job_obj.gcode_parse()
job_obj.create_geometry() job_obj.create_geometry()
obj.app.new_object("cncjob", job_name, job_init) obj.app.new_object("cncjob", job_name, job_init)
except Exception, e: except Exception, e:
@@ -2600,7 +2614,7 @@ class App(QtCore.QObject):
types = {'dia': float, types = {'dia': float,
'passes': int, 'passes': int,
'overlap': float, 'overlap': float,
'outname': str, 'outname': str,
'combine': int} 'combine': int}
for key in kwa: for key in kwa:
@@ -2634,7 +2648,9 @@ class App(QtCore.QObject):
'feedrate': float, 'feedrate': float,
'tooldia': float, 'tooldia': float,
'outname': str, 'outname': str,
'spindlespeed': int 'spindlespeed': int,
'multidepth' : bool,
'depthperpass' : float
} }
for key in kwa: for key in kwa:
@@ -2718,7 +2734,7 @@ class App(QtCore.QObject):
return add_poly(obj_name, botleft_x, botleft_y, botleft_x, topright_y, return add_poly(obj_name, botleft_x, botleft_y, botleft_x, topright_y,
topright_x, topright_y, topright_x, botleft_y) topright_x, topright_y, topright_x, botleft_y)
def del_poly(obj_name, *args): def subtract_poly(obj_name, *args):
if len(args) % 2 != 0: if len(args) % 2 != 0:
return "Incomplete coordinate." return "Incomplete coordinate."
@@ -2731,19 +2747,13 @@ class App(QtCore.QObject):
if obj is None: if obj is None:
return "Object not found: %s" % obj_name return "Object not found: %s" % obj_name
def init_obj_me(init_obj, app): obj.subtract_polygon(points)
assert isinstance(init_obj, FlatCAMGeometry) obj.plot()
init_obj.solid_geometry=cascaded_union(diff)
diff= obj.del_polygon(points) return "OK."
try:
delete(obj_name)
obj.app.new_object("geometry", obj_name, init_obj_me)
except Exception as e:
return "Failed: %s" % str(e)
def del_rectangle(obj_name, botleft_x, botleft_y, topright_x, topright_y): def subtract_rectangle(obj_name, botleft_x, botleft_y, topright_x, topright_y):
return del_poly(obj_name, botleft_x, botleft_y, botleft_x, topright_y, return subtract_poly(obj_name, botleft_x, botleft_y, botleft_x, topright_y,
topright_x, topright_y, topright_x, botleft_y) topright_x, topright_y, topright_x, botleft_y)
def add_circle(obj_name, center_x, center_y, radius): def add_circle(obj_name, center_x, center_y, radius):
@@ -2764,6 +2774,8 @@ class App(QtCore.QObject):
def delete(obj_name): def delete(obj_name):
try: try:
#deselect all to avoid delete selected object when run delete from shell
self.collection.set_all_inactive()
self.collection.set_active(str(obj_name)) self.collection.set_active(str(obj_name))
self.on_delete() self.on_delete()
except Exception, e: except Exception, e:
@@ -2805,7 +2817,7 @@ class App(QtCore.QObject):
objs.append(obj) objs.append(obj)
def initialize(obj, app): def initialize(obj, app):
FlatCAMExcellon.merge(objs, obj,True) FlatCAMExcellon.merge(objs, obj)
if objs is not None: if objs is not None:
self.new_object("excellon", obj_name, initialize) self.new_object("excellon", obj_name, initialize)
@@ -2870,14 +2882,14 @@ class App(QtCore.QObject):
obj_init.offset([float(currentx), float(currenty)]), obj_init.offset([float(currentx), float(currenty)]),
def initialize_local_excellon(obj_init, app): def initialize_local_excellon(obj_init, app):
FlatCAMExcellon.merge(obj, obj_init,True) FlatCAMExcellon.merge(obj, obj_init)
obj_init.offset([float(currentx), float(currenty)]), obj_init.offset([float(currentx), float(currenty)]),
def initialize_geometry(obj_init, app): def initialize_geometry(obj_init, app):
FlatCAMGeometry.merge(objs, obj_init) FlatCAMGeometry.merge(objs, obj_init)
def initialize_excellon(obj_init, app): def initialize_excellon(obj_init, app):
FlatCAMExcellon.merge(objs, obj_init,True) FlatCAMExcellon.merge(objs, obj_init)
objs=[] objs=[]
if obj is not None: if obj is not None:
@@ -2899,7 +2911,8 @@ class App(QtCore.QObject):
else: else:
self.new_object("geometry", outname, initialize_geometry) self.new_object("geometry", outname, initialize_geometry)
#deselect all to avoid delete selected object when run delete from shell
self.collection.set_all_inactive()
for delobj in objs: for delobj in objs:
self.collection.set_active(delobj.options['name']) self.collection.set_active(delobj.options['name'])
self.on_delete() self.on_delete()
@@ -3091,8 +3104,8 @@ class App(QtCore.QObject):
}, },
'geocutout': { 'geocutout': {
'fcn': geocutout, 'fcn': geocutout,
'help': "Cut holding gaps closed geometry.\n" + 'help': "Cut holding gaps from geometry.\n" +
"> geocutout <name> [-dia <3.0 (float)>] [-margin <0.0 (float)>] [-gapsize <0.5 (float)>] [-gaps <lr (4|tb|lr)>]\n" + "> geocutout <name> [-dia <3.0 (float)>] [-margin <0.0 (float)>] [-gapsize <0.5 (float)>] [-gaps <lr (8|4|tb|lr|2tb|2lr)>]\n" +
" name: Name of the geometry object\n" + " name: Name of the geometry object\n" +
" dia: Tool diameter\n" + " dia: Tool diameter\n" +
" margin: Margin over bounds\n" + " margin: Margin over bounds\n" +
@@ -3138,12 +3151,13 @@ class App(QtCore.QObject):
'aligndrill': { 'aligndrill': {
'fcn': aligndrill, 'fcn': aligndrill,
'help': "Create excellon with drills for aligment.\n" + 'help': "Create excellon with drills for aligment.\n" +
"> aligndrill <name> [-dia <3.0 (float)>] -axis <X|Y> [-box <nameOfBox> [-grid <10 (float)> -gridoffset <5 (float)> [-axisoffset <0 (float)>]] | -dist <number>]\n" + "> aligndrill <name> [-dia <3.0 (float)>] -axis <X|Y> [-box <nameOfBox> -minoffset <float> [-grid <10 (float)> -gridoffset <5 (float)> [-axisoffset <0 (float)>]] | -dist <number>]\n" +
" name: Name of the object (Gerber or Excellon) to mirror.\n" + " name: Name of the object (Gerber or Excellon) to mirror.\n" +
" dia: Tool diameter\n" + " dia: Tool diameter\n" +
" box: Name of object which act as box (cutout for example.)\n" + " box: Name of object which act as box (cutout for example.)\n" +
" grid: aligning to grid, for thouse, who have aligning pins inside table in grid (-5,0),(5,0),(15,0)..." + " grid: aligning to grid, for thouse, who have aligning pins inside table in grid (-5,0),(5,0),(15,0)..." +
" gridoffset: offset from pcb from 0 position and minimal offset to grid on max" + " gridoffset: offset of grid from 0 position" +
" minoffset: min and max distance between align hole and pcb" +
" axisoffset: offset on second axis before aligment holes" + " axisoffset: offset on second axis before aligment holes" +
" axis: Mirror axis parallel to the X or Y axis.\n" + " axis: Mirror axis parallel to the X or Y axis.\n" +
" dist: Distance of the mirror axis to the X or Y axis." " dist: Distance of the mirror axis to the X or Y axis."
@@ -3207,13 +3221,15 @@ class App(QtCore.QObject):
'cncjob': { 'cncjob': {
'fcn': cncjob, 'fcn': cncjob,
'help': 'Generates a CNC Job from a Geometry Object.\n' + 'help': 'Generates a CNC Job from a Geometry Object.\n' +
'> cncjob <name> [-z_cut <c>] [-z_move <m>] [-feedrate <f>] [-tooldia <t>] [-spindlespeed (int)] [-outname <n>]\n' + '> cncjob <name> [-z_cut <c>] [-z_move <float>] [-feedrate <float>] [-tooldia <float>] [-spindlespeed <int>] [-multidepth <bool>] [-depthperpass <float>] [-outname <str>]\n' +
' name: Name of the source object\n' + ' name: Name of the source object\n' +
' z_cut: Z-axis cutting position\n' + ' z_cut: Z-axis cutting position\n' +
' z_move: Z-axis moving position\n' + ' z_move: Z-axis moving position\n' +
' feedrate: Moving speed when cutting\n' + ' feedrate: Moving speed when cutting\n' +
' tooldia: Tool diameter to show on screen\n' + ' tooldia: Tool diameter to show on screen\n' +
' spindlespeed: Speed of the spindle in rpm (example: 4000)\n' + ' spindlespeed: Speed of the spindle in rpm (example: 4000)\n' +
' multidepth: Use or not multidepth cnccut\n'+
' depthperpass: Height of one layer for multidepth\n'+
' outname: Name of the output object' ' outname: Name of the output object'
}, },
'write_gcode': { 'write_gcode': {
@@ -3245,11 +3261,11 @@ class App(QtCore.QObject):
' name: Name of the geometry object to which to append the polygon.\n' + ' name: Name of the geometry object to which to append the polygon.\n' +
' xi, yi: Coordinates of points in the polygon.' ' xi, yi: Coordinates of points in the polygon.'
}, },
'del_poly': { 'subtract_poly': {
'fcn': del_poly, 'fcn': subtract_poly,
'help': ' - Remove a polygon from the given Geometry object.\n' + 'help': 'Subtract polygon from the given Geometry object.\n' +
'> del_poly <name> <x0> <y0> <x1> <y1> <x2> <y2> [x3 y3 [...]]\n' + '> subtract_poly <name> <x0> <y0> <x1> <y1> <x2> <y2> [x3 y3 [...]]\n' +
' name: Name of the geometry object to which to remove the polygon.\n' + ' name: Name of the geometry object, which will be sutracted.\n' +
' xi, yi: Coordinates of points in the polygon.' ' xi, yi: Coordinates of points in the polygon.'
}, },
'delete': { 'delete': {
@@ -3295,11 +3311,11 @@ class App(QtCore.QObject):
" rows: number of rows\n"+ " rows: number of rows\n"+
" outname: Name of the new geometry object." " outname: Name of the new geometry object."
}, },
'del_rect': { 'subtract_rect': {
'fcn': del_rectangle, 'fcn': subtract_rectangle,
'help': 'Delete a rectange from the given Geometry object.\n' + 'help': 'Subtract rectange from the given Geometry object.\n' +
'> del_rect <name> <botleft_x> <botleft_y> <topright_x> <topright_y>\n' + '> subtract_rect <name> <botleft_x> <botleft_y> <topright_x> <topright_y>\n' +
' name: Name of the geometry object to which to remove the rectangle.\n' + ' name: Name of the geometry object, which will be subtracted.\n' +
' botleft_x, botleft_y: Coordinates of the bottom left corner.\n' + ' botleft_x, botleft_y: Coordinates of the bottom left corner.\n' +
' topright_x, topright_y Coordinates of the top right corner.' ' topright_x, topright_y Coordinates of the top right corner.'
}, },
@@ -3412,13 +3428,17 @@ class App(QtCore.QObject):
for recent in self.recent: for recent in self.recent:
filename = recent['filename'].split('/')[-1].split('\\')[-1] filename = recent['filename'].split('/')[-1].split('\\')[-1]
action = QtGui.QAction(QtGui.QIcon(icons[recent["kind"]]), filename, self) try:
action = QtGui.QAction(QtGui.QIcon(icons[recent["kind"]]), filename, self)
# Attach callback # Attach callback
o = make_callback(openers[recent["kind"]], recent['filename']) o = make_callback(openers[recent["kind"]], recent['filename'])
action.triggered.connect(o) action.triggered.connect(o)
self.ui.recent.addAction(action) self.ui.recent.addAction(action)
except KeyError:
App.log.error("Unsupported file type: %s" % recent["kind"])
# self.builder.get_object('open_recent').set_submenu(recent_menu) # self.builder.get_object('open_recent').set_submenu(recent_menu)
# self.ui.menufilerecent.set_submenu(recent_menu) # self.ui.menufilerecent.set_submenu(recent_menu)

View File

@@ -123,8 +123,12 @@ class FlatCAMObj(QtCore.QObject):
:return: None :return: None
""" """
FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> FlatCAMObj.to_form()")
for option in self.options: for option in self.options:
self.set_form_item(option) try:
self.set_form_item(option)
except:
self.app.log.warning("Unexpected error:", sys.exc_info())
def read_form(self): def read_form(self):
""" """
@@ -135,7 +139,10 @@ class FlatCAMObj(QtCore.QObject):
""" """
FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> FlatCAMObj.read_form()") FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> FlatCAMObj.read_form()")
for option in self.options: for option in self.options:
self.read_form_item(option) try:
self.read_form_item(option)
except:
self.app.log.warning("Unexpected error:", sys.exc_info())
def build_ui(self): def build_ui(self):
""" """
@@ -197,6 +204,17 @@ class FlatCAMObj(QtCore.QObject):
except KeyError: except KeyError:
self.app.log.warning("Failed to read option from field: %s" % option) self.app.log.warning("Failed to read option from field: %s" % option)
# #try read field only when option have equivalent in form_fields
# if option in self.form_fields:
# option_type=type(self.options[option])
# try:
# value=self.form_fields[option].get_value()
# #catch per option as it was ignored anyway, also when syntax error (probably uninitialized field),don't read either.
# except (KeyError,SyntaxError):
# self.app.log.warning("Failed to read option from field: %s" % option)
# else:
# self.app.log.warning("Form fied does not exists: %s" % option)
def plot(self): def plot(self):
""" """
Plot this object (Extend this method to implement the actual plotting). Plot this object (Extend this method to implement the actual plotting).
@@ -631,13 +649,16 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
self.ser_attrs += ['options', 'kind'] self.ser_attrs += ['options', 'kind']
@staticmethod @staticmethod
def merge(exc_list, exc_final, copy_options): def merge(exc_list, exc_final):
""" """
Merges(copy if used on one) the excellon of objects in exc_list into Merge excellons in exc_list into exc_final.
options have same like exc_final Options are allways copied from source .
the geometry of geo_final.
:param exc_list: List of FlatCAMExcellon Objects to join. Tools are also merged, if name for tool is same and size differs, then as name is used next available number from both lists
if only one object is specified in exc_list then this acts as copy only
:param exc_list: List or one object of FlatCAMExcellon Objects to join.
:param exc_final: Destination FlatCAMExcellon object. :param exc_final: Destination FlatCAMExcellon object.
:return: None :return: None
""" """
@@ -648,26 +669,27 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
else: else:
exc_list_real=exc_list exc_list_real=exc_list
for exc in exc_list_real: for exc in exc_list_real:
# Expand lists # Expand lists
if type(exc) is list: if type(exc) is list:
FlatCAMExcellon.merge(exc, exc_final, copy_options) FlatCAMExcellon.merge(exc, exc_final)
# If not list, merge excellons
# If not list, just append
else: else:
if copy_options is True:
exc_final.options["plot"]=exc.options["plot"]
exc_final.options["solid"]=exc.options["solid"]
exc_final.options["drillz"]=exc.options["drillz"]
exc_final.options["travelz"]=exc.options["travelz"]
exc_final.options["feedrate"]=exc.options["feedrate"]
exc_final.options["tooldia"]=exc.options["tooldia"]
exc_final.options["toolchange"]=exc.options["toolchange"]
exc_final.options["toolchangez"]=exc.options["toolchangez"]
exc_final.options["spindlespeed"]=exc.options["spindlespeed"]
# TODO: I realize forms does not save values into options , when object is deselected
# leave this here for future use
# this reinitialize options based on forms, all steps may not be necessary
# exc.app.collection.set_active(exc.options['name'])
# exc.to_form()
# exc.read_form()
for option in exc.options:
if option is not 'name':
try:
exc_final.options[option] = exc.options[option]
except:
exc.app.log.warning("Failed to copy option.",option)
#deep copy of all drills,to avoid any references
for drill in exc.drills: for drill in exc.drills:
point = Point(drill['point'].x,drill['point'].y) point = Point(drill['point'].x,drill['point'].y)
exc_final.drills.append({"point": point, "tool": drill['tool']}) exc_final.drills.append({"point": point, "tool": drill['tool']})
@@ -679,7 +701,7 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
max_numeric_tool=numeric_tool max_numeric_tool=numeric_tool
toolsrework[exc.tools[toolname]['C']]=toolname toolsrework[exc.tools[toolname]['C']]=toolname
#final as last becouse names from final tools will be used #exc_final as last because names from final tools will be used
for toolname in exc_final.tools.iterkeys(): for toolname in exc_final.tools.iterkeys():
numeric_tool=int(toolname) numeric_tool=int(toolname)
if numeric_tool>max_numeric_tool: if numeric_tool>max_numeric_tool:
@@ -692,9 +714,10 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
exc_final.tools[str(max_numeric_tool+1)]={"C": toolvalues} exc_final.tools[str(max_numeric_tool+1)]={"C": toolvalues}
else: else:
exc_final.tools[toolsrework[toolvalues]]={"C": toolvalues} exc_final.tools[toolsrework[toolvalues]]={"C": toolvalues}
#this value was not co
exc_final.zeros=exc.zeros
exc_final.create_geometry() exc_final.create_geometry()
def build_ui(self): def build_ui(self):
FlatCAMObj.build_ui(self) FlatCAMObj.build_ui(self)

View File

@@ -244,6 +244,27 @@ class ObjectCollection(QtCore.QAbstractListModel):
iobj = self.createIndex(self.get_names().index(name), 0) # Column 0 iobj = self.createIndex(self.get_names().index(name), 0) # Column 0
self.view.selectionModel().select(iobj, QtGui.QItemSelectionModel.Select) self.view.selectionModel().select(iobj, QtGui.QItemSelectionModel.Select)
def set_inactive(self, name):
"""
Unselect object by name from the project list. This triggers the
list_selection_changed event and call on_list_selection_changed.
:param name: Name of the FlatCAM Object
:return: None
"""
iobj = self.createIndex(self.get_names().index(name), 0) # Column 0
self.view.selectionModel().select(iobj, QtGui.QItemSelectionModel.Deselect)
def set_all_inactive(self):
"""
Unselect all objects from the project list. This triggers the
list_selection_changed event and call on_list_selection_changed.
:return: None
"""
for name in self.get_names():
self.set_inactive(name)
def on_list_selection_change(self, current, previous): def on_list_selection_change(self, current, previous):
FlatCAMApp.App.log.debug("on_list_selection_change()") FlatCAMApp.App.log.debug("on_list_selection_change()")
FlatCAMApp.App.log.debug("Current: %s, Previous %s" % (str(current), str(previous))) FlatCAMApp.App.log.debug("Current: %s, Previous %s" % (str(current), str(previous)))

View File

@@ -136,17 +136,17 @@ class Geometry(object):
log.error("Failed to run union on polygons.") log.error("Failed to run union on polygons.")
raise raise
def del_polygon(self, points): def subtract_polygon(self, points):
""" """
Delete a polygon from the object Subtract polygon from the given object. This only operates on the paths in the original geometry, i.e. it converts polygons into paths.
:param points: The vertices of the polygon. :param points: The vertices of the polygon.
:return: None :return: none
""" """
if self.solid_geometry is None: if self.solid_geometry is None:
self.solid_geometry = [] self.solid_geometry = []
#pathonly should be allways True, otherwise polygons are not subtracted
flat_geometry = self.flatten(pathonly=True) flat_geometry = self.flatten(pathonly=True)
log.debug("%d paths" % len(flat_geometry)) log.debug("%d paths" % len(flat_geometry))
polygon=Polygon(points) polygon=Polygon(points)
@@ -157,7 +157,7 @@ class Geometry(object):
diffs.append(target.difference(toolgeo)) diffs.append(target.difference(toolgeo))
else: else:
log.warning("Not implemented.") log.warning("Not implemented.")
return cascaded_union(diffs) self.solid_geometry=cascaded_union(diffs)
def bounds(self): def bounds(self):
""" """