Commit dd4b030a authored by sumpfralle's avatar sumpfralle

r689@erker: lars | 2010-02-19 03:52:19 +0100

 enabled "material allowance" (minimum distance between cutter and the model - for rough and semi-finish operations)
 derive the ToroidalCutter shape from the CylindricalCutter (not perfect, but it works)
 prevent all impossible combinations of tool and path settings by disabling the respective controls


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@147 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent ba6da836
...@@ -25,13 +25,23 @@ class CylindricalCutter(BaseCutter): ...@@ -25,13 +25,23 @@ class CylindricalCutter(BaseCutter):
def __repr__(self): def __repr__(self):
return "CylindricalCutter<%s,%s>" % (self.location,self.radius) return "CylindricalCutter<%s,%s>" % (self.location,self.radius)
def get_shape(self, format="ODE"): def get_shape(self, format="ODE", additional_distance=0.0):
if format == "ODE": if format == "ODE":
import ode import ode
geom = ode.GeomCylinder(None, self.radius, self.height) """ We don't handle the the "additional_distance" perfectly, since
the "right" shape would be a cylinder with a small flat cap that
grows to the full expanded radius through a partial sphere. The
following ascii art shows the idea:
| |
\_/
This slight incorrectness should be neglectable and causes no harm.
"""
radius = self.radius + additional_distance
height = self.height + additional_distance
geom = ode.GeomCylinder(None, radius, height)
def set_position(x, y, z): def set_position(x, y, z):
geom.setPosition((x, y, z)) geom.setPosition((x, y, z))
self.shape[format] = (geom, set_position, (0, 0, 0.5 * self.height)) self.shape[format] = (geom, set_position, (0, 0, 0.5 * height - additional_distance))
return self.shape[format] return self.shape[format]
def to_OpenGL(self): def to_OpenGL(self):
......
...@@ -25,13 +25,14 @@ class SphericalCutter(BaseCutter): ...@@ -25,13 +25,14 @@ class SphericalCutter(BaseCutter):
def __repr__(self): def __repr__(self):
return "SphericalCutter<%s,%s>" % (self.location,self.radius) return "SphericalCutter<%s,%s>" % (self.location,self.radius)
def get_shape(self, format="ODE"): def get_shape(self, format="ODE", additional_distance=0.0):
if format == "ODE": if format == "ODE":
import ode import ode
geom = ode.GeomCapsule(None, self.radius, self.height) radius = self.radius + additional_distance
geom = ode.GeomCapsule(None, radius, self.height)
def set_position(x, y, z): def set_position(x, y, z):
geom.setPosition((x, y, z)) geom.setPosition((x, y, z))
self.shape[format] = (geom, set_position, (0, 0, 0.5 * self.height + self.radius)) self.shape[format] = (geom, set_position, (0, 0, 0.5 * self.height + radius))
return self.shape[format] return self.shape[format]
def to_OpenGL(self): def to_OpenGL(self):
......
...@@ -30,14 +30,14 @@ class ToroidalCutter(BaseCutter): ...@@ -30,14 +30,14 @@ class ToroidalCutter(BaseCutter):
def __repr__(self): def __repr__(self):
return "ToroidalCutter<%s,%f,R=%f,r=%f>" % (self.location,self.radius,self.majorradius,self.minorradius) return "ToroidalCutter<%s,%f,R=%f,r=%f>" % (self.location,self.radius,self.majorradius,self.minorradius)
def get_shape(self, format="ODE"): def get_shape(self, format="ODE", additional_distance=0.0):
if format == "ODE": if format == "ODE":
import ode import ode
from pycam.Cutters.CylindricalCutter import CylindricalCutter
# TODO: use an appromixated trimesh instead (ODE does not support toroidal shapes) # TODO: use an appromixated trimesh instead (ODE does not support toroidal shapes)
geom = ode.GeomCapsule(None, self.radius, self.height) # for now: use the simple cylinder shape - this should not do any harm
def set_position(x, y, z): self.shape[format] = CylindricalCutter(self.radius, self.location,
geom.setPosition((x, y, z)) height=self.height).get_shape(format, additional_distance)
self.shape[format] = (geom, set_position, (0, 0, 0.5 * self.height + self.minorradius))
return self.shape[format] return self.shape[format]
def to_OpenGL(self): def to_OpenGL(self):
......
...@@ -370,13 +370,18 @@ class ProjectGui: ...@@ -370,13 +370,18 @@ class ProjectGui:
self.settings.add_item("path_postprocessor", get_path_postprocessor, set_path_postprocessor) self.settings.add_item("path_postprocessor", get_path_postprocessor, set_path_postprocessor)
# path direction (combined get/set function) # path direction (combined get/set function)
def set_get_path_direction(input=None): def set_get_path_direction(input=None):
for obj, value in [("PathDirectionX", "x"), ("PathDirectionY", "y"), ("PathDirectionXY", "xy")]: for obj, value in (("PathDirectionX", "x"), ("PathDirectionY", "y"), ("PathDirectionXY", "xy")):
if value == input: if value == input:
self.gui.get_object(obj).set_active(True) self.gui.get_object(obj).set_active(True)
return return
if self.gui.get_object(obj).get_active(): if self.gui.get_object(obj).get_active():
return value return value
self.settings.add_item("path_direction", set_get_path_direction, set_get_path_direction) self.settings.add_item("path_direction", set_get_path_direction, set_get_path_direction)
# connect the "consistency check" with all toolpath settings
for objname in ("PathAccumulator", "SimpleCutter", "ZigZagCutter", "PolygonCutter", "ContourCutter",
"DropCutter", "PushCutter", "SphericalCutter", "CylindricalCutter", "ToroidalCutter",
"PathDirectionX", "PathDirectionY", "PathDirectionXY"):
self.gui.get_object(objname).connect("toggled", self.disable_invalid_toolpath_settings)
# load a processing configuration object # load a processing configuration object
self.processing_settings = pycam.Gui.Settings.ProcessingSettings(self.settings) self.processing_settings = pycam.Gui.Settings.ProcessingSettings(self.settings)
self.processing_config_selection = self.gui.get_object("ProcessingTemplatesList") self.processing_config_selection = self.gui.get_object("ProcessingTemplatesList")
...@@ -398,6 +403,8 @@ class ProjectGui: ...@@ -398,6 +403,8 @@ class ProjectGui:
filter.add_pattern("*.conf") filter.add_pattern("*.conf")
load_processing_settings_file_control.add_filter(filter) load_processing_settings_file_control.add_filter(filter)
load_processing_settings_file_control.set_filter(filter) load_processing_settings_file_control.set_filter(filter)
# make sure that the toolpath settings are consistent
self.disable_invalid_toolpath_settings()
def gui_activity_guard(func): def gui_activity_guard(func):
def wrapper(self, *args, **kwargs): def wrapper(self, *args, **kwargs):
...@@ -422,6 +429,30 @@ class ProjectGui: ...@@ -422,6 +429,30 @@ class ProjectGui:
else: else:
self.physics = None self.physics = None
def disable_invalid_toolpath_settings(self, widget=None, data=None):
# possible dependencies of the DropCutter
if self.settings.get("path_generator") == "DropCutter":
if self.settings.get("path_direction") == "xy":
self.settings.set("path_direction", "x")
if not self.settings.get("path_postprocessor") in ("PathAccumulator", "ZigZagCutter"):
self.settings.set("path_postprocessor", "PathAccumulator")
dropcutter_active = True
else:
dropcutter_active = False
for objname in ("PathDirectionXY", "SimpleCutter", "PolygonCutter", "ContourCutter"):
self.gui.get_object(objname).set_sensitive(not dropcutter_active)
self.gui.get_object("PathDirectionXY").set_sensitive(not dropcutter_active)
# disable the dropcutter, if "xy" or one of "SimpleCutter", "PolygonCutter", "ContourCutter" is enabled
if (self.settings.get("path_postprocessor") in ("SimpleCutter", "PolygonCutter", "ContourCutter")) \
or (self.settings.get("path_direction") == "xy"):
self.gui.get_object("DropCutter").set_sensitive(False)
else:
self.gui.get_object("DropCutter").set_sensitive(True)
# disable the toroidal radius if the toroidal cutter is not enabled
self.gui.get_object("TorusRadiusControl").set_sensitive(self.settings.get("cutter_shape") == "ToroidalCutter")
# disable "step down" control, if PushCutter is not active
self.gui.get_object("MaxStepDownControl").set_sensitive(self.settings.get("path_generator") == "PushCutter")
@gui_activity_guard @gui_activity_guard
def toggle_3d_view(self, widget=None, value=None): def toggle_3d_view(self, widget=None, value=None):
current_state = not ((self.view3d is None) or (not self.view3d.is_visible)) current_state = not ((self.view3d is None) or (not self.view3d.is_visible))
...@@ -651,6 +682,8 @@ class ProjectGui: ...@@ -651,6 +682,8 @@ class ProjectGui:
pathgenerator = self.settings.get("path_generator") pathgenerator = self.settings.get("path_generator")
pathprocessor = self.settings.get("path_postprocessor") pathprocessor = self.settings.get("path_postprocessor")
direction = self.settings.get("path_direction") direction = self.settings.get("path_direction")
# Due to some weirdness the height of the drill must be bigger than the object's size.
# Otherwise some collisions are not detected.
cutter_height = 2 * (self.settings.get("maxz") - self.settings.get("minz")) cutter_height = 2 * (self.settings.get("maxz") - self.settings.get("minz"))
if cuttername == "SphericalCutter": if cuttername == "SphericalCutter":
self.cutter = pycam.Cutters.SphericalCutter(radius, height=cutter_height) self.cutter = pycam.Cutters.SphericalCutter(radius, height=cutter_height)
......
...@@ -73,7 +73,7 @@ tool_radius: 1.0 ...@@ -73,7 +73,7 @@ tool_radius: 1.0
torus_radius: 0.25 torus_radius: 0.25
speed: 1000 speed: 1000
feedrate: 200 feedrate: 200
material_allowance: 0 material_allowance: 0.0
overlap: 20 overlap: 20
step_down: 1.0 step_down: 1.0
# default sort weight is low (thus new items will appear above the defaults) # default sort weight is low (thus new items will appear above the defaults)
...@@ -85,6 +85,7 @@ cutter_shape: CylindricalCutter ...@@ -85,6 +85,7 @@ cutter_shape: CylindricalCutter
path_generator: PushCutter path_generator: PushCutter
path_postprocessor: PolygonCutter path_postprocessor: PolygonCutter
tool_radius: 1.0 tool_radius: 1.0
material_allowance: 1.0
[Semi-finish] [Semi-finish]
...@@ -93,6 +94,7 @@ cutter_shape: ToroidalCutter ...@@ -93,6 +94,7 @@ cutter_shape: ToroidalCutter
path_generator: PushCutter path_generator: PushCutter
path_postprocessor: ContourCutter path_postprocessor: ContourCutter
tool_radius: 0.5 tool_radius: 0.5
material_allowance: 0.3
[Finish] [Finish]
sort_weight: 92 sort_weight: 92
...@@ -100,6 +102,7 @@ cutter_shape: SphericalCutter ...@@ -100,6 +102,7 @@ cutter_shape: SphericalCutter
path_generator: DropCutter path_generator: DropCutter
path_postprocessor: ZigZagCutter path_postprocessor: ZigZagCutter
tool_radius: 0.1 tool_radius: 0.1
material_allowance: 0.0
""" """
SETTING_TYPES = { SETTING_TYPES = {
......
...@@ -196,7 +196,7 @@ def generate_physics(settings, cutter, physics=None): ...@@ -196,7 +196,7 @@ def generate_physics(settings, cutter, physics=None):
#height = 2 * (settings.get("maxz") - settings.get("minz")) #height = 2 * (settings.get("maxz") - settings.get("minz"))
#physics.set_drill(ode_objects.ShapeCylinder(radius, height), (settings.get("minx"), settings.get("miny"), settings.get("maxz"))) #physics.set_drill(ode_objects.ShapeCylinder(radius, height), (settings.get("minx"), settings.get("miny"), settings.get("maxz")))
#physics.set_drill(ode_objects.ShapeCylinder(radius, height), (0, 0, height/2.0)) #physics.set_drill(ode_objects.ShapeCylinder(radius, height), (0, 0, height/2.0))
shape_info = cutter.get_shape("ODE") shape_info = cutter.get_shape("ODE", settings.get("material_allowance"))
physics.set_drill(shape_info[0], shape_info[2]) physics.set_drill(shape_info[0], shape_info[2])
return physics return physics
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
<!-- interface-requires gtk+ 2.12 --> <!-- interface-requires gtk+ 2.12 -->
<!-- interface-naming-policy project-wide --> <!-- interface-naming-policy project-wide -->
<object class="GtkWindow" id="ProjectWindow"> <object class="GtkWindow" id="ProjectWindow">
<property name="title" translatable="yes">PyCAM Settings</property>
<property name="destroy_with_parent">True</property> <property name="destroy_with_parent">True</property>
<child> <child>
<object class="GtkNotebook" id="Tasks"> <object class="GtkNotebook" id="Tasks">
...@@ -1222,6 +1223,7 @@ ...@@ -1222,6 +1223,7 @@
<object class="GtkSpinButton" id="TorusRadiusControl"> <object class="GtkSpinButton" id="TorusRadiusControl">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Radius of the "doughnut" top of a Toroidal Cutter.</property>
<property name="invisible_char">&#x2022;</property> <property name="invisible_char">&#x2022;</property>
<property name="adjustment">torusradius</property> <property name="adjustment">torusradius</property>
<property name="digits">3</property> <property name="digits">3</property>
...@@ -1386,6 +1388,8 @@ ...@@ -1386,6 +1388,8 @@
<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 abrades a limited slice of material in each step.
It does not work with the "xy" direction and it requires the "Path Accumulator" or the "ZigZag Cutter".</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>
...@@ -1481,6 +1485,8 @@ ...@@ -1481,6 +1485,8 @@
<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">Dynamic switching between x and y axis direction.
Only available for the Push Cutter.</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>
<property name="group">PathDirectionX</property> <property name="group">PathDirectionX</property>
</object> </object>
...@@ -1543,6 +1549,7 @@ ...@@ -1543,6 +1549,7 @@
<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">Practically useless path processor for testing purposes.</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>
...@@ -1557,6 +1564,8 @@ ...@@ -1557,6 +1564,8 @@
<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">Practically useless path processor for testing purposes.
Only available for the Push Cutter.</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>
<property name="group">PathAccumulator</property> <property name="group">PathAccumulator</property>
</object> </object>
...@@ -1571,6 +1580,7 @@ ...@@ -1571,6 +1580,7 @@
<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">Quite simple path processor for finishing operations.</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>
<property name="group">PathAccumulator</property> <property name="group">PathAccumulator</property>
</object> </object>
...@@ -1585,6 +1595,8 @@ ...@@ -1585,6 +1595,8 @@
<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">Complex path processor for first rough operations.
Only available for the Push Cutter.</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>
<property name="group">PathAccumulator</property> <property name="group">PathAccumulator</property>
</object> </object>
...@@ -1599,6 +1611,8 @@ ...@@ -1599,6 +1611,8 @@
<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">Complex path processor for semi-finish operations.
Only available for the Push Cutter.</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>
<property name="group">PathAccumulator</property> <property name="group">PathAccumulator</property>
</object> </object>
...@@ -1709,6 +1723,7 @@ ...@@ -1709,6 +1723,7 @@
<object class="GtkSpinButton" id="MaxStepDownControl"> <object class="GtkSpinButton" id="MaxStepDownControl">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Height of each slice abraded by the Push Cutter.</property>
<property name="invisible_char">&#x2022;</property> <property name="invisible_char">&#x2022;</property>
<property name="adjustment">MaxStepDownValue</property> <property name="adjustment">MaxStepDownValue</property>
<property name="digits">2</property> <property name="digits">2</property>
...@@ -2095,6 +2110,7 @@ ...@@ -2095,6 +2110,7 @@
<property name="page_size">10</property> <property name="page_size">10</property>
</object> </object>
<object class="GtkWindow" id="view3dwindow"> <object class="GtkWindow" id="view3dwindow">
<property name="title" translatable="yes">PyCAM Visualization</property>
<child> <child>
<object class="GtkVBox" id="view3dbox"> <object class="GtkVBox" id="view3dbox">
<property name="visible">True</property> <property name="visible">True</property>
......
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