-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcompute5axisgcode.rb
executable file
·488 lines (291 loc) · 11.6 KB
/
compute5axisgcode.rb
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
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
=begin
Updated: 14th June 2018
# --- SketchUp Extension by ---
Jesper Nagel Kirial
Niklas Buhl - https://niklasbuhl.xyz
Developed in the relation to a special course at Technical University of Denmark
Supervisers:
Bjørn Klink Christensen
Jacob Lawaetz
# --- Description ---
# --- More Information ---
Link to report
http://www.diplom.dtu.dk/5axislaser
=end
require 'sketchup'
require_relative 'compute5axisgcode/analysemodel.rb'
require_relative 'compute5axisgcode/analysefaces.rb'
require_relative 'compute5axisgcode/calculatecuttingstrategy.rb'
require_relative 'compute5axisgcode/calculatetrajectory.rb'
require_relative 'compute5axisgcode/settings.rb'
module Main
# Hello World
puts "Hello World. v2.7 - Initializing Prismatic Accelerator..."
# Includes
include AnalyseModel
include AnalyseFaces
include CalculateCuttingStrategy
include CalculateTrajectory
# Model
$model = Sketchup.active_model
$entities = $model.active_entities
# Entity Arrays
$edgeArray = Array.new # Collect all edges
$faceArray = Array.new # Keep track of found faces
$vertexArray = Array.new # Keep track of all the vertices
# Face Arrays
$cuttingArray = Array.new # Keep track of the faces to be cut
$cuttingStrategy = Array.new # Keep track of cutting strategies
# Laser Arrays
$laserCutArray = Array.new # For all the laser cutting lines
$laserRayArray = Array.new # For all the ray
# GCode Arrays
$gcodeArray = Array.new # Keep track of the GCode
# Program states
$programState = 0
# ---
# --- Primary Methods ---
# ---
def self.AnalyseModel
puts "Analysing model v1.1"
t1 = Time.now
# Updating all sketchup entities
$model = Sketchup.active_model
$entities = $model.active_entities
# Clear arrays
$faceArray.clear
$edgeArray.clear
$vertexArray.clear
$cuttingArray.clear
$cuttingStrategy.clear
# Remove and clear the cuts and rays
CalculateCuttingStrategy.ClearCutRay
# Explode Model!
AnalyseModel.ExplodeModel $model.entities
# Find faces in the model
AnalyseModel.FindFaces $model.entities
# Color found faces green
AnalyseModel.FoundFaces $faceArray
# Remove dublicate vertices, as they a for each edge, if more edges use the
# same vertex - there are dublicate vertices in the array.
$vertexArray.uniq!
puts "#{$faceArray.count} faces found!"
puts "#{$edgeArray.count} edges found!"
puts "#{$vertexArray.count} vertices found!"
puts "Checking all vertices to be inside the lasercutting machine boundaries..." if $debugAnalyseModel
AnalyseModel.CheckBoundaries $vertexArray
# [FUTURE WORK] If there are vertices out of bound return with error
$programState = 1
t2 = Time.now
puts "Model analysed! It took #{t2 - t1} seconds."
end
def self.AnalyseFaces
unless $programState == 1
# [FUTURE WORK] Give a waring to analyse model
return
end
puts "Analysing faces v1.2"
t1 = Time.now
$faceArray.each do |face|
# Check for top and bottom
next if AnalyseFaces.TopBottom face
# Check for faces with too many vertices (This is probably not necessary)
next if AnalyseFaces.TooManyVertices face
# Check if faces is too angled
next if AnalyseFaces.TooAngled face
# Rest of faces is cutting faces
AnalyseFaces.CutThisFace face, $cuttingArray # Function to color remaining red and put them into cutting faces array
end
puts "#{$cuttingArray.count} faces to cut!"
$programState = 2
t2 = Time.now
puts "Faces Analysed! It took #{t2 - t1} seconds."
end
def self.CalculateCuttingStrategy
unless $programState == 2
# [FUTURE WORK] Give a waring to analyse faces
return
end
puts "Calculating cutting faces v1.7"
t1 = Time.now
puts "Hidding all edges..." if $debugCalculateCuttingStrategy
# Hide all edges, so raytest does not cause unessacary trouble
$edgeArray.each do |edge|
edge.hidden = true
end
# Clear the array
$cuttingStrategy.clear
CalculateCuttingStrategy.ClearCutRay
# Loop through all 3 strategies
$cuttingArray.each_with_index do |cuttingFace, cutting_index|
puts "Face #{cutting_index}..." if $debugCalculateCuttingStrategy
# Create new face cutting strategy
faceCuttingStrategy = FaceCuttingStrategy.new(cuttingFace)
# Push to the array
$cuttingStrategy.push(faceCuttingStrategy)
# Calculate top and bottom vertices
CalculateCuttingStrategy.TopBottomVertices faceCuttingStrategy
# Calculate OuterVertices
CalculateCuttingStrategy.OuterVertices faceCuttingStrategy
puts "First Strategy" if $debugStrategy1
# --- First Strategy ---
next if CalculateCuttingStrategy.FirstStrategy faceCuttingStrategy, cutting_index
puts "Second Strategy" if $debugStrategy2
# --- Second Raytest ---
next if CalculateCuttingStrategy.SecondStrategy faceCuttingStrategy, cutting_index
puts "Third Strategy" if $debugStrategy3
# --- Third Raytest: Viften / Kegle ---
next if CalculateCuttingStrategy.ThirdStrategy faceCuttingStrategy, cutting_index
# --- Face cannot be cut
puts "Face #{cutting_index}. Face cannot be cut!" if $debugCalculateCuttingStrategy
faceCuttingStrategy.cuttable = false
faceCuttingStrategy.face.material = "black"
faceCuttingStrategy.face.back_material = "black"
# [FUTURE WORK] Remove from array again if it cannot be cut...
end
# --- Calculate Actual Laser Positions and Orientations ---
$cuttingStrategy.each do |faceCuttingStrategy|
# Calculate the vectors for the entry and exit rays
CalculateCuttingStrategy.LaserCut faceCuttingStrategy
# Calculate the angles A and B for entry and exit ray
CalculateCuttingStrategy.CalculateOrientation faceCuttingStrategy
end
if $drawLaserCut
puts "Drawing #{$cuttingStrategy.size} lasercuts" if $debugCalculateCuttingStrategy
counter = 0
$cuttingStrategy.each do |faceCuttingStrategy|
puts "#{faceCuttingStrategy.strategy}" if $debugCalculateCuttingStrategy
# If the face cannot be cut, proceed
if faceCuttingStrategy.cuttable != true
# Shows the rays of the face cutting strategy that did not succeed
$laserRayArray.push($entities.add_line(faceCuttingStrategy.rays[0]))
$laserRayArray.push($entities.add_line(faceCuttingStrategy.rays[1]))
puts "Wrong cutting strategy: #{faceCuttingStrategy.strategy}" if $debugCalculateCuttingStrategy
next
end
counter = counter + 1
# Add line
$laserCutArray.push($entities.add_line faceCuttingStrategy.laserStartPosition, faceCuttingStrategy.laserEndPosition)
end
puts "Drawed #{counter} laser cuts"
end
# Show all cutting rays, disabled by default
if $drawRaytest
$cuttingStrategy.each_with_index do |faceCuttingStrategy, strategy_index|
# If the face cannot be cut, proceed.
next if faceCuttingStrategy.cuttable != true
puts "Drawing strategy #{strategy_index}, Strategy: #{faceCuttingStrategy.strategy}"
# Add lines
$laserRayArray.push($entities.add_line faceCuttingStrategy.rays[0])
$laserRayArray.push($entities.add_line faceCuttingStrategy.rays[1])
end
end
# Show all edges again...
$edgeArray.each do |edge|
edge.hidden = false
end
$programState = 3
t2 = Time.now
puts "Cutting strategy calculated! It took #{t2 - t1} seconds."
end
def self.CalculateTrajectory
unless $programState == 3
# [FUTURE WORK] Give a waring to calculate cutting strategies
return
end
puts "Calculating Trajectory v2.2"
t1 = Time.now
# Clear the array
$gcodeArray.clear
# Clear the cut and ray array and erase lines
CalculateCuttingStrategy.ClearCutRay
# New temporay array for the unpathed gcodes
tempGCodeArray = Array.new
# Load all the [G1] cuts from the strategy array
CalculateTrajectory.GetCuts tempGCodeArray
# Calculate shortest path between vectors
CalculateTrajectory.PathAlgorithm tempGCodeArray
$gcodeArray.each do |gcode|
# Calculate relative path from absolute points and orienations
# Next if the relative GCode G0/G1 is 0,0,0,0,0 (No cut or movement)
next unless CalculateTrajectory.RelativeGCodeRelativeXYZ gcode
# Write the G0 X1 Y2... string
CalculateTrajectory.WriteGCodeString gcode
end
# Draw all the GCodes
CalculateTrajectory.DrawGCodes
$programState = 4
t2 = Time.now
puts "Trajectory Calculated! It took #{t2 - t1} seconds."
end
def self.ExportGCode
unless $programState == 4
# [FUTURE WORK] Give a waring to calculate trajectory
return
end
puts "Export GCode v1.0"
t1 = Time.now
# Set filepath to nil so if the save panel is cancelled it simply gives an error
filepath_filename = nil
# Open the save panel to select destination and name for the gcode file
filepath_filename = UI.savepanel("Save GCode File", "", "gcodes.gcode")
puts "#{filepath_filename}" if $debugExportGCode
puts "#{$gcodeArray.size} lines of instructions." if $debugExportGCode
# Save panel is stopped or cancelled
if filepath_filename == nil
t2 = Time.now
puts "Failed to create file. It took #{t2 - t1} seconds."
return
end
# Write all the gcodes to the file
File.open(filepath_filename, "w") do |line|
# Start with the G91 to state it is relative codes
line.puts("G91")
# Loop through all GCodes and check if they got a string
$gcodeArray.each_with_index do |gcode, index|
# Write the gcode string to the file
line.puts "#{gcode.string}" if gcode.string != nil
puts "Writing [#{index}]: #{gcode.string}" if $debugExportGCode
end
end
t2 = Time.now
puts "Created a file with all the gcodes! It took #{t2 - t1} seconds."
end
# ---
# Developer Utilities
# ---
def self.GenerateTestModels
puts "Generate Test Models. v0.2"
model = Sketchup.active_model
testModelPath = File.join(File.dirname(__FILE__),'/compute5axisgcode/test-geometrier-laser.skp')
model.import(testModelPath)
end
def self.UpdateExtension
# Function to update the modules, classes and functions without having to restart SketchUp
puts "Updating modules. v2.1"
projectdir = File.dirname(__FILE__)
load projectdir + "/compute5axisgcode/analysemodel.rb"
load projectdir + "/compute5axisgcode/analysefaces.rb"
load projectdir + "/compute5axisgcode/calculatecuttingstrategy.rb"
load projectdir + "/compute5axisgcode/calculatetrajectory.rb"
load projectdir + "/compute5axisgcode/settings.rb"
end
# ---
# User Interface Dropdown Menu
# ---
# Only loads them the first time
unless file_loaded?(__FILE__)
menu = UI.menu('Plugins')
menu.add_item('1. Analyse Model') {self.AnalyseModel}
menu.add_item('2. Analyse Faces') {self.AnalyseFaces}
menu.add_item('3. Calculate Cutting Strategy') {self.CalculateCuttingStrategy}
menu.add_item('4. Calculate Trajectory') {self.CalculateTrajectory}
menu.add_item('5. Export GCode') {self.ExportGCode}
# Sub Menu with Developing Tools
# Remove everything and generate test models (Used for development purposes)
menu.add_item('Generate Test Models') {self.GenerateTestModels}
# To remove extension (Used for development purposes)
menu.add_item('Developer: Update Extension') {self.UpdateExtension}
file_loaded(__FILE__)
end
end