-
Notifications
You must be signed in to change notification settings - Fork 5
/
CNC-Toolkit.ms
2909 lines (2494 loc) · 124 KB
/
CNC-Toolkit.ms
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
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
--------------------------------------------------------------------------------
-- CNC Toolkit - Copyright 2009 Rab Gordon
-- email: rab@cnc-toolkit.com
-- www.cnc-toolkit.com
-- This MaxScript is distributed as free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or any later version.
-- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-- See the GNU General Public License for more details.
-- You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
-- Thanks and Acknowledgements:
-- For help and advice from swami*, a.k.a. "codeWarrior()
-- For the Roland File Format Import by Doug McNabb ~ this is where it all began.
-- For some functions and ideas inspired by John Burnett's MaxScript library
-- Change log
-- 4.34 - "Digitise": -- Use Digitise Probe routine following toolpath
---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
-- DEBUG = true -- just uncomment (remove the '--' at the start of this line) to enable DEBUG output to the MaxScript Listener
-- DECLARE FUNCTIONS, etc.
-- Function List
Global ZeroPointPos,Debug,InitialiseVariables,StartTimer1,EndTimer1,StartTimer2,EndTimer2,ImportZMatrixToPlane,SplineFilter,MeshFilter,padLeadingZeros,HAPFOLineNo,ResetXforms,dbpyr,difference,ImportCSVMatrix,NumberAsLimitedFloat,RoundOffNumber,HideVectors,UnHideVectors,readnumber,readCSVnumber,readtext,SceneSetup,CreateZeroPoint,CreateCutter,CreateAAxis,CreateBAxis,CreateCAxis,MakeTextRing,SplineFromObjects,create_preview_toolpath,ImportRolandToolpath,ImportGCODE,ImportPLC,ImportCSV,MakeDrillCycleToolPath,MakeParallelSplines,MakeToolpath,DigitisePeckToolpath,AppendToolpath,CalcToolAngleVector,GetClosestVertexVectorOLD,GetClosestVertexVectorNEW,GetClosestVertexVector,detach_splines,Is_Curved_Seg,Subdivide_Shape,SubdivideAndRenameShape,make_contour_lines,attach_splines,create_vertex_array,closest_vertex,check_vertices,fuse_vertices,weld_vertices,ProjectSpline,SplineFromMesh,PostProcessToolpath,GetMoveType,GetToolVector,CalcToolPathExportCoordsXYZ,CalcToolPathExportCoordsXYZA,CalcToolPathExportCoordsXYZBC,CalcToolPathExportCoordsXYZAC,CalcToolPathExportCoordsXYZAB,CalcToolPathExportCoordsRobotArm,CalcToolPathExportCoords,WriteToolpath,ToolpathExportString,CleanTPDialogs,LaunchCNCToolkitUI
-- Rollout list
Global CNCTKFloater,ToolpathGenerator_Rollout,TPFShapeDialog,TPFProjdShapeDialog,TPFStepoversDia,MachineTypeDialog,TPFDrillCycleDia
---------------------------------------------------------------------------------
fn InitialiseVariables = ( -- Initialise all Variables, but import values from ini file if available
try (filein "CNC_Toolkit.ini" ; format "CNC_Toolkit.ini loaded\n") catch (format "CNC_Toolkit.ini not found\n")
Global GMAX = (maxversion())[2] == 128 -- Check Max Version
Global MachineTypes = #("XYZ","XZA","XYZA","XYZAB","XYZAC","XYZBC","Robot Arm")
if MachineType == undefined then Global MachineType = 1
Global ProjectionMethods = #("Downwards" , "Around X Axis" , "Around Y Axis" , "Around Z Axis")
if ProjectionMethod == undefined then Global ProjectionMethod = 1
Global StepoverMethods = #("Flat, Parallel to X-Axis","Flat, Parallel to Y-Axis","Flat, Spiral","Spiral around X-Axis","Spiral around Y-Axis","Spiral around Z-Axis" )
if StepoverMethod == undefined then Global StepoverMethod = 1
Global VectorCalcMethods = #("Don't Calculate Angles","Angle is Parallel to Z-axis","Angle from Origin","Angle Around X-Axis","Angle from Reference Spline","Angle from Reference Surface")
if VectorCalcMethod == undefined then Global VectorCalcMethod = 2
Global ExportFormats = #("Standard G-Code","Digitise","Standard HPGL","Roland CNC HPGL","HAPFO-CNC","CSV","CamBam")
if ExportFormat == undefined then Global ExportFormat = 1
Global ExportDestinations = #("File","Printer/Serial Port","Default File","Script Listener Window")
if GMAX then Global ExportDestination = 4
if ExportDestination == undefined then Global ExportDestination = 1
-- Waterline Splines variables
if Dist_from_top == undefined then Global Dist_from_top= 1.0
if Dist_from_base == undefined then Global Dist_from_base= 1.0
if Spacing == undefined then Global Spacing= 10.0
if Fuse_n_Weld_threshold == undefined then Global Fuse_n_Weld_threshold= 1.0
-- Parallel Splines variables
if Stepover == undefined then Global Stepover = 10.0
if ProjectionPreSubdivide == undefined then Global ProjectionPreSubdivide = false
if ProjectionOffset == undefined then Global ProjectionOffset = 0.0
-- Spline Subdivision variables
if pre_subdivide == undefined then Global pre_subdivide = true
if min_Seg_length == undefined then Global min_Seg_length = 1.0
if max_Seg_length == undefined then Global max_Seg_length = 5.0
if Max_Curvature == undefined then Global Max_Curvature = 20.0
if subdivide_recursions == undefined then Global subdivide_recursions = 5
-- Toolpath from spline variables
Global tool_clearance,VectorSize
if tool_clearance == undefined then Global tool_clearance = 25.0
Global VectorSize = (tool_clearance / 3)
if ToolDiameter == undefined then Global ToolDiameter = 3.0
if SpindleSpeed == undefined then Global SpindleSpeed = 1000.0
if Dwell == undefined then Global Dwell = 0.25
if DrillDepth == undefined then Global DrillDepth = 1.0
if PeckDepth == undefined then Global PeckDepth = 1.0
if CutDepth == undefined then Global CutDepth = 0.0
if MultiPasses == undefined then Global MultiPasses = 1
if ToolOffset == undefined then Global ToolOffset = 0.0
if MakeVectors == undefined then Global MakeVectors = false
-- Vector Calculations , default no. of checkbow
if TangentMode == undefined then Global TangentMode = false
-- Toolpath Export & Options
if Feedrate == undefined then Global Feedrate = 100.0
if PlungeRatio == undefined then Global PlungeRatio = 50.0
if OffsetAroundAaxis== undefined then Global OffsetAroundAaxis= 100.0
if OffsetAroundBaxis== undefined then Global OffsetAroundBaxis= 100.0
if OffsetAroundCaxis== undefined then Global OffsetAroundCaxis= 100.0
if ClearanceMode == undefined then Global ClearanceMode= 1
if ZDirection == undefined then Global ZDirection = 1
if RecalcFeedrateEnabled == undefined then Global RecalcFeedrateEnabled = false
if OutputPort == undefined then Global OutputPort = 1
if DefaultFileName == undefined then Global DefaultFileName = sysInfo.currentdir + "\\tempfile.tap"
if OutputLineNo == undefined then Global OutputLineNo = false -- Write Line Numbers
if SubRoutine == undefined then Global SubRoutine = false -- is GCode to be used as part of a subroutine ?
if FixedZ == undefined then Global FixedZ = false
if FixedZDown == undefined then Global FixedZDown = "-1"
if FixedZUp == undefined then Global FixedZUp = "0"
-------------------------------------------------------
Global Toolpath , Angle , Depth , AngleDiff , Revolutions , PathNormalAngle , clr , tmpstring , k1 , nearest_angle_zero , k , NearestAngleZero , ShapeToProcess , ToolAngleVector
Global start_at_Zero = true , end_at_Zero = true , preview_toolpath = true
Global inFile , out
Global new_toolpath , ToolAngle , ReferenceSpline , ReferenceMesh , Cutter , Toolpivot , KnotDistances , ToolAngles , startTime1 , endTime1 , startTime2 , endTime2 , ToolpathHasVectors
Global ReferenceMesh , tempReferenceMesh
Global MoveType = "Rapid Move"
Global SixAxisCoords -- Data structure for 6 axes , ie. x ,y ,z coords plus angle of rotation around x ,y ,z planes
Struct SixAxisCoords (pos ,ang) -- pos. ~ x ,y ,z position -- ang.x ~ rotation around x-axis (4th-axis) , ang.y ~ rotation around y-axis (5th-axis) , ang.z ~ rotation around z-axis (6th-axis)
Global MachineCoords = SixAxisCoords [0.0 ,0.0 ,0.0] [0.0 ,0.0 ,0.0]
Global LastMachineCoords = SixAxisCoords [0.0 ,0.0 ,0.0] [0.0 ,0.0 ,0.0]
Global ClosestVertexCoords = SixAxisCoords [0.0 ,0.0 ,0.0] [0.0 ,0.0 ,0.0]
Global MachineCoordsStart = SixAxisCoords [0.0 ,0.0 ,0.0] [0.0 ,0.0 ,0.0]
----------------------------------------------------------------------
-- Setup Toolpath Material
Global ToolpathMaterial
ToolpathMaterial = Multimaterial numsubs:6
ToolpathMaterial.name = "Toolpath"
ToolpathMaterial.materialList[1].Diffuse = color 255 0 0 ; ToolpathMaterial.materialList[1].name = "Feed Move"
ToolpathMaterial.materialList[2].Diffuse = color 23 121 0 ; ToolpathMaterial.materialList[2].name = "Retract Move"
ToolpathMaterial.materialList[3].Diffuse = color 37 47 174 ; ToolpathMaterial.materialList[3].name = "Rapid Move"
ToolpathMaterial.materialList[4].Diffuse = color 150 255 209 ; ToolpathMaterial.materialList[4].name = "Plunge Move"
ToolpathMaterial.materialList[5].Diffuse = color 255 200 0 ; ToolpathMaterial.materialList[5].name = "Vector"
ToolpathMaterial.materialList[6].Diffuse = color 155 0 155 ; ToolpathMaterial.materialList[6].name = "Plunge/Dwell"
setMeditMaterial 1 ToolpathMaterial
-- Setup Axis Material
AxesMaterial = Multimaterial numsubs:5
AxesMaterial.name = "Axes"
AxesMaterial.materialList[1].Diffuse = color 255 0 0 ; AxesMaterial.materialList[1].name = "X-Axis"
AxesMaterial.materialList[2].Diffuse = color 0 255 0 ; AxesMaterial.materialList[2].name = "Y-Axis"
AxesMaterial.materialList[3].Diffuse = color 0 0 255 ; AxesMaterial.materialList[3].name = "Z-Axis"
AxesMaterial.materialList[4].Diffuse = color 60 60 60 ; AxesMaterial.materialList[4].name = "Pointer"
AxesMaterial.materialList[5].Diffuse = color 255 255 255 ; AxesMaterial.materialList[5].name = "Spare"
setMeditMaterial 2 AxesMaterial
AAxisMaterial = StandardMaterial name: "A-Axis" diffuse: (color 255 0 0) opacity: 15 ; setMeditMaterial 7 AAxisMaterial
BAxisMaterial = StandardMaterial name: "B-Axis" diffuse: (color 0 255 0) opacity: 15 ; setMeditMaterial 8 BAxisMaterial
CAxisMaterial = StandardMaterial name: "C-Axis" diffuse: (color 0 0 255) opacity: 15 ; setMeditMaterial 9 CAxisMaterial
PointerMaterial = StandardMaterial name: "Pointer" diffuse: (color 60 60 60) opacity: 15 ; setMeditMaterial 4 PointerMaterial
)
-- MINOR FUNCTIONS--
fn HideVectors = (hideselectedsplines $; updateshape $)
fn UnHideVectors = (unhidesegments $; updateshape $)
fn SplineFilter obj = SuperClassOf obj == Shape
fn MeshFilter obj = SuperClassOf obj == GeometryClass
fn padLeadingZeros num numMaxChar=(n=numMaxChar-((numStr=num as string).count);for i=1 to n do numStr="0"+numStr;numStr)
fn HAPFOLineNo = (LineNo += 1 ; return "N" + (padLeadingZeros LineNo 6) + " " as string )
fn dbpyr dbpyr_val size =( --Debugging tool
pyramid width:size depth:size height:size pos:dbpyr_val wirecolor: clr
)
fn difference val1 val2 = ( if val1 < val2 then diff1 = val2 - val1 else diff1 = val1 - val2
if diff1 > 180 then diff1 = 180 - (diff1 - 180)
return diff1 )
fn NumberAsLimitedFloat val =(
val *= 1000; --print val
val = val as integer; --print val
val = val as float; --print val
val /= 1000; --print val
return val
)
fn RoundOffNumber n places:4 =(
local mult = pow 10 places
n *= mult
if n < 0 then n -= 0.5 else n += 0.5
return ((n as integer) / mult)
)
fn readnumber file=(
local str="" ; local Char ; local end_of_number = false
if readchar inFile != " " then seek inFile ( filepos inFile - 1 ) -- filter out first space if it exists
while not end_of_number do
( Char= readchar inFile; --format "no: % \n" Char
if findString "-.1234567890E+" Char == undefined then end_of_number = true else Str += Char
)
number = execute Str
seek inFile ( filepos inFile - 1 )
return number
)
fn readCSVnumber file=(
local str="[" ; local Char ; local end_of_number = false
if readchar inFile != " " then seek inFile ( filepos inFile - 1 ) -- filter out first space if it exists
while not end_of_number and not eof file do
( Char= readchar inFile ; --if eof inFile do print "EOF"
if DEBUG then format "no: % \n" Char
if findString "-.1234567890,E" Char == undefined then end_of_number = true else Str += Char
)
str += "]"
seek inFile ( filepos inFile - 1 )
thePoint3 = execute str
if DEBUG then format "thePoint3: %\n" thePoint3
return thePoint3
)
fn readtext file=(
local str="" ; local Char ; local number = false
str = readchar inFile
if findString "-.1234567890" str != undefined then return str
while ( not number and not eof inFile )do
( Char= readchar inFile; --format "Char: % \n" Char
if findString "-.1234567890" Char != undefined then number = true else Str += Char
)
return str
)
fn ResetXforms =(
for obj in selection do
( if DEBUG then Format "ResetXforms %\n" obj
old_ot = obj.objecttransform ; old_t = obj.transform ; offset = old_ot.row4 - old_t.row4 ; old_piv = obj.pivot
obj.transform = matrix3 1 ; obj.objectoffsetpos = [0,0,0] ; obj.objectoffsetrot = quat 1 ; obj.objectoffsetscale = [1,1,1]
mody = xform() ; addmodifier obj mody ; mody.gizmo.transform = old_ot ; mody.gizmo.position = offset ; obj.position = old_piv
Local extents=[0,0,0] ; extents.x=abs (obj.max.x-obj.min.x) ; extents.y=abs (obj.max.y-obj.min.y) ; extents.z=abs (obj.max.z-obj.min.z)
obj.pivot = [obj.min.x,obj.min.y,obj.min.z] + extents / 2
collapseStack obj
)
)
-- TIMER1 --
fn StartTimer1 = (format "Starting Timer\n" ; startTime1 = TimeStamp())
fn EndTimer1 timingof1 =(
endTime1 = TimeStamp()
local midNiteAdj, dt, dtMin, dtSec
midNiteAdj=if startTime1<endTime1 then 0 else 86400000 -- Handle midnite spanning.
dt=(endTime1-startTime1+midNiteAdj)/1000.
if dt>=60 then
( -- We are here if dt is one minute or more.
dtMin=(dt/60.) as integer
dtSec=(mod dt 60) as integer
) else ( dtMin=0 ; dtSec=dt ) -- Less than a Minute
-- RoundOffNumber off the seconds.
dtSec*=10^2 ; dtSec= (dtSec+0.5) as integer ; dtSec/=((10^2) as float)
format "% Timed at; % Min, % sec \n" timingof1 dtMin dtSec
)
-- TIMER2 -- For timing within another timed process
fn StartTimer2 = (format "Starting Timer2\n" ; startTime2 = TimeStamp())
fn EndTimer2 timingof2 =(
endTime2 = TimeStamp()
local midNiteAdj, dt, dtMin, dtSec
midNiteAdj=if startTime2<endTime2 then 0 else 86400000 -- Handle midnite spanning.
dt=(endTime2-startTime2+midNiteAdj)/1000.
if dt>=60 then
( -- We are here if dt is one minute or more.
dtMin=(dt/60.) as integer
dtSec=(mod dt 60) as integer
) else ( dtMin=0 ; dtSec=dt ) -- Less than a Minute
-- RoundOffNumber off the seconds.
dtSec*=10^2 ; dtSec= (dtSec+0.5) as integer ; dtSec/=((10^2) as float)
format "% Timed at; % Min, % sec \n" timingof2 dtMin dtSec
)
-- SCENE SETUP (MACHINE CONFIGURATION) --
function SceneSetup mode:"export"= (
if DEBUG then format "fn SceneSetup: %\n mode: %\n" MachineTypes[MachineType] mode
Global AAxis, BAxis, CAxis, ZeroPoint, Cutter
try (delete AAxis) catch() ;try (delete BAxis) catch() ; try (delete CAxis) catch()
try (delete $AAxis) catch() ;try (delete $BAxis) catch() ; try (delete $CAxis) catch()
CreateZeroPoint() ; CreateCutter()
case MachineTypes[MachineType] of
(
"XYZ" :()
"XYZA" :(CreateAAxis())
"XZA" :(CreateAAxis())
"XYZAB" :(
CreateAAxis();CreateBAxis()
BAxis.pos =[0,0,(ZeroPoint.pos.z + OffsetAroundBAxis)]
Cutter.pos = ZeroPoint.pos
if mode == "export" then
( -- Links For Export
BAxis.parent = Cutter
)
else
( -- Links for Import
Cutter.parent= BAxis
)
)
"XYZBC" :(CreateBAxis();CreateCAxis())
"XYZAC" :(
CreateAAxis();CreateCAxis()
AAxis.ObjectOffsetPos = [(-OffsetAroundCAxis + (OffsetAroundAAxis/200)),0,0]
AAxis.pos = ZeroPoint.pos + [0,0,OffsetAroundAAxis]
CAxis.ObjectOffsetRot = (quat 0 0 0 1)
CAxis.ObjectOffsetPos = [0,0,0]
CAxis.pos = ZeroPoint.pos + [-OffsetAroundCAxis,0,OffsetAroundAAxis]
Cutter.pos = ZeroPoint.pos
if mode == "export" then
( -- Links For Export
AAxis.parent = Cutter
CAxis.parent = AAxis; setInheritanceFlags CAxis #{1..3, 6..9}
)
else
( -- Links for Import
Cutter.parent= AAxis
AAxis.parent = CAxis
)
)
)
if DEBUG then format "Scene Now Setup\n"
)
function CreateZeroPoint =(
if DEBUG then format "fn CreateZeroPoint\n"
if IsValidNode $ZeroPoint then ZeroPointPos = $ZeroPoint.pos else ZeroPointPos = [0,0,0]
try (delete $ZeroPoint ) Catch()
ZeroPoint = Point pos:ZeroPointPos isSelected:off Box:off axistripod:on wirecolor:red centermarker:on size:50 constantscreensize:on drawontop:on name:"ZeroPoint"
)
function CreateCutter =(
if DEBUG then format "fn CreateCutter\n"
try (delete $Cutter) Catch()
if GMAX then Cutter = Cylinder fillet:1 wirecolor:black opacity:20 smooth:on heightsegs:1 capsegs:1 sides:6 height:OffsetAroundAaxis radius:(ToolDiameter/2) name:"Cutter"
else Cutter = ChamferCyl fillet:1 wirecolor:black opacity:20 smooth:on heightsegs:1 capsegs:1 sides:6 height:OffsetAroundAaxis radius:(ToolDiameter/2) name:"Cutter"
Cutter.dir = [0,0,1]
in coordsys local Cutter.rotation = quat -90 z_axis
)
function CreateAAxis =(
if DEBUG then format "fn CreateAAxis\n"
Local AxisSize = OffsetAroundAaxis
try (delete AAxis) Catch()
if IsValidNode AAxis then Position = AAxis.pos
AAxis = Tube smooth:on sides:22 wirecolor:red capsegs:1 heightsegs:1 radius1:AxisSize radius2:(AxisSize/1.1) height:(AxisSize/10) name:"A-Axis" material:AAxisMaterial
AAxisPointer = Cylinder smooth:off wirecolor:gray heightsegs:1 capsegs:1 sides:3 height:(AxisSize/9) radius:(AxisSize/9) material:PointerMaterial
AAxis.pos.x = AAxis.pos.x + (AxisSize/20)
AAxisPointer.pos.x = AAxis.pos.x + (AxisSize/1.05)
AAxisPointer.pos.z = AAxis.pos.z - (AxisSize/200)
convertToMesh AAxis
attach AAxis AAxisPointer
--AAxis.ObjectOffsetRot = quat 90 y_axis
AAxis.ObjectOffsetRot = quat -90 y_axis
)
function CreateBAxis =(
if DEBUG then format "fn CreateBAxis\n"
Local AxisSize = OffsetAroundBAxis
try (delete BAxis) Catch()
if IsValidNode BAxis then Position = BAxis.pos
BAxis = Tube smooth:on sides:22 wirecolor:green capsegs:1 heightsegs:1 radius1:AxisSize radius2:(AxisSize/1.1) height:(AxisSize/10) name:"B-Axis" material:BAxisMaterial
BAxisPointer = Cylinder smooth:off wirecolor:gray heightsegs:1 capsegs:1 sides:3 height:(AxisSize/9) radius:(AxisSize/9) material:PointerMaterial
BAxisPointer.pos.x = BAxis.pos.x + (AxisSize/1.05)
BAxisPointer.pos.z = BAxis.pos.z - (AxisSize/200)
convertToMesh BAxis
attach BAxis BAxisPointer
BAxis.ObjectOffsetRot = (quat 1 1 -1 -1)
)
function CreateCAxis =(
if DEBUG then format "fn CreateCAxis\n"
Local AxisSize = OffsetAroundCAxis
try (delete CAxis) Catch()
if IsValidNode CAxis then Position = CAxis.pos
CAxis = Tube smooth:on sides:22 wirecolor:blue capsegs:1 heightsegs:1 radius1:AxisSize radius2:(AxisSize/1.1) height:(AxisSize/10) name:"C-Axis" material:CAxisMaterial
CAxisPointer = Cylinder smooth:off wirecolor:gray heightsegs:1 capsegs:1 sides:3 height:(AxisSize/9) radius:(AxisSize/9) material:PointerMaterial
CAxisPointer.pos.x = CAxis.pos.x + (AxisSize/1.05)
CAxisPointer.pos.z = CAxis.pos.z - (AxisSize/200)
convertToMesh CAxis
attach CAxis CAxisPointer
CAxis.ObjectOffsetRot = (quat 0 0 1 1)
)
-- UTILITIES --
function MakeTextRing =(
text size:100 pos:[0,0,0] isSelected:on text:"CNC Toolkit"
rotate $ (angleaxis 90 [0,0,1])
modPanel.addModToSelection (Bend ()) ui:on
$.modifiers[#Bend].BendAngle = 360
$.modifiers[#Bend].BendAxis = 0
Local extents=[0,0,0] ; extents.x=abs ($.max.x-$.min.x) ; extents.y=abs ($.max.y-$.min.y) ; extents.z=abs ($.max.z-$.min.z)
MinPoint = [$.min.x,$.min.y,$.min.z] ; MaxPoint = [$.max.x,$.max.y,$.max.z]
center = MinPoint = [$.min.x,$.min.y,$.min.z] + extents / 2
$.pivot = center ; $.pos = [0,0,0] ; rotate $ (angleaxis -180 [1,0,0])
max tool zoomextents all
)
function SplineFromObjects =( -- Create a Spline from a Selection of Objects, useful for getting a toolpath from digitised points
NewShape = splineShape prefix: "Spline From Objects"
TmpSpline = addNewSpline NewShape
for obj in Selection do
(
pos = obj.pos
format "% \t %\n" obj.name pos
addKnot NewShape TmpSpline #corner #line pos
)
try (updateshape NewShape) catch()
select NewShape
)
function create_preview_toolpath = (
p=$
t = Point pos:[0,0,0] isSelected:off Box:off axistripod:on wirecolor:Blue centermarker:on size:tool_clearance constantscreensize:off drawontop:on name:"PreviewGizmo"
t.pos.controller=path follow:false
tool_control=t.pos.controller
tool_control.path=p
tool_control.constantVel = true
nk = numknots p 1
animationrange = (interval 1 nk)
animate on ( at time 0 tool_control.percent=0 at time 1000 tool_control.percent=100 )
sliderTime = 0f
playAnimation()
)
-- IMPORT --
function ImportRolandToolpath = ( -- Original script for importing the Roland File Format written by Doug McNabb
inFileName = getOpenFileName caption:"Select Roland ASCII File" types:"Roland Files (*.rol)|*.ROL|Text files (*.txt)|*.TXT|All Files (*.*)|*.*|"
( -- open specified file
inFile = openFile inFileName mode:"r"
if inFile == undefined then messagebox "There was an error opening the File!" title:"Roland file import" else
( -- Create the splineShape and add the spline
Imported_Spline = splineShape prefix: "Imported_Spline"
tmpSpline = addNewSpline Imported_Spline
while not eof inFile do --loop through the file until the end again...
( tmpChar = readchar inFile
case tmpChar of
( "Z" : ( -- "Z" starts the vertex data. -- read file until we have X, Y, and Z coordinates.
coords = "["
tmpChar = readchar inFile -- skip the "Z"
while tmpChar != ";" and tmpChar != "\n" and not eof inFile do
( -- TODO: add check. tmpChar must be either a number, a comma, or a space.
coords = coords + tmpChar
tmpChar = readchar inFile
)
coords = coords + "]"
thePoint3 = execute coords
addKnot Imported_Spline tmpSpline #corner #line thePoint3
) -- "Z"
) -- case
) -- while not eof
close inFile
updateShape Imported_Spline ; select Imported_Spline
) -- file open
) -- get filename
) -- import_toolpath
function ImportGCODE = (
if not IsValidNode ZeroPoint then (messageBox "You must have a valid Zero Point, re-run CNC Toolkit to create one." ; return 0)
inFileName = getOpenFileName caption:"Select G_Code File" types:"All Files (*.*)|*.*|TAP(*.tap)|*.tap|Text files (*.txt)|*.TXT|"
( inFile = openFile inFileName mode:"r"
if inFile == undefined then messagebox "There was an error opening the File!" title:"G_Code file import" else
(
Imported_Spline = splineShape prefix: inFileName
tmpSpline = addNewSpline Imported_Spline
Local coords = [0.0,0.0,0.0]
Local Movemade = false
while not eof inFile do
(
tmpChar = readchar inFile
--format " FilePos % \n" (filepos inFile); format ": % \n" tmpChar
case tmpChar of
(
"X" : ( coords.x = readnumber inFile; movemade=true)
"Y" : ( coords.y = readnumber inFile; movemade=true)
"Z" : ( coords.z = readnumber inFile; movemade=true)
"A" : ( Local ToolpathAngleA =readnumber inFile
-- format "Rotating % \n" angle -- try (updateShape Imported_Spline) catch()
Imported_Spline.rotation = quat ToolpathAngleA x_axis
movemade=true
)
/*
"B" : ( Local ToolpathAngleB =readnumber inFile
-- format "Rotating % \n" angle -- try (updateShape Imported_Spline) catch()
Imported_Spline.rotation = quat ToolpathAngleB x_axis
movemade=true
)
"C" : ( Local ToolpathAngleC =readnumber inFile
-- format "Rotating % \n" angle -- try (updateShape Imported_Spline) catch()
Imported_Spline.rotation = quat ToolpathAngleC x_axis
movemade=true
)
*/
"\n" : ( --format " End of Line \n"
if movemade==true then
(
addKnot Imported_Spline tmpSpline #smooth #line (coords + $ZeroPoint.pos)
--format "Knot % \n \n" (numKnots Imported_Spline)
--ToolAngle = addNewSpline Imported_Spline
--addKnot new_toolpath ToolAngle #corner #line coords
--addKnot new_toolpath ToolAngle #corner #line (coords *2)
--if (numKnots Imported_Spline) > 1 then updateShape Imported_Spline
)
Movemade = false
)
"(" : ( format " Comment \n" ; skipToNextLine inFile )
"*" : ( format " Comment \n" ; skipToNextLine inFile )
"G" : ( Local GCommand=readnumber inFile ; format "G% \n" GCommand )
"F" : ( Local Feedrate=readnumber inFile ; format "F% \n" Feedrate )
--"N": ( -- format "Line Number"
-- LineNumber = readvalue inFile -- seek inFile ( filepos inFile - 1 )
-- )
) -- case
)
) -- while not eof
)
close inFile
try (updateShape Imported_Spline) catch()
select Imported_Spline
)
function ImportPLC = (
if not IsValidNode ZeroPoint then (messageBox "You must have a valid Zero Point, re-run CNC Toolkit to create one." ; return 0)
inFileName = getOpenFileName caption:"Select G_Code File" types:"Text files (*.txt)|*.TXT|PLC(*.plc)|*.plc|All Files (*.*)|*.*|"
( inFile = openFile inFileName mode:"r"
if inFile == undefined then messagebox "There was an error opening the File!" title:"PLC file import" else
(
Imported_Spline = splineShape prefix: inFileName ; tmpSpline = addNewSpline Imported_Spline
Imported_Spline.baseobject.renderable=true ; Imported_Spline.material = ToolpathMaterial
Local coords = [0.0,0.0,0.0] ; Local MoveType = 1
while not eof inFile do
(--format " FilePos % \n" (filepos inFile)
tmpChar = readtext inFile ; --format "tmpChar: % \n" tmpChar
if (findstring tmpChar "Rapids") != undefined then
( format "Rapid \n"
MoveType = 3
)
if (findstring tmpChar "Toolpaths") != undefined then
( format "Toolpath \n"
MoveType = 1
)
if (findstring tmpChar "Line") != undefined then
(format "Line \n"
seek inFile ( filepos inFile - 1 )
coords.x = readnumber inFile ; readchar inFile
coords.y = readnumber inFile ; readchar inFile
coords.z = readnumber inFile
--format "coords %\n" coords
addKnot Imported_Spline tmpSpline #corner #line (coords + $ZeroPoint.pos)
if (numKnots Imported_Spline) > 1 then (setMaterialID Imported_Spline 1 (numsegments Imported_Spline 1) MoveType ; updateShape Imported_Spline )
)
)
)
)
close inFile
updateShape Imported_Spline; select Imported_Spline
)
function ImportCSV = (
inFileName = getOpenFileName caption:"Select Comma Delimited File" types:"CSV (*.csv)|*.CSV|Text files (*.txt)|*.TXT|All Files (*.*)|*.*|"
( -- open specified file
inFile = openFile inFileName mode:"r"
SplineName = inFileName as String
format "Importing %\n" inFileName
if inFile == undefined then messagebox "There was an error opening the File!" title:"CSV file import" else
( -- Create the splineShape and add the spline
Imported_Spline = splineShape name: SplineName
tmpSpline = addNewSpline Imported_Spline
while not eof inFile do --loop through the file until the end again...
(
tmpChar = ""
Character = true
tmpChar = readchar inFile
while Character == true and not eof inFile do
(
if findString "-.1234567890" tmpChar == undefined then
( Character = true ; tmpChar = readchar inFile )
else
(
Character = false
)
)
if not eof inFile do
(
seek inFile ( filepos inFile - 1 )
coords = readCSVnumber inFile
coords += $ZeroPoint.pos
addKnot Imported_Spline tmpSpline #corner #line coords
--addKnot Imported_Spline tmpSpline #smooth #curve coords
)
) -- while not eof
close inFile
updateShape Imported_Spline ; select Imported_Spline
) -- file open
) -- get filename
)
function ImportCSVMatrix = (
inFileName = getOpenFileName caption:"Select Comma Delimited File" types:"CSV (*.csv)|*.CSV|Text files (*.txt)|*.TXT|All Files (*.*)|*.*|"
( -- open specified file
inFile = openFile inFileName mode:"r"
SplineName = inFileName as String
format "Importing %\n" inFileName
if inFile == undefined then messagebox "There was an error opening the File!" title:"CSV file import" else
( -- Create the splineShape and add the spline
Imported_Spline = splineShape name: SplineName
-- tmpSpline = addNewSpline Imported_Spline
Local coords = [0.0,0.0,0.0]
Local Char = ""
Local IsANumber = false
Local EndOfLine = true
Local LineGoingRight = true
Local Cols = 0
Local Rows = 0
while not eof inFile do --loop through the file until the end again...
(
Local Char =""
Local IsANumber = false
Char= readchar inFile
format "Char % \n" Char
--seek inFile ( filepos inFile - 1 )
if Char == "\n" then
(format "EndOfLine %\n" EndOfLine
EndOfLine = true ; IsANumber = false
coords.y +=1 ; Rows += 1
if LineGoingRight == true then LineGoingRight = false else LineGoingRight = true
) else
(
seek inFile ( filepos inFile - 1 )
Local Number = readvalue inFile
IsANumber = true
format "Number: %\n" Number
)
if IsANumber == true then
(
if EndOfLine then (
tmpSpline = addNewSpline Imported_Spline
try ( updateShape Imported_Spline ) catch ()
)
--Local Number = execute (readDelimitedString inFile ",")
coords.z = Number
coords += $ZeroPoint.pos
addKnot Imported_Spline tmpSpline #corner #line coords
-- try ( updateShape Imported_Spline ) catch ()
-- addKnot Imported_Spline tmpSpline #smooth #curve coords
if LineGoingRight == true then coords.x += 1 else coords.x -= 1
Cols += 1
)
Local EndOfLine = false
)
close inFile
try ( updateShape Imported_Spline ) catch ()
select Imported_Spline
Cols = Cols / Rows
format "Cols:% Rows% \n" Cols Rows
) -- file open
) -- get filename
)
function ImportZMatrixToPlane = (
GC()
inFileName = getOpenFileName caption:"Select Comma Delimited File" types:"CSV (*.csv)|*.CSV|Text files (*.txt)|*.TXT|All Files (*.*)|*.*|"
( -- open specified file
inFile = openFile inFileName mode:"r"
SplineName = inFileName as String
format "Importing %\n" inFileName
if inFile == undefined then messagebox "There was an error opening the File!" title:"CSV file import" else
( -- Create the splineShape and add the spline
-- Imported_Spline = splineShape name: SplineName
-- tmpSpline = addNewSpline Imported_Spline
Local coords = [0.0,0.0,0.0]
Local LineGoingRight = true
Local Cols = 0
Local Rows = 0
Local EndOfLine = true
Local Numbers = 0
while not eof inFile do --loop through the file until the end again...
(
if EndOfLine then
(
-- tmpSpline = addNewSpline Imported_Spline
-- try ( updateShape Imported_Spline ) catch ()
) Local EndOfLine = false
Local IsANumber = false
Local Char = readchar inFile
if findString "-.1234567890E+" Char != undefined then IsANumber = true ; --format "IsANumber %\n" IsANumber
if Char == "\n" then
(--format "EndOfLine %\n" EndOfLine
EndOfLine = true
coords.y +=1
Rows += 1
coords.x = 0
if LineGoingRight == true then LineGoingRight = false else LineGoingRight = true
)
if IsANumber == true then
(
Numbers += 1
seek inFile ( filepos inFile - 1 )
--Local Number = execute (readDelimitedString inFile ",")
Local Number = readnumber inFile
coords.z = Number
coords += $ZeroPoint.pos
-- addKnot Imported_Spline tmpSpline #corner #line coords
--addKnot Imported_Spline tmpSpline #smooth #curve coords
--if LineGoingRight == true then coords.x += 1 else coords.x -= 1
coords.x += 1
Cols += 1
)
)
try ( updateShape Imported_Spline ) catch ()
--select Imported_Spline
Cols = Cols / Rows
format "Cols:% Rows:% Rows*Cols:% Numbers:% \n" Cols Rows (Rows * Cols) Numbers
seek inFile 0
ThePlane = Plane realWorldMapSize:off length:(Rows - 1) width:(Cols - 1) lengthsegs:(Rows - 1) widthsegs:(Cols - 1) pos:[((Cols - 1) /2.0),((Rows - 1)/2.0),0]
ConvertToMesh ThePlane
Local n = 1
while not eof inFile do --loop through the file until the end again...
(
coords = getVert ThePlane n
coords.z = readvalue infile
coords += $ZeroPoint.pos
SetVert ThePlane n coords
n += 1
)
close inFile
format "n: %\n" n
) -- file open
) -- get filename
)
-- CREATE TOOLPATHS --
function MakeDrillCycleToolPath =(
Local PeckCycles = DrillDepth / PeckDepth as integer
Global new_toolpath = splineShape prefix: ("Toolpath_" + ($selection[1].name as string))
Global ToolPosition = addNewSpline new_toolpath
new_toolpath.baseobject.renderable=true ; new_toolpath.material = ToolpathMaterial
AppendToolpath ZeroPoint.pos "Start/End"
for obj in Selection do
(
Local pos = obj.pos
Local dir = obj.dir
format "\npos: % \t dir: %\n" pos dir
AppendToolpath pos "Position+Clearance"
setMaterialID new_toolpath 1 (numsegments new_toolpath 1) 3 -- Rapid
for i = 1 to PeckCycles do
(
pos.z = -i * PeckDepth
AppendToolpath pos "Plunge/Dwell"
setMaterialID new_toolpath 1 (numsegments new_toolpath 1) 6 -- Plunge
AppendToolpath obj.pos "Position+Clearance"
setMaterialID new_toolpath 1 (numsegments new_toolpath 1) 2 -- Retract
)
if pos.z != DrillDepth then
(
pos.z = - DrillDepth
AppendToolpath pos "Plunge/Dwell"
setMaterialID new_toolpath 1 (numsegments new_toolpath 1) 6 -- Plunge
AppendToolpath obj.pos "Position+Clearance"
setMaterialID new_toolpath 1 (numsegments new_toolpath 1) 2 -- Retract
)
)
AppendToolpath ZeroPoint.pos "Start/End"
setMaterialID new_toolpath 1 (numsegments new_toolpath 1) 3 -- Rapid
updateshape new_toolpath; select new_toolpath
)
function MakeParallelSplines mode Stepover x y r =(
Global pos = [0,0,0]
new_toolpath = splineShape prefix: "Parallel_Lines"
tmpSpline = addNewSpline new_toolpath
case mode of
(
1: -- X Horizontal
( ysteps = (y / (2* Stepover)) + 1
xsteps = (x / (Stepover)) + .5
for ystep = 1 to ysteps do
(
if pos.y <= y then
(
addKnot new_toolpath tmpSpline #corner #line pos
for xstep = 1 to xsteps do addKnot new_toolpath tmpSpline #corner #line (pos += [stepover,0,0])
)
if pos.y + Stepover <= y then
(
addKnot new_toolpath tmpSpline #corner #line (pos += [0,stepover,0])
for xstep = 1 to xsteps do addKnot new_toolpath tmpSpline #corner #line (pos -= [stepover,0,0])
)
pos += [0,stepover,0]
)
)
2: -- Y Horizontal
( xsteps = (x / (2* Stepover)) + 1
ysteps = (y / (Stepover)) + .5
for xstep = 1 to xsteps do
(
if pos.x <= x then
(
addKnot new_toolpath tmpSpline #corner #line pos
for ystep = 1 to ysteps do addKnot new_toolpath tmpSpline #corner #line (pos += [0,stepover,0])
)
if pos.x + Stepover <= x then
(
addKnot new_toolpath tmpSpline #corner #line (pos += [stepover,0,0])
for ystep = 1 to ysteps do addKnot new_toolpath tmpSpline #corner #line (pos -= [0,stepover,0])
)
pos += [stepover,0,0]
)
)
3: -- Spiral
( new_toolpath = Helix radius1:0 radius2:r height:0 turns:(r/Stepover) bias:0 direction:0 pos:[0,0,0] isSelected:on
)
4: -- Radial (Rotary)
( MakeParallelSplines 1 Stepover x (2* pi * r) r
modPanel.addModToSelection (Bend ()) ui:on
$.modifiers[#Bend].BendAngle = 360
$.modifiers[#Bend].BendAxis = 0
$.modifiers[#Bend].BendDir = 90
$.modifiers[#Bend].BendAxis = 1
Converttosplineshape $
local extents=[0,0,0]
--extents.x=abs ($.max.x-$.min.x)
extents.y=abs ($.max.y-$.min.y)
extents.z=abs ($.max.z-$.min.z)
MinPoint = [$.min.x,$.min.y,$.min.z]
MaxPoint = [$.max.x,$.max.y,$.max.z]
center = [$.min.x,$.min.y,$.min.z] + extents / 2
$.pivot = center
$.pos = [0,0,0]
$.dir = [0,0,-1]
)
5: -- Helix (Rotary)
( new_toolpath = Helix radius1:r radius2:r height:x turns:(x/Stepover) bias:0 direction:0 pos:[0,0,0] isSelected:on
new_toolpath.dir = [1,0,0]
)
)
try (updateshape new_toolpath) catch()
select new_toolpath
)
function MakeToolpath =(
if $ == undefined then (messageBox "Select Splines / Shapes to Convert to a Toolpath" ; return 0)
if not IsValidNode ZeroPoint then (messageBox "You must have a valid Zero Point, re-run CNC Toolkit to create one." ; return 0)
if DEBUG then format "MakeToolpath\nVectorCalcMethod: %\n" VectorCalcMethod
Global new_toolpath = splineShape prefix: ("Toolpath:" + ($selection[1].name as string))
new_toolpath.baseobject.renderable=true ; new_toolpath.material = ToolpathMaterial ; new_toolpath.DisplayRenderMesh=false
Global ToolPosition = addNewSpline new_toolpath
Global ToolAngles = #(), ThisKnifeAngle, LastKnifeAngle = [0,0,0] , LastPoint , LastOffsetPoint = [0,0,0]
TargetDepth = CutDepth
if VectorCalcMethods[VectorCalcMethod] == "Angle from Reference Surface" or VectorCalcMethods[VectorCalcMethod] == "Tangent to Surface" then
( if not IsValidNode ReferenceMesh then ( messagebox "Pick Reference Surface from Vector Calculations Menu" ; return 0)
tempReferenceMesh = copy ReferenceMesh ; ConvertToMesh tempReferenceMesh
Global VertexArray= #() ; VertexArray[tempReferenceMesh.numVerts] = undefined
VertexArray = for i = 1 to VertexArray.count collect (GetVert tempReferenceMesh i)
)
AppendToolpath ZeroPoint.pos "Start/End"
if MakeVectors then setMaterialID new_toolpath ToolAngle 1 5 -- Vector
for ShapeInSelection in Selection as Array do -- Number of shapes loop
(
for Pass = 1.0 to MultiPasses do
( CutDepth = (Pass / MultiPasses) * TargetDepth ; if DEBUG then format "CutDepth: %\n" CutDepth
if DEBUG then Format "Processing % \n" ShapeInSelection
if SuperClassOf ShapeInSelection == SHAPE then
( ShapeToProcess = Copy ShapeInSelection
Convertto ShapeToProcess splineshape
ResetXforms
if DEBUG then format "ShapeToProcess: %\n" ShapeToProcess
if pre_subdivide then Subdivide_Shape ShapeToProcess
for pns = 1 to numsplines ShapeToProcess do -- Number of splines loop
(
nk = numknots ShapeToProcess pns
for pnk = 1 to nk do -- Number of knots loop
(k = getknotpoint ShapeToProcess pns pnk
if ToolOffset != 0 then -- Use for Drag Knife Cutting
(--format "\nKnot: %\n" pnk
if pnk == 1 then ThisKnifeAngle = normalize (k-(getknotpoint ShapeToProcess pns (pnk + 1))) else ThisKnifeAngle = normalize (k - LastPoint) -- format "ThisKnifeAngle: %\n" ThisKnifeAngle
KnifeAngleDelta = dot ThisKnifeAngle LastKnifeAngle -- format "KnifeAngleDelta: % \n" KnifeAngleDelta
KnifeAngleDelta = 180 - (abs (acos KnifeAngleDelta)) -- format "KnifeAngleDelta: % \n" KnifeAngleDelta
if abs KnifeAngleDelta < 0 then
(--format "Big Angle\n"
kk = (LastOffsetPoint + ( ToolOffset * (normalize(rotatez (MatrixFromNormal ThisKnifeAngle) -135).row3)))
AppendToolpath kk "Position" ; LastOffsetPoint = kk
kk = (LastOffsetPoint + ( ToolOffset * (normalize(rotatez (MatrixFromNormal ThisKnifeAngle) -225).row3)))
AppendToolpath kk "Position" ; LastOffsetPoint = kk
kk = (LastOffsetPoint + ( ToolOffset * (normalize(rotatez (MatrixFromNormal ThisKnifeAngle) -315).row3)))
AppendToolpath kk "Position" ; LastOffsetPoint = kk
-- kk = (LastOffsetPoint + ( ToolOffset * (normalize(rotatez (MatrixFromNormal ThisKnifeAngle) -405).row3)))
-- AppendToolpath kk "Position" ; LastOffsetPoint = kk
)
LastPoint = k ; k = k + ( ToolOffset * ThisKnifeAngle )
)
if pnk == 1 then --Plunge -- if first knot then first raise tool to tool_clearance
(--format "Toolangle %\n" toolangle
AppendToolpath k "Position+Clearance"
if MakeVectors then setMaterialID new_toolpath ToolAngle 1 5 -- Vector
setMaterialID new_toolpath 1 (numsegments new_toolpath 1) 3 -- Rapid
AppendToolpath k "Plunge"
if MakeVectors then setMaterialID new_toolpath ToolAngle 1 5 -- Vector
setMaterialID new_toolpath 1 (numsegments new_toolpath 1) 4 -- Plunge
)
else -- for all other knots between first and last
(
AppendToolpath k "Position" --Standard knot
if MakeVectors then setMaterialID new_toolpath ToolAngle 1 5 -- Vector
setMaterialID new_toolpath 1 (numsegments new_toolpath 1) 1 -- Feedmove
)
if pnk == nk then --Retract -- If last knot --
(
if (isclosed ShapeToProcess pns) then pnk = 1 -- If shape is closed then go back to first knot to finish shape
k = getknotpoint ShapeToProcess pns pnk
if ToolOffset != 0 then
(
ThisKnifeAngle = normalize (k - LastPoint)
LastPoint = k
k = k + ( ToolOffset * ThisKnifeAngle )