-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPathDialog.py
More file actions
256 lines (201 loc) · 10.8 KB
/
Copy pathPathDialog.py
File metadata and controls
256 lines (201 loc) · 10.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
################################################################################
# PathDialog.py
# Copyright (c) 2019 Joshua Liu
################################################################################
import rhinoscriptsyntax as rs
import Rhino.UI
import Eto.Drawing as drawing
import Eto.Forms as forms
from RegistrationDialog import RegistrationDialog
from TopographyPath import TopographyPath
from VLinePath import VLinePath
class PathDialog(forms.Dialog[bool]):
def __init__(self):
self.Title = 'Laser Path Generation'
self.Paddomg = drawing.Padding(5)
self.Resizable = False
# *** Window Layout ***
layout = forms.DynamicLayout(Padding = drawing.Padding(10, 5), DefaultSpacing = drawing.Size(2,2))
# Status Textbox, non-edit
status_label = forms.Label(Text = 'Status: ', VerticalAlignment = forms.VerticalAlignment.Center, TextAlignment = forms.TextAlignment.Right)
self.status_textbox = forms.TextBox(Text = 'Get Started', TextAlignment = forms.TextAlignment.Center)
self.status_textbox.ReadOnly = True
layout.BeginVertical()
layout.AddRow(status_label, self.status_textbox)
layout.EndVertical()
# = Begin of group boxes =
layout.BeginVertical()
# ---------------------------
# - Registration group box -
registration_groupbox = forms.GroupBox(Text = 'Implant', Padding = 5)
self.register_button = forms.Button(Text = 'Registration')
self.register_button.Click += self.OnRegisterButtonClick
grouplayout = forms.DynamicLayout()
grouplayout.AddRow(self.register_button)
registration_groupbox.Content = grouplayout
layout.AddRow(registration_groupbox)
# ---------------------------
# - Topography Path group box -
topography_groupbox = forms.GroupBox(Text = 'Topography Path', Padding = 5)
self.topo_config_btn = forms.Button(Text = 'Configure')
self.topo_config_btn.Click += self.OnTopoConfigButtonClick
self.topo_gen_btn = forms.Button(Text = 'Generate')
self.topo_gen_btn.Click += self.OnTopoGenButtonClick
grouplayout = forms.DynamicLayout()
grouplayout.AddRow(self.topo_config_btn,' ', self.topo_gen_btn)
topography_groupbox.Content = grouplayout
layout.AddRow(topography_groupbox)
# ---------------------------
# - 'V' Line Path group box -
vline_groupbox = forms.GroupBox(Text = '\'V\' Path', Padding = 5)
self.vline_gen_button = forms.Button(Text = 'Generate')
self.vline_gen_button.Click += self.OnVLineGenButtonClick
grouplayout = forms.DynamicLayout()
grouplayout.AddRow(None, self.vline_gen_button, None)
vline_groupbox.Content = grouplayout
layout.AddRow(vline_groupbox)
# ---------------------------
# - G-code group box -
gcode_groupbox = forms.GroupBox(Text = 'Export', Padding = 5)
self.export_csv_button = forms.Button(Text = '*.csv')
self.export_gcode_button = forms.Button(Text = '*.gcode')
self.export_gcode_button.Click += self.OnExportButtonClick
grouplayout = forms.DynamicLayout()
grouplayout.AddRow(self.export_csv_button,' ', self.export_gcode_button)
gcode_groupbox.Content = grouplayout
layout.AddRow(gcode_groupbox)
# = End of group boxes =
layout.EndVertical()
# add a logo at the bottom
logo_image_view = forms.ImageView()
logo_image_view.Size = drawing.Size(200, 30)
logo_image_view.Image = drawing.Bitmap(__file__ + '../../img/longeviti.bmp')
layout.BeginVertical()
layout.AddRow(logo_image_view)
layout.EndVertical()
# Create the default button
self.DefaultButton = forms.Button(Text = 'OK')
self.DefaultButton.Click += self.OnOKButtonClick
# Create the abort button
self.AbortButton = forms.Button(Text = 'Cancel')
self.AbortButton.Click += self.OnCloseButtonClick
layout.AddSeparateRow(None, self.DefaultButton, self.AbortButton, None)
self.Content = layout
# Registration Start button click handler
def OnRegisterButtonClick(self, sender, e):
self.status_textbox.Text = 'registration in progress ...'
registration_dialog = RegistrationDialog()
Rhino.UI.EtoExtensions.ShowSemiModal(registration_dialog, Rhino.RhinoDoc.ActiveDoc, Rhino.UI.RhinoEtoApp.MainWindow)
self.status_textbox.Text = 'registration complete'
# Topography configure button click handler
def OnTopoConfigButtonClick(self, sender, e):
self.status_textbox.Text = 'configuring topography...'
self.topography_configure_dialog = TopographyConfigureDialog()
self.topography_configure_dialog.ShowModal(Rhino.UI.RhinoEtoApp.MainWindow)
[self.topo_gen_mode, self.topo_path_count, self.topo_offset_dist] = self.topography_configure_dialog.OnOKButtonClick(sender, e)
self.status_textbox.Text = 'configuration complete'
# Topography generate button click handler
def OnTopoGenButtonClick(self, sender, e):
self.status_textbox.Text = 'generating topography path'
# create a topography path object, select the mesh
self.topography_path = TopographyPath(rs.GetObject("Select mesh", rs.filter.mesh ), self.topo_path_count, self.topo_offset_dist)
if self.topo_gen_mode is TOPO_PICK_3_POINTS:
# Select 3 vertex on the mesh to construct a intersection plane
pt_1 = rs.GetPointOnMesh(mesh, "Select 1st vertice on mesh for constructing a plane")
pt_2 = rs.GetPointOnMesh(mesh, "Select 2nd vertice on mesh for constructing a plane")
pt_3 = rs.GetPointOnMesh(mesh, "Select 3rd vertice on mesh for constructing a plane")
self.polyline_point_array = self.topography_path.generatePolylineFrom3Pts(pt_1, pt_2, pt_3)
elif self.topo_gen_mode is TOPO_PICK_TOP_POINT:
# Select a top vertice on the mesh to construct a plane normal
mesh_top_pt = rs.GetPointOnMesh(mesh, "Select a top vertice on mesh")
self.polyline_point_array = self.topography_path.generatePolylineFromCentroidTopPt(mesh_top_pt)
else:
pass
result = rs.LastCommandResult()
if result == 0:
self.status_textbox.Text = 'topography path generated'
else:
self.status_textbox.Text = 'unsuccessful'
# V Line path generate button click handler
def OnVLineGenButtonClick(self, sender, e):
self.status_textbox.Text = 'generating V line path'
# create a V line path object, select the mesh
self.vline_path = VLinePath(rs.GetObject("Select mesh", rs.filter.mesh ))
self.vline_path.generateVLineFrom3Pts()
self.vline_path.exportGcode()
# G-code Export button click handler
def OnExportButtonClick(self, sender, e):
self.status_textbox.Text = 'Gcode conversion'
self.topography_path.exportPolylineGcode(self.polyline_point_array)
self.status_textbox.Text = 'Gcode exported'
# Close button click handler
def OnCloseButtonClick(self, sender, e):
self.status_textbox.Text = ""
self.Close(False)
# Close button click handler
def OnOKButtonClick(self, sender, e):
self.Close(True)
class TopographyConfigureDialog(forms.Dialog[bool]):
def __init__(self):
self.Title = 'Topography Path'
self.Paddomg = drawing.Padding(5)
self.Resizable = True
# define two global constants
global TOPO_PICK_3_POINTS
global TOPO_PICK_TOP_POINT
TOPO_PICK_3_POINTS = 0
TOPO_PICK_TOP_POINT = 1
# intersection plane creation mode
mode_label = forms.Label(Text = 'Mode: ', VerticalAlignment = forms.VerticalAlignment.Center, TextAlignment = forms.TextAlignment.Right)
self.mode_combobox = forms.ComboBox()
self.mode_combobox.ReadOnly = True
self.mode_combobox.DataStore = ['pick 3 points', 'pick top point only']
self.mode_combobox.SelectedIndex = TOPO_PICK_3_POINTS
# number of path to generate
path_count_label = forms.Label(Text = 'Layers: ', VerticalAlignment = forms.VerticalAlignment.Center, TextAlignment = forms.TextAlignment.Right)
self.path_count_stepper = forms.NumericStepper(Value = 10)
self.path_count_stepper.MinValue = 1
# offset distance between layers
offset_dist_label = forms.Label(Text = 'Distance: ', VerticalAlignment = forms.VerticalAlignment.Center, TextAlignment = forms.TextAlignment.Right)
self.offset_dist_stepper = forms.NumericStepper(Value = 3)
self.offset_dist_stepper.MinValue = 0
self.offset_dist_stepper.Increment = 0.5
self.offset_dist_stepper.DecimalPlaces = 2
self.offset_dist_stepper.MaximumDecimalPlaces = 4
# Create the default button
self.DefaultButton = forms.Button(Text = 'OK')
self.DefaultButton.Click += self.OnOKButtonClick
# Create the abort button
self.AbortButton = forms.Button(Text = 'Cancel')
self.AbortButton.Click += self.OnCloseButtonClick
layout = forms.DynamicLayout(Padding = drawing.Padding(5, 5), DefaultSpacing = drawing.Size(2,2))
layout.BeginVertical()
layout.AddRow(mode_label, self.mode_combobox)
layout.AddRow(path_count_label, self.path_count_stepper)
layout.AddRow(offset_dist_label, self.offset_dist_stepper)
layout.EndVertical()
layout.BeginVertical()
layout.AddRow(None, self.DefaultButton, self.AbortButton, None)
layout.EndVertical()
self.Content = layout
# Close button click handler
def OnCloseButtonClick(self, sender, e):
self.Close(False)
# Close button click handler
def OnOKButtonClick(self, sender, e):
self.Close(True)
return [self.mode_combobox.SelectedIndex, int(self.path_count_stepper.Value), self.offset_dist_stepper.Value]
# The script that will be using the dialog.
def openPathDialog():
dialog = PathDialog();
# Use Semi-Modal instead to allow interaction with Rhino Document
rc = Rhino.UI.EtoExtensions.ShowSemiModal(dialog, Rhino.RhinoDoc.ActiveDoc, Rhino.UI.RhinoEtoApp.MainWindow)
# rc = dialog.ShowModal(Rhino.UI.RhinoEtoApp.MainWindow)
if (rc):
print 'Thanks for using Laser Path Generation'
##########################################################################
# Check to see if this file is being executed as the "main" python
# script instead of being used as a module by some other python script
# This allows us to use the module which ever way we want.
if __name__ == "__main__":
openPathDialog()