Merged jpcgt/flatcam into master
This commit is contained in:
124
FlatCAMApp.py
124
FlatCAMApp.py
@@ -2137,7 +2137,7 @@ class App(QtCore.QObject):
|
||||
|
||||
def geocutout(name, *args):
|
||||
"""
|
||||
cut gaps in current geometry
|
||||
subtract gaps from geometry, this will not create new object
|
||||
|
||||
:param name:
|
||||
:param args:
|
||||
@@ -2148,6 +2148,14 @@ class App(QtCore.QObject):
|
||||
'gapsize': float,
|
||||
'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:
|
||||
if key not in types:
|
||||
return 'Unknown parameter: %s' % key
|
||||
@@ -2159,15 +2167,23 @@ class App(QtCore.QObject):
|
||||
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()
|
||||
px = 0.5 * (xmin + xmax)
|
||||
py = 0.5 * (ymin + ymax)
|
||||
lenghtx = (xmax - xmin)
|
||||
lenghty = (ymax - ymin)
|
||||
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':
|
||||
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':
|
||||
del_rectangle(name,px-gapsize,ymin-gapsize,px+gapsize,ymax+gapsize)
|
||||
subtract_rectangle(name,px-gapsize,ymin-gapsize,px+gapsize,ymax+gapsize)
|
||||
return 'Ok'
|
||||
|
||||
def mirror(name, *args):
|
||||
@@ -2299,6 +2315,7 @@ class App(QtCore.QObject):
|
||||
'axis': str,
|
||||
'holes': str,
|
||||
'grid': float,
|
||||
'minoffset': float,
|
||||
'gridoffset': float,
|
||||
'axisoffset': float,
|
||||
'dia': float,
|
||||
@@ -2359,25 +2376,22 @@ class App(QtCore.QObject):
|
||||
else:
|
||||
axisoffset=0
|
||||
|
||||
|
||||
#this will align hole to given aligngridoffset and minimal offset from pcb, based on selected axis
|
||||
if axis == "X":
|
||||
firstpoint=-kwa['gridoffset']+xmin
|
||||
#-5
|
||||
minlenght=(xmax-xmin+2*kwa['gridoffset'])
|
||||
#57+10=67
|
||||
gridstripped=(minlenght//kwa['grid'])*kwa['grid']
|
||||
#67//10=60
|
||||
if (minlenght-gridstripped) >kwa['gridoffset']:
|
||||
gridstripped=gridstripped+kwa['grid']
|
||||
lastpoint=(firstpoint+gridstripped)
|
||||
firstpoint=kwa['gridoffset']
|
||||
while (xmin-kwa['minoffset'])<firstpoint:
|
||||
firstpoint=firstpoint-kwa['grid']
|
||||
lastpoint=kwa['gridoffset']
|
||||
while (xmax+kwa['minoffset'])>lastpoint:
|
||||
lastpoint=lastpoint+kwa['grid']
|
||||
localHoles=(firstpoint,axisoffset),(lastpoint,axisoffset)
|
||||
else:
|
||||
firstpoint=-kwa['gridoffset']+ymin
|
||||
minlenght=(ymax-ymin+2*kwa['gridoffset'])
|
||||
gridstripped=minlenght//kwa['grid']*kwa['grid']
|
||||
if (minlenght-gridstripped) >kwa['gridoffset']:
|
||||
gridstripped=gridstripped+kwa['grid']
|
||||
lastpoint=(firstpoint+gridstripped)
|
||||
firstpoint=kwa['gridoffset']
|
||||
while (ymin-kwa['minoffset'])<firstpoint:
|
||||
firstpoint=firstpoint-kwa['grid']
|
||||
lastpoint=kwa['gridoffset']
|
||||
while (ymax+kwa['minoffset'])>lastpoint:
|
||||
lastpoint=lastpoint+kwa['grid']
|
||||
localHoles=(axisoffset,firstpoint),(axisoffset,lastpoint)
|
||||
|
||||
for hole in localHoles:
|
||||
@@ -2634,7 +2648,9 @@ class App(QtCore.QObject):
|
||||
'feedrate': float,
|
||||
'tooldia': float,
|
||||
'outname': str,
|
||||
'spindlespeed': int
|
||||
'spindlespeed': int,
|
||||
'multidepth' : bool,
|
||||
'depthperpass' : float
|
||||
}
|
||||
|
||||
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,
|
||||
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:
|
||||
return "Incomplete coordinate."
|
||||
|
||||
@@ -2731,19 +2747,13 @@ class App(QtCore.QObject):
|
||||
if obj is None:
|
||||
return "Object not found: %s" % obj_name
|
||||
|
||||
def init_obj_me(init_obj, app):
|
||||
assert isinstance(init_obj, FlatCAMGeometry)
|
||||
init_obj.solid_geometry=cascaded_union(diff)
|
||||
obj.subtract_polygon(points)
|
||||
obj.plot()
|
||||
|
||||
diff= obj.del_polygon(points)
|
||||
try:
|
||||
delete(obj_name)
|
||||
obj.app.new_object("geometry", obj_name, init_obj_me)
|
||||
except Exception as e:
|
||||
return "Failed: %s" % str(e)
|
||||
return "OK."
|
||||
|
||||
def del_rectangle(obj_name, botleft_x, botleft_y, topright_x, topright_y):
|
||||
return del_poly(obj_name, botleft_x, botleft_y, botleft_x, topright_y,
|
||||
def subtract_rectangle(obj_name, botleft_x, botleft_y, topright_x, topright_y):
|
||||
return subtract_poly(obj_name, botleft_x, botleft_y, botleft_x, topright_y,
|
||||
topright_x, topright_y, topright_x, botleft_y)
|
||||
|
||||
def add_circle(obj_name, center_x, center_y, radius):
|
||||
@@ -2764,6 +2774,8 @@ class App(QtCore.QObject):
|
||||
|
||||
def delete(obj_name):
|
||||
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.on_delete()
|
||||
except Exception, e:
|
||||
@@ -2805,7 +2817,7 @@ class App(QtCore.QObject):
|
||||
objs.append(obj)
|
||||
|
||||
def initialize(obj, app):
|
||||
FlatCAMExcellon.merge(objs, obj,True)
|
||||
FlatCAMExcellon.merge(objs, obj)
|
||||
|
||||
if objs is not None:
|
||||
self.new_object("excellon", obj_name, initialize)
|
||||
@@ -2870,14 +2882,14 @@ class App(QtCore.QObject):
|
||||
obj_init.offset([float(currentx), float(currenty)]),
|
||||
|
||||
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)]),
|
||||
|
||||
def initialize_geometry(obj_init, app):
|
||||
FlatCAMGeometry.merge(objs, obj_init)
|
||||
|
||||
def initialize_excellon(obj_init, app):
|
||||
FlatCAMExcellon.merge(objs, obj_init,True)
|
||||
FlatCAMExcellon.merge(objs, obj_init)
|
||||
|
||||
objs=[]
|
||||
if obj is not None:
|
||||
@@ -2899,7 +2911,8 @@ class App(QtCore.QObject):
|
||||
else:
|
||||
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:
|
||||
self.collection.set_active(delobj.options['name'])
|
||||
self.on_delete()
|
||||
@@ -3091,8 +3104,8 @@ class App(QtCore.QObject):
|
||||
},
|
||||
'geocutout': {
|
||||
'fcn': geocutout,
|
||||
'help': "Cut holding gaps closed geometry.\n" +
|
||||
"> geocutout <name> [-dia <3.0 (float)>] [-margin <0.0 (float)>] [-gapsize <0.5 (float)>] [-gaps <lr (4|tb|lr)>]\n" +
|
||||
'help': "Cut holding gaps from geometry.\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" +
|
||||
" dia: Tool diameter\n" +
|
||||
" margin: Margin over bounds\n" +
|
||||
@@ -3138,12 +3151,13 @@ class App(QtCore.QObject):
|
||||
'aligndrill': {
|
||||
'fcn': aligndrill,
|
||||
'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" +
|
||||
" dia: Tool diameter\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)..." +
|
||||
" 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" +
|
||||
" axis: Mirror axis parallel to the X or Y axis.\n" +
|
||||
" dist: Distance of the mirror axis to the X or Y axis."
|
||||
@@ -3207,13 +3221,15 @@ class App(QtCore.QObject):
|
||||
'cncjob': {
|
||||
'fcn': cncjob,
|
||||
'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' +
|
||||
' z_cut: Z-axis cutting position\n' +
|
||||
' z_move: Z-axis moving position\n' +
|
||||
' feedrate: Moving speed when cutting\n' +
|
||||
' tooldia: Tool diameter to show on screen\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'
|
||||
},
|
||||
'write_gcode': {
|
||||
@@ -3245,11 +3261,11 @@ class App(QtCore.QObject):
|
||||
' name: Name of the geometry object to which to append the polygon.\n' +
|
||||
' xi, yi: Coordinates of points in the polygon.'
|
||||
},
|
||||
'del_poly': {
|
||||
'fcn': del_poly,
|
||||
'help': ' - Remove a polygon from the given Geometry object.\n' +
|
||||
'> del_poly <name> <x0> <y0> <x1> <y1> <x2> <y2> [x3 y3 [...]]\n' +
|
||||
' name: Name of the geometry object to which to remove the polygon.\n' +
|
||||
'subtract_poly': {
|
||||
'fcn': subtract_poly,
|
||||
'help': 'Subtract polygon from the given Geometry object.\n' +
|
||||
'> subtract_poly <name> <x0> <y0> <x1> <y1> <x2> <y2> [x3 y3 [...]]\n' +
|
||||
' name: Name of the geometry object, which will be sutracted.\n' +
|
||||
' xi, yi: Coordinates of points in the polygon.'
|
||||
},
|
||||
'delete': {
|
||||
@@ -3295,11 +3311,11 @@ class App(QtCore.QObject):
|
||||
" rows: number of rows\n"+
|
||||
" outname: Name of the new geometry object."
|
||||
},
|
||||
'del_rect': {
|
||||
'fcn': del_rectangle,
|
||||
'help': 'Delete a rectange from the given Geometry object.\n' +
|
||||
'> del_rect <name> <botleft_x> <botleft_y> <topright_x> <topright_y>\n' +
|
||||
' name: Name of the geometry object to which to remove the rectangle.\n' +
|
||||
'subtract_rect': {
|
||||
'fcn': subtract_rectangle,
|
||||
'help': 'Subtract rectange from the given Geometry object.\n' +
|
||||
'> subtract_rect <name> <botleft_x> <botleft_y> <topright_x> <topright_y>\n' +
|
||||
' name: Name of the geometry object, which will be subtracted.\n' +
|
||||
' botleft_x, botleft_y: Coordinates of the bottom left corner.\n' +
|
||||
' topright_x, topright_y Coordinates of the top right corner.'
|
||||
},
|
||||
@@ -3412,6 +3428,7 @@ class App(QtCore.QObject):
|
||||
for recent in self.recent:
|
||||
filename = recent['filename'].split('/')[-1].split('\\')[-1]
|
||||
|
||||
try:
|
||||
action = QtGui.QAction(QtGui.QIcon(icons[recent["kind"]]), filename, self)
|
||||
|
||||
# Attach callback
|
||||
@@ -3420,6 +3437,9 @@ class App(QtCore.QObject):
|
||||
|
||||
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.ui.menufilerecent.set_submenu(recent_menu)
|
||||
# recent_menu.show_all()
|
||||
|
||||
@@ -123,8 +123,12 @@ class FlatCAMObj(QtCore.QObject):
|
||||
|
||||
:return: None
|
||||
"""
|
||||
FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> FlatCAMObj.to_form()")
|
||||
for option in self.options:
|
||||
try:
|
||||
self.set_form_item(option)
|
||||
except:
|
||||
self.app.log.warning("Unexpected error:", sys.exc_info())
|
||||
|
||||
def read_form(self):
|
||||
"""
|
||||
@@ -135,7 +139,10 @@ class FlatCAMObj(QtCore.QObject):
|
||||
"""
|
||||
FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> FlatCAMObj.read_form()")
|
||||
for option in self.options:
|
||||
try:
|
||||
self.read_form_item(option)
|
||||
except:
|
||||
self.app.log.warning("Unexpected error:", sys.exc_info())
|
||||
|
||||
def build_ui(self):
|
||||
"""
|
||||
@@ -197,6 +204,17 @@ class FlatCAMObj(QtCore.QObject):
|
||||
except KeyError:
|
||||
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):
|
||||
"""
|
||||
Plot this object (Extend this method to implement the actual plotting).
|
||||
@@ -631,13 +649,16 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
|
||||
self.ser_attrs += ['options', 'kind']
|
||||
|
||||
@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
|
||||
options have same like exc_final
|
||||
the geometry of geo_final.
|
||||
Merge excellons in exc_list into exc_final.
|
||||
Options are allways copied from source .
|
||||
|
||||
: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.
|
||||
:return: None
|
||||
"""
|
||||
@@ -648,26 +669,27 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
|
||||
else:
|
||||
exc_list_real=exc_list
|
||||
|
||||
|
||||
for exc in exc_list_real:
|
||||
# Expand lists
|
||||
if type(exc) is list:
|
||||
FlatCAMExcellon.merge(exc, exc_final, copy_options)
|
||||
|
||||
# If not list, just append
|
||||
FlatCAMExcellon.merge(exc, exc_final)
|
||||
# If not list, merge excellons
|
||||
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:
|
||||
point = Point(drill['point'].x,drill['point'].y)
|
||||
exc_final.drills.append({"point": point, "tool": drill['tool']})
|
||||
@@ -679,7 +701,7 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
|
||||
max_numeric_tool=numeric_tool
|
||||
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():
|
||||
numeric_tool=int(toolname)
|
||||
if numeric_tool>max_numeric_tool:
|
||||
@@ -692,9 +714,10 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
|
||||
exc_final.tools[str(max_numeric_tool+1)]={"C": toolvalues}
|
||||
else:
|
||||
exc_final.tools[toolsrework[toolvalues]]={"C": toolvalues}
|
||||
#this value was not co
|
||||
exc_final.zeros=exc.zeros
|
||||
exc_final.create_geometry()
|
||||
|
||||
|
||||
def build_ui(self):
|
||||
FlatCAMObj.build_ui(self)
|
||||
|
||||
|
||||
@@ -244,6 +244,27 @@ class ObjectCollection(QtCore.QAbstractListModel):
|
||||
iobj = self.createIndex(self.get_names().index(name), 0) # Column 0
|
||||
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):
|
||||
FlatCAMApp.App.log.debug("on_list_selection_change()")
|
||||
FlatCAMApp.App.log.debug("Current: %s, Previous %s" % (str(current), str(previous)))
|
||||
|
||||
10
camlib.py
10
camlib.py
@@ -136,17 +136,17 @@ class Geometry(object):
|
||||
log.error("Failed to run union on polygons.")
|
||||
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.
|
||||
:return: None
|
||||
:return: none
|
||||
"""
|
||||
if self.solid_geometry is None:
|
||||
self.solid_geometry = []
|
||||
|
||||
|
||||
#pathonly should be allways True, otherwise polygons are not subtracted
|
||||
flat_geometry = self.flatten(pathonly=True)
|
||||
log.debug("%d paths" % len(flat_geometry))
|
||||
polygon=Polygon(points)
|
||||
@@ -157,7 +157,7 @@ class Geometry(object):
|
||||
diffs.append(target.difference(toolgeo))
|
||||
else:
|
||||
log.warning("Not implemented.")
|
||||
return cascaded_union(diffs)
|
||||
self.solid_geometry=cascaded_union(diffs)
|
||||
|
||||
def bounds(self):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user