- fixed Tcl Command CncJob

- fixed crash due of Properties Tool trying to have a convex hull area on FlatCAMCNCJob objects which is not possible due of their nature
- modified Tcl Command SubtractRectangle
- fixed and modernized the Tcl Command Scale to be able to scale on X axis or on Y axis or on both and having as scale reference either the (0, 0) point or the minimum point of the bounding box or the center of the bounding box.
- fixed and modernized the Tcl Command Skew
This commit is contained in:
Marius Stanciu 2019-08-26 00:40:35 +03:00 committed by Marius
parent 65ab17e308
commit ba1e0bc94b
11 changed files with 133 additions and 50 deletions

View File

@ -6016,7 +6016,12 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
try:
if self.multitool is False: # single tool usage
self.plot2(tooldia=float(self.options["tooldia"]), obj=self, visible=visible, kind=kind)
try:
dia_plot = float(self.options["tooldia"])
except ValueError:
# we may have a tuple with only one element and a comma
dia_plot = [float(el) for el in self.options["tooldia"].split(',') if el != ''][0]
self.plot2(dia_plot, obj=self, visible=visible, kind=kind)
else:
# multiple tools usage
for tooluid_key in self.cnc_tools:

View File

@ -18,6 +18,11 @@ CAD program, and create G-Code for Isolation routing.
- fixed issue #298. The changes in postprocessors done in Preferences dis not update the object UI layout as it was supposed to. The selection of Marlin postproc. did not unhidden the Feedrate Rapids entry.
- fixed minor issues
- fixed Tcl Command AddPolygon, AddPolyline
- fixed Tcl Command CncJob
- fixed crash due of Properties Tool trying to have a convex hull area on FlatCAMCNCJob objects which is not possible due of their nature
- modified Tcl Command SubtractRectangle
- fixed and modernized the Tcl Command Scale to be able to scale on X axis or on Y axis or on both and having as scale reference either the (0, 0) point or the minimum point of the bounding box or the center of the bounding box.
- fixed and modernized the Tcl Command Skew
24.08.2019

View File

@ -6001,7 +6001,10 @@ class CNCjob(Geometry):
flat_geometry = self.flatten(temp_solid_geometry, pathonly=True)
log.debug("%d paths" % len(flat_geometry))
self.tooldia = float(tooldia) if tooldia else None
try:
self.tooldia = float(tooldia) if tooldia else None
except ValueError:
self.tooldia = [float(el) for el in tooldia.split(',') if el != ''] if tooldia else None
self.z_cut = float(z_cut) if z_cut else None
self.z_move = float(z_move) if z_move else None
@ -6669,6 +6672,10 @@ class CNCjob(Geometry):
if tooldia is None:
tooldia = self.tooldia
# this should be unlikely unless when upstream the tooldia is a tuple made by one dia and a comma like (2.4,)
if isinstance(tooldia, list):
tooldia = tooldia[0] if tooldia[0] is not None else self.tooldia
if tooldia == 0:
for geo in gcode_parsed:
if kind == 'all':
@ -7042,7 +7049,10 @@ class CNCjob(Geometry):
bounds_coords = bounds_rec(self.solid_geometry)
else:
minx = Inf
miny = Inf
maxx = -Inf
maxy = -Inf
for k, v in self.cnc_tools.items():
minx = Inf
miny = Inf

View File

