Commit c6e15d92 authored by sumpfralle's avatar sumpfralle

implemented basic interface for loading DXF contour files


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@355 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 4f4dc7a1
...@@ -52,7 +52,7 @@ GTKBUILD_FILE = "pycam-project.ui" ...@@ -52,7 +52,7 @@ GTKBUILD_FILE = "pycam-project.ui"
GTKMENU_FILE = "menubar.xml" GTKMENU_FILE = "menubar.xml"
FILTER_GCODE = ("GCode files", ("*.ngc", "*.nc", "*.gc", "*.gcode")) FILTER_GCODE = ("GCode files", ("*.ngc", "*.nc", "*.gc", "*.gcode"))
FILTER_MODEL = ("STL models", "*.stl") FILTER_MODEL = (("STL models", "*.stl"), ("DXF contours", "*.dxf"))
FILTER_CONFIG = ("Config files", "*.conf") FILTER_CONFIG = ("Config files", "*.conf")
FILTER_EMC_TOOL = ("EMC tool files", "*.tbl") FILTER_EMC_TOOL = ("EMC tool files", "*.tbl")
...@@ -309,7 +309,7 @@ class ProjectGui: ...@@ -309,7 +309,7 @@ class ProjectGui:
# connect the "consistency check" and the update-handler with all toolpath settings # connect the "consistency check" and the update-handler with all toolpath settings
for objname in ("PathAccumulator", "SimpleCutter", "ZigZagCutter", "PolygonCutter", "ContourCutter", for objname in ("PathAccumulator", "SimpleCutter", "ZigZagCutter", "PolygonCutter", "ContourCutter",
"DropCutter", "PushCutter", "PathDirectionX", "PathDirectionY", "PathDirectionXY", "SettingEnableODE"): "DropCutter", "PushCutter", "PathDirectionX", "PathDirectionY", "PathDirectionXY", "SettingEnableODE"):
self.gui.get_object(objname).connect("toggled", self.disable_invalid_process_settings) self.gui.get_object(objname).connect("toggled", self.update_process_controls)
if objname != "SettingEnableODE": if objname != "SettingEnableODE":
self.gui.get_object(objname).connect("toggled", self.handle_process_settings_change) self.gui.get_object(objname).connect("toggled", self.handle_process_settings_change)
for objname in ("SafetyHeightControl", "OverlapPercentControl", for objname in ("SafetyHeightControl", "OverlapPercentControl",
...@@ -406,7 +406,7 @@ class ProjectGui: ...@@ -406,7 +406,7 @@ class ProjectGui:
def update_all_controls(self): def update_all_controls(self):
self.update_toolpath_table() self.update_toolpath_table()
self.update_tool_table() self.update_tool_table()
self.disable_invalid_process_settings() self.update_process_controls()
self.update_process_table() self.update_process_table()
self.update_tasklist_table() self.update_tasklist_table()
self.update_tasklist_controls() self.update_tasklist_controls()
...@@ -605,28 +605,45 @@ class ProjectGui: ...@@ -605,28 +605,45 @@ class ProjectGui:
break break
progress_bar.hide() progress_bar.hide()
def disable_invalid_process_settings(self, widget=None, data=None): def update_process_controls(self, widget=None, data=None):
# possible dependencies of the DropCutter # possible dependencies of the DropCutter
get_obj = lambda name: self.gui.get_object(name) get_obj = lambda name: self.gui.get_object(name)
if get_obj("DropCutter").get_active(): cutter_name = None
for one_cutter in ("DropCutter", "PushCutter", "EngraveCutter"):
if get_obj(one_cutter).get_active():
cutter_name = one_cutter
if cutter_name == "DropCutter":
if get_obj("PathDirectionXY").get_active(): if get_obj("PathDirectionXY").get_active():
get_obj("PathDirectionX").set_active(True) get_obj("PathDirectionX").set_active(True)
if not (get_obj("PathAccumulator").get_active() or get_obj("ZigZagCutter").get_active()): if not (get_obj("PathAccumulator").get_active() or get_obj("ZigZagCutter").get_active()):
get_obj("PathAccumulator").set_active(True) get_obj("PathAccumulator").set_active(True)
dropcutter_active = True dropcutter_active = True
else: elif cutter_name == "PushCutter":
# PushCutter
if not (get_obj("SimpleCutter").get_active() \ if not (get_obj("SimpleCutter").get_active() \
or get_obj("PolygonCutter").get_active() \ or get_obj("PolygonCutter").get_active() \
or get_obj("ContourCutter").get_active()): or get_obj("ContourCutter").get_active()):
get_obj("SimpleCutter").set_active(True) get_obj("SimpleCutter").set_active(True)
dropcutter_active = False dropcutter_active = False
for objname in ("PathDirectionXY", "SimpleCutter", "PolygonCutter", "ContourCutter"): else:
self.gui.get_object(objname).set_sensitive(not dropcutter_active) # engraving
for objname in ("PathAccumulator", "ZigZagCutter"): if not get_obj("PathAccumulator").get_active():
self.gui.get_object(objname).set_sensitive(dropcutter_active) get_obj("PathAccumulator").set_active(True)
# disable "step down" control, if PushCutter is not active all_controls = ("PathDirectionX", "PathDirectionY", "PathDirectionXY",
self.gui.get_object("MaxStepDownControl").set_sensitive(get_obj("PushCutter").get_active()) "SimpleCutter", "PolygonCutter", "ContourCutter",
"PathAccumulator", "ZigZagCutter", "MaxStepDownControl",
"MaterialAllowanceControl", "OverlapPercentControl")
active_controls = {
"DropCutter": ("PathAccumulator", "ZigZagCutter", "PathDirectionX",
"PathDirectionY", "MaterialAllowanceControl",
"OverlapPercentControl"),
"PushCutter": ("SimpleCutter", "PolygonCutter", "ContourCutter",
"PathDirectionX", "PathDirectionY", "PathDirectionXY",
"MaxStepDownControl", "MaterialAllowanceControl",
"OverlapPercentControl"),
"EngraveCutter": ("PathAccumulator", "MaxStepDownControl"),
}
for one_control in all_controls:
get_obj(one_control).set_sensitive(one_control in active_controls[cutter_name])
def update_tool_controls(self, widget=None, data=None): def update_tool_controls(self, widget=None, data=None):
# disable the toroidal radius if the toroidal cutter is not enabled # disable the toroidal radius if the toroidal cutter is not enabled
...@@ -978,6 +995,9 @@ class ProjectGui: ...@@ -978,6 +995,9 @@ class ProjectGui:
def get_filename_with_suffix(self, filename, type_filter): def get_filename_with_suffix(self, filename, type_filter):
# use the first extension provided by the filter as the default # use the first extension provided by the filter as the default
if isinstance(type_filter[0], (tuple, list)):
filter_ext = type_filter[0][1]
else:
filter_ext = type_filter[1] filter_ext = type_filter[1]
if isinstance(filter_ext, (list, tuple)): if isinstance(filter_ext, (list, tuple)):
filter_ext = filter_ext[0] filter_ext = filter_ext[0]
...@@ -1225,7 +1245,11 @@ class ProjectGui: ...@@ -1225,7 +1245,11 @@ class ProjectGui:
self.last_model_file = filename self.last_model_file = filename
self.update_save_actions() self.update_save_actions()
if filename: if filename:
self.load_model(pycam.Importers.STLImporter.ImportModel(filename)) file_type, importer = pycam.Importers.detect_file_type(filename)
if file_type and callable(importer):
self.load_model(importer(filename))
else:
show_error_dialog(self.window, "Failed to detect filetype!")
@gui_activity_guard @gui_activity_guard
def export_emc_tools(self, widget=None, filename=None): def export_emc_tools(self, widget=None, filename=None):
...@@ -1731,14 +1755,17 @@ class ProjectGui: ...@@ -1731,14 +1755,17 @@ class ProjectGui:
gtk.STOCK_SAVE, gtk.RESPONSE_OK)) gtk.STOCK_SAVE, gtk.RESPONSE_OK))
# add filter for files # add filter for files
if type_filter: if type_filter:
filter = gtk.FileFilter() if not isinstance(type_filter[0], (list, tuple)):
filter.set_name(type_filter[0]) type_filter = [type_filter]
file_extensions = type_filter[1] for one_filter in type_filter:
file_filter = gtk.FileFilter()
file_filter.set_name(one_filter[0])
file_extensions = one_filter[1]
if not isinstance(file_extensions, (list, tuple)): if not isinstance(file_extensions, (list, tuple)):
file_extensions = [file_extensions] file_extensions = [file_extensions]
for ext in file_extensions: for ext in file_extensions:
filter.add_pattern(ext) file_filter.add_pattern(ext)
dialog.add_filter(filter) dialog.add_filter(file_filter)
# add filter for all files # add filter for all files
filter = gtk.FileFilter() filter = gtk.FileFilter()
filter.set_name("All files") filter.set_name("All files")
......
...@@ -4051,6 +4051,8 @@ You should have received a copy of the GNU General Public License along with thi ...@@ -4051,6 +4051,8 @@ You should have received a copy of the GNU General Public License along with thi
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">False</property> <property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">The Drop Cutter goes down to the lowest possible point at any location within the working area.
This is suitable for finishing processes after removing the material above.</property>
<property name="active">True</property> <property name="active">True</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>
</object> </object>
...@@ -4065,6 +4067,9 @@ You should have received a copy of the GNU General Public License along with thi ...@@ -4065,6 +4067,9 @@ You should have received a copy of the GNU General Public License along with thi
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">False</property> <property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">The Push Cutter removes material in multiple layers down to the bottom of the working area.
This is suitable for roughly processing the material.
It will spare some material close to the model (depending on the "step down" value).</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>
<property name="group">DropCutter</property> <property name="group">DropCutter</property>
</object> </object>
...@@ -4073,6 +4078,21 @@ You should have received a copy of the GNU General Public License along with thi ...@@ -4073,6 +4078,21 @@ You should have received a copy of the GNU General Public License along with thi
<property name="position">1</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkRadioButton" id="EngraveCutter">
<property name="label" translatable="yes">Engraving</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Engraving is only applicable to contour models (e.g. DXF files).</property>
<property name="draw_indicator">True</property>
<property name="group">DropCutter</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</child>
</object> </object>
</child> </child>
</object> </object>
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
$Id$ $Id$
Copyright 2008 Lode Leroy Copyright 2008 Lode Leroy
Copyright 2010 Lars Kruse <devel@sumpfralle.de>
This file is part of PyCAM. This file is part of PyCAM.
...@@ -20,6 +21,27 @@ You should have received a copy of the GNU General Public License ...@@ -20,6 +21,27 @@ You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>. along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
""" """
list = ["STLImporter"] __all__ = ["STLImporter", "DXFImporter", "TestModel"]
__all__ = ["TestModel"] + list
import DXFImporter
import STLImporter
import os
import sys
def detect_file_type(filename):
failure = (None, None)
if not os.path.isfile(filename):
return failure
else:
# check all listed importers
# TODO: this should be done by evaluating the header of the file
if filename.endswith(".stl"):
return ("stl", STLImporter.ImportModel)
elif filename.endswith(".dxf"):
return ("dxf", DXFImporter.import_model)
else:
print >>sys.stderr, "Failed to detect the model type of '%s'." \
% filename + " Is the file extension (.stl/.dxf) correct?"
failure
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment