Commit 0cc5946a authored by sumpfralle's avatar sumpfralle

added toolpath grid pattern operation: clone a single toolpath into rows and columns


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@993 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent b8aab86d
......@@ -9,6 +9,7 @@ Version 0.4.1 - UNRELEASED
* added a very simple "pocketing" mode for 2D models
* added 2D projection of 3D models
* added toolpath cropping
* added toolpath grid pattern: clone a single toolpath in rows and columns
* added support for DXF features "LWPOLYLINE" and "ARC"
* added a configuration setting for automatically loading a custom task settings file on startup
* added a simple "undo" feature for reversing model manipulations
......
......@@ -4247,6 +4247,19 @@ Usually you will want to use the cutter radius here to cut around the outline.</
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="ToolpathGrid">
<property name="label">gtk-page-setup</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="toolpath_crop">
<property name="label" translatable="yes">Crop</property>
......@@ -4259,7 +4272,7 @@ Usually you will want to use the cutter radius here to cut around the outline.</
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
<property name="position">2</property>
</packing>
</child>
<child>
......@@ -4273,7 +4286,7 @@ Usually you will want to use the cutter radius here to cut around the outline.</
</object>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
<property name="position">3</property>
</packing>
</child>
<child>
......@@ -4287,7 +4300,7 @@ Usually you will want to use the cutter radius here to cut around the outline.</
</object>
<packing>
<property name="expand">False</property>
<property name="position">3</property>
<property name="position">4</property>
</packing>
</child>
<child>
......@@ -4301,7 +4314,7 @@ Usually you will want to use the cutter radius here to cut around the outline.</
</object>
<packing>
<property name="expand">False</property>
<property name="position">4</property>
<property name="position">5</property>
</packing>
</child>
</object>
......@@ -4851,6 +4864,7 @@ Usually you will want to use the cutter radius here to cut around the outline.</
<property name="border_width">5</property>
<property name="title" translatable="yes">PyCAM Preferences</property>
<property name="destroy_with_parent">True</property>
<property name="icon_name">preferences-desktop</property>
<property name="type_hint">normal</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox1">
......@@ -6753,6 +6767,7 @@ You should have received a copy of the GNU General Public License along with thi
<property name="border_width">5</property>
<property name="title" translatable="yes">Unit change compensation</property>
<property name="modal">True</property>
<property name="icon_name">accessories-calculator</property>
<property name="type_hint">normal</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox7">
......@@ -7516,6 +7531,7 @@ Please read the description of the Server Mode (linked below) to understand the
<property name="title" translatable="yes">Engrave text</property>
<property name="window_position">center</property>
<property name="destroy_with_parent">True</property>
<property name="icon_name">accessories-character-map</property>
<property name="type_hint">dialog</property>
<property name="transient_for">ProjectWindow</property>
<child internal-child="vbox">
......@@ -8174,4 +8190,260 @@ upon interesting bugs and weird results.</property>
<property name="upper">100</property>
<property name="step_increment">5.0000000000000002e-05</property>
</object>
<object class="GtkDialog" id="ToolpathGridDialog">
<property name="border_width">5</property>
<property name="title" translatable="yes">Toolpath Grid</property>
<property name="destroy_with_parent">True</property>
<property name="icon_name">document-page-setup</property>
<property name="type_hint">normal</property>
<property name="has_separator">False</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox10">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child>
<object class="GtkTable" id="table16">
<property name="visible">True</property>
<property name="n_rows">4</property>
<property name="n_columns">3</property>
<property name="column_spacing">3</property>
<property name="row_spacing">3</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkLabel" id="LabelGridRows">
<property name="visible">True</property>
<property name="label" translatable="yes">Rows</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="LabelGridColumns">
<property name="visible">True</property>
<property name="label" translatable="yes">Columns</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="LabelGridCount">
<property name="visible">True</property>
<property name="label" translatable="yes">Count:</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="LabelGridDistance">
<property name="visible">True</property>
<property name="label" translatable="yes">Distance:</property>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="GridYCount">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">&#x25CF;</property>
<property name="adjustment">GridYCountValue</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="GridXCount">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">&#x25CF;</property>
<property name="adjustment">GridXCountValue</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="GridYDistance">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">&#x25CF;</property>
<property name="adjustment">GridYDistanceValue</property>
<property name="digits">3</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="GridXDistance">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">&#x25CF;</property>
<property name="adjustment">GridXDistanceValue</property>
<property name="digits">3</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkAlignment" id="alignment47">
<property name="visible">True</property>
<child>
<placeholder/>
</child>
</object>
</child>
<child>
<object class="GtkLabel" id="LabelWidth">
<property name="visible">True</property>
<property name="label" translatable="yes">Width:</property>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="LabelGridYWidth">
<property name="visible">True</property>
<property name="label" translatable="yes">?</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="LabelGridXWidth">
<property name="visible">True</property>
<property name="label" translatable="yes">?</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area9">
<property name="visible">True</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="ToolpathGridClose">
<property name="label">gtk-cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="ToolpathGridOK">
<property name="label">gtk-ok</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">ToolpathGridClose</action-widget>
<action-widget response="1">ToolpathGridOK</action-widget>
</action-widgets>
</object>
<object class="GtkAdjustment" id="GridYCountValue">
<property name="value">1</property>
<property name="lower">1</property>
<property name="upper">1000</property>
<property name="step_increment">1</property>
</object>
<object class="GtkAdjustment" id="GridXCountValue">
<property name="value">1</property>
<property name="lower">1</property>
<property name="upper">1000</property>
<property name="step_increment">1</property>
</object>
<object class="GtkAdjustment" id="GridYDistanceValue">
<property name="lower">-1000</property>
<property name="upper">1000</property>
<property name="step_increment">1</property>
</object>
<object class="GtkAdjustment" id="GridXDistanceValue">
<property name="lower">-1000</property>
<property name="upper">1000</property>
<property name="step_increment">1</property>
</object>
</interface>
......@@ -32,6 +32,7 @@ import pycam.Importers.CXFImporter
import pycam.Importers
from pycam.Geometry.Point import Point, Vector
from pycam.Geometry.Plane import Plane
import pycam.Geometry.Path
import pycam.Utils.log
import pycam.Utils
from pycam.Geometry.utils import sqrt
......@@ -43,7 +44,6 @@ from pycam.Utils import ProgressCounter, check_uri_exists
from pycam.Toolpath import Bounds
from pycam import VERSION
import pycam.Physics.ode_physics
import pycam.Toolpath.MotionGrid
# this requires ODE - we import it later, if necessary
#import pycam.Simulation.ODEBlocks
import gtk
......@@ -448,6 +448,7 @@ class ProjectGui:
self.grid_adjustments_x = []
self.grid_adjustments_y = []
self._last_unit = None
self._toolpath_for_grid_data = {}
# add some dummies - to be implemented later ...
self.settings.add_item("model", lambda: self.model)
self.settings.add_item("toolpath", lambda: self.toolpath)
......@@ -672,6 +673,11 @@ class ProjectGui:
self.settings.set("support_grid_minimum_bridges", 2)
self.settings.set("support_grid_length", 5)
self.grid_adjustment_axis_x_last = True
# toolpath grid pattern
for objname in ("GridYCount", "GridXCount", "GridYDistance",
"GridXDistance"):
self.gui.get_object(objname).connect("value-changed",
self.update_toolpath_grid_window)
# visual and general settings
for name, objname in (("show_model", "ShowModelCheckBox"),
("show_support_grid", "ShowSupportGridCheckBox"),
......@@ -843,6 +849,7 @@ class ProjectGui:
self.gui.get_object("toolpath_delete").connect("clicked", self.toolpath_table_event, "delete")
self.gui.get_object("toolpath_simulate").connect("clicked", self.toolpath_table_event, "simulate")
self.gui.get_object("toolpath_crop").connect("clicked", self.toolpath_table_event, "crop")
self.gui.get_object("ToolpathGrid").connect("clicked", self.toolpath_table_event, "grid")
self.gui.get_object("ExitSimulationButton").connect("clicked", self.finish_toolpath_simulation)
speed_factor_widget = self.gui.get_object("SimulationSpeedFactor")
self.settings.add_item("simulation_speed_factor",
......@@ -3223,14 +3230,67 @@ class ProjectGui:
index = self._treeview_get_active_index(self.toolpath_table, self.toolpath)
if not index is None:
self.crop_toolpath(self.toolpath[index])
elif action == "grid":
index = self._treeview_get_active_index(self.toolpath_table, self.toolpath)
if not index is None:
self.create_toolpath_grid(self.toolpath[index])
# process the default operations (move, delete)
self._treeview_button_event(self.toolpath_table, self.toolpath, action,
self.update_toolpath_table)
# do some post-processing ...
if action in ("delete", "crop"):
# hide the deleted toolpath immediately
if action in ("delete", "crop", "grid"):
self.update_view()
def update_toolpath_grid_window(self, widget=None):
data = self._toolpath_for_grid_data
x_dim = data["maxx"] - data["minx"]
y_dim = data["maxy"] - data["miny"]
x_count = self.gui.get_object("GridXCount").get_value()
x_space = self.gui.get_object("GridXDistance").get_value()
y_count = self.gui.get_object("GridYCount").get_value()
y_space = self.gui.get_object("GridYDistance").get_value()
x_width = x_dim * x_count + x_space * (x_count - 1)
y_width = y_dim * y_count + y_space * (y_count - 1)
self.gui.get_object("LabelGridXWidth").set_label("%g%s" % \
(x_width, self.settings.get("unit")))
self.gui.get_object("LabelGridYWidth").set_label("%g%s" % \
(y_width, self.settings.get("unit")))
def create_toolpath_grid(self, toolpath):
dialog = self.gui.get_object("ToolpathGridDialog")
data = self._toolpath_for_grid_data
data["minx"] = toolpath.minx()
data["maxx"] = toolpath.maxx()
data["miny"] = toolpath.miny()
data["maxy"] = toolpath.maxy()
self.gui.get_object("GridXCount").set_value(1)
self.gui.get_object("GridYCount").set_value(1)
self.update_toolpath_grid_window()
result = dialog.run()
if result == 1:
# "OK" was pressed
new_tp = []
x_count = int(self.gui.get_object("GridXCount").get_value())
y_count = int(self.gui.get_object("GridYCount").get_value())
x_space = self.gui.get_object("GridXDistance").get_value()
y_space = self.gui.get_object("GridYDistance").get_value()
x_dim = data["maxx"] - data["minx"]
y_dim = data["maxy"] - data["miny"]
for x in range(x_count):
for y in range(y_count):
shift = Point(x * (x_space + x_dim),
y * (y_space + y_dim), 0)
for path in toolpath.get_paths():
new_path = pycam.Geometry.Path.Path()
new_path.points = [shift.add(p) for p in path.points]
new_tp.append(new_path)
new_toolpath = pycam.Toolpath.Toolpath(new_tp, toolpath.name,
toolpath.toolpath_settings)
toolpath.visible = False
new_toolpath.visible = True
self.toolpath.append(new_toolpath)
dialog.hide()
@progress_activity_guard
def crop_toolpath(self, toolpath):
if hasattr(self.model, "get_polygons"):
......@@ -3297,6 +3357,7 @@ class ProjectGui:
self.gui.get_object("toolpath_down").set_sensitive((not new_index is None) and (new_index + 1 < len(self.toolpath)))
self.gui.get_object("toolpath_simulate").set_sensitive(not new_index is None)
self.gui.get_object("toolpath_crop").set_sensitive(not new_index is None)
self.gui.get_object("ToolpathGrid").set_sensitive(not new_index is None)
@gui_activity_guard
def save_task_settings_file(self, widget=None, filename=None):
......
......@@ -77,6 +77,31 @@ class Toolpath(object):
# generate random color
self.set_color()
def _get_limit_generic(self, attr, func):
path_min = []
for path in self.get_paths():
if path.points:
path_min.append(func([getattr(p, attr) for p in path.points]))
return func(path_min)
def minx(self):
return self._get_limit_generic("x", min)
def maxx(self):
return self._get_limit_generic("x", max)
def miny(self):
return self._get_limit_generic("y", min)
def maxy(self):
return self._get_limit_generic("y", max)
def minz(self):
return self._get_limit_generic("z", min)
def maxz(self):
return self._get_limit_generic("z", max)
def get_paths(self):
return self.toolpath
......
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