@ -169,25 +169,26 @@ class Properties(FlatCAMTool):
area = length * width
self.addChild(dims, ['%s:' % _('Box Area'), '%.4f %s' % (area, 'in2')], True)
# calculate and add convex hull area
geo = obj.solid_geometry
if isinstance(geo, MultiPolygon):
env_obj = geo.convex_hull
elif (isinstance(geo, MultiPolygon) and len(geo) == 1) or \
(isinstance(geo, list) and len(geo) == 1) and isinstance(geo[0], Polygon):
env_obj = cascaded_union(obj.solid_geometry)
env_obj = env_obj.convex_hull
else:
env_obj = cascaded_union(obj.solid_geometry)
env_obj = env_obj.convex_hull
if not isinstance(obj, FlatCAMCNCjob):
# calculate and add convex hull area
geo = obj.solid_geometry
if isinstance(geo, MultiPolygon):
env_obj = geo.convex_hull
elif (isinstance(geo, MultiPolygon) and len(geo) == 1) or \
(isinstance(geo, list) and len(geo) == 1) and isinstance(geo[0], Polygon):
env_obj = cascaded_union(obj.solid_geometry)
env_obj = env_obj.convex_hull
else:
env_obj = cascaded_union(obj.solid_geometry)
env_obj = env_obj.convex_hull
area_chull = env_obj.area
if self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower() == 'mm':
area_chull = area_chull / 100
self.addChild(dims, ['%s:' % _('Convex_Hull Area'), '%.4f %s' % (area_chull, 'cm2')], True)
else:
area_chull = area_chull
self.addChild(dims, ['%s:' % _('Convex_Hull Area'), '%.4f %s' % (area_chull, 'in2')], True)
area_chull = env_obj.area
if self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower() == 'mm':
area_chull = area_chull / 100
self.addChild(dims, ['%s:' % _('Convex_Hull Area'), '%.4f %s' % (area_chull, 'cm2')], True)
else:
area_chull = area_chull
self.addChild(dims, ['%s:' % _('Convex_Hull Area'), '%.4f %s' % (area_chull, 'in2')], True)
self.addChild(units,
['FlatCAM units:',

View File

@ -4,7 +4,7 @@ from ObjectCollection import *
class TclCommandClearShell(TclCommand):
"""
Tcl shell command to creates a circle in the given Geometry object.
Tcl shell command to clear the text in the Tcl Shell browser.
example:

View File

@ -24,15 +24,18 @@ class TclCommandCncjob(TclCommandSignaled):
# dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
option_types = collections.OrderedDict([
('tooldia', float),
('z_cut', float),
('z_move', float),
('feedrate', float),
('feedrate_rapid', float),
('tooldia', float),
('spindlespeed', int),
('multidepth', bool),
('extracut', bool),
('depthperpass', float),
('toolchange', int),
('toolchangez', float),
('toolchangexy', tuple),
('endz', float),
('ppname_g', str),
('outname', str)
@ -62,7 +65,7 @@ class TclCommandCncjob(TclCommandSignaled):
('outname', 'Name of the resulting Geometry object.'),
('ppname_g', 'Name of the Geometry postprocessor. No quotes, case sensitive')
]),
'examples': []
'examples': ['cncjob geo_name -tooldia 0.5 -z_cut -1.7 -z_move 2 -feedrate 120 -ppname_g default']
}
def execute(self, args, unnamed_args):

View File

@ -21,20 +21,30 @@ class TclCommandScale(TclCommand):
# Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
option_types = collections.OrderedDict([
('x', float),
('y', float),
('origin', str)
])
# array of mandatory options for current Tcl command: required = {'name','outname'}
required = ['name', 'factor']
required = ['name']
# structured help for current command, args needs to be ordered
help = {
'main': "Resizes the object by a factor.",
'main': "Resizes the object by a factor on X axis and a factor on Y axis, having as scale origin the point ",
'args': collections.OrderedDict([
('name', 'Name of the object to resize.'),
('factor', 'Fraction by which to scale.')
('factor', 'Fraction by which to scale on both axis. '),
('x', 'Fraction by which to scale on X axis. If "factor" is used then this parameter is ignored'),
('y', 'Fraction by which to scale on Y axis. If "factor" is used then this parameter is ignored'),
('origin', 'Reference used for scale. It can be: "origin" which means point (0, 0) or "min_bounds" which '
'means the lower left point of the bounding box or it can be "center" which means the center '
'of the bounding box.')
]),
'examples': ['scale my_geometry 4.2']
'examples': ['scale my_geometry 4.2',
'scale my_geo -x 3.1 -y 2.8',
'scale my_geo 1.2 -origin min_bounds']
}
def execute(self, args, unnamed_args):
@ -46,6 +56,49 @@ class TclCommandScale(TclCommand):
"""
name = args['name']
factor = args['factor']
try:
obj_to_scale = self.app.collection.get_by_name(name)
except Exception as e:
log.debug("TclCommandCopperClear.execute() --> %s" % str(e))
self.raise_tcl_error("%s: %s" % (_("Could not retrieve box object"), name))
return "Could not retrieve object: %s" % name
self.app.collection.get_by_name(name).scale(factor)
if 'origin' not in args:
xmin, ymin, xmax, ymax = obj_to_scale.bounds()
c_x = xmin + (xmax - xmin) / 2
c_y = ymin + (ymax - ymin) / 2
point = (c_x, c_y)
else:
if args['origin'] == 'origin':
point = (0, 0)
elif args['origin'] == 'min_bounds':
xmin, ymin, xmax, ymax = obj_to_scale.bounds()
point = (xmin, ymin)
elif args['origin'] == 'center':
xmin, ymin, xmax, ymax = obj_to_scale.bounds()
c_x = xmin + (xmax - xmin) / 2
c_y = ymin + (ymax - ymin) / 2
point = (c_x, c_y)
else:
self.raise_tcl_error('%s' % _("Expected -origin <origin> or -origin <min_bounds> or -origin <center>."))
return 'fail'
if 'factor' in args:
factor = float(args['factor'])
obj_to_scale.scale(factor, point=point)
return
if 'x' not in args and 'y' not in args:
self.raise_tcl_error('%s' % _("Expected -x <value> -y <value>."))
return 'fail'
if 'x' in args and 'y' not in args:
f_x = float(args['x'])
obj_to_scale.scale(f_x, 0, point=point)
elif 'x' not in args and 'y' in args:
f_y = float(args['y'])
obj_to_scale.scale(0, f_y, point=point)
elif 'x' in args and 'y' in args:
f_x = float(args['x'])
f_y = float(args['y'])
obj_to_scale.scale(f_x, f_y, point=point)

View File

@ -30,7 +30,8 @@ class TclCommandSkew(TclCommand):
# structured help for current command, args needs to be ordered
help = {
'main': "Shear/Skew an object by angles along x and y dimensions.",
'main': "Shear/Skew an object by angles along x and y dimensions. The reference point is the left corner of "
"the bounding box of the object.",
'args': collections.OrderedDict([
('name', 'Name of the object to skew.'),
('angle_x', 'Angle in degrees by which to skew on the X axis.'),
@ -48,7 +49,9 @@ class TclCommandSkew(TclCommand):
"""
name = args['name']
angle_x = args['angle_x']
angle_y = args['angle_y']
angle_x = float(args['angle_x'])
angle_y = float(args['angle_y'])
self.app.collection.get_by_name(name).skew(angle_x, angle_y)
obj_to_skew = self.app.collection.get_by_name(name)
xmin, ymin, xmax, ymax = obj_to_skew.bounds()
obj_to_skew.skew(angle_x, angle_y, point=(xmin, ymin))

View File

@ -4,7 +4,7 @@ from tclCommands.TclCommand import TclCommandSignaled
class TclCommandSubtractRectangle(TclCommandSignaled):
"""
Tcl shell command to subtract a rectange from the given Geometry object.
Tcl shell command to subtract a rectangle from the given Geometry object.
"""
# array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
@ -13,11 +13,7 @@ class TclCommandSubtractRectangle(TclCommandSignaled):
# Dictionary of types from Tcl command, needs to be ordered.
# For positional arguments
arg_names = collections.OrderedDict([
('name', str),
('x0', float),
('y0', float),
('x1', float),
('y1', float)
('name', str)
])
# Dictionary of types from Tcl command, needs to be ordered.
@ -27,7 +23,7 @@ class TclCommandSubtractRectangle(TclCommandSignaled):
])
# array of mandatory options for current Tcl command: required = {'name','outname'}
required = ['name', 'x0', 'y0', 'x1', 'y1']
required = ['name']
# structured help for current command, args needs to be ordered
help = {
@ -37,7 +33,7 @@ class TclCommandSubtractRectangle(TclCommandSignaled):
('x0 y0', 'Bottom left corner coordinates.'),
('x1 y1', 'Top right corner coordinates.')
]),
'examples': []
'examples': ['subtract_rectangle geo_obj 8 8 15 15']
}
def execute(self, args, unnamed_args):
@ -49,12 +45,19 @@ class TclCommandSubtractRectangle(TclCommandSignaled):
without -somename and we do not have them in known arg_names
:return: None or exception
"""
if 'name' not in args:
self.raise_tcl_error("%s:" % _("No Geometry name in args. Provide a name and try again."))
return 'fail'
obj_name = args['name']
x0 = args['x0']
y0 = args['y0']
x1 = args['x1']
y1 = args['y1']
if len(unnamed_args) != 4:
self.raise_tcl_error("Incomplete coordinates. There are 4 required: x0 y0 x1 y1.")
return 'fail'
x0 = float(unnamed_args[0])
y0 = float(unnamed_args[1])
x1 = float(unnamed_args[2])
y1 = float(unnamed_args[3])
try:
obj = self.app.collection.get_by_name(str(obj_name))

View File

@ -32,7 +32,7 @@ class TclCommandVersion(TclCommand):
'args': collections.OrderedDict([
]),
'examples': []
'examples': ['version']
}
def execute(self, args, unnamed_args):

View File

@ -37,7 +37,7 @@ class TclCommandWriteGCode(TclCommandSignaled):
('preamble', 'Text to append at the beginning.'),
('postamble', 'Text to append at the end.')
]),
'examples': []
'examples': ["write_gcode name c:\\\\gcode_repo"]
}
def execute(self, args, unnamed_args):