- added a Laser preprocessor named 'Z_laser' which will change the Z to the Travel Z on each ToolChange event allowing therefore control of the dot size
- by default now a new blank Geometry object created by FlatCAM is of type multigeo - made sure that optimizations of lines when importing SVG or DXF as lines will not encounter polygons but only LinesStrings or LinearRings, otherwise having crashes - fixed the import SVG and import DXF, when importing as Geometry to be imported as multigeo tool - fixed the import SVG and import DXF, the source files will be saved as loaded into the source_file attribute of the resulting object (be it Geometry or Gerber)
This commit is contained in:
parent
cf78211a6f
commit
b8fb64a143
|
@ -11,6 +11,11 @@ CHANGELOG for FlatCAM beta
|
||||||
|
|
||||||
- working on a proper GCode Editor
|
- working on a proper GCode Editor
|
||||||
- wip in the GCode Editor
|
- wip in the GCode Editor
|
||||||
|
- added a Laser preprocessor named 'Z_laser' which will change the Z to the Travel Z on each ToolChange event allowing therefore control of the dot size
|
||||||
|
- by default now a new blank Geometry object created by FlatCAM is of type multigeo
|
||||||
|
- made sure that optimizations of lines when importing SVG or DXF as lines will not encounter polygons but only LinesStrings or LinearRings, otherwise having crashes
|
||||||
|
- fixed the import SVG and import DXF, when importing as Geometry to be imported as multigeo tool
|
||||||
|
- fixed the import SVG and import DXF, the source files will be saved as loaded into the source_file attribute of the resulting object (be it Geometry or Gerber)
|
||||||
|
|
||||||
21.07.2020
|
21.07.2020
|
||||||
|
|
||||||
|
|
|
@ -3979,77 +3979,6 @@ class AppGeoEditor(QtCore.QObject):
|
||||||
# self.storage = AppGeoEditor.make_storage()
|
# self.storage = AppGeoEditor.make_storage()
|
||||||
self.replot()
|
self.replot()
|
||||||
|
|
||||||
def edit_fcgeometry(self, fcgeometry, multigeo_tool=None):
|
|
||||||
"""
|
|
||||||
Imports the geometry from the given FlatCAM Geometry object
|
|
||||||
into the editor.
|
|
||||||
|
|
||||||
:param fcgeometry: GeometryObject
|
|
||||||
:param multigeo_tool: A tool for the case of the edited geometry being of type 'multigeo'
|
|
||||||
:return: None
|
|
||||||
"""
|
|
||||||
assert isinstance(fcgeometry, Geometry), "Expected a Geometry, got %s" % type(fcgeometry)
|
|
||||||
|
|
||||||
self.deactivate()
|
|
||||||
self.activate()
|
|
||||||
|
|
||||||
self.set_ui()
|
|
||||||
|
|
||||||
# Hide original geometry
|
|
||||||
self.fcgeometry = fcgeometry
|
|
||||||
fcgeometry.visible = False
|
|
||||||
|
|
||||||
# Set selection tolerance
|
|
||||||
DrawToolShape.tolerance = fcgeometry.drawing_tolerance * 10
|
|
||||||
|
|
||||||
self.select_tool("select")
|
|
||||||
|
|
||||||
if self.app.defaults['geometry_spindledir'] == 'CW':
|
|
||||||
if self.app.defaults['geometry_editor_milling_type'] == 'cl':
|
|
||||||
milling_type = 1 # CCW motion = climb milling (spindle is rotating CW)
|
|
||||||
else:
|
|
||||||
milling_type = -1 # CW motion = conventional milling (spindle is rotating CW)
|
|
||||||
else:
|
|
||||||
if self.app.defaults['geometry_editor_milling_type'] == 'cl':
|
|
||||||
milling_type = -1 # CCW motion = climb milling (spindle is rotating CCW)
|
|
||||||
else:
|
|
||||||
milling_type = 1 # CW motion = conventional milling (spindle is rotating CCW)
|
|
||||||
|
|
||||||
# Link shapes into editor.
|
|
||||||
if multigeo_tool:
|
|
||||||
self.multigeo_tool = multigeo_tool
|
|
||||||
geo_to_edit = self.flatten(geometry=fcgeometry.tools[self.multigeo_tool]['solid_geometry'],
|
|
||||||
orient_val=milling_type)
|
|
||||||
self.app.inform.emit(
|
|
||||||
'[WARNING_NOTCL] %s: %s %s: %s' % (
|
|
||||||
_("Editing MultiGeo Geometry, tool"),
|
|
||||||
str(self.multigeo_tool),
|
|
||||||
_("with diameter"),
|
|
||||||
str(fcgeometry.tools[self.multigeo_tool]['tooldia'])
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
geo_to_edit = self.flatten(geometry=fcgeometry.solid_geometry, orient_val=milling_type)
|
|
||||||
|
|
||||||
for shape in geo_to_edit:
|
|
||||||
if shape is not None:
|
|
||||||
if type(shape) == Polygon:
|
|
||||||
self.add_shape(DrawToolShape(shape.exterior))
|
|
||||||
for inter in shape.interiors:
|
|
||||||
self.add_shape(DrawToolShape(inter))
|
|
||||||
else:
|
|
||||||
self.add_shape(DrawToolShape(shape))
|
|
||||||
|
|
||||||
self.replot()
|
|
||||||
|
|
||||||
# updated units
|
|
||||||
self.units = self.app.defaults['units'].upper()
|
|
||||||
self.decimals = self.app.decimals
|
|
||||||
|
|
||||||
# start with GRID toolbar activated
|
|
||||||
if self.app.ui.grid_snap_btn.isChecked() is False:
|
|
||||||
self.app.ui.grid_snap_btn.trigger()
|
|
||||||
|
|
||||||
def on_buffer_tool(self):
|
def on_buffer_tool(self):
|
||||||
buff_tool = BufferSelectionTool(self.app, self)
|
buff_tool = BufferSelectionTool(self.app, self)
|
||||||
buff_tool.run()
|
buff_tool.run()
|
||||||
|
@ -4700,6 +4629,77 @@ class AppGeoEditor(QtCore.QObject):
|
||||||
|
|
||||||
return snap_x, snap_y
|
return snap_x, snap_y
|
||||||
|
|
||||||
|
def edit_fcgeometry(self, fcgeometry, multigeo_tool=None):
|
||||||
|
"""
|
||||||
|
Imports the geometry from the given FlatCAM Geometry object
|
||||||
|
into the editor.
|
||||||
|
|
||||||
|
:param fcgeometry: GeometryObject
|
||||||
|
:param multigeo_tool: A tool for the case of the edited geometry being of type 'multigeo'
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
assert isinstance(fcgeometry, Geometry), "Expected a Geometry, got %s" % type(fcgeometry)
|
||||||
|
|
||||||
|
self.deactivate()
|
||||||
|
self.activate()
|
||||||
|
|
||||||
|
self.set_ui()
|
||||||
|
|
||||||
|
# Hide original geometry
|
||||||
|
self.fcgeometry = fcgeometry
|
||||||
|
fcgeometry.visible = False
|
||||||
|
|
||||||
|
# Set selection tolerance
|
||||||
|
DrawToolShape.tolerance = fcgeometry.drawing_tolerance * 10
|
||||||
|
|
||||||
|
self.select_tool("select")
|
||||||
|
|
||||||
|
if self.app.defaults['geometry_spindledir'] == 'CW':
|
||||||
|
if self.app.defaults['geometry_editor_milling_type'] == 'cl':
|
||||||
|
milling_type = 1 # CCW motion = climb milling (spindle is rotating CW)
|
||||||
|
else:
|
||||||
|
milling_type = -1 # CW motion = conventional milling (spindle is rotating CW)
|
||||||
|
else:
|
||||||
|
if self.app.defaults['geometry_editor_milling_type'] == 'cl':
|
||||||
|
milling_type = -1 # CCW motion = climb milling (spindle is rotating CCW)
|
||||||
|
else:
|
||||||
|
milling_type = 1 # CW motion = conventional milling (spindle is rotating CCW)
|
||||||
|
|
||||||
|
# Link shapes into editor.
|
||||||
|
if multigeo_tool:
|
||||||
|
self.multigeo_tool = multigeo_tool
|
||||||
|
geo_to_edit = self.flatten(geometry=fcgeometry.tools[self.multigeo_tool]['solid_geometry'],
|
||||||
|
orient_val=milling_type)
|
||||||
|
self.app.inform.emit(
|
||||||
|
'[WARNING_NOTCL] %s: %s %s: %s' % (
|
||||||
|
_("Editing MultiGeo Geometry, tool"),
|
||||||
|
str(self.multigeo_tool),
|
||||||
|
_("with diameter"),
|
||||||
|
str(fcgeometry.tools[self.multigeo_tool]['tooldia'])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
geo_to_edit = self.flatten(geometry=fcgeometry.solid_geometry, orient_val=milling_type)
|
||||||
|
|
||||||
|
for shape in geo_to_edit:
|
||||||
|
if shape is not None:
|
||||||
|
if type(shape) == Polygon:
|
||||||
|
self.add_shape(DrawToolShape(shape.exterior))
|
||||||
|
for inter in shape.interiors:
|
||||||
|
self.add_shape(DrawToolShape(inter))
|
||||||
|
else:
|
||||||
|
self.add_shape(DrawToolShape(shape))
|
||||||
|
|
||||||
|
self.replot()
|
||||||
|
|
||||||
|
# updated units
|
||||||
|
self.units = self.app.defaults['units'].upper()
|
||||||
|
self.decimals = self.app.decimals
|
||||||
|
|
||||||
|
# start with GRID toolbar activated
|
||||||
|
if self.app.ui.grid_snap_btn.isChecked() is False:
|
||||||
|
self.app.ui.grid_snap_btn.trigger()
|
||||||
|
|
||||||
def update_fcgeometry(self, fcgeometry):
|
def update_fcgeometry(self, fcgeometry):
|
||||||
"""
|
"""
|
||||||
Transfers the geometry tool shape buffer to the selected geometry
|
Transfers the geometry tool shape buffer to the selected geometry
|
||||||
|
|
|
@ -36,14 +36,15 @@ class AppGCodeEditor(QtCore.QObject):
|
||||||
|
|
||||||
self.ui = AppGCodeEditorUI(app=self.app)
|
self.ui = AppGCodeEditorUI(app=self.app)
|
||||||
|
|
||||||
# #################################################################################
|
|
||||||
# ################### SIGNALS #####################################################
|
|
||||||
# #################################################################################
|
|
||||||
|
|
||||||
self.gcode_obj = None
|
self.gcode_obj = None
|
||||||
self.code_edited = ''
|
self.code_edited = ''
|
||||||
|
|
||||||
def set_ui(self):
|
def set_ui(self):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:return:
|
||||||
|
:rtype:
|
||||||
|
"""
|
||||||
# #############################################################################################################
|
# #############################################################################################################
|
||||||
# ############# ADD a new TAB in the PLot Tab Area
|
# ############# ADD a new TAB in the PLot Tab Area
|
||||||
# #############################################################################################################
|
# #############################################################################################################
|
||||||
|
@ -73,9 +74,18 @@ class AppGCodeEditor(QtCore.QObject):
|
||||||
self.ui.append_text.set_value(self.app.defaults["cncjob_append"])
|
self.ui.append_text.set_value(self.app.defaults["cncjob_append"])
|
||||||
self.ui.prepend_text.set_value(self.app.defaults["cncjob_prepend"])
|
self.ui.prepend_text.set_value(self.app.defaults["cncjob_prepend"])
|
||||||
|
|
||||||
self.ui.exit_editor_button.buttonSave.clicked.connect(self.update_fcgcode)
|
# #################################################################################
|
||||||
|
# ################### SIGNALS #####################################################
|
||||||
|
# #################################################################################
|
||||||
|
self.ui.update_gcode_button.clicked.connect(self.insert_gcode)
|
||||||
|
self.ui.exit_editor_button.clicked.connect(self.update_fcgcode)
|
||||||
|
|
||||||
def build_ui(self):
|
def build_ui(self):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:return:
|
||||||
|
:rtype:
|
||||||
|
"""
|
||||||
# Remove anything else in the GUI Selected Tab
|
# Remove anything else in the GUI Selected Tab
|
||||||
self.app.ui.selected_scroll_area.takeWidget()
|
self.app.ui.selected_scroll_area.takeWidget()
|
||||||
# Put ourselves in the GUI Selected Tab
|
# Put ourselves in the GUI Selected Tab
|
||||||
|
@ -84,12 +94,27 @@ class AppGCodeEditor(QtCore.QObject):
|
||||||
self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
|
self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
|
||||||
|
|
||||||
def ui_connect(self):
|
def ui_connect(self):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:return:
|
||||||
|
:rtype:
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def ui_disconnect(self):
|
def ui_disconnect(self):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:return:
|
||||||
|
:rtype:
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def handleTextChanged(self):
|
def handleTextChanged(self):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:return:
|
||||||
|
:rtype:
|
||||||
|
"""
|
||||||
# enable = not self.ui.code_editor.document().isEmpty()
|
# enable = not self.ui.code_editor.document().isEmpty()
|
||||||
# self.ui.buttonPrint.setEnabled(enable)
|
# self.ui.buttonPrint.setEnabled(enable)
|
||||||
# self.ui.buttonPreview.setEnabled(enable)
|
# self.ui.buttonPreview.setEnabled(enable)
|
||||||
|
@ -97,7 +122,22 @@ class AppGCodeEditor(QtCore.QObject):
|
||||||
self.buttonSave.setStyleSheet("QPushButton {color: red;}")
|
self.buttonSave.setStyleSheet("QPushButton {color: red;}")
|
||||||
self.buttonSave.setIcon(QtGui.QIcon(self.app.resource_location + '/save_as_red.png'))
|
self.buttonSave.setIcon(QtGui.QIcon(self.app.resource_location + '/save_as_red.png'))
|
||||||
|
|
||||||
|
def insert_gcode(self):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:return:
|
||||||
|
:rtype:
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
def edit_fcgcode(self, cnc_obj):
|
def edit_fcgcode(self, cnc_obj):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param cnc_obj:
|
||||||
|
:type cnc_obj:
|
||||||
|
:return:
|
||||||
|
:rtype:
|
||||||
|
"""
|
||||||
assert isinstance(cnc_obj, CNCJobObject)
|
assert isinstance(cnc_obj, CNCJobObject)
|
||||||
self.gcode_obj = cnc_obj
|
self.gcode_obj = cnc_obj
|
||||||
|
|
||||||
|
@ -111,6 +151,11 @@ class AppGCodeEditor(QtCore.QObject):
|
||||||
self.app.inform.emit('[success] %s...' % _('Loaded Machine Code into Code Editor'))
|
self.app.inform.emit('[success] %s...' % _('Loaded Machine Code into Code Editor'))
|
||||||
|
|
||||||
def update_fcgcode(self):
|
def update_fcgcode(self):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:return:
|
||||||
|
:rtype:
|
||||||
|
"""
|
||||||
preamble = str(self.ui.prepend_text.get_value())
|
preamble = str(self.ui.prepend_text.get_value())
|
||||||
postamble = str(self.ui.append_text.get_value())
|
postamble = str(self.ui.append_text.get_value())
|
||||||
my_gcode = self.ui.gcode_editor_tab.code_editor.toPlainText()
|
my_gcode = self.ui.gcode_editor_tab.code_editor.toPlainText()
|
||||||
|
@ -120,7 +165,11 @@ class AppGCodeEditor(QtCore.QObject):
|
||||||
self.ui.gcode_editor_tab.setIcon(QtGui.QIcon(self.app.resource_location + '/save_as.png'))
|
self.ui.gcode_editor_tab.setIcon(QtGui.QIcon(self.app.resource_location + '/save_as.png'))
|
||||||
|
|
||||||
def on_open_gcode(self):
|
def on_open_gcode(self):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:return:
|
||||||
|
:rtype:
|
||||||
|
"""
|
||||||
_filter_ = "G-Code Files (*.nc);; G-Code Files (*.txt);; G-Code Files (*.tap);; G-Code Files (*.cnc);; " \
|
_filter_ = "G-Code Files (*.nc);; G-Code Files (*.txt);; G-Code Files (*.tap);; G-Code Files (*.cnc);; " \
|
||||||
"All Files (*.*)"
|
"All Files (*.*)"
|
||||||
|
|
||||||
|
|
|
@ -223,11 +223,37 @@ class AppObject(QtCore.QObject):
|
||||||
|
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
|
outname = 'new_geo'
|
||||||
|
|
||||||
def initialize(obj, app):
|
def initialize(obj, app):
|
||||||
obj.multitool = False
|
obj.multitool = True
|
||||||
|
obj.multigeo = True
|
||||||
|
# store here the default data for Geometry Data
|
||||||
|
default_data = {}
|
||||||
|
|
||||||
self.new_object('geometry', 'new_geo', initialize, plot=False)
|
for opt_key, opt_val in app.options.items():
|
||||||
|
if opt_key.find('geometry' + "_") == 0:
|
||||||
|
oname = opt_key[len('geometry') + 1:]
|
||||||
|
default_data[oname] = self.app.options[opt_key]
|
||||||
|
if opt_key.find('tools_mill' + "_") == 0:
|
||||||
|
oname = opt_key[len('tools_mill') + 1:]
|
||||||
|
default_data[oname] = self.app.options[opt_key]
|
||||||
|
|
||||||
|
obj.tools = {}
|
||||||
|
obj.tools.update({
|
||||||
|
1: {
|
||||||
|
'tooldia': float(app.defaults["geometry_cnctooldia"]),
|
||||||
|
'offset': 'Path',
|
||||||
|
'offset_value': 0.0,
|
||||||
|
'type': _('Rough'),
|
||||||
|
'tool_type': 'C1',
|
||||||
|
'data': deepcopy(default_data),
|
||||||
|
'solid_geometry': []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
obj.tools[1]['data']['name'] = outname
|
||||||
|
|
||||||
|
self.new_object('geometry', outname, initialize, plot=False)
|
||||||
|
|
||||||
def new_gerber_object(self):
|
def new_gerber_object(self):
|
||||||
"""
|
"""
|
||||||
|
|
19
app_Main.py
19
app_Main.py
|
@ -2193,9 +2193,10 @@ class App(QtCore.QObject):
|
||||||
if edited_object.tools[tool]['tooldia'] == selected_tooldia:
|
if edited_object.tools[tool]['tooldia'] == selected_tooldia:
|
||||||
multi_tool = tool
|
multi_tool = tool
|
||||||
break
|
break
|
||||||
|
log.debug("Editing MultiGeo Geometry with tool diameter: %s" % str(multi_tool))
|
||||||
self.geo_editor.edit_fcgeometry(edited_object, multigeo_tool=multi_tool)
|
self.geo_editor.edit_fcgeometry(edited_object, multigeo_tool=multi_tool)
|
||||||
else:
|
else:
|
||||||
|
log.debug("Editing SingleGeo Geometry with tool diameter.")
|
||||||
self.geo_editor.edit_fcgeometry(edited_object)
|
self.geo_editor.edit_fcgeometry(edited_object)
|
||||||
|
|
||||||
# set call source to the Editor we go into
|
# set call source to the Editor we go into
|
||||||
|
@ -8780,9 +8781,15 @@ class App(QtCore.QObject):
|
||||||
units = self.defaults['units'].upper()
|
units = self.defaults['units'].upper()
|
||||||
|
|
||||||
def obj_init(geo_obj, app_obj):
|
def obj_init(geo_obj, app_obj):
|
||||||
geo_obj.import_svg(filename, obj_type, units=units)
|
if obj_type == "geometry":
|
||||||
geo_obj.multigeo = False
|
geo_obj.import_svg(filename, obj_type, units=units)
|
||||||
geo_obj.source_file = self.export_gerber(obj_name=name, filename=None, local_use=geo_obj, use_thread=False)
|
elif obj_type == "gerber":
|
||||||
|
geo_obj.import_svg(filename, obj_type, units=units)
|
||||||
|
|
||||||
|
geo_obj.multigeo = True
|
||||||
|
with open(filename) as f:
|
||||||
|
file_content = f.read()
|
||||||
|
geo_obj.source_file = file_content
|
||||||
|
|
||||||
with self.proc_container.new(_("Importing SVG")) as proc:
|
with self.proc_container.new(_("Importing SVG")) as proc:
|
||||||
|
|
||||||
|
@ -8833,7 +8840,11 @@ class App(QtCore.QObject):
|
||||||
geo_obj.import_dxf_as_gerber(filename, units=units)
|
geo_obj.import_dxf_as_gerber(filename, units=units)
|
||||||
else:
|
else:
|
||||||
return "fail"
|
return "fail"
|
||||||
|
|
||||||
geo_obj.multigeo = True
|
geo_obj.multigeo = True
|
||||||
|
with open(filename) as f:
|
||||||
|
file_content = f.read()
|
||||||
|
geo_obj.source_file = file_content
|
||||||
|
|
||||||
with self.proc_container.new(_("Importing DXF")):
|
with self.proc_container.new(_("Importing DXF")):
|
||||||
|
|
||||||
|
|
26
camlib.py
26
camlib.py
|
@ -1058,6 +1058,7 @@ class Geometry(object):
|
||||||
geos = [translate(scale(g, 1.0, -1.0, origin=(0, 0)), yoff=h) for g in geos]
|
geos = [translate(scale(g, 1.0, -1.0, origin=(0, 0)), yoff=h) for g in geos]
|
||||||
|
|
||||||
# trying to optimize the resulting geometry by merging contiguous lines
|
# trying to optimize the resulting geometry by merging contiguous lines
|
||||||
|
geos = self.flatten(geos, reset=True, pathonly=True)
|
||||||
geos = linemerge(geos)
|
geos = linemerge(geos)
|
||||||
|
|
||||||
# Add to object
|
# Add to object
|
||||||
|
@ -1081,12 +1082,31 @@ class Geometry(object):
|
||||||
if flip:
|
if flip:
|
||||||
# Change origin to bottom left
|
# Change origin to bottom left
|
||||||
for i in geos_text:
|
for i in geos_text:
|
||||||
_, minimy, _, maximy = i.bounds
|
__, minimy, __, maximy = i.bounds
|
||||||
h2 = (maximy - minimy) * 0.5
|
h2 = (maximy - minimy) * 0.5
|
||||||
geos_text_f.append(translate(scale(i, 1.0, -1.0, origin=(0, 0)), yoff=(h + h2)))
|
geos_text_f.append(translate(scale(i, 1.0, -1.0, origin=(0, 0)), yoff=(h + h2)))
|
||||||
if geos_text_f:
|
if geos_text_f:
|
||||||
self.solid_geometry = self.solid_geometry + geos_text_f
|
self.solid_geometry = self.solid_geometry + geos_text_f
|
||||||
|
|
||||||
|
tooldia = float(self.app.defaults["geometry_cnctooldia"])
|
||||||
|
tooldia = float('%.*f' % (self.decimals, tooldia))
|
||||||
|
|
||||||
|
new_data = {k: v for k, v in self.options.items()}
|
||||||
|
|
||||||
|
self.tools.update({
|
||||||
|
1: {
|
||||||
|
'tooldia': tooldia,
|
||||||
|
'offset': 'Path',
|
||||||
|
'offset_value': 0.0,
|
||||||
|
'type': _('Rough'),
|
||||||
|
'tool_type': 'C1',
|
||||||
|
'data': deepcopy(new_data),
|
||||||
|
'solid_geometry': self.solid_geometry
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
self.tools[1]['data']['name'] = self.options['name']
|
||||||
|
|
||||||
def import_dxf_as_geo(self, filename, units='MM'):
|
def import_dxf_as_geo(self, filename, units='MM'):
|
||||||
"""
|
"""
|
||||||
Imports shapes from an DXF file into the object's geometry.
|
Imports shapes from an DXF file into the object's geometry.
|
||||||
|
@ -1103,6 +1123,7 @@ class Geometry(object):
|
||||||
geos = getdxfgeo(dxf)
|
geos = getdxfgeo(dxf)
|
||||||
|
|
||||||
# trying to optimize the resulting geometry by merging contiguous lines
|
# trying to optimize the resulting geometry by merging contiguous lines
|
||||||
|
geos = self.flatten(geos, reset=True, pathonly=True)
|
||||||
geos = linemerge(geos)
|
geos = linemerge(geos)
|
||||||
|
|
||||||
# Add to object
|
# Add to object
|
||||||
|
@ -5176,7 +5197,8 @@ class CNCjob(Geometry):
|
||||||
|
|
||||||
geo_storage = {}
|
geo_storage = {}
|
||||||
for geo in temp_solid_geometry:
|
for geo in temp_solid_geometry:
|
||||||
geo_storage[geo.coords[0]] = geo
|
if not geo is None:
|
||||||
|
geo_storage[geo.coords[0]] = geo
|
||||||
locations = list(geo_storage.keys())
|
locations = list(geo_storage.keys())
|
||||||
|
|
||||||
if opt_type == 'M':
|
if opt_type == 'M':
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
# ##########################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Matthieu Berthomé #
|
||||||
|
# Date: 5/26/2017 #
|
||||||
|
# MIT Licence #
|
||||||
|
# ##########################################################
|
||||||
|
|
||||||
|
from appPreProcessor import *
|
||||||
|
|
||||||
|
# This post processor is configured to output code that
|
||||||
|
# is compatible with almost any version of Grbl.
|
||||||
|
|
||||||
|
|
||||||
|
class Z_laser(PreProc):
|
||||||
|
|
||||||
|
include_header = True
|
||||||
|
coordinate_format = "%.*f"
|
||||||
|
feedrate_format = '%.*f'
|
||||||
|
|
||||||
|
def start_code(self, p):
|
||||||
|
units = ' ' + str(p['units']).lower()
|
||||||
|
gcode = '(This preprocessor is used with a motion controller loaded with GRBL firmware. )\n'
|
||||||
|
gcode += '(It is for the case when it is used together with a LASER connected on the SPINDLE connector.)\n'
|
||||||
|
gcode += '(On toolchange event the laser will move to a defined Z height to change the laser dot size.)\n\n'
|
||||||
|
|
||||||
|
xmin = '%.*f' % (p.coords_decimals, p['options']['xmin'])
|
||||||
|
xmax = '%.*f' % (p.coords_decimals, p['options']['xmax'])
|
||||||
|
ymin = '%.*f' % (p.coords_decimals, p['options']['ymin'])
|
||||||
|
ymax = '%.*f' % (p.coords_decimals, p['options']['ymax'])
|
||||||
|
|
||||||
|
gcode += '(Feedrate: ' + str(p['feedrate']) + units + '/min' + ')\n'
|
||||||
|
gcode += '(Feedrate rapids: ' + str(p['feedrate_rapid']) + units + '/min' + ')\n' + '\n'
|
||||||
|
|
||||||
|
gcode += '(Z Focus: ' + str(p['z_move']) + units + ')\n'
|
||||||
|
|
||||||
|
gcode += '(Steps per circle: ' + str(p['steps_per_circle']) + ')\n'
|
||||||
|
|
||||||
|
if str(p['options']['type']) == 'Excellon' or str(p['options']['type']) == 'Excellon Geometry':
|
||||||
|
gcode += '(Preprocessor Excellon: ' + str(p['pp_excellon_name']) + ')\n'
|
||||||
|
else:
|
||||||
|
gcode += '(Preprocessor Geometry: ' + str(p['pp_geometry_name']) + ')\n' + '\n'
|
||||||
|
|
||||||
|
gcode += '(X range: ' + '{: >9s}'.format(xmin) + ' ... ' + '{: >9s}'.format(xmax) + ' ' + units + ')\n'
|
||||||
|
gcode += '(Y range: ' + '{: >9s}'.format(ymin) + ' ... ' + '{: >9s}'.format(ymax) + ' ' + units + ')\n\n'
|
||||||
|
|
||||||
|
gcode += '(Laser Power (Spindle Speed): ' + str(p['spindlespeed']) + ')\n\n'
|
||||||
|
|
||||||
|
gcode += ('G20' if p.units.upper() == 'IN' else 'G21') + "\n"
|
||||||
|
gcode += 'G90\n'
|
||||||
|
gcode += 'G17\n'
|
||||||
|
gcode += 'G94'
|
||||||
|
|
||||||
|
return gcode
|
||||||
|
|
||||||
|
def startz_code(self, p):
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def lift_code(self, p):
|
||||||
|
return 'M5'
|
||||||
|
|
||||||
|
def down_code(self, p):
|
||||||
|
sdir = {'CW': 'M03', 'CCW': 'M04'}[p.spindledir]
|
||||||
|
if p.spindlespeed:
|
||||||
|
return '%s S%s' % (sdir, str(p.spindlespeed))
|
||||||
|
else:
|
||||||
|
return sdir
|
||||||
|
|
||||||
|
def toolchange_code(self, p):
|
||||||
|
return 'G00 Z' + self.coordinate_format % (p.coords_decimals, p.z_move)
|
||||||
|
|
||||||
|
def up_to_zero_code(self, p):
|
||||||
|
return 'M5'
|
||||||
|
|
||||||
|
def position_code(self, p):
|
||||||
|
return ('X' + self.coordinate_format + ' Y' + self.coordinate_format) % \
|
||||||
|
(p.coords_decimals, p.x, p.coords_decimals, p.y)
|
||||||
|
|
||||||
|
def rapid_code(self, p):
|
||||||
|
return ('G00 ' + self.position_code(p)).format(**p)
|
||||||
|
|
||||||
|
def linear_code(self, p):
|
||||||
|
return ('G01 ' + self.position_code(p)).format(**p) + \
|
||||||
|
' F' + str(self.feedrate_format % (p.fr_decimals, p.feedrate))
|
||||||
|
|
||||||
|
def end_code(self, p):
|
||||||
|
coords_xy = p['xy_end']
|
||||||
|
gcode = ('G00 Z' + self.feedrate_format % (p.fr_decimals, p.z_end) + "\n")
|
||||||
|
|
||||||
|
if coords_xy and coords_xy != '':
|
||||||
|
gcode += 'G00 X{x} Y{y}'.format(x=coords_xy[0], y=coords_xy[1]) + "\n"
|
||||||
|
return gcode
|
||||||
|
|
||||||
|
def feedrate_code(self, p):
|
||||||
|
return 'G01 F' + str(self.feedrate_format % (p.fr_decimals, p.feedrate))
|
||||||
|
|
||||||
|
def z_feedrate_code(self, p):
|
||||||
|
return 'G01 F' + str(self.feedrate_format % (p.fr_decimals, p.z_feedrate))
|
||||||
|
|
||||||
|
def spindle_code(self, p):
|
||||||
|
sdir = {'CW': 'M03', 'CCW': 'M04'}[p.spindledir]
|
||||||
|
if p.spindlespeed:
|
||||||
|
return '%s S%s' % (sdir, str(p.spindlespeed))
|
||||||
|
else:
|
||||||
|
return sdir
|
||||||
|
|
||||||
|
def dwell_code(self, p):
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def spindle_stop_code(self, p):
|
||||||
|
return 'M5'
|
Loading…
Reference in New Issue