diff --git a/20cube_export.gcode b/20cube_export.gcode
new file mode 100644
index 000000000..a3cb5f4bc
--- /dev/null
+++ b/20cube_export.gcode
@@ -0,0 +1,3075 @@
+G90
+G21
+G92 E0
+; S70.0
+; S45.0
+G1 X86.7 Y113.3 Z0.2 F18300.0
+G1 F900.0
+G1 E1.0
+G1 F18300.0
+G92 E0
+G1 X111.167 Y113.3 Z0.2 F2700.0 E0.8012
+G1 X113.3 Y111.167 Z0.2 F2700.0 E0.9
+G1 X113.3 Y86.7 Z0.2 F2700.0 E1.7011
+G1 X86.7 Y86.7 Z0.2 F2700.0 E2.5722
+G1 X86.7 Y113.3 Z0.2 F2700.0 E3.4432
+G1 F900.0
+G1 E2.4432
+G1 F2700.0
+; S70.0
+; S45.0
+G1 X90.643 Y90.3 Z0.2 F19800.0
+G1 F900.0
+G1 E3.4432
+G1 F19800.0
+G92 E0
+G1 X109.7 Y90.3 Z0.2 F2700.0 E0.624
+G1 X109.7 Y109.7 Z0.2 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z0.2 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z0.2 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z0.2 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z0.2 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z0.2 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z0.2 F4200.0 E4.334
+G1 X90.857 Y91.201 Z0.2 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z0.2 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z0.2 F4200.0 E0.0013
+G1 X108.739 Y92.015 Z0.2 F4200.0 E0.0251
+G1 X107.985 Y91.261 Z0.2 F4200.0 E0.06
+G1 X107.258 Y91.261 Z0.2 F4200.0 E0.0838
+G1 X108.739 Y92.742 Z0.2 F4200.0 E0.1524
+G1 X108.739 Y93.469 Z0.2 F4200.0 E0.1762
+G1 X106.531 Y91.261 Z0.2 F4200.0 E0.2785
+G1 X105.803 Y91.261 Z0.2 F4200.0 E0.3023
+G1 X108.739 Y94.197 Z0.2 F4200.0 E0.4382
+G1 X108.739 Y94.924 Z0.2 F4200.0 E0.462
+G1 X105.076 Y91.261 Z0.2 F4200.0 E0.6317
+G1 X104.349 Y91.261 Z0.2 F4200.0 E0.6555
+G1 X108.739 Y95.651 Z0.2 F4200.0 E0.8588
+G1 X108.739 Y96.378 Z0.2 F4200.0 E0.8826
+G1 X103.622 Y91.261 Z0.2 F4200.0 E1.1195
+G1 X102.895 Y91.261 Z0.2 F4200.0 E1.1433
+G1 X108.739 Y97.105 Z0.2 F4200.0 E1.414
+G1 X108.739 Y97.832 Z0.2 F4200.0 E1.4378
+G1 X102.168 Y91.261 Z0.2 F4200.0 E1.7421
+G1 X101.441 Y91.261 Z0.2 F4200.0 E1.7659
+G1 X108.739 Y98.559 Z0.2 F4200.0 E2.1039
+G1 X108.739 Y99.286 Z0.2 F4200.0 E2.1277
+G1 X100.714 Y91.261 Z0.2 F4200.0 E2.4994
+G1 X99.987 Y91.261 Z0.2 F4200.0 E2.5232
+G1 X108.739 Y100.013 Z0.2 F4200.0 E2.9285
+G1 X108.739 Y100.741 Z0.2 F4200.0 E2.9523
+G1 X99.259 Y91.261 Z0.2 F4200.0 E3.3913
+G1 X98.532 Y91.261 Z0.2 F4200.0 E3.4151
+G1 X108.739 Y101.468 Z0.2 F4200.0 E3.8878
+G1 X108.739 Y102.195 Z0.2 F4200.0 E3.9116
+G1 X97.805 Y91.261 Z0.2 F4200.0 E4.4179
+G1 X97.078 Y91.261 Z0.2 F4200.0 E4.4417
+G1 X108.739 Y102.922 Z0.2 F4200.0 E4.9818
+G1 X108.739 Y103.649 Z0.2 F4200.0 E5.0056
+G1 X96.351 Y91.261 Z0.2 F4200.0 E5.5793
+G1 X95.624 Y91.261 Z0.2 F4200.0 E5.6031
+G1 X108.739 Y104.376 Z0.2 F4200.0 E6.2104
+G1 X108.739 Y105.103 Z0.2 F4200.0 E6.2342
+G1 X94.897 Y91.261 Z0.2 F4200.0 E6.8753
+G1 X94.169 Y91.261 Z0.2 F4200.0 E6.8991
+G1 X108.739 Y105.831 Z0.2 F4200.0 E7.5738
+G1 X108.739 Y106.558 Z0.2 F4200.0 E7.5976
+G1 X93.442 Y91.261 Z0.2 F4200.0 E8.306
+G1 X92.715 Y91.261 Z0.2 F4200.0 E8.3298
+G1 X108.739 Y107.285 Z0.2 F4200.0 E9.0719
+G1 X108.739 Y108.012 Z0.2 F4200.0 E9.0957
+G1 X91.988 Y91.261 Z0.2 F4200.0 E9.8714
+G1 X91.261 Y91.261 Z0.2 F4200.0 E9.8952
+G1 X108.739 Y108.739 Z0.2 F4200.0 E10.7046
+G1 X108.012 Y108.739 Z0.2 F4200.0 E10.7284
+G1 X91.261 Y91.988 Z0.2 F4200.0 E11.5041
+G1 X91.261 Y92.715 Z0.2 F4200.0 E11.528
+G1 X107.285 Y108.739 Z0.2 F4200.0 E12.27
+G1 X106.558 Y108.739 Z0.2 F4200.0 E12.2938
+G1 X91.261 Y93.442 Z0.2 F4200.0 E13.0022
+G1 X91.261 Y94.169 Z0.2 F4200.0 E13.026
+G1 X105.831 Y108.739 Z0.2 F4200.0 E13.7007
+G1 X105.103 Y108.739 Z0.2 F4200.0 E13.7245
+G1 X91.261 Y94.897 Z0.2 F4200.0 E14.3656
+G1 X91.261 Y95.624 Z0.2 F4200.0 E14.3894
+G1 X104.376 Y108.739 Z0.2 F4200.0 E14.9967
+G1 X103.649 Y108.739 Z0.2 F4200.0 E15.0205
+G1 X91.261 Y96.351 Z0.2 F4200.0 E15.5942
+G1 X91.261 Y97.078 Z0.2 F4200.0 E15.618
+G1 X102.922 Y108.739 Z0.2 F4200.0 E16.1581
+G1 X102.195 Y108.739 Z0.2 F4200.0 E16.1819
+G1 X91.261 Y97.805 Z0.2 F4200.0 E16.6882
+G1 X91.261 Y98.532 Z0.2 F4200.0 E16.712
+G1 X101.468 Y108.739 Z0.2 F4200.0 E17.1847
+G1 X100.741 Y108.739 Z0.2 F4200.0 E17.2085
+G1 X91.261 Y99.259 Z0.2 F4200.0 E17.6475
+G1 X91.261 Y99.987 Z0.2 F4200.0 E17.6713
+G1 X100.013 Y108.739 Z0.2 F4200.0 E18.0767
+G1 X99.286 Y108.739 Z0.2 F4200.0 E18.1005
+G1 X91.261 Y100.714 Z0.2 F4200.0 E18.4721
+G1 X91.261 Y101.441 Z0.2 F4200.0 E18.4959
+G1 X98.559 Y108.739 Z0.2 F4200.0 E18.8339
+G1 X97.832 Y108.739 Z0.2 F4200.0 E18.8577
+G1 X91.261 Y102.168 Z0.2 F4200.0 E19.162
+G1 X91.261 Y102.895 Z0.2 F4200.0 E19.1858
+G1 X97.105 Y108.739 Z0.2 F4200.0 E19.4565
+G1 X96.378 Y108.739 Z0.2 F4200.0 E19.4803
+G1 X91.261 Y103.622 Z0.2 F4200.0 E19.7172
+G1 X91.261 Y104.349 Z0.2 F4200.0 E19.7411
+G1 X95.651 Y108.739 Z0.2 F4200.0 E19.9443
+G1 X94.924 Y108.739 Z0.2 F4200.0 E19.9682
+G1 X91.261 Y105.076 Z0.2 F4200.0 E20.1378
+G1 X91.261 Y105.803 Z0.2 F4200.0 E20.1616
+G1 X94.197 Y108.739 Z0.2 F4200.0 E20.2975
+G1 X93.469 Y108.739 Z0.2 F4200.0 E20.3213
+G1 X91.261 Y106.531 Z0.2 F4200.0 E20.4236
+G1 X91.261 Y107.258 Z0.2 F4200.0 E20.4474
+G1 X92.742 Y108.739 Z0.2 F4200.0 E20.516
+G1 X92.015 Y108.739 Z0.2 F4200.0 E20.5398
+G1 X91.261 Y107.985 Z0.2 F4200.0 E20.5748
+G1 X91.261 Y108.712 Z0.2 F4200.0 E20.5986
+G1 X91.288 Y108.739 Z0.2 F4200.0 E20.5998
+G1 F900.0
+G1 E19.5998
+G1 F4200.0
+; S45.0
+G1 X86.7 Y113.3 Z0.6 F3402.8568
+G1 F900.0
+G1 E20.5998
+G1 F3402.8568
+G92 E0
+G1 X111.167 Y113.3 Z0.6 F2700.0 E0.8012
+G1 X113.3 Y111.167 Z0.6 F2700.0 E0.9
+G1 X113.3 Y86.7 Z0.6 F2700.0 E1.7011
+G1 X86.7 Y86.7 Z0.6 F2700.0 E2.5722
+G1 X86.7 Y113.3 Z0.6 F2700.0 E3.4432
+G1 F900.0
+G1 E2.4432
+G1 F2700.0
+; S70.0
+; S45.0
+G1 X90.643 Y90.3 Z0.6 F19800.0
+G1 F900.0
+G1 E3.4432
+G1 F19800.0
+G92 E0
+G1 X109.7 Y90.3 Z0.6 F2700.0 E0.624
+G1 X109.7 Y109.7 Z0.6 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z0.6 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z0.6 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z0.6 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z0.6 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z0.6 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z0.6 F4200.0 E4.334
+G1 X90.857 Y91.201 Z0.6 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z0.6 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z0.6 F4200.0 E0.0013
+G1 X107.985 Y108.739 Z0.6 F4200.0 E0.0251
+G1 X108.739 Y107.985 Z0.6 F4200.0 E0.06
+G1 X108.739 Y107.258 Z0.6 F4200.0 E0.0838
+G1 X107.258 Y108.739 Z0.6 F4200.0 E0.1524
+G1 X106.531 Y108.739 Z0.6 F4200.0 E0.1762
+G1 X108.739 Y106.531 Z0.6 F4200.0 E0.2785
+G1 X108.739 Y105.803 Z0.6 F4200.0 E0.3023
+G1 X105.803 Y108.739 Z0.6 F4200.0 E0.4382
+G1 X105.076 Y108.739 Z0.6 F4200.0 E0.462
+G1 X108.739 Y105.076 Z0.6 F4200.0 E0.6317
+G1 X108.739 Y104.349 Z0.6 F4200.0 E0.6555
+G1 X104.349 Y108.739 Z0.6 F4200.0 E0.8588
+G1 X103.622 Y108.739 Z0.6 F4200.0 E0.8826
+G1 X108.739 Y103.622 Z0.6 F4200.0 E1.1195
+G1 X108.739 Y102.895 Z0.6 F4200.0 E1.1433
+G1 X102.895 Y108.739 Z0.6 F4200.0 E1.414
+G1 X102.168 Y108.739 Z0.6 F4200.0 E1.4378
+G1 X108.739 Y102.168 Z0.6 F4200.0 E1.7421
+G1 X108.739 Y101.441 Z0.6 F4200.0 E1.7659
+G1 X101.441 Y108.739 Z0.6 F4200.0 E2.1039
+G1 X100.714 Y108.739 Z0.6 F4200.0 E2.1277
+G1 X108.739 Y100.714 Z0.6 F4200.0 E2.4994
+G1 X108.739 Y99.987 Z0.6 F4200.0 E2.5232
+G1 X99.987 Y108.739 Z0.6 F4200.0 E2.9285
+G1 X99.259 Y108.739 Z0.6 F4200.0 E2.9523
+G1 X108.739 Y99.259 Z0.6 F4200.0 E3.3913
+G1 X108.739 Y98.532 Z0.6 F4200.0 E3.4151
+G1 X98.532 Y108.739 Z0.6 F4200.0 E3.8878
+G1 X97.805 Y108.739 Z0.6 F4200.0 E3.9116
+G1 X108.739 Y97.805 Z0.6 F4200.0 E4.4179
+G1 X108.739 Y97.078 Z0.6 F4200.0 E4.4417
+G1 X97.078 Y108.739 Z0.6 F4200.0 E4.9818
+G1 X96.351 Y108.739 Z0.6 F4200.0 E5.0056
+G1 X108.739 Y96.351 Z0.6 F4200.0 E5.5793
+G1 X108.739 Y95.624 Z0.6 F4200.0 E5.6031
+G1 X95.624 Y108.739 Z0.6 F4200.0 E6.2104
+G1 X94.897 Y108.739 Z0.6 F4200.0 E6.2342
+G1 X108.739 Y94.897 Z0.6 F4200.0 E6.8753
+G1 X108.739 Y94.169 Z0.6 F4200.0 E6.8991
+G1 X94.169 Y108.739 Z0.6 F4200.0 E7.5738
+G1 X93.442 Y108.739 Z0.6 F4200.0 E7.5976
+G1 X108.739 Y93.442 Z0.6 F4200.0 E8.306
+G1 X108.739 Y92.715 Z0.6 F4200.0 E8.3298
+G1 X92.715 Y108.739 Z0.6 F4200.0 E9.0719
+G1 X91.988 Y108.739 Z0.6 F4200.0 E9.0957
+G1 X108.739 Y91.988 Z0.6 F4200.0 E9.8714
+G1 X108.739 Y91.261 Z0.6 F4200.0 E9.8952
+G1 X91.261 Y108.739 Z0.6 F4200.0 E10.7046
+G1 X91.261 Y108.012 Z0.6 F4200.0 E10.7284
+G1 X108.012 Y91.261 Z0.6 F4200.0 E11.5041
+G1 X107.285 Y91.261 Z0.6 F4200.0 E11.528
+G1 X91.261 Y107.285 Z0.6 F4200.0 E12.27
+G1 X91.261 Y106.558 Z0.6 F4200.0 E12.2938
+G1 X106.558 Y91.261 Z0.6 F4200.0 E13.0022
+G1 X105.831 Y91.261 Z0.6 F4200.0 E13.026
+G1 X91.261 Y105.831 Z0.6 F4200.0 E13.7007
+G1 X91.261 Y105.103 Z0.6 F4200.0 E13.7245
+G1 X105.103 Y91.261 Z0.6 F4200.0 E14.3656
+G1 X104.376 Y91.261 Z0.6 F4200.0 E14.3894
+G1 X91.261 Y104.376 Z0.6 F4200.0 E14.9967
+G1 X91.261 Y103.649 Z0.6 F4200.0 E15.0205
+G1 X103.649 Y91.261 Z0.6 F4200.0 E15.5942
+G1 X102.922 Y91.261 Z0.6 F4200.0 E15.618
+G1 X91.261 Y102.922 Z0.6 F4200.0 E16.1581
+G1 X91.261 Y102.195 Z0.6 F4200.0 E16.1819
+G1 X102.195 Y91.261 Z0.6 F4200.0 E16.6882
+G1 X101.468 Y91.261 Z0.6 F4200.0 E16.712
+G1 X91.261 Y101.468 Z0.6 F4200.0 E17.1847
+G1 X91.261 Y100.741 Z0.6 F4200.0 E17.2085
+G1 X100.741 Y91.261 Z0.6 F4200.0 E17.6475
+G1 X100.013 Y91.261 Z0.6 F4200.0 E17.6713
+G1 X91.261 Y100.013 Z0.6 F4200.0 E18.0767
+G1 X91.261 Y99.286 Z0.6 F4200.0 E18.1005
+G1 X99.286 Y91.261 Z0.6 F4200.0 E18.4721
+G1 X98.559 Y91.261 Z0.6 F4200.0 E18.4959
+G1 X91.261 Y98.559 Z0.6 F4200.0 E18.8339
+G1 X91.261 Y97.832 Z0.6 F4200.0 E18.8577
+G1 X97.832 Y91.261 Z0.6 F4200.0 E19.162
+G1 X97.105 Y91.261 Z0.6 F4200.0 E19.1858
+G1 X91.261 Y97.105 Z0.6 F4200.0 E19.4565
+G1 X91.261 Y96.378 Z0.6 F4200.0 E19.4803
+G1 X96.378 Y91.261 Z0.6 F4200.0 E19.7172
+G1 X95.651 Y91.261 Z0.6 F4200.0 E19.7411
+G1 X91.261 Y95.651 Z0.6 F4200.0 E19.9443
+G1 X91.261 Y94.924 Z0.6 F4200.0 E19.9682
+G1 X94.924 Y91.261 Z0.6 F4200.0 E20.1378
+G1 X94.197 Y91.261 Z0.6 F4200.0 E20.1616
+G1 X91.261 Y94.197 Z0.6 F4200.0 E20.2975
+G1 X91.261 Y93.469 Z0.6 F4200.0 E20.3213
+G1 X93.469 Y91.261 Z0.6 F4200.0 E20.4236
+G1 X92.742 Y91.261 Z0.6 F4200.0 E20.4474
+G1 X91.261 Y92.742 Z0.6 F4200.0 E20.516
+G1 X91.261 Y92.015 Z0.6 F4200.0 E20.5398
+G1 X92.015 Y91.261 Z0.6 F4200.0 E20.5748
+G1 X91.288 Y91.261 Z0.6 F4200.0 E20.5986
+G1 X91.261 Y91.288 Z0.6 F4200.0 E20.5998
+G1 F900.0
+G1 E19.5998
+G1 F4200.0
+; S45.0
+G1 X86.7 Y113.3 Z1.0 F11803.6295
+G1 F900.0
+G1 E20.5998
+G1 F11803.6295
+G92 E0
+G1 X111.167 Y113.3 Z1.0 F2700.0 E0.8012
+G1 X113.3 Y111.167 Z1.0 F2700.0 E0.9
+G1 X113.3 Y86.7 Z1.0 F2700.0 E1.7011
+G1 X86.7 Y86.7 Z1.0 F2700.0 E2.5722
+G1 X86.7 Y113.3 Z1.0 F2700.0 E3.4432
+G1 F900.0
+G1 E2.4432
+G1 F2700.0
+; S70.0
+; S45.0
+G1 X90.643 Y90.3 Z1.0 F19800.0
+G1 F900.0
+G1 E3.4432
+G1 F19800.0
+G92 E0
+G1 X109.7 Y90.3 Z1.0 F2700.0 E0.624
+G1 X109.7 Y109.7 Z1.0 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z1.0 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z1.0 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z1.0 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z1.0 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z1.0 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z1.0 F4200.0 E4.334
+G1 X90.857 Y91.201 Z1.0 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z1.0 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z1.0 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z1.0 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z1.0 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z1.0 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z1.0 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z1.0 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z1.0 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z1.0 F4200.0 E1.28
+G1 X108.739 Y100.741 Z1.0 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z1.0 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z1.0 F4200.0 E2.565
+G1 X91.261 Y91.261 Z1.0 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z1.0 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z1.0 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z1.0 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z1.0 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z1.0 F4200.0 E4.383
+G1 X91.261 Y99.259 Z1.0 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z1.0 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z1.0 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z1.0 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z1.0 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z1.0 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z1.0 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z1.0 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z1.0 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z1.0 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z1.0 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z1.4 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z1.4 F2700.0 E0.624
+G1 X109.7 Y109.7 Z1.4 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z1.4 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z1.4 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z1.4 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z1.4 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z1.4 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z1.4 F4200.0 E4.334
+G1 X90.857 Y91.201 Z1.4 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z1.4 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z1.4 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z1.4 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z1.4 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z1.4 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z1.4 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z1.4 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z1.4 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z1.4 F4200.0 E1.28
+G1 X99.259 Y108.739 Z1.4 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z1.4 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z1.4 F4200.0 E2.565
+G1 X108.739 Y91.261 Z1.4 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z1.4 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z1.4 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z1.4 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z1.4 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z1.4 F4200.0 E4.383
+G1 X100.741 Y91.261 Z1.4 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z1.4 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z1.4 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z1.4 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z1.4 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z1.4 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z1.4 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z1.4 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z1.4 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z1.4 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z1.4 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z1.8 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z1.8 F2700.0 E0.624
+G1 X109.7 Y109.7 Z1.8 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z1.8 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z1.8 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z1.8 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z1.8 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z1.8 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z1.8 F4200.0 E4.334
+G1 X90.857 Y91.201 Z1.8 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z1.8 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z1.8 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z1.8 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z1.8 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z1.8 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z1.8 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z1.8 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z1.8 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z1.8 F4200.0 E1.28
+G1 X108.739 Y100.741 Z1.8 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z1.8 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z1.8 F4200.0 E2.565
+G1 X91.261 Y91.261 Z1.8 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z1.8 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z1.8 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z1.8 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z1.8 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z1.8 F4200.0 E4.383
+G1 X91.261 Y99.259 Z1.8 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z1.8 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z1.8 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z1.8 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z1.8 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z1.8 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z1.8 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z1.8 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z1.8 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z1.8 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z1.8 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z2.2 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z2.2 F2700.0 E0.624
+G1 X109.7 Y109.7 Z2.2 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z2.2 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z2.2 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z2.2 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z2.2 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z2.2 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z2.2 F4200.0 E4.334
+G1 X90.857 Y91.201 Z2.2 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z2.2 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z2.2 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z2.2 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z2.2 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z2.2 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z2.2 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z2.2 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z2.2 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z2.2 F4200.0 E1.28
+G1 X99.259 Y108.739 Z2.2 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z2.2 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z2.2 F4200.0 E2.565
+G1 X108.739 Y91.261 Z2.2 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z2.2 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z2.2 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z2.2 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z2.2 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z2.2 F4200.0 E4.383
+G1 X100.741 Y91.261 Z2.2 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z2.2 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z2.2 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z2.2 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z2.2 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z2.2 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z2.2 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z2.2 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z2.2 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z2.2 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z2.2 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z2.6 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z2.6 F2700.0 E0.624
+G1 X109.7 Y109.7 Z2.6 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z2.6 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z2.6 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z2.6 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z2.6 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z2.6 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z2.6 F4200.0 E4.334
+G1 X90.857 Y91.201 Z2.6 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z2.6 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z2.6 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z2.6 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z2.6 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z2.6 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z2.6 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z2.6 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z2.6 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z2.6 F4200.0 E1.28
+G1 X108.739 Y100.741 Z2.6 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z2.6 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z2.6 F4200.0 E2.565
+G1 X91.261 Y91.261 Z2.6 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z2.6 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z2.6 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z2.6 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z2.6 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z2.6 F4200.0 E4.383
+G1 X91.261 Y99.259 Z2.6 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z2.6 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z2.6 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z2.6 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z2.6 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z2.6 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z2.6 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z2.6 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z2.6 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z2.6 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z2.6 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z3.0 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z3.0 F2700.0 E0.624
+G1 X109.7 Y109.7 Z3.0 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z3.0 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z3.0 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z3.0 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z3.0 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z3.0 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z3.0 F4200.0 E4.334
+G1 X90.857 Y91.201 Z3.0 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z3.0 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z3.0 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z3.0 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z3.0 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z3.0 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z3.0 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z3.0 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z3.0 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z3.0 F4200.0 E1.28
+G1 X99.259 Y108.739 Z3.0 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z3.0 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z3.0 F4200.0 E2.565
+G1 X108.739 Y91.261 Z3.0 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z3.0 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z3.0 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z3.0 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z3.0 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z3.0 F4200.0 E4.383
+G1 X100.741 Y91.261 Z3.0 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z3.0 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z3.0 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z3.0 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z3.0 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z3.0 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z3.0 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z3.0 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z3.0 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z3.0 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z3.0 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z3.4 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z3.4 F2700.0 E0.624
+G1 X109.7 Y109.7 Z3.4 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z3.4 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z3.4 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z3.4 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z3.4 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z3.4 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z3.4 F4200.0 E4.334
+G1 X90.857 Y91.201 Z3.4 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z3.4 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z3.4 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z3.4 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z3.4 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z3.4 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z3.4 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z3.4 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z3.4 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z3.4 F4200.0 E1.28
+G1 X108.739 Y100.741 Z3.4 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z3.4 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z3.4 F4200.0 E2.565
+G1 X91.261 Y91.261 Z3.4 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z3.4 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z3.4 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z3.4 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z3.4 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z3.4 F4200.0 E4.383
+G1 X91.261 Y99.259 Z3.4 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z3.4 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z3.4 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z3.4 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z3.4 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z3.4 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z3.4 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z3.4 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z3.4 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z3.4 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z3.4 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z3.8 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z3.8 F2700.0 E0.624
+G1 X109.7 Y109.7 Z3.8 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z3.8 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z3.8 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z3.8 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z3.8 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z3.8 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z3.8 F4200.0 E4.334
+G1 X90.857 Y91.201 Z3.8 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z3.8 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z3.8 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z3.8 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z3.8 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z3.8 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z3.8 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z3.8 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z3.8 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z3.8 F4200.0 E1.28
+G1 X99.259 Y108.739 Z3.8 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z3.8 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z3.8 F4200.0 E2.565
+G1 X108.739 Y91.261 Z3.8 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z3.8 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z3.8 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z3.8 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z3.8 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z3.8 F4200.0 E4.383
+G1 X100.741 Y91.261 Z3.8 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z3.8 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z3.8 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z3.8 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z3.8 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z3.8 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z3.8 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z3.8 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z3.8 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z3.8 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z3.8 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z4.2 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z4.2 F2700.0 E0.624
+G1 X109.7 Y109.7 Z4.2 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z4.2 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z4.2 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z4.2 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z4.2 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z4.2 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z4.2 F4200.0 E4.334
+G1 X90.857 Y91.201 Z4.2 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z4.2 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z4.2 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z4.2 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z4.2 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z4.2 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z4.2 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z4.2 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z4.2 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z4.2 F4200.0 E1.28
+G1 X108.739 Y100.741 Z4.2 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z4.2 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z4.2 F4200.0 E2.565
+G1 X91.261 Y91.261 Z4.2 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z4.2 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z4.2 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z4.2 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z4.2 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z4.2 F4200.0 E4.383
+G1 X91.261 Y99.259 Z4.2 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z4.2 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z4.2 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z4.2 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z4.2 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z4.2 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z4.2 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z4.2 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z4.2 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z4.2 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z4.2 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z4.6 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z4.6 F2700.0 E0.624
+G1 X109.7 Y109.7 Z4.6 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z4.6 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z4.6 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z4.6 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z4.6 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z4.6 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z4.6 F4200.0 E4.334
+G1 X90.857 Y91.201 Z4.6 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z4.6 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z4.6 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z4.6 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z4.6 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z4.6 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z4.6 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z4.6 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z4.6 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z4.6 F4200.0 E1.28
+G1 X99.259 Y108.739 Z4.6 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z4.6 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z4.6 F4200.0 E2.565
+G1 X108.739 Y91.261 Z4.6 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z4.6 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z4.6 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z4.6 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z4.6 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z4.6 F4200.0 E4.383
+G1 X100.741 Y91.261 Z4.6 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z4.6 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z4.6 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z4.6 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z4.6 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z4.6 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z4.6 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z4.6 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z4.6 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z4.6 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z4.6 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z5.0 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z5.0 F2700.0 E0.624
+G1 X109.7 Y109.7 Z5.0 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z5.0 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z5.0 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z5.0 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z5.0 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z5.0 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z5.0 F4200.0 E4.334
+G1 X90.857 Y91.201 Z5.0 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z5.0 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z5.0 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z5.0 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z5.0 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z5.0 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z5.0 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z5.0 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z5.0 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z5.0 F4200.0 E1.28
+G1 X108.739 Y100.741 Z5.0 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z5.0 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z5.0 F4200.0 E2.565
+G1 X91.261 Y91.261 Z5.0 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z5.0 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z5.0 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z5.0 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z5.0 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z5.0 F4200.0 E4.383
+G1 X91.261 Y99.259 Z5.0 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z5.0 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z5.0 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z5.0 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z5.0 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z5.0 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z5.0 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z5.0 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z5.0 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z5.0 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z5.0 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z5.4 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z5.4 F2700.0 E0.624
+G1 X109.7 Y109.7 Z5.4 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z5.4 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z5.4 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z5.4 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z5.4 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z5.4 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z5.4 F4200.0 E4.334
+G1 X90.857 Y91.201 Z5.4 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z5.4 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z5.4 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z5.4 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z5.4 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z5.4 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z5.4 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z5.4 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z5.4 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z5.4 F4200.0 E1.28
+G1 X99.259 Y108.739 Z5.4 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z5.4 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z5.4 F4200.0 E2.565
+G1 X108.739 Y91.261 Z5.4 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z5.4 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z5.4 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z5.4 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z5.4 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z5.4 F4200.0 E4.383
+G1 X100.741 Y91.261 Z5.4 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z5.4 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z5.4 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z5.4 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z5.4 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z5.4 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z5.4 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z5.4 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z5.4 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z5.4 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z5.4 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z5.8 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z5.8 F2700.0 E0.624
+G1 X109.7 Y109.7 Z5.8 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z5.8 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z5.8 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z5.8 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z5.8 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z5.8 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z5.8 F4200.0 E4.334
+G1 X90.857 Y91.201 Z5.8 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z5.8 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z5.8 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z5.8 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z5.8 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z5.8 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z5.8 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z5.8 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z5.8 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z5.8 F4200.0 E1.28
+G1 X108.739 Y100.741 Z5.8 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z5.8 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z5.8 F4200.0 E2.565
+G1 X91.261 Y91.261 Z5.8 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z5.8 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z5.8 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z5.8 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z5.8 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z5.8 F4200.0 E4.383
+G1 X91.261 Y99.259 Z5.8 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z5.8 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z5.8 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z5.8 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z5.8 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z5.8 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z5.8 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z5.8 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z5.8 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z5.8 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z5.8 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z6.2 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z6.2 F2700.0 E0.624
+G1 X109.7 Y109.7 Z6.2 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z6.2 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z6.2 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z6.2 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z6.2 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z6.2 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z6.2 F4200.0 E4.334
+G1 X90.857 Y91.201 Z6.2 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z6.2 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z6.2 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z6.2 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z6.2 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z6.2 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z6.2 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z6.2 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z6.2 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z6.2 F4200.0 E1.28
+G1 X99.259 Y108.739 Z6.2 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z6.2 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z6.2 F4200.0 E2.565
+G1 X108.739 Y91.261 Z6.2 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z6.2 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z6.2 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z6.2 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z6.2 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z6.2 F4200.0 E4.383
+G1 X100.741 Y91.261 Z6.2 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z6.2 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z6.2 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z6.2 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z6.2 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z6.2 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z6.2 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z6.2 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z6.2 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z6.2 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z6.2 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z6.6 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z6.6 F2700.0 E0.624
+G1 X109.7 Y109.7 Z6.6 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z6.6 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z6.6 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z6.6 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z6.6 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z6.6 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z6.6 F4200.0 E4.334
+G1 X90.857 Y91.201 Z6.6 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z6.6 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z6.6 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z6.6 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z6.6 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z6.6 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z6.6 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z6.6 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z6.6 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z6.6 F4200.0 E1.28
+G1 X108.739 Y100.741 Z6.6 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z6.6 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z6.6 F4200.0 E2.565
+G1 X91.261 Y91.261 Z6.6 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z6.6 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z6.6 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z6.6 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z6.6 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z6.6 F4200.0 E4.383
+G1 X91.261 Y99.259 Z6.6 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z6.6 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z6.6 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z6.6 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z6.6 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z6.6 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z6.6 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z6.6 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z6.6 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z6.6 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z6.6 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z7.0 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z7.0 F2700.0 E0.624
+G1 X109.7 Y109.7 Z7.0 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z7.0 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z7.0 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z7.0 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z7.0 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z7.0 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z7.0 F4200.0 E4.334
+G1 X90.857 Y91.201 Z7.0 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z7.0 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z7.0 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z7.0 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z7.0 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z7.0 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z7.0 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z7.0 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z7.0 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z7.0 F4200.0 E1.28
+G1 X99.259 Y108.739 Z7.0 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z7.0 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z7.0 F4200.0 E2.565
+G1 X108.739 Y91.261 Z7.0 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z7.0 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z7.0 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z7.0 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z7.0 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z7.0 F4200.0 E4.383
+G1 X100.741 Y91.261 Z7.0 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z7.0 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z7.0 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z7.0 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z7.0 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z7.0 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z7.0 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z7.0 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z7.0 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z7.0 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z7.0 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z7.4 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z7.4 F2700.0 E0.624
+G1 X109.7 Y109.7 Z7.4 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z7.4 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z7.4 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z7.4 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z7.4 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z7.4 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z7.4 F4200.0 E4.334
+G1 X90.857 Y91.201 Z7.4 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z7.4 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z7.4 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z7.4 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z7.4 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z7.4 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z7.4 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z7.4 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z7.4 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z7.4 F4200.0 E1.28
+G1 X108.739 Y100.741 Z7.4 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z7.4 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z7.4 F4200.0 E2.565
+G1 X91.261 Y91.261 Z7.4 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z7.4 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z7.4 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z7.4 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z7.4 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z7.4 F4200.0 E4.383
+G1 X91.261 Y99.259 Z7.4 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z7.4 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z7.4 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z7.4 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z7.4 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z7.4 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z7.4 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z7.4 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z7.4 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z7.4 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z7.4 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z7.8 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z7.8 F2700.0 E0.624
+G1 X109.7 Y109.7 Z7.8 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z7.8 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z7.8 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z7.8 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z7.8 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z7.8 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z7.8 F4200.0 E4.334
+G1 X90.857 Y91.201 Z7.8 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z7.8 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z7.8 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z7.8 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z7.8 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z7.8 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z7.8 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z7.8 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z7.8 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z7.8 F4200.0 E1.28
+G1 X99.259 Y108.739 Z7.8 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z7.8 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z7.8 F4200.0 E2.565
+G1 X108.739 Y91.261 Z7.8 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z7.8 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z7.8 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z7.8 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z7.8 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z7.8 F4200.0 E4.383
+G1 X100.741 Y91.261 Z7.8 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z7.8 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z7.8 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z7.8 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z7.8 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z7.8 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z7.8 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z7.8 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z7.8 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z7.8 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z7.8 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z8.2 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z8.2 F2700.0 E0.624
+G1 X109.7 Y109.7 Z8.2 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z8.2 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z8.2 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z8.2 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z8.2 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z8.2 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z8.2 F4200.0 E4.334
+G1 X90.857 Y91.201 Z8.2 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z8.2 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z8.2 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z8.2 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z8.2 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z8.2 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z8.2 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z8.2 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z8.2 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z8.2 F4200.0 E1.28
+G1 X108.739 Y100.741 Z8.2 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z8.2 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z8.2 F4200.0 E2.565
+G1 X91.261 Y91.261 Z8.2 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z8.2 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z8.2 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z8.2 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z8.2 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z8.2 F4200.0 E4.383
+G1 X91.261 Y99.259 Z8.2 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z8.2 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z8.2 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z8.2 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z8.2 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z8.2 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z8.2 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z8.2 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z8.2 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z8.2 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z8.2 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z8.6 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z8.6 F2700.0 E0.624
+G1 X109.7 Y109.7 Z8.6 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z8.6 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z8.6 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z8.6 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z8.6 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z8.6 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z8.6 F4200.0 E4.334
+G1 X90.857 Y91.201 Z8.6 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z8.6 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z8.6 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z8.6 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z8.6 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z8.6 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z8.6 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z8.6 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z8.6 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z8.6 F4200.0 E1.28
+G1 X99.259 Y108.739 Z8.6 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z8.6 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z8.6 F4200.0 E2.565
+G1 X108.739 Y91.261 Z8.6 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z8.6 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z8.6 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z8.6 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z8.6 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z8.6 F4200.0 E4.383
+G1 X100.741 Y91.261 Z8.6 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z8.6 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z8.6 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z8.6 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z8.6 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z8.6 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z8.6 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z8.6 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z8.6 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z8.6 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z8.6 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z9.0 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z9.0 F2700.0 E0.624
+G1 X109.7 Y109.7 Z9.0 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z9.0 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z9.0 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z9.0 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z9.0 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z9.0 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z9.0 F4200.0 E4.334
+G1 X90.857 Y91.201 Z9.0 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z9.0 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z9.0 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z9.0 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z9.0 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z9.0 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z9.0 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z9.0 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z9.0 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z9.0 F4200.0 E1.28
+G1 X108.739 Y100.741 Z9.0 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z9.0 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z9.0 F4200.0 E2.565
+G1 X91.261 Y91.261 Z9.0 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z9.0 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z9.0 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z9.0 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z9.0 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z9.0 F4200.0 E4.383
+G1 X91.261 Y99.259 Z9.0 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z9.0 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z9.0 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z9.0 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z9.0 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z9.0 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z9.0 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z9.0 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z9.0 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z9.0 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z9.0 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z9.4 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z9.4 F2700.0 E0.624
+G1 X109.7 Y109.7 Z9.4 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z9.4 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z9.4 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z9.4 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z9.4 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z9.4 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z9.4 F4200.0 E4.334
+G1 X90.857 Y91.201 Z9.4 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z9.4 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z9.4 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z9.4 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z9.4 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z9.4 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z9.4 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z9.4 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z9.4 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z9.4 F4200.0 E1.28
+G1 X99.259 Y108.739 Z9.4 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z9.4 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z9.4 F4200.0 E2.565
+G1 X108.739 Y91.261 Z9.4 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z9.4 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z9.4 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z9.4 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z9.4 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z9.4 F4200.0 E4.383
+G1 X100.741 Y91.261 Z9.4 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z9.4 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z9.4 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z9.4 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z9.4 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z9.4 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z9.4 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z9.4 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z9.4 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z9.4 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z9.4 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z9.8 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z9.8 F2700.0 E0.624
+G1 X109.7 Y109.7 Z9.8 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z9.8 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z9.8 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z9.8 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z9.8 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z9.8 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z9.8 F4200.0 E4.334
+G1 X90.857 Y91.201 Z9.8 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z9.8 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z9.8 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z9.8 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z9.8 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z9.8 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z9.8 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z9.8 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z9.8 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z9.8 F4200.0 E1.28
+G1 X108.739 Y100.741 Z9.8 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z9.8 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z9.8 F4200.0 E2.565
+G1 X91.261 Y91.261 Z9.8 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z9.8 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z9.8 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z9.8 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z9.8 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z9.8 F4200.0 E4.383
+G1 X91.261 Y99.259 Z9.8 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z9.8 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z9.8 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z9.8 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z9.8 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z9.8 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z9.8 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z9.8 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z9.8 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z9.8 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z9.8 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z10.2 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z10.2 F2700.0 E0.624
+G1 X109.7 Y109.7 Z10.2 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z10.2 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z10.2 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z10.2 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z10.2 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z10.2 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z10.2 F4200.0 E4.334
+G1 X90.857 Y91.201 Z10.2 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z10.2 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z10.2 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z10.2 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z10.2 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z10.2 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z10.2 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z10.2 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z10.2 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z10.2 F4200.0 E1.28
+G1 X99.259 Y108.739 Z10.2 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z10.2 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z10.2 F4200.0 E2.565
+G1 X108.739 Y91.261 Z10.2 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z10.2 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z10.2 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z10.2 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z10.2 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z10.2 F4200.0 E4.383
+G1 X100.741 Y91.261 Z10.2 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z10.2 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z10.2 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z10.2 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z10.2 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z10.2 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z10.2 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z10.2 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z10.2 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z10.2 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z10.2 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z10.6 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z10.6 F2700.0 E0.624
+G1 X109.7 Y109.7 Z10.6 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z10.6 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z10.6 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z10.6 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z10.6 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z10.6 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z10.6 F4200.0 E4.334
+G1 X90.857 Y91.201 Z10.6 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z10.6 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z10.6 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z10.6 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z10.6 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z10.6 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z10.6 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z10.6 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z10.6 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z10.6 F4200.0 E1.28
+G1 X108.739 Y100.741 Z10.6 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z10.6 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z10.6 F4200.0 E2.565
+G1 X91.261 Y91.261 Z10.6 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z10.6 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z10.6 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z10.6 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z10.6 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z10.6 F4200.0 E4.383
+G1 X91.261 Y99.259 Z10.6 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z10.6 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z10.6 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z10.6 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z10.6 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z10.6 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z10.6 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z10.6 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z10.6 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z10.6 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z10.6 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z11.0 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z11.0 F2700.0 E0.624
+G1 X109.7 Y109.7 Z11.0 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z11.0 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z11.0 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z11.0 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z11.0 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z11.0 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z11.0 F4200.0 E4.334
+G1 X90.857 Y91.201 Z11.0 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z11.0 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z11.0 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z11.0 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z11.0 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z11.0 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z11.0 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z11.0 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z11.0 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z11.0 F4200.0 E1.28
+G1 X99.259 Y108.739 Z11.0 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z11.0 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z11.0 F4200.0 E2.565
+G1 X108.739 Y91.261 Z11.0 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z11.0 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z11.0 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z11.0 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z11.0 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z11.0 F4200.0 E4.383
+G1 X100.741 Y91.261 Z11.0 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z11.0 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z11.0 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z11.0 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z11.0 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z11.0 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z11.0 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z11.0 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z11.0 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z11.0 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z11.0 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z11.4 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z11.4 F2700.0 E0.624
+G1 X109.7 Y109.7 Z11.4 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z11.4 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z11.4 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z11.4 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z11.4 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z11.4 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z11.4 F4200.0 E4.334
+G1 X90.857 Y91.201 Z11.4 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z11.4 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z11.4 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z11.4 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z11.4 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z11.4 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z11.4 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z11.4 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z11.4 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z11.4 F4200.0 E1.28
+G1 X108.739 Y100.741 Z11.4 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z11.4 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z11.4 F4200.0 E2.565
+G1 X91.261 Y91.261 Z11.4 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z11.4 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z11.4 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z11.4 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z11.4 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z11.4 F4200.0 E4.383
+G1 X91.261 Y99.259 Z11.4 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z11.4 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z11.4 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z11.4 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z11.4 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z11.4 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z11.4 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z11.4 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z11.4 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z11.4 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z11.4 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z11.8 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z11.8 F2700.0 E0.624
+G1 X109.7 Y109.7 Z11.8 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z11.8 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z11.8 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z11.8 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z11.8 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z11.8 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z11.8 F4200.0 E4.334
+G1 X90.857 Y91.201 Z11.8 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z11.8 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z11.8 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z11.8 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z11.8 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z11.8 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z11.8 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z11.8 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z11.8 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z11.8 F4200.0 E1.28
+G1 X99.259 Y108.739 Z11.8 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z11.8 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z11.8 F4200.0 E2.565
+G1 X108.739 Y91.261 Z11.8 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z11.8 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z11.8 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z11.8 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z11.8 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z11.8 F4200.0 E4.383
+G1 X100.741 Y91.261 Z11.8 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z11.8 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z11.8 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z11.8 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z11.8 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z11.8 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z11.8 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z11.8 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z11.8 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z11.8 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z11.8 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z12.2 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z12.2 F2700.0 E0.624
+G1 X109.7 Y109.7 Z12.2 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z12.2 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z12.2 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z12.2 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z12.2 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z12.2 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z12.2 F4200.0 E4.334
+G1 X90.857 Y91.201 Z12.2 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z12.2 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z12.2 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z12.2 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z12.2 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z12.2 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z12.2 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z12.2 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z12.2 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z12.2 F4200.0 E1.28
+G1 X108.739 Y100.741 Z12.2 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z12.2 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z12.2 F4200.0 E2.565
+G1 X91.261 Y91.261 Z12.2 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z12.2 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z12.2 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z12.2 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z12.2 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z12.2 F4200.0 E4.383
+G1 X91.261 Y99.259 Z12.2 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z12.2 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z12.2 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z12.2 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z12.2 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z12.2 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z12.2 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z12.2 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z12.2 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z12.2 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z12.2 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z12.6 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z12.6 F2700.0 E0.624
+G1 X109.7 Y109.7 Z12.6 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z12.6 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z12.6 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z12.6 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z12.6 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z12.6 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z12.6 F4200.0 E4.334
+G1 X90.857 Y91.201 Z12.6 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z12.6 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z12.6 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z12.6 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z12.6 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z12.6 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z12.6 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z12.6 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z12.6 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z12.6 F4200.0 E1.28
+G1 X99.259 Y108.739 Z12.6 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z12.6 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z12.6 F4200.0 E2.565
+G1 X108.739 Y91.261 Z12.6 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z12.6 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z12.6 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z12.6 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z12.6 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z12.6 F4200.0 E4.383
+G1 X100.741 Y91.261 Z12.6 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z12.6 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z12.6 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z12.6 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z12.6 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z12.6 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z12.6 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z12.6 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z12.6 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z12.6 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z12.6 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z13.0 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z13.0 F2700.0 E0.624
+G1 X109.7 Y109.7 Z13.0 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z13.0 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z13.0 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z13.0 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z13.0 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z13.0 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z13.0 F4200.0 E4.334
+G1 X90.857 Y91.201 Z13.0 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z13.0 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z13.0 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z13.0 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z13.0 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z13.0 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z13.0 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z13.0 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z13.0 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z13.0 F4200.0 E1.28
+G1 X108.739 Y100.741 Z13.0 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z13.0 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z13.0 F4200.0 E2.565
+G1 X91.261 Y91.261 Z13.0 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z13.0 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z13.0 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z13.0 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z13.0 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z13.0 F4200.0 E4.383
+G1 X91.261 Y99.259 Z13.0 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z13.0 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z13.0 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z13.0 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z13.0 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z13.0 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z13.0 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z13.0 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z13.0 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z13.0 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z13.0 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z13.4 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z13.4 F2700.0 E0.624
+G1 X109.7 Y109.7 Z13.4 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z13.4 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z13.4 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z13.4 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z13.4 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z13.4 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z13.4 F4200.0 E4.334
+G1 X90.857 Y91.201 Z13.4 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z13.4 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z13.4 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z13.4 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z13.4 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z13.4 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z13.4 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z13.4 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z13.4 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z13.4 F4200.0 E1.28
+G1 X99.259 Y108.739 Z13.4 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z13.4 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z13.4 F4200.0 E2.565
+G1 X108.739 Y91.261 Z13.4 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z13.4 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z13.4 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z13.4 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z13.4 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z13.4 F4200.0 E4.383
+G1 X100.741 Y91.261 Z13.4 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z13.4 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z13.4 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z13.4 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z13.4 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z13.4 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z13.4 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z13.4 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z13.4 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z13.4 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z13.4 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z13.8 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z13.8 F2700.0 E0.624
+G1 X109.7 Y109.7 Z13.8 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z13.8 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z13.8 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z13.8 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z13.8 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z13.8 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z13.8 F4200.0 E4.334
+G1 X90.857 Y91.201 Z13.8 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z13.8 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z13.8 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z13.8 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z13.8 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z13.8 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z13.8 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z13.8 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z13.8 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z13.8 F4200.0 E1.28
+G1 X108.739 Y100.741 Z13.8 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z13.8 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z13.8 F4200.0 E2.565
+G1 X91.261 Y91.261 Z13.8 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z13.8 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z13.8 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z13.8 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z13.8 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z13.8 F4200.0 E4.383
+G1 X91.261 Y99.259 Z13.8 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z13.8 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z13.8 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z13.8 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z13.8 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z13.8 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z13.8 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z13.8 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z13.8 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z13.8 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z13.8 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z14.2 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z14.2 F2700.0 E0.624
+G1 X109.7 Y109.7 Z14.2 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z14.2 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z14.2 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z14.2 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z14.2 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z14.2 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z14.2 F4200.0 E4.334
+G1 X90.857 Y91.201 Z14.2 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z14.2 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z14.2 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z14.2 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z14.2 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z14.2 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z14.2 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z14.2 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z14.2 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z14.2 F4200.0 E1.28
+G1 X99.259 Y108.739 Z14.2 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z14.2 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z14.2 F4200.0 E2.565
+G1 X108.739 Y91.261 Z14.2 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z14.2 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z14.2 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z14.2 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z14.2 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z14.2 F4200.0 E4.383
+G1 X100.741 Y91.261 Z14.2 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z14.2 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z14.2 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z14.2 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z14.2 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z14.2 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z14.2 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z14.2 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z14.2 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z14.2 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z14.2 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z14.6 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z14.6 F2700.0 E0.624
+G1 X109.7 Y109.7 Z14.6 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z14.6 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z14.6 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z14.6 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z14.6 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z14.6 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z14.6 F4200.0 E4.334
+G1 X90.857 Y91.201 Z14.6 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z14.6 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z14.6 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z14.6 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z14.6 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z14.6 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z14.6 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z14.6 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z14.6 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z14.6 F4200.0 E1.28
+G1 X108.739 Y100.741 Z14.6 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z14.6 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z14.6 F4200.0 E2.565
+G1 X91.261 Y91.261 Z14.6 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z14.6 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z14.6 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z14.6 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z14.6 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z14.6 F4200.0 E4.383
+G1 X91.261 Y99.259 Z14.6 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z14.6 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z14.6 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z14.6 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z14.6 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z14.6 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z14.6 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z14.6 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z14.6 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z14.6 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z14.6 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z15.0 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z15.0 F2700.0 E0.624
+G1 X109.7 Y109.7 Z15.0 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z15.0 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z15.0 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z15.0 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z15.0 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z15.0 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z15.0 F4200.0 E4.334
+G1 X90.857 Y91.201 Z15.0 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z15.0 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z15.0 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z15.0 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z15.0 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z15.0 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z15.0 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z15.0 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z15.0 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z15.0 F4200.0 E1.28
+G1 X99.259 Y108.739 Z15.0 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z15.0 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z15.0 F4200.0 E2.565
+G1 X108.739 Y91.261 Z15.0 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z15.0 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z15.0 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z15.0 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z15.0 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z15.0 F4200.0 E4.383
+G1 X100.741 Y91.261 Z15.0 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z15.0 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z15.0 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z15.0 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z15.0 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z15.0 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z15.0 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z15.0 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z15.0 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z15.0 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z15.0 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z15.4 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z15.4 F2700.0 E0.624
+G1 X109.7 Y109.7 Z15.4 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z15.4 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z15.4 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z15.4 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z15.4 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z15.4 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z15.4 F4200.0 E4.334
+G1 X90.857 Y91.201 Z15.4 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z15.4 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z15.4 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z15.4 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z15.4 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z15.4 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z15.4 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z15.4 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z15.4 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z15.4 F4200.0 E1.28
+G1 X108.739 Y100.741 Z15.4 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z15.4 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z15.4 F4200.0 E2.565
+G1 X91.261 Y91.261 Z15.4 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z15.4 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z15.4 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z15.4 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z15.4 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z15.4 F4200.0 E4.383
+G1 X91.261 Y99.259 Z15.4 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z15.4 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z15.4 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z15.4 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z15.4 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z15.4 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z15.4 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z15.4 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z15.4 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z15.4 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z15.4 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z15.8 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z15.8 F2700.0 E0.624
+G1 X109.7 Y109.7 Z15.8 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z15.8 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z15.8 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z15.8 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z15.8 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z15.8 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z15.8 F4200.0 E4.334
+G1 X90.857 Y91.201 Z15.8 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z15.8 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z15.8 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z15.8 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z15.8 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z15.8 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z15.8 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z15.8 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z15.8 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z15.8 F4200.0 E1.28
+G1 X99.259 Y108.739 Z15.8 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z15.8 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z15.8 F4200.0 E2.565
+G1 X108.739 Y91.261 Z15.8 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z15.8 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z15.8 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z15.8 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z15.8 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z15.8 F4200.0 E4.383
+G1 X100.741 Y91.261 Z15.8 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z15.8 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z15.8 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z15.8 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z15.8 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z15.8 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z15.8 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z15.8 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z15.8 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z15.8 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z15.8 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z16.2 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z16.2 F2700.0 E0.624
+G1 X109.7 Y109.7 Z16.2 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z16.2 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z16.2 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z16.2 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z16.2 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z16.2 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z16.2 F4200.0 E4.334
+G1 X90.857 Y91.201 Z16.2 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z16.2 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z16.2 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z16.2 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z16.2 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z16.2 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z16.2 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z16.2 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z16.2 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z16.2 F4200.0 E1.28
+G1 X108.739 Y100.741 Z16.2 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z16.2 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z16.2 F4200.0 E2.565
+G1 X91.261 Y91.261 Z16.2 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z16.2 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z16.2 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z16.2 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z16.2 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z16.2 F4200.0 E4.383
+G1 X91.261 Y99.259 Z16.2 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z16.2 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z16.2 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z16.2 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z16.2 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z16.2 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z16.2 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z16.2 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z16.2 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z16.2 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z16.2 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z16.6 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z16.6 F2700.0 E0.624
+G1 X109.7 Y109.7 Z16.6 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z16.6 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z16.6 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z16.6 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z16.6 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z16.6 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z16.6 F4200.0 E4.334
+G1 X90.857 Y91.201 Z16.6 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z16.6 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z16.6 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z16.6 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z16.6 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z16.6 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z16.6 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z16.6 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z16.6 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z16.6 F4200.0 E1.28
+G1 X99.259 Y108.739 Z16.6 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z16.6 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z16.6 F4200.0 E2.565
+G1 X108.739 Y91.261 Z16.6 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z16.6 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z16.6 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z16.6 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z16.6 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z16.6 F4200.0 E4.383
+G1 X100.741 Y91.261 Z16.6 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z16.6 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z16.6 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z16.6 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z16.6 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z16.6 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z16.6 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z16.6 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z16.6 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z16.6 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z16.6 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z17.0 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z17.0 F2700.0 E0.624
+G1 X109.7 Y109.7 Z17.0 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z17.0 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z17.0 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z17.0 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z17.0 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z17.0 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z17.0 F4200.0 E4.334
+G1 X90.857 Y91.201 Z17.0 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z17.0 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z17.0 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z17.0 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z17.0 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z17.0 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z17.0 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z17.0 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z17.0 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z17.0 F4200.0 E1.28
+G1 X108.739 Y100.741 Z17.0 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z17.0 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z17.0 F4200.0 E2.565
+G1 X91.261 Y91.261 Z17.0 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z17.0 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z17.0 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z17.0 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z17.0 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z17.0 F4200.0 E4.383
+G1 X91.261 Y99.259 Z17.0 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z17.0 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z17.0 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z17.0 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z17.0 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z17.0 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z17.0 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z17.0 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z17.0 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z17.0 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z17.0 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z17.4 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z17.4 F2700.0 E0.624
+G1 X109.7 Y109.7 Z17.4 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z17.4 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z17.4 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z17.4 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z17.4 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z17.4 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z17.4 F4200.0 E4.334
+G1 X90.857 Y91.201 Z17.4 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z17.4 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z17.4 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z17.4 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z17.4 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z17.4 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z17.4 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z17.4 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z17.4 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z17.4 F4200.0 E1.28
+G1 X99.259 Y108.739 Z17.4 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z17.4 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z17.4 F4200.0 E2.565
+G1 X108.739 Y91.261 Z17.4 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z17.4 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z17.4 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z17.4 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z17.4 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z17.4 F4200.0 E4.383
+G1 X100.741 Y91.261 Z17.4 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z17.4 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z17.4 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z17.4 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z17.4 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z17.4 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z17.4 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z17.4 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z17.4 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z17.4 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z17.4 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z17.8 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z17.8 F2700.0 E0.624
+G1 X109.7 Y109.7 Z17.8 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z17.8 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z17.8 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z17.8 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z17.8 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z17.8 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z17.8 F4200.0 E4.334
+G1 X90.857 Y91.201 Z17.8 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z17.8 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z17.8 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z17.8 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z17.8 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z17.8 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z17.8 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z17.8 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z17.8 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z17.8 F4200.0 E1.28
+G1 X108.739 Y100.741 Z17.8 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z17.8 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z17.8 F4200.0 E2.565
+G1 X91.261 Y91.261 Z17.8 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z17.8 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z17.8 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z17.8 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z17.8 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z17.8 F4200.0 E4.383
+G1 X91.261 Y99.259 Z17.8 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z17.8 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z17.8 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z17.8 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z17.8 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z17.8 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z17.8 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z17.8 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z17.8 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z17.8 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z17.8 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z18.2 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z18.2 F2700.0 E0.624
+G1 X109.7 Y109.7 Z18.2 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z18.2 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z18.2 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z18.2 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z18.2 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z18.2 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z18.2 F4200.0 E4.334
+G1 X90.857 Y91.201 Z18.2 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z18.2 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z18.2 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z18.2 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z18.2 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z18.2 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z18.2 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z18.2 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z18.2 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z18.2 F4200.0 E1.28
+G1 X99.259 Y108.739 Z18.2 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z18.2 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z18.2 F4200.0 E2.565
+G1 X108.739 Y91.261 Z18.2 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z18.2 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z18.2 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z18.2 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z18.2 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z18.2 F4200.0 E4.383
+G1 X100.741 Y91.261 Z18.2 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z18.2 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z18.2 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z18.2 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z18.2 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z18.2 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z18.2 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z18.2 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z18.2 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z18.2 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z18.2 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z18.6 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z18.6 F2700.0 E0.624
+G1 X109.7 Y109.7 Z18.6 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z18.6 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z18.6 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z18.6 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z18.6 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z18.6 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z18.6 F4200.0 E4.334
+G1 X90.857 Y91.201 Z18.6 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z18.6 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z18.6 F4200.0 E0.0013
+G1 X108.739 Y94.197 Z18.6 F4200.0 E0.0965
+G1 X107.985 Y91.261 Z18.6 F4200.0 E0.1957
+G1 X102.895 Y91.261 Z18.6 F4200.0 E0.3624
+G1 X108.739 Y94.924 Z18.6 F4200.0 E0.5883
+G1 X108.739 Y100.013 Z18.6 F4200.0 E0.7549
+G1 X102.168 Y91.261 Z18.6 F4200.0 E1.1133
+G1 X97.078 Y91.261 Z18.6 F4200.0 E1.28
+G1 X108.739 Y100.741 Z18.6 F4200.0 E1.7721
+G1 X108.739 Y105.831 Z18.6 F4200.0 E1.9388
+G1 X96.351 Y91.261 Z18.6 F4200.0 E2.565
+G1 X91.261 Y91.261 Z18.6 F4200.0 E2.7317
+G1 X91.261 Y93.442 Z18.6 F4200.0 E2.8031
+G1 X108.739 Y106.558 Z18.6 F4200.0 E3.5187
+G1 X108.739 Y108.739 Z18.6 F4200.0 E3.5901
+G1 X103.649 Y108.739 Z18.6 F4200.0 E3.7568
+G1 X91.261 Y94.169 Z18.6 F4200.0 E4.383
+G1 X91.261 Y99.259 Z18.6 F4200.0 E4.5497
+G1 X102.922 Y108.739 Z18.6 F4200.0 E5.0418
+G1 X97.832 Y108.739 Z18.6 F4200.0 E5.2085
+G1 X91.261 Y99.987 Z18.6 F4200.0 E5.5669
+G1 X91.261 Y105.076 Z18.6 F4200.0 E5.7335
+G1 X97.105 Y108.739 Z18.6 F4200.0 E5.9594
+G1 X92.742 Y108.739 Z18.6 F4200.0 E6.1022
+G1 X91.261 Y105.803 Z18.6 F4200.0 E6.2099
+G1 X91.261 Y108.712 Z18.6 F4200.0 E6.3052
+G1 X91.288 Y108.739 Z18.6 F4200.0 E6.3064
+G1 X92.015 Y108.739 Z18.6 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z19.0 F9709.5478
+G1 F900.0
+G1 E6.3302
+G1 F9709.5478
+G92 E0
+G1 X109.7 Y90.3 Z19.0 F2700.0 E0.624
+G1 X109.7 Y109.7 Z19.0 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z19.0 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z19.0 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z19.0 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z19.0 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z19.0 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z19.0 F4200.0 E4.334
+G1 X90.857 Y91.201 Z19.0 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z19.0 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z19.0 F4200.0 E0.0013
+G1 X105.803 Y108.739 Z19.0 F4200.0 E0.0965
+G1 X108.739 Y107.985 Z19.0 F4200.0 E0.1957
+G1 X108.739 Y102.895 Z19.0 F4200.0 E0.3624
+G1 X105.076 Y108.739 Z19.0 F4200.0 E0.5883
+G1 X99.987 Y108.739 Z19.0 F4200.0 E0.7549
+G1 X108.739 Y102.168 Z19.0 F4200.0 E1.1133
+G1 X108.739 Y97.078 Z19.0 F4200.0 E1.28
+G1 X99.259 Y108.739 Z19.0 F4200.0 E1.7721
+G1 X94.169 Y108.739 Z19.0 F4200.0 E1.9388
+G1 X108.739 Y96.351 Z19.0 F4200.0 E2.565
+G1 X108.739 Y91.261 Z19.0 F4200.0 E2.7317
+G1 X106.558 Y91.261 Z19.0 F4200.0 E2.8031
+G1 X93.442 Y108.739 Z19.0 F4200.0 E3.5187
+G1 X91.261 Y108.739 Z19.0 F4200.0 E3.5901
+G1 X91.261 Y103.649 Z19.0 F4200.0 E3.7568
+G1 X105.831 Y91.261 Z19.0 F4200.0 E4.383
+G1 X100.741 Y91.261 Z19.0 F4200.0 E4.5497
+G1 X91.261 Y102.922 Z19.0 F4200.0 E5.0418
+G1 X91.261 Y97.832 Z19.0 F4200.0 E5.2085
+G1 X100.013 Y91.261 Z19.0 F4200.0 E5.5669
+G1 X94.924 Y91.261 Z19.0 F4200.0 E5.7335
+G1 X91.261 Y97.105 Z19.0 F4200.0 E5.9594
+G1 X91.261 Y92.742 Z19.0 F4200.0 E6.1022
+G1 X94.197 Y91.261 Z19.0 F4200.0 E6.2099
+G1 X91.288 Y91.261 Z19.0 F4200.0 E6.3052
+G1 X91.261 Y91.288 Z19.0 F4200.0 E6.3064
+G1 X91.261 Y92.015 Z19.0 F4200.0 E6.3302
+G1 F900.0
+G1 E5.3302
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z19.4 F979.7792
+G1 F900.0
+G1 E6.3302
+G1 F979.7792
+G92 E0
+G1 X109.7 Y90.3 Z19.4 F2700.0 E0.624
+G1 X109.7 Y109.7 Z19.4 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z19.4 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z19.4 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z19.4 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z19.4 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z19.4 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z19.4 F4200.0 E4.334
+G1 X90.857 Y91.201 Z19.4 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.712 Y91.261 Z19.4 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.739 Y91.288 Z19.4 F4200.0 E0.0013
+G1 X108.739 Y92.015 Z19.4 F4200.0 E0.0251
+G1 X107.985 Y91.261 Z19.4 F4200.0 E0.06
+G1 X107.258 Y91.261 Z19.4 F4200.0 E0.0838
+G1 X108.739 Y92.742 Z19.4 F4200.0 E0.1524
+G1 X108.739 Y93.469 Z19.4 F4200.0 E0.1762
+G1 X106.531 Y91.261 Z19.4 F4200.0 E0.2785
+G1 X105.803 Y91.261 Z19.4 F4200.0 E0.3023
+G1 X108.739 Y94.197 Z19.4 F4200.0 E0.4382
+G1 X108.739 Y94.924 Z19.4 F4200.0 E0.462
+G1 X105.076 Y91.261 Z19.4 F4200.0 E0.6317
+G1 X104.349 Y91.261 Z19.4 F4200.0 E0.6555
+G1 X108.739 Y95.651 Z19.4 F4200.0 E0.8588
+G1 X108.739 Y96.378 Z19.4 F4200.0 E0.8826
+G1 X103.622 Y91.261 Z19.4 F4200.0 E1.1195
+G1 X102.895 Y91.261 Z19.4 F4200.0 E1.1433
+G1 X108.739 Y97.105 Z19.4 F4200.0 E1.414
+G1 X108.739 Y97.832 Z19.4 F4200.0 E1.4378
+G1 X102.168 Y91.261 Z19.4 F4200.0 E1.7421
+G1 X101.441 Y91.261 Z19.4 F4200.0 E1.7659
+G1 X108.739 Y98.559 Z19.4 F4200.0 E2.1039
+G1 X108.739 Y99.286 Z19.4 F4200.0 E2.1277
+G1 X100.714 Y91.261 Z19.4 F4200.0 E2.4994
+G1 X99.987 Y91.261 Z19.4 F4200.0 E2.5232
+G1 X108.739 Y100.013 Z19.4 F4200.0 E2.9285
+G1 X108.739 Y100.741 Z19.4 F4200.0 E2.9523
+G1 X99.259 Y91.261 Z19.4 F4200.0 E3.3913
+G1 X98.532 Y91.261 Z19.4 F4200.0 E3.4151
+G1 X108.739 Y101.468 Z19.4 F4200.0 E3.8878
+G1 X108.739 Y102.195 Z19.4 F4200.0 E3.9116
+G1 X97.805 Y91.261 Z19.4 F4200.0 E4.4179
+G1 X97.078 Y91.261 Z19.4 F4200.0 E4.4417
+G1 X108.739 Y102.922 Z19.4 F4200.0 E4.9818
+G1 X108.739 Y103.649 Z19.4 F4200.0 E5.0056
+G1 X96.351 Y91.261 Z19.4 F4200.0 E5.5793
+G1 X95.624 Y91.261 Z19.4 F4200.0 E5.6031
+G1 X108.739 Y104.376 Z19.4 F4200.0 E6.2104
+G1 X108.739 Y105.103 Z19.4 F4200.0 E6.2342
+G1 X94.897 Y91.261 Z19.4 F4200.0 E6.8753
+G1 X94.169 Y91.261 Z19.4 F4200.0 E6.8991
+G1 X108.739 Y105.831 Z19.4 F4200.0 E7.5738
+G1 X108.739 Y106.558 Z19.4 F4200.0 E7.5976
+G1 X93.442 Y91.261 Z19.4 F4200.0 E8.306
+G1 X92.715 Y91.261 Z19.4 F4200.0 E8.3298
+G1 X108.739 Y107.285 Z19.4 F4200.0 E9.0719
+G1 X108.739 Y108.012 Z19.4 F4200.0 E9.0957
+G1 X91.988 Y91.261 Z19.4 F4200.0 E9.8714
+G1 X91.261 Y91.261 Z19.4 F4200.0 E9.8952
+G1 X108.739 Y108.739 Z19.4 F4200.0 E10.7046
+G1 X108.012 Y108.739 Z19.4 F4200.0 E10.7284
+G1 X91.261 Y91.988 Z19.4 F4200.0 E11.5041
+G1 X91.261 Y92.715 Z19.4 F4200.0 E11.528
+G1 X107.285 Y108.739 Z19.4 F4200.0 E12.27
+G1 X106.558 Y108.739 Z19.4 F4200.0 E12.2938
+G1 X91.261 Y93.442 Z19.4 F4200.0 E13.0022
+G1 X91.261 Y94.169 Z19.4 F4200.0 E13.026
+G1 X105.831 Y108.739 Z19.4 F4200.0 E13.7007
+G1 X105.103 Y108.739 Z19.4 F4200.0 E13.7245
+G1 X91.261 Y94.897 Z19.4 F4200.0 E14.3656
+G1 X91.261 Y95.624 Z19.4 F4200.0 E14.3894
+G1 X104.376 Y108.739 Z19.4 F4200.0 E14.9967
+G1 X103.649 Y108.739 Z19.4 F4200.0 E15.0205
+G1 X91.261 Y96.351 Z19.4 F4200.0 E15.5942
+G1 X91.261 Y97.078 Z19.4 F4200.0 E15.618
+G1 X102.922 Y108.739 Z19.4 F4200.0 E16.1581
+G1 X102.195 Y108.739 Z19.4 F4200.0 E16.1819
+G1 X91.261 Y97.805 Z19.4 F4200.0 E16.6882
+G1 X91.261 Y98.532 Z19.4 F4200.0 E16.712
+G1 X101.468 Y108.739 Z19.4 F4200.0 E17.1847
+G1 X100.741 Y108.739 Z19.4 F4200.0 E17.2085
+G1 X91.261 Y99.259 Z19.4 F4200.0 E17.6475
+G1 X91.261 Y99.987 Z19.4 F4200.0 E17.6713
+G1 X100.013 Y108.739 Z19.4 F4200.0 E18.0767
+G1 X99.286 Y108.739 Z19.4 F4200.0 E18.1005
+G1 X91.261 Y100.714 Z19.4 F4200.0 E18.4721
+G1 X91.261 Y101.441 Z19.4 F4200.0 E18.4959
+G1 X98.559 Y108.739 Z19.4 F4200.0 E18.8339
+G1 X97.832 Y108.739 Z19.4 F4200.0 E18.8577
+G1 X91.261 Y102.168 Z19.4 F4200.0 E19.162
+G1 X91.261 Y102.895 Z19.4 F4200.0 E19.1858
+G1 X97.105 Y108.739 Z19.4 F4200.0 E19.4565
+G1 X96.378 Y108.739 Z19.4 F4200.0 E19.4803
+G1 X91.261 Y103.622 Z19.4 F4200.0 E19.7172
+G1 X91.261 Y104.349 Z19.4 F4200.0 E19.7411
+G1 X95.651 Y108.739 Z19.4 F4200.0 E19.9443
+G1 X94.924 Y108.739 Z19.4 F4200.0 E19.9682
+G1 X91.261 Y105.076 Z19.4 F4200.0 E20.1378
+G1 X91.261 Y105.803 Z19.4 F4200.0 E20.1616
+G1 X94.197 Y108.739 Z19.4 F4200.0 E20.2975
+G1 X93.469 Y108.739 Z19.4 F4200.0 E20.3213
+G1 X91.261 Y106.531 Z19.4 F4200.0 E20.4236
+G1 X91.261 Y107.258 Z19.4 F4200.0 E20.4474
+G1 X92.742 Y108.739 Z19.4 F4200.0 E20.516
+G1 X92.015 Y108.739 Z19.4 F4200.0 E20.5398
+G1 X91.261 Y107.985 Z19.4 F4200.0 E20.5748
+G1 X91.261 Y108.712 Z19.4 F4200.0 E20.5986
+G1 X91.288 Y108.739 Z19.4 F4200.0 E20.5998
+G1 F900.0
+G1 E19.5998
+G1 F4200.0
+; S45.0
+G1 X90.643 Y90.3 Z19.8 F9688.717
+G1 F900.0
+G1 E20.5998
+G1 F9688.717
+G92 E0
+G1 X109.7 Y90.3 Z19.8 F2700.0 E0.624
+G1 X109.7 Y109.7 Z19.8 F2700.0 E1.2593
+G1 X90.3 Y109.7 Z19.8 F2700.0 E1.8945
+G1 X90.3 Y90.643 Z19.8 F2700.0 E2.5186
+; S70.0
+G1 X91.201 Y90.857 Z19.8 F4200.0 E2.5489
+G1 X109.143 Y90.857 Z19.8 F4200.0 E3.1364
+G1 X109.143 Y109.143 Z19.8 F4200.0 E3.7352
+G1 X90.857 Y109.143 Z19.8 F4200.0 E4.334
+G1 X90.857 Y91.201 Z19.8 F4200.0 E4.9215
+G1 F900.0
+G1 E3.9215
+G1 F4200.0
+G1 X108.739 Y108.712 Z19.8 F19800.0
+G1 F900.0
+G1 E4.9215
+G1 F19800.0
+G92 E0
+G1 X108.712 Y108.739 Z19.8 F4200.0 E0.0013
+G1 X107.985 Y108.739 Z19.8 F4200.0 E0.0251
+G1 X108.739 Y107.985 Z19.8 F4200.0 E0.06
+G1 X108.739 Y107.258 Z19.8 F4200.0 E0.0838
+G1 X107.258 Y108.739 Z19.8 F4200.0 E0.1524
+G1 X106.531 Y108.739 Z19.8 F4200.0 E0.1762
+G1 X108.739 Y106.531 Z19.8 F4200.0 E0.2785
+G1 X108.739 Y105.803 Z19.8 F4200.0 E0.3023
+G1 X105.803 Y108.739 Z19.8 F4200.0 E0.4382
+G1 X105.076 Y108.739 Z19.8 F4200.0 E0.462
+G1 X108.739 Y105.076 Z19.8 F4200.0 E0.6317
+G1 X108.739 Y104.349 Z19.8 F4200.0 E0.6555
+G1 X104.349 Y108.739 Z19.8 F4200.0 E0.8588
+G1 X103.622 Y108.739 Z19.8 F4200.0 E0.8826
+G1 X108.739 Y103.622 Z19.8 F4200.0 E1.1195
+G1 X108.739 Y102.895 Z19.8 F4200.0 E1.1433
+G1 X102.895 Y108.739 Z19.8 F4200.0 E1.414
+G1 X102.168 Y108.739 Z19.8 F4200.0 E1.4378
+G1 X108.739 Y102.168 Z19.8 F4200.0 E1.7421
+G1 X108.739 Y101.441 Z19.8 F4200.0 E1.7659
+G1 X101.441 Y108.739 Z19.8 F4200.0 E2.1039
+G1 X100.714 Y108.739 Z19.8 F4200.0 E2.1277
+G1 X108.739 Y100.714 Z19.8 F4200.0 E2.4994
+G1 X108.739 Y99.987 Z19.8 F4200.0 E2.5232
+G1 X99.987 Y108.739 Z19.8 F4200.0 E2.9285
+G1 X99.259 Y108.739 Z19.8 F4200.0 E2.9523
+G1 X108.739 Y99.259 Z19.8 F4200.0 E3.3913
+G1 X108.739 Y98.532 Z19.8 F4200.0 E3.4151
+G1 X98.532 Y108.739 Z19.8 F4200.0 E3.8878
+G1 X97.805 Y108.739 Z19.8 F4200.0 E3.9116
+G1 X108.739 Y97.805 Z19.8 F4200.0 E4.4179
+G1 X108.739 Y97.078 Z19.8 F4200.0 E4.4417
+G1 X97.078 Y108.739 Z19.8 F4200.0 E4.9818
+G1 X96.351 Y108.739 Z19.8 F4200.0 E5.0056
+G1 X108.739 Y96.351 Z19.8 F4200.0 E5.5793
+G1 X108.739 Y95.624 Z19.8 F4200.0 E5.6031
+G1 X95.624 Y108.739 Z19.8 F4200.0 E6.2104
+G1 X94.897 Y108.739 Z19.8 F4200.0 E6.2342
+G1 X108.739 Y94.897 Z19.8 F4200.0 E6.8753
+G1 X108.739 Y94.169 Z19.8 F4200.0 E6.8991
+G1 X94.169 Y108.739 Z19.8 F4200.0 E7.5738
+G1 X93.442 Y108.739 Z19.8 F4200.0 E7.5976
+G1 X108.739 Y93.442 Z19.8 F4200.0 E8.306
+G1 X108.739 Y92.715 Z19.8 F4200.0 E8.3298
+G1 X92.715 Y108.739 Z19.8 F4200.0 E9.0719
+G1 X91.988 Y108.739 Z19.8 F4200.0 E9.0957
+G1 X108.739 Y91.988 Z19.8 F4200.0 E9.8714
+G1 X108.739 Y91.261 Z19.8 F4200.0 E9.8952
+G1 X91.261 Y108.739 Z19.8 F4200.0 E10.7046
+G1 X91.261 Y108.012 Z19.8 F4200.0 E10.7284
+G1 X108.012 Y91.261 Z19.8 F4200.0 E11.5041
+G1 X107.285 Y91.261 Z19.8 F4200.0 E11.528
+G1 X91.261 Y107.285 Z19.8 F4200.0 E12.27
+G1 X91.261 Y106.558 Z19.8 F4200.0 E12.2938
+G1 X106.558 Y91.261 Z19.8 F4200.0 E13.0022
+G1 X105.831 Y91.261 Z19.8 F4200.0 E13.026
+G1 X91.261 Y105.831 Z19.8 F4200.0 E13.7007
+G1 X91.261 Y105.103 Z19.8 F4200.0 E13.7245
+G1 X105.103 Y91.261 Z19.8 F4200.0 E14.3656
+G1 X104.376 Y91.261 Z19.8 F4200.0 E14.3894
+G1 X91.261 Y104.376 Z19.8 F4200.0 E14.9967
+G1 X91.261 Y103.649 Z19.8 F4200.0 E15.0205
+G1 X103.649 Y91.261 Z19.8 F4200.0 E15.5942
+G1 X102.922 Y91.261 Z19.8 F4200.0 E15.618
+G1 X91.261 Y102.922 Z19.8 F4200.0 E16.1581
+G1 X91.261 Y102.195 Z19.8 F4200.0 E16.1819
+G1 X102.195 Y91.261 Z19.8 F4200.0 E16.6882
+G1 X101.468 Y91.261 Z19.8 F4200.0 E16.712
+G1 X91.261 Y101.468 Z19.8 F4200.0 E17.1847
+G1 X91.261 Y100.741 Z19.8 F4200.0 E17.2085
+G1 X100.741 Y91.261 Z19.8 F4200.0 E17.6475
+G1 X100.013 Y91.261 Z19.8 F4200.0 E17.6713
+G1 X91.261 Y100.013 Z19.8 F4200.0 E18.0767
+G1 X91.261 Y99.286 Z19.8 F4200.0 E18.1005
+G1 X99.286 Y91.261 Z19.8 F4200.0 E18.4721
+G1 X98.559 Y91.261 Z19.8 F4200.0 E18.4959
+G1 X91.261 Y98.559 Z19.8 F4200.0 E18.8339
+G1 X91.261 Y97.832 Z19.8 F4200.0 E18.8577
+G1 X97.832 Y91.261 Z19.8 F4200.0 E19.162
+G1 X97.105 Y91.261 Z19.8 F4200.0 E19.1858
+G1 X91.261 Y97.105 Z19.8 F4200.0 E19.4565
+G1 X91.261 Y96.378 Z19.8 F4200.0 E19.4803
+G1 X96.378 Y91.261 Z19.8 F4200.0 E19.7172
+G1 X95.651 Y91.261 Z19.8 F4200.0 E19.7411
+G1 X91.261 Y95.651 Z19.8 F4200.0 E19.9443
+G1 X91.261 Y94.924 Z19.8 F4200.0 E19.9682
+G1 X94.924 Y91.261 Z19.8 F4200.0 E20.1378
+G1 X94.197 Y91.261 Z19.8 F4200.0 E20.1616
+G1 X91.261 Y94.197 Z19.8 F4200.0 E20.2975
+G1 X91.261 Y93.469 Z19.8 F4200.0 E20.3213
+G1 X93.469 Y91.261 Z19.8 F4200.0 E20.4236
+G1 X92.742 Y91.261 Z19.8 F4200.0 E20.4474
+G1 X91.261 Y92.742 Z19.8 F4200.0 E20.516
+G1 X91.261 Y92.015 Z19.8 F4200.0 E20.5398
+G1 X92.015 Y91.261 Z19.8 F4200.0 E20.5748
+G1 X91.288 Y91.261 Z19.8 F4200.0 E20.5986
+G1 X91.261 Y91.288 Z19.8 F4200.0 E20.5998
+G1 F900.0
+G1 E19.5998
+G1 F4200.0
diff --git a/README.md b/README.md
index d7d38e61d..ff377d9db 100644
--- a/README.md
+++ b/README.md
@@ -7,27 +7,38 @@ Printrun consists of printcore, pronsole and pronterface, and a small collection
# INSTALLING DEPENDENCIES
## Windows
+
+A precompiled version is available at http://koti.kapsi.fi/~kliment/printrun/
+
Download the following, and install in this order:
1. http://python.org/ftp/python/2.7.2/python-2.7.2.msi
2. http://pypi.python.org/packages/any/p/pyserial/pyserial-2.5.win32.exe
3. http://downloads.sourceforge.net/wxpython/wxPython2.8-win32-unicode-2.8.12.0-py27.exe
4. http://launchpad.net/pyreadline/1.7/1.7/+download/pyreadline-1.7.win32.exe
+ 5. http://pyglet.googlecode.com/files/pyglet-1.1.4.zip
+
+For the last one, you will need to unpack it, open a command terminal,
+go into the the directory you unpacked it in and run
+`python setup.py install`
## Ubuntu/Debian
-`sudo apt-get install python-serial python-wxgtk2.8`
+`sudo apt-get install python-serial python-wxgtk2.8 python-pyglet`
## Fedora 15
-`sudo yum install pyserial wxpython`
+`sudo yum install pyserial wxpython pyglet`
## Mac OS X Lion
+A precompiled version is available at http://koti.kapsi.fi/~kliment/printrun/
+
1. Ensure that the active Python is the system version. (`brew uninstall python` or other appropriate incantations)
2. Download an install [wxPython2.8-osx-unicode] matching to your python version (most likely 2.7 on Lion,
check with: python --version) from: http://wxpython.org/download.php#stable
Known to work PythonWX: http://superb-sea2.dl.sourceforge.net/project/wxpython/wxPython/2.8.12.1/wxPython2.8-osx-unicode-2.8.12.1-universal-py2.7.dmg
3. Download and unpack pyserial from http://pypi.python.org/packages/source/p/pyserial/pyserial-2.5.tar.gz
4. In a terminal, change to the folder you unzipped to, then type in: `sudo python setup.py install`
+ 5. Repeat 4. with http://http://pyglet.googlecode.com/files/pyglet-1.1.4.zip
The tools will probably run just fine in 64bit on Lion, you don't need to mess
with any of the 32bit settings. In case they don't, try
@@ -35,6 +46,9 @@ with any of the 32bit settings. In case they don't, try
in a terminal before running Pronterface
## Mac OS X (pre Lion)
+
+A precompiled version is available at http://koti.kapsi.fi/~kliment/printrun/
+
1. Download and install http://downloads.sourceforge.net/wxpython/wxPython2.8-osx-unicode-2.8.12.0-universal-py2.6.dmg
2. Grab the source for pyserial from http://pypi.python.org/packages/source/p/pyserial/pyserial-2.5.tar.gz
3. Unzip pyserial to a folder. Then, in a terminal, change to the folder you unzipped to, then type in:
@@ -52,6 +66,7 @@ This alternative approach is confirmed to work on Mac OS X 10.6.8.
`sudo python setup.py install`
Then repeat the same with http://launchpad.net/pyreadline/trunk/1.7/+download/pyreadline-1.7.zip
+Then repeat the same with http://http://pyglet.googlecode.com/files/pyglet-1.1.4.zip
# USING PRONTERFACE
@@ -59,6 +74,7 @@ To use pronterface, you need:
* python (ideally 2.6.x or 2.7.x),
* pyserial (or python-serial on ubuntu/debian),
+ * pyglet
* pyreadline (not needed on Linux) and
* wxPython
@@ -98,4 +114,19 @@ sender, or the following code example:
p.resume()
p.disconnect()
+# LICENSE
+
+```
+Printrun is 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
+(at your option) any later version.
+
+Printrun 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 Printrun. If not, see .
+```
diff --git a/gviz.py b/gviz.py
index 3678450a6..5e70a0357 100755
--- a/gviz.py
+++ b/gviz.py
@@ -1,12 +1,25 @@
+# This file is part of the Printrun suite.
+#
+# Printrun is 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
+# (at your option) any later version.
+#
+# Printrun 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 Printrun. If not, see .
+
import wx,time
class window(wx.Frame):
- def __init__(self,f,size=(600,600),bedsize=(200,200),grid=(10,50),extrusion_width=0.5):
- wx.Frame.__init__(self,None,title="Layer view (Use shift+mousewheel to switch layers)",size=(size[0],size[1]))
- self.p=gviz(self,size=size,bedsize=bedsize,grid=grid,extrusion_width=extrusion_width)
+ def __init__(self,f,size=(600,600),build_dimensions=[200,200,100,0,0,0],grid=(10,50),extrusion_width=0.5):
+ wx.Frame.__init__(self,None,title="Gcode view, shift to move view, mousewheel to set layer",size=(size[0],size[1]))
+ self.p=gviz(self,size=size,build_dimensions=build_dimensions,grid=grid,extrusion_width=extrusion_width)
s=time.time()
- for i in f:
- self.p.addgcode(i)
#print time.time()-s
self.initpos=[0,0]
self.p.Bind(wx.EVT_KEY_DOWN,self.key)
@@ -15,7 +28,7 @@ def __init__(self,f,size=(600,600),bedsize=(200,200),grid=(10,50),extrusion_widt
self.Bind(wx.EVT_MOUSEWHEEL,self.zoom)
self.p.Bind(wx.EVT_MOUSE_EVENTS,self.mouse)
self.Bind(wx.EVT_MOUSE_EVENTS,self.mouse)
-
+
def mouse(self,event):
if event.ButtonUp(wx.MOUSE_BTN_LEFT):
if(self.initpos is not None):
@@ -53,15 +66,15 @@ def zoom(self, event):
elif z < 0: self.p.zoom(event.GetX(),event.GetY(),1/1.2)
class gviz(wx.Panel):
- def __init__(self,parent,size=(200,200),bedsize=(200,200),grid=(10,50),extrusion_width=0.5):
+ def __init__(self,parent,size=(200,200),build_dimensions=[200,200,100,0,0,0],grid=(10,50),extrusion_width=0.5):
wx.Panel.__init__(self,parent,-1,size=(size[0],size[1]))
self.size=size
- self.bedsize=bedsize
+ self.build_dimensions=build_dimensions
self.grid=grid
self.lastpos=[0,0,0,0,0,0,0]
self.hilightpos=self.lastpos[:]
self.Bind(wx.EVT_PAINT,self.paint)
- self.Bind(wx.EVT_SIZE,lambda *e:(wx.CallAfter(self.repaint),wx.CallAfter(self.Refresh)))
+ self.Bind(wx.EVT_SIZE,self.resize)
self.lines={}
self.pens={}
self.arcs={}
@@ -69,7 +82,8 @@ def __init__(self,parent,size=(200,200),bedsize=(200,200),grid=(10,50),extrusion
self.layers=[]
self.layerindex=0
self.filament_width=extrusion_width # set it to 0 to disable scaling lines with zoom
- self.scale=[min(float(size[0])/bedsize[0],float(size[1])/bedsize[1])]*2
+ self.basescale=[min(float(size[0])/build_dimensions[0],float(size[1])/build_dimensions[1])]*2
+ self.scale=self.basescale
penwidth = max(1.0,self.filament_width*((self.scale[0]+self.scale[1])/2.0))
self.translate=[0.0,0.0]
self.mainpen=wx.Pen(wx.Colour(0,0,0),penwidth)
@@ -88,7 +102,11 @@ def clear(self):
self.lastpos=[0,0,0,0,0,0,0]
self.lines={}
self.pens={}
+ self.arcs={}
+ self.arcpens={}
self.layers=[]
+ self.hilight=[]
+ self.hilightarcs=[]
self.layerindex=0
self.showall=0
self.dirty=1
@@ -114,9 +132,16 @@ def setlayer(self,layer):
except:
pass
+ def resize(self,event):
+ size=self.GetClientSize()
+ newsize=min(float(size[0])/self.size[0],float(size[1])/self.size[1])
+ self.size=self.GetClientSize()
+ wx.CallAfter(self.zoom,0,0,newsize)
+
def zoom(self,x,y,factor):
self.scale = [s * factor for s in self.scale]
+
self.translate = [ x - (x-self.translate[0]) * factor,
y - (y-self.translate[1]) * factor]
penwidth = max(1.0,self.filament_width*((self.scale[0]+self.scale[1])/2.0))
@@ -126,6 +151,7 @@ def zoom(self,x,y,factor):
self.repaint()
self.Refresh()
+
def repaint(self):
self.blitmap=wx.EmptyBitmap(self.GetClientSize()[0],self.GetClientSize()[1],-1)
dc=wx.MemoryDC()
@@ -135,10 +161,10 @@ def repaint(self):
dc.SetPen(wx.Pen(wx.Colour(180,180,150)))
for grid_unit in self.grid:
if grid_unit > 0:
- for x in xrange(int(self.bedsize[0]/grid_unit)+1):
- dc.DrawLine(self.translate[0]+x*self.scale[0]*grid_unit,self.translate[1],self.translate[0]+x*self.scale[0]*grid_unit,self.translate[1]+self.scale[1]*self.bedsize[1])
- for y in xrange(int(self.bedsize[1]/grid_unit)+1):
- dc.DrawLine(self.translate[0],self.translate[1]+y*self.scale[1]*grid_unit,self.translate[0]+self.scale[0]*self.bedsize[0],self.translate[1]+y*self.scale[1]*grid_unit)
+ for x in xrange(int(self.build_dimensions[0]/grid_unit)+1):
+ dc.DrawLine(self.translate[0]+x*self.scale[0]*grid_unit,self.translate[1],self.translate[0]+x*self.scale[0]*grid_unit,self.translate[1]+self.scale[1]*self.build_dimensions[1])
+ for y in xrange(int(self.build_dimensions[1]/grid_unit)+1):
+ dc.DrawLine(self.translate[0],self.translate[1]+y*self.scale[1]*grid_unit,self.translate[0]+self.scale[0]*self.build_dimensions[0],self.translate[1]+y*self.scale[1]*grid_unit)
dc.SetPen(wx.Pen(wx.Colour(0,0,0)))
if not self.showall:
self.size = self.GetSize()
@@ -200,12 +226,19 @@ def paint(self,event):
dc.DrawBitmap(self.blitmap,0,0)
del dc
+ def addfile(self,gcodes=[]):
+ self.clear()
+ for i in gcodes:
+ self.addgcode(i)
+
def addgcode(self,gcode="M105",hilight=0):
gcode=gcode.split("*")[0]
gcode=gcode.split(";")[0]
gcode = gcode.lower().strip().split()
if len(gcode) == 0:
return
+ if gcode[0][0] == 'n':
+ gcode.pop(0)
def _readgcode():
target=self.lastpos[:]
@@ -236,13 +269,15 @@ def _readgcode():
return target
def _y(y):
- return self.bedsize[1]-y
+ return self.build_dimensions[1]-(y-self.build_dimensions[4])
+ def _x(x):
+ return x-self.build_dimensions[3]
start_pos = self.hilightpos[:] if hilight else self.lastpos[:]
if gcode[0] == "g1":
target = _readgcode()
- line = [ start_pos[0], _y(start_pos[1]), target[0], _y(target[1]) ]
+ line = [ _x(start_pos[0]), _y(start_pos[1]), _x(target[0]), _y(target[1]) ]
if not hilight:
self.lines[ target[2] ] += [line]
self.pens[ target[2] ] += [self.mainpen if target[3] != self.lastpos[3] else self.travelpen]
@@ -255,9 +290,9 @@ def _y(y):
if gcode[0] in [ "g2", "g3" ]:
target = _readgcode()
arc = []
- arc += [ start_pos[0], _y(start_pos[1]) ]
- arc += [ target[0], _y(target[1]) ]
- arc += [ start_pos[0] + target[5], _y(start_pos[1] + target[6]) ] # center
+ arc += [ _x(start_pos[0]), _y(start_pos[1]) ]
+ arc += [ _x(target[0]), _y(target[1]) ]
+ arc += [ _x(start_pos[0] + target[5]), _y(start_pos[1] + target[6]) ] # center
if gcode[0] == "g2": # clockwise, reverse endpoints
arc[0], arc[1], arc[2], arc[3] = arc[2], arc[3], arc[0], arc[1]
diff --git a/locale/de/LC_MESSAGES/de.po b/locale/de/LC_MESSAGES/de.po
deleted file mode 100755
index de01b90f8..000000000
--- a/locale/de/LC_MESSAGES/de.po
+++ /dev/null
@@ -1,632 +0,0 @@
-# Pronterface
-# Copyright (C) 2011 Jonathan Marsden
-# Jonathan Marsden , 2011.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: Pronterface jm1\n"
-"POT-Creation-Date: 2011-09-06 16:31+0100\n"
-"PO-Revision-Date: 2011-09-06 16:31+0100\n"
-"Last-Translator: Jonathan Marsden \n"
-"Language-Team: DE \n"
-"Language: \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-#: pronterface.py:10
-msgid "WX is not installed. This program requires WX to run."
-msgstr "WX ist nicht installiert. Dieses Programm erfordert WX zu laufen."
-
-#: pronterface.py:60
-msgid "Printer Interface"
-msgstr "Druckerschnittstelle"
-
-#: pronterface.py:72
-msgid "X+100"
-msgstr ""
-
-#: pronterface.py:73
-msgid "X+10"
-msgstr ""
-
-#: pronterface.py:74
-msgid "X+1"
-msgstr ""
-
-#: pronterface.py:75
-msgid "X+0.1"
-msgstr ""
-
-#: pronterface.py:76
-msgid "HomeX"
-msgstr "XHeimkehren"
-
-#: pronterface.py:77
-msgid "X-0.1"
-msgstr ""
-
-#: pronterface.py:78
-msgid "X-1"
-msgstr ""
-
-#: pronterface.py:79
-msgid "X-10"
-msgstr ""
-
-#: pronterface.py:80
-msgid "X-100"
-msgstr ""
-
-#: pronterface.py:81
-msgid "Y+100"
-msgstr ""
-
-#: pronterface.py:82
-msgid "Y+10"
-msgstr ""
-
-#: pronterface.py:83
-msgid "Y+1"
-msgstr ""
-
-#: pronterface.py:84
-msgid "Y+0.1"
-msgstr ""
-
-#: pronterface.py:85
-msgid "HomeY"
-msgstr "YHeimkehren"
-
-#: pronterface.py:86
-msgid "Y-0.1"
-msgstr ""
-
-#: pronterface.py:87
-msgid "Y-1"
-msgstr ""
-
-#: pronterface.py:88
-msgid "Y-10"
-msgstr ""
-
-#: pronterface.py:89
-msgid "Y-100"
-msgstr ""
-
-#: pronterface.py:90
-msgid "Motors off"
-msgstr "Motoren aus"
-
-#: pronterface.py:91
-msgid "Z+10"
-msgstr ""
-
-#: pronterface.py:92
-msgid "Z+1"
-msgstr ""
-
-#: pronterface.py:93
-msgid "Z+0.1"
-msgstr ""
-
-#: pronterface.py:94
-msgid "HomeZ"
-msgstr "ZHeimkehren"
-
-#: pronterface.py:95
-msgid "Z-0.1"
-msgstr ""
-
-#: pronterface.py:96
-msgid "Z-1"
-msgstr ""
-
-#: pronterface.py:97
-msgid "Z-10"
-msgstr ""
-
-#: pronterface.py:98
-msgid "Home"
-msgstr "Heimkehren"
-
-#: pronterface.py:99
-msgid "Check temp"
-msgstr "Temperatur prüfen"
-
-#: pronterface.py:100
-msgid "Extrude"
-msgstr ""
-
-#: pronterface.py:101
-msgid "Reverse"
-msgstr "Umkehren"
-
-#: pronterface.py:117
-msgid ""
-"# I moved all your custom buttons into .pronsolerc.\n"
-"# Please don't add them here any more.\n"
-"# Backup of your old buttons is in custombtn.old\n"
-msgstr ""
-
-#: pronterface.py:122
-msgid "Note!!! You have specified custom buttons in both custombtn.txt and .pronsolerc"
-msgstr "Beachten! Sie haben benutzerdefinierte Schaltflächen in custombtn.txt und .pronsolerc angegeben"
-
-#: pronterface.py:123
-msgid "Ignoring custombtn.txt. Remove all current buttons to revert to custombtn.txt"
-msgstr "Ignorieren custombtn.txt. Zur Nutzung custombtn.txt wieder entfernen alle gängigen Tasten"
-
-#: pronterface.py:146
-#: pronterface.py:434
-#: pronterface.py:971
-#: pronterface.py:1020
-#: pronterface.py:1134
-#: pronterface.py:1161
-#: pronterface.py:1175
-msgid "Print"
-msgstr "Drucken"
-
-#: pronterface.py:150
-msgid "Printer is now online"
-msgstr "Drucker wird jetzt online"
-
-#: pronterface.py:199
-msgid "Setting hotend temperature to "
-msgstr "Einstellen hotend Temperatur auf "
-
-#: pronterface.py:199
-#: pronterface.py:220
-msgid " degrees Celsius."
-msgstr " Grad Celsius."
-
-#: pronterface.py:203
-#: pronterface.py:224
-msgid "Printer is not online."
-msgstr "Drucker wird nicht online."
-
-#: pronterface.py:205
-msgid "You cannot set negative temperatures. To turn the hotend off entirely, set its temperature to 0."
-msgstr "Sie können keine negativen Temperaturen einstellen. Um den hotend ganz auszushalten, einstellen Sie die Temperatur auf 0"
-
-#: pronterface.py:207
-#: pronterface.py:228
-msgid "You must enter a temperature."
-msgstr "Sie müssen eine Temperatur eingeben."
-
-#: pronterface.py:220
-msgid "Setting bed temperature to "
-msgstr "Bett-Temperatur eingestellt: "
-
-#: pronterface.py:226
-msgid "You cannot set negative temperatures. To turn the bed off entirely, set its temperature to 0."
-msgstr "Sie können keine negativen Temperaturen einstellen. Um den Bett ganz auszushalten, einstellen Sie die Temperatur auf 0"
-
-#: pronterface.py:243
-msgid "Do you want to erase the macro?"
-msgstr "Möchten Sie das Makro löschen?"
-
-#: pronterface.py:247
-msgid "Cancelled."
-msgstr "Abgesagt."
-
-#: pronterface.py:277
-msgid "&Open..."
-msgstr "&Öffnen..."
-
-#: pronterface.py:277
-msgid " Opens file"
-msgstr " Öffnet eine Datei"
-
-#: pronterface.py:278
-msgid "&Edit..."
-msgstr "&Bearbeiten..."
-
-#: pronterface.py:278
-msgid " Edit open file"
-msgstr " Datei bearbeiten"
-
-#: pronterface.py:279
-msgid "E&xit"
-msgstr "Verlassen"
-
-#: pronterface.py:279
-msgid " Closes the Window"
-msgstr " schließt das Fenster"
-
-#: pronterface.py:280
-msgid "&File"
-msgstr ""
-
-#: pronterface.py:285
-msgid "&Macros"
-msgstr "&Makros"
-
-#: pronterface.py:286
-msgid "<&New...>"
-msgstr "<&Neu...>"
-
-#: pronterface.py:287
-msgid "&Options"
-msgstr "&Optionen"
-
-#: pronterface.py:287
-msgid " Options dialog"
-msgstr " Optionen-Dialog"
-
-#: pronterface.py:289
-msgid "SFACT Settings"
-msgstr "SFACT Einstellungen"
-
-#: pronterface.py:289
-msgid " Adjust SFACT settings"
-msgstr " SFACT Einstellungen anpassen"
-
-#: pronterface.py:292
-msgid "SFACT Quick Settings"
-msgstr "SFACT schnelle Einstellungen"
-
-#: pronterface.py:292
-msgid " Quickly adjust SFACT settings for active profile"
-msgstr " SFACT Einstellungen für aktive Profil schnell anpassen"
-
-#: pronterface.py:295
-msgid "&Settings"
-msgstr "&Einstellungen"
-
-#: pronterface.py:311
-msgid "Enter macro name"
-msgstr "Makro name eingeben"
-
-#: pronterface.py:314
-msgid "Macro name:"
-msgstr "Makro name:"
-
-#: pronterface.py:317
-msgid "Ok"
-msgstr ""
-
-#: pronterface.py:321
-#: pronterface.py:1197
-msgid "Cancel"
-msgstr "Absagen"
-
-#: pronterface.py:339
-msgid "Name '"
-msgstr ""
-
-#: pronterface.py:339
-msgid "' is being used by built-in command"
-msgstr ""
-
-#: pronterface.py:342
-msgid "Macro name may contain only alphanumeric symbols and underscores"
-msgstr ""
-
-#: pronterface.py:375
-msgid "Port:"
-msgstr ""
-
-#: pronterface.py:397
-msgid "Connect"
-msgstr "Verbinden"
-
-#: pronterface.py:399
-msgid "Connect to the printer"
-msgstr "Drucker Verbinden"
-
-#: pronterface.py:401
-msgid "Disconnect"
-msgstr "Trennen"
-
-#: pronterface.py:405
-msgid "Reset"
-msgstr "Zurücksetzen"
-
-#: pronterface.py:408
-#: pronterface.py:592
-msgid "Mini mode"
-msgstr "Mini-Modus"
-
-#: pronterface.py:414
-msgid ""
-"Monitor\n"
-"printer"
-msgstr ""
-"Drucker\n"
-"überwachen"
-
-#: pronterface.py:423
-msgid "Load file"
-msgstr "Datei laden"
-
-#: pronterface.py:426
-msgid "SD Upload"
-msgstr "SD hochladen"
-
-#: pronterface.py:430
-msgid "SD Print"
-msgstr "SD Drucken"
-
-#: pronterface.py:438
-#: pronterface.py:1021
-#: pronterface.py:1061
-#: pronterface.py:1109
-#: pronterface.py:1133
-#: pronterface.py:1160
-#: pronterface.py:1174
-msgid "Pause"
-msgstr ""
-
-#: pronterface.py:452
-msgid "Send"
-msgstr "Senden"
-
-#: pronterface.py:460
-#: pronterface.py:518
-msgid "mm/min"
-msgstr ""
-
-#: pronterface.py:462
-msgid "XY:"
-msgstr ""
-
-#: pronterface.py:464
-msgid "Z:"
-msgstr ""
-
-#: pronterface.py:481
-msgid "Heater:"
-msgstr "Heizung:"
-
-#: pronterface.py:489
-#: pronterface.py:501
-msgid "Set"
-msgstr ""
-
-#: pronterface.py:493
-msgid "Bed:"
-msgstr "Bett"
-
-#: pronterface.py:512
-msgid "mm"
-msgstr ""
-
-#: pronterface.py:551
-#: pronterface.py:846
-#: pronterface.py:1055
-msgid "Not connected to printer."
-msgstr "Keine Verbindung zum Drucker."
-
-#: pronterface.py:599
-msgid "Full mode"
-msgstr "voll-Modus"
-
-#: pronterface.py:637
-msgid "Defines custom button. Usage: button \"title\" [/c \"colour\"] command"
-msgstr ""
-
-#: pronterface.py:659
-msgid "Custom button number should be between 0 and 63"
-msgstr ""
-
-#: pronterface.py:749
-#, python-format
-msgid "Edit custom button '%s'"
-msgstr ""
-
-#: pronterface.py:751
-msgid "Move left <<"
-msgstr ""
-
-#: pronterface.py:754
-msgid "Move right >>"
-msgstr ""
-
-#: pronterface.py:758
-#, python-format
-msgid "Remove custom button '%s'"
-msgstr ""
-
-#: pronterface.py:761
-msgid "Add custom button"
-msgstr ""
-
-#: pronterface.py:776
-msgid "event object missing"
-msgstr ""
-
-#: pronterface.py:804
-msgid "Invalid period given."
-msgstr ""
-
-#: pronterface.py:807
-msgid "Monitoring printer."
-msgstr ""
-
-#: pronterface.py:809
-msgid "Done monitoring."
-msgstr ""
-
-#: pronterface.py:828
-msgid "Printer is online. "
-msgstr ""
-
-#: pronterface.py:830
-#: pronterface.py:969
-#: pronterface.py:1019
-msgid "Loaded "
-msgstr ""
-
-#: pronterface.py:833
-msgid "Hotend"
-msgstr ""
-
-#: pronterface.py:833
-msgid "Bed"
-msgstr "Bett"
-
-#: pronterface.py:836
-#, python-format
-msgid " SD printing:%04.2f %%"
-msgstr ""
-
-#: pronterface.py:838
-#, python-format
-msgid " Printing:%04.2f %%"
-msgstr ""
-
-#: pronterface.py:892
-msgid "Opening file failed."
-msgstr ""
-
-#: pronterface.py:898
-msgid "Starting print"
-msgstr ""
-
-#: pronterface.py:921
-msgid "Select the file to print"
-msgstr ""
-
-#: pronterface.py:921
-msgid "Pick SD file"
-msgstr ""
-
-#: pronterface.py:949
-msgid "Skeinforge execution failed."
-msgstr ""
-
-#: pronterface.py:956
-msgid "Skeining..."
-msgstr ""
-
-#: pronterface.py:969
-#: pronterface.py:1019
-#, python-format
-msgid ", %d lines"
-msgstr ""
-
-#: pronterface.py:978
-msgid "Skeining "
-msgstr ""
-
-#: pronterface.py:980
-msgid ""
-"Skeinforge not found. \n"
-"Please copy Skeinforge into a directory named \"skeinforge\" in the same directory as this file."
-msgstr ""
-
-#: pronterface.py:999
-msgid "Open file to print"
-msgstr "Zu druckenden Datei öffnen"
-
-#: pronterface.py:1000
-msgid "STL and GCODE files (;*.gcode;*.g;*.stl;*.STL;)"
-msgstr ""
-
-#: pronterface.py:1007
-msgid "File not found!"
-msgstr ""
-
-#: pronterface.py:1029
-msgid "mm of filament used in this print\n"
-msgstr ""
-
-#: pronterface.py:1030
-#: pronterface.py:1031
-#: pronterface.py:1032
-msgid "the print goes from"
-msgstr ""
-
-#: pronterface.py:1030
-#: pronterface.py:1031
-#: pronterface.py:1032
-msgid "mm to"
-msgstr ""
-
-#: pronterface.py:1030
-msgid ""
-"mm in X\n"
-"and is"
-msgstr ""
-
-#: pronterface.py:1030
-#: pronterface.py:1031
-msgid "mm wide\n"
-msgstr ""
-
-#: pronterface.py:1031
-msgid ""
-"mm in Y\n"
-"and is"
-msgstr ""
-
-#: pronterface.py:1032
-msgid ""
-"mm in Z\n"
-"and is"
-msgstr ""
-
-#: pronterface.py:1032
-msgid "mm high\n"
-msgstr ""
-
-#: pronterface.py:1052
-msgid "No file loaded. Please use load first."
-msgstr ""
-
-#: pronterface.py:1063
-msgid "Restart"
-msgstr "Neustart"
-
-#: pronterface.py:1067
-msgid "File upload complete"
-msgstr ""
-
-#: pronterface.py:1086
-msgid "Pick SD filename"
-msgstr ""
-
-#: pronterface.py:1102
-msgid "Resume"
-msgstr ""
-
-#: pronterface.py:1168
-msgid "Are you sure you want to reset the printer?"
-msgstr "Möchten Sie wirklich, der Drucker Zurückzusetzen?"
-
-#: pronterface.py:1168
-msgid "Reset?"
-msgstr "Zurücksetzen?"
-
-#: pronterface.py:1193
-msgid "Save"
-msgstr ""
-
-#: pronterface.py:1248
-msgid "Edit settings"
-msgstr "Einstellungen bearbeiten"
-
-#: pronterface.py:1250
-msgid "Defaults"
-msgstr "Standardwerte"
-
-#: pronterface.py:1272
-msgid "Custom button"
-msgstr ""
-
-#: pronterface.py:1280
-msgid "Button title"
-msgstr ""
-
-#: pronterface.py:1283
-msgid "Command"
-msgstr ""
-
-#: pronterface.py:1292
-msgid "Color"
-msgstr "Farbe"
-
-#~ msgid "&Print"
-#~ msgstr "&Drucken"
diff --git a/locale/de/LC_MESSAGES/plater.mo b/locale/de/LC_MESSAGES/plater.mo
new file mode 100644
index 000000000..902c7cd22
Binary files /dev/null and b/locale/de/LC_MESSAGES/plater.mo differ
diff --git a/locale/de/LC_MESSAGES/plater.po b/locale/de/LC_MESSAGES/plater.po
new file mode 100644
index 000000000..32b21146b
--- /dev/null
+++ b/locale/de/LC_MESSAGES/plater.po
@@ -0,0 +1,89 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: Plater\n"
+"POT-Creation-Date: 2012-01-09 15:07+CET\n"
+"PO-Revision-Date: \n"
+"Last-Translator: Christian Metzen \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: German\n"
+"X-Poedit-Country: GERMANY\n"
+
+#: plater.py:223
+msgid "Plate building tool"
+msgstr "Plate building tool"
+
+#: plater.py:229
+msgid "Clear"
+msgstr "Löschen"
+
+#: plater.py:230
+msgid "Load"
+msgstr "Laden"
+
+#: plater.py:232
+msgid "Export"
+msgstr "Exportieren"
+
+#: plater.py:235
+msgid "Done"
+msgstr "Fertig"
+
+#: plater.py:237
+msgid "Cancel"
+msgstr "Abbrechen"
+
+#: plater.py:239
+msgid "Snap to Z = 0"
+msgstr "Einrasten auf Z = 0"
+
+#: plater.py:240
+msgid "Put at 100, 100"
+msgstr "Auf 100, 100 setzen"
+
+#: plater.py:241
+msgid "Delete"
+msgstr "Löschen"
+
+#: plater.py:242
+msgid "Auto"
+msgstr "Auto"
+
+#: plater.py:266
+msgid "Autoplating"
+msgstr "Autoplating"
+
+#: plater.py:294
+msgid "Bed full, sorry sir :("
+msgstr "Das Druckbett ist voll! Sorry."
+
+#: plater.py:304
+msgid "Are you sure you want to clear the grid? All unsaved changes will be lost."
+msgstr "Bist du sicher dass du das Raster leeren willst? Alle ungesicherten Änderungen gehen verloren."
+
+#: plater.py:304
+msgid "Clear the grid?"
+msgstr "Raster leeren?"
+
+#: plater.py:346
+msgid "Pick file to save to"
+msgstr "Wähle die zu sichernde Datei"
+
+#: plater.py:347
+msgid "STL files (;*.stl;)"
+msgstr "STL Dateien (;*.stl;)"
+
+#: plater.py:367
+msgid "wrote "
+msgstr "geschrieben"
+
+#: plater.py:370
+msgid "Pick file to load"
+msgstr "Wähle die zu ladende Datei"
+
+#: plater.py:371
+msgid "STL files (;*.stl;)|*.stl|OpenSCAD files (;*.scad;)|*.scad"
+msgstr "STL Dateien (;*.stl;)|*.stl|OpenSCAD Dateien (;*.scad;)|*.scad"
+
diff --git a/locale/de/LC_MESSAGES/pronterface.mo b/locale/de/LC_MESSAGES/pronterface.mo
index 3079929d6..a1a42cd39 100644
Binary files a/locale/de/LC_MESSAGES/pronterface.mo and b/locale/de/LC_MESSAGES/pronterface.mo differ
diff --git a/locale/de/LC_MESSAGES/pronterface.po b/locale/de/LC_MESSAGES/pronterface.po
new file mode 100644
index 000000000..e6c864d06
--- /dev/null
+++ b/locale/de/LC_MESSAGES/pronterface.po
@@ -0,0 +1,702 @@
+# Pronterface
+# Copyright (C) 2011 Jonathan Marsden
+# Jonathan Marsden , 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Pronterface jm1\n"
+"POT-Creation-Date: 2012-01-19 09:21+CET\n"
+"PO-Revision-Date: 2012-01-23 10:01+0100\n"
+"Last-Translator: Christian Metzen \n"
+"Language-Team: DE \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: \n"
+"Generated-By: pygettext.py 1.5\n"
+
+#: pronsole.py:250
+msgid "Communications Speed (default: 115200)"
+msgstr "Kommunikationsgeschwindigkeit (Vorgabe: 115200)"
+
+#: pronsole.py:251
+msgid "Heated Build Platform temp for ABS (default: 110 deg C)"
+msgstr "Heizbett Temp. für ABS (Vorgabe: 110 Grad Celsius)"
+
+#: pronsole.py:252
+msgid "Heated Build Platform temp for PLA (default: 60 deg C)"
+msgstr "Heizbett Temp. für PLA (Vorgabe: 60 Grad Celsius)"
+
+#: pronsole.py:253
+msgid "Feedrate for Control Panel Moves in Extrusions (default: 300mm/min)"
+msgstr "Vorschub Control Panel Bewegungen Extrudierung (Vorgabe: 300mm/min)"
+
+#: pronsole.py:254
+msgid "Port used to communicate with printer"
+msgstr "Port für Druckerkommunikation"
+
+#: pronsole.py:255
+msgid ""
+"Slice command\n"
+" default:\n"
+" python skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_craft.py $s)"
+msgstr ""
+"Kommando Slicing\n"
+" Vorgabe:\n"
+" python skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_craft.py $s)"
+
+#: pronsole.py:256
+msgid ""
+"Slice settings command\n"
+" default:\n"
+" python skeinforge/skeinforge_application/skeinforge.py"
+msgstr ""
+"Kommando Slicing Einstellungen\n"
+" Vorgabe:\n"
+" python skeinforge/skeinforge_application/skeinforge.py"
+
+#: pronsole.py:257
+msgid "Extruder temp for ABS (default: 230 deg C)"
+msgstr "Extruder Temperatur für ABS (Vorgabe: 230 Grad Celsius)"
+
+#: pronsole.py:258
+msgid "Extruder temp for PLA (default: 185 deg C)"
+msgstr "Extruder Temperatur für PLA (Vorgabe: 185 Grad Celsius)"
+
+#: pronsole.py:259
+msgid "Feedrate for Control Panel Moves in X and Y (default: 3000mm/min)"
+msgstr "Vorschub Control Panel Bewegungen X und Y (Vorgabe: 3000mm/min)"
+
+#: pronsole.py:260
+msgid "Feedrate for Control Panel Moves in Z (default: 200mm/min)"
+msgstr "Vorschub Control Panel Bewegungen Z (Vorgabe: 200mm/min)"
+
+#: pronterface.py:15
+msgid "WX is not installed. This program requires WX to run."
+msgstr "WX ist nicht installiert. Dieses Programm erfordert WX zum Starten."
+
+#: pronterface.py:66
+msgid ""
+"Dimensions of Build Platform\n"
+" & optional offset of origin\n"
+"\n"
+"Examples:\n"
+" XXXxYYY\n"
+" XXX,YYY,ZZZ\n"
+" XXXxYYYxZZZ+OffX+OffY+OffZ"
+msgstr ""
+"Abmessungen der Bauplattform\n"
+" & optional Versatz vom Ausgangspunkt\n"
+"\n"
+"Beispiel:\n"
+" XXXxYYY\n"
+" XXX,YYY,ZZZ\n"
+" XXXxYYYxZZZ+OffX+OffY+OffZ"
+
+#: pronterface.py:67
+msgid "Last Set Temperature for the Heated Print Bed"
+msgstr "Letzte gesetzte Temperatur für das Heizbett"
+
+#: pronterface.py:68
+msgid "Folder of last opened file"
+msgstr "Verzeichniss der zuletzt geöffneten Datei"
+
+#: pronterface.py:69
+msgid "Last Temperature of the Hot End"
+msgstr "Letzte Hotend Temperatur"
+
+#: pronterface.py:70
+msgid "Width of Extrusion in Preview (default: 0.5)"
+msgstr "Vorschaubreite der Extrudierung (Vorgabe: 0.5)"
+
+#: pronterface.py:71
+msgid "Fine Grid Spacing (default: 10)"
+msgstr "Feiner Rasterabstand (Vorgabe: 10)"
+
+#: pronterface.py:72
+msgid "Coarse Grid Spacing (default: 50)"
+msgstr "Grober Rasterabstand (Vorgabe: 50)"
+
+#: pronterface.py:73
+msgid "Pronterface background color (default: #FFFFFF)"
+msgstr "Pronterface Hintergrundfarbe (Vorgabe: #FFFFFF)"
+
+#: pronterface.py:76
+msgid "Printer Interface"
+msgstr "Printer Interface"
+
+#: pronterface.py:93
+msgid "Motors off"
+msgstr "Motoren aus"
+
+#: pronterface.py:94
+msgid "Check temp"
+msgstr "Temperatur prüfen"
+
+#: pronterface.py:95
+msgid "Extrude"
+msgstr "Extrudieren"
+
+#: pronterface.py:96
+msgid "Reverse"
+msgstr "Rückwärts"
+
+#: pronterface.py:114
+msgid ""
+"# I moved all your custom buttons into .pronsolerc.\n"
+"# Please don't add them here any more.\n"
+"# Backup of your old buttons is in custombtn.old\n"
+msgstr ""
+"# Alle individuellen Buttons in .pronsolerc eingetragen.\n"
+"# Bitte fügen Sie sie hier nicht mehr ein.\n"
+"# Backup Ihrer alten Buttons befindet sich in custombtn.old\n"
+
+#: pronterface.py:119
+msgid "Note!!! You have specified custom buttons in both custombtn.txt and .pronsolerc"
+msgstr "Achtung! Sie haben benutzerdefinierte Buttons in custombtn.txt und .pronsolerc angegeben"
+
+#: pronterface.py:120
+msgid "Ignoring custombtn.txt. Remove all current buttons to revert to custombtn.txt"
+msgstr "Ignoriere custombtn.txt. Alle aktuellen Buttons entfernen um wieder zu custombtn.txt zurückzukehren"
+
+#: pronterface.py:148
+#: pronterface.py:499
+#: pronterface.py:1319
+#: pronterface.py:1373
+#: pronterface.py:1495
+#: pronterface.py:1529
+#: pronterface.py:1544
+msgid "Print"
+msgstr "Drucken"
+
+#: pronterface.py:152
+msgid "Printer is now online."
+msgstr "Drucker ist jetzt Online."
+
+#: pronterface.py:212
+msgid "Setting hotend temperature to "
+msgstr "Setze Hotend Temperatur auf "
+
+#: pronterface.py:212
+#: pronterface.py:248
+msgid " degrees Celsius."
+msgstr " Grad Celsius."
+
+#: pronterface.py:231
+#: pronterface.py:267
+#: pronterface.py:325
+msgid "Printer is not online."
+msgstr "Drucker ist nicht online."
+
+#: pronterface.py:233
+msgid "You cannot set negative temperatures. To turn the hotend off entirely, set its temperature to 0."
+msgstr "Sie können keine negativen Temperaturen einstellen. Um das Hotend ganz auszuschalten, Temperatur auf 0 setzen."
+
+#: pronterface.py:248
+msgid "Setting bed temperature to "
+msgstr "Setze Heizbett Temperatur auf"
+
+#: pronterface.py:269
+msgid "You cannot set negative temperatures. To turn the bed off entirely, set its temperature to 0."
+msgstr "Sie können keine negativen Temperaturen einstellen. Um das Heizbett ganz auszuschalten, Temperatur auf 0 setzen."
+
+#: pronterface.py:271
+msgid "You must enter a temperature."
+msgstr "Sie müssen eine Temperatur eingeben."
+
+#: pronterface.py:286
+msgid "Do you want to erase the macro?"
+msgstr "Möchten Sie das Makro löschen?"
+
+#: pronterface.py:290
+msgid "Cancelled."
+msgstr "Abgebrochen."
+
+#: pronterface.py:331
+msgid " Opens file"
+msgstr " Öffnet eine Datei"
+
+#: pronterface.py:331
+msgid "&Open..."
+msgstr "&Öffnen..."
+
+#: pronterface.py:332
+msgid " Edit open file"
+msgstr " Offene Datei bearbeiten"
+
+#: pronterface.py:332
+msgid "&Edit..."
+msgstr "&Bearbeiten..."
+
+#: pronterface.py:333
+msgid " Clear output console"
+msgstr " Ausgabe Konsole leeren"
+
+#: pronterface.py:333
+msgid "Clear console"
+msgstr "Konsole leeren"
+
+#: pronterface.py:334
+msgid " Project slices"
+msgstr " Projekt Slices"
+
+#: pronterface.py:334
+msgid "Projector"
+msgstr "Projektor"
+
+#: pronterface.py:335
+msgid " Closes the Window"
+msgstr " Schliesst das Fenster"
+
+#: pronterface.py:335
+msgid "E&xit"
+msgstr "&Verlassen"
+
+#: pronterface.py:336
+msgid "&File"
+msgstr "&Datei"
+
+#: pronterface.py:341
+msgid "&Macros"
+msgstr "&Makros"
+
+#: pronterface.py:342
+msgid "<&New...>"
+msgstr "<&Neu...>"
+
+#: pronterface.py:343
+msgid " Options dialog"
+msgstr " Optionen Dialog"
+
+#: pronterface.py:343
+msgid "&Options"
+msgstr "&Optionen"
+
+#: pronterface.py:345
+msgid " Adjust slicing settings"
+msgstr " Slicing Einstellungen anpassen"
+
+#: pronterface.py:345
+msgid "Slicing Settings"
+msgstr "Slicing Einstellungen"
+
+#: pronterface.py:352
+msgid "&Settings"
+msgstr "&Einstellungen"
+
+#: pronterface.py:368
+msgid "Enter macro name"
+msgstr "Makro Name eingeben"
+
+#: pronterface.py:371
+msgid "Macro name:"
+msgstr "Makro Name:"
+
+#: pronterface.py:374
+msgid "Ok"
+msgstr "Ok"
+
+#: pronterface.py:378
+#: pronterface.py:1330
+#: pronterface.py:1587
+msgid "Cancel"
+msgstr "Abbrechen"
+
+#: pronterface.py:396
+msgid "' is being used by built-in command"
+msgstr "' wird durch eingebautes Kommando genutzt"
+
+#: pronterface.py:396
+msgid "Name '"
+msgstr "Name '"
+
+#: pronterface.py:399
+msgid "Macro name may contain only alphanumeric symbols and underscores"
+msgstr "Makro Name darf nur alphanumerische Zeichen und Unterstriche enthalten"
+
+#: pronterface.py:448
+msgid "Port"
+msgstr "Port:"
+
+#: pronterface.py:467
+msgid "Connect"
+msgstr "Verbinden"
+
+#: pronterface.py:469
+msgid "Connect to the printer"
+msgstr "Drucker Verbinden"
+
+#: pronterface.py:471
+msgid "Reset"
+msgstr "Zurücksetzen"
+
+#: pronterface.py:474
+#: pronterface.py:751
+msgid "Mini mode"
+msgstr "Mini-Modus"
+
+#: pronterface.py:478
+msgid "Monitor Printer"
+msgstr "Drucker überwachen"
+
+#: pronterface.py:488
+msgid "Load file"
+msgstr "Datei laden"
+
+#: pronterface.py:491
+msgid "Compose"
+msgstr "Zusammenstellen"
+
+#: pronterface.py:495
+msgid "SD"
+msgstr "SD"
+
+#: pronterface.py:503
+#: pronterface.py:1374
+#: pronterface.py:1419
+#: pronterface.py:1469
+#: pronterface.py:1494
+#: pronterface.py:1528
+#: pronterface.py:1543
+msgid "Pause"
+msgstr "Pause"
+
+#: pronterface.py:516
+msgid "Send"
+msgstr "Senden"
+
+#: pronterface.py:524
+#: pronterface.py:625
+msgid "mm/min"
+msgstr "mm/min"
+
+#: pronterface.py:526
+msgid "XY:"
+msgstr "XY:"
+
+#: pronterface.py:528
+msgid "Z:"
+msgstr "Z:"
+
+#: pronterface.py:551
+#: pronterface.py:632
+msgid "Heater:"
+msgstr "Heizelement:"
+
+#: pronterface.py:554
+#: pronterface.py:574
+msgid "Off"
+msgstr "Aus"
+
+#: pronterface.py:566
+#: pronterface.py:586
+msgid "Set"
+msgstr "Ein"
+
+#: pronterface.py:571
+#: pronterface.py:634
+msgid "Bed:"
+msgstr "Heizbett:"
+
+#: pronterface.py:619
+msgid "mm"
+msgstr "mm"
+
+#: pronterface.py:677
+#: pronterface.py:1182
+#: pronterface.py:1413
+msgid "Not connected to printer."
+msgstr "Keine Verbindung zum Drucker."
+
+#: pronterface.py:706
+msgid "SD Upload"
+msgstr "SD Laden"
+
+#: pronterface.py:710
+msgid "SD Print"
+msgstr "SD Drucken"
+
+#: pronterface.py:758
+msgid "Full mode"
+msgstr "Voll-Modus"
+
+#: pronterface.py:783
+msgid "Execute command: "
+msgstr "Kommando ausführen:"
+
+#: pronterface.py:794
+msgid "click to add new custom button"
+msgstr "Individuellen Button hinzufügen"
+
+#: pronterface.py:813
+msgid "Defines custom button. Usage: button \"title\" [/c \"colour\"] command"
+msgstr "Definiert einen individuellen Button. Nutzung: button \"title\" [/c \"colour\"] command"
+
+#: pronterface.py:835
+msgid "Custom button number should be between 0 and 63"
+msgstr "Nummer des individuellen Button sollte zwischen 0 und 63 sein."
+
+#: pronterface.py:927
+msgid "Edit custom button '%s'"
+msgstr "Individuellen Button '%s' bearbeiten"
+
+#: pronterface.py:929
+msgid "Move left <<"
+msgstr "Links bewegen <<"
+
+#: pronterface.py:932
+msgid "Move right >>"
+msgstr "Rechts bewegen >>"
+
+#: pronterface.py:936
+msgid "Remove custom button '%s'"
+msgstr "Individuellen Button '%s' entfernen"
+
+#: pronterface.py:939
+msgid "Add custom button"
+msgstr "Individuellen Button hinzufuegen"
+
+#: pronterface.py:1084
+msgid "event object missing"
+msgstr "Ereigniss Objekt fehlt"
+
+#: pronterface.py:1112
+msgid "Invalid period given."
+msgstr "Ungültiger Abschnitt angegeben."
+
+#: pronterface.py:1115
+msgid "Monitoring printer."
+msgstr "Ãœberwache Drucker."
+
+#: pronterface.py:1117
+msgid "Done monitoring."
+msgstr "Ãœberwachung abgeschlossen."
+
+#: pronterface.py:1139
+msgid "Printer is online. "
+msgstr "Drucker ist online."
+
+#: pronterface.py:1141
+#: pronterface.py:1317
+#: pronterface.py:1372
+msgid "Loaded "
+msgstr "Geladen"
+
+#: pronterface.py:1144
+msgid "Bed"
+msgstr "Heizbett"
+
+#: pronterface.py:1144
+msgid "Hotend"
+msgstr "Hotend"
+
+#: pronterface.py:1154
+msgid " SD printing:%04.2f %%"
+msgstr "SD Drucken:%04.2f %%"
+
+#: pronterface.py:1157
+msgid " Printing:%04.2f %% |"
+msgstr " Drucken:%04.2f %% |"
+
+#: pronterface.py:1158
+msgid " Line# "
+msgstr "Zeile#"
+
+#: pronterface.py:1158
+msgid " lines |"
+msgstr " Zeilen |"
+
+#: pronterface.py:1158
+msgid "of "
+msgstr "von"
+
+#: pronterface.py:1163
+msgid " Est: "
+msgstr " Erw:"
+
+#: pronterface.py:1164
+msgid " of: "
+msgstr " von: "
+
+#: pronterface.py:1165
+msgid " Remaining | "
+msgstr " Verbleibend | "
+
+#: pronterface.py:1166
+msgid " Z: %0.2f mm"
+msgstr " Z: %0.2f mm"
+
+#: pronterface.py:1233
+msgid "Opening file failed."
+msgstr "Datei öffnen fehlgeschlagen."
+
+#: pronterface.py:1239
+msgid "Starting print"
+msgstr "Starte Druck"
+
+#: pronterface.py:1262
+msgid "Pick SD file"
+msgstr "Wähle SD Datei"
+
+#: pronterface.py:1262
+msgid "Select the file to print"
+msgstr "Wähle Druckdatei"
+
+#: pronterface.py:1297
+msgid "Failed to execute slicing software: "
+msgstr "Fehler beim Ausführen der Slicing Software:"
+
+#: pronterface.py:1304
+msgid "Slicing..."
+msgstr "Slicing..."
+
+#: pronterface.py:1317
+#: pronterface.py:1372
+msgid ", %d lines"
+msgstr ", %d Zeilen"
+
+#: pronterface.py:1324
+msgid "Load File"
+msgstr "Datei laden"
+
+#: pronterface.py:1331
+msgid "Slicing "
+msgstr "Slicing"
+
+#: pronterface.py:1350
+msgid "Open file to print"
+msgstr "Öffne zu druckende Datei"
+
+#: pronterface.py:1351
+msgid "OBJ, STL, and GCODE files (;*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ;)"
+msgstr "OBJ,STL und GCODE Dateien (;*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ;)"
+
+#: pronterface.py:1358
+msgid "File not found!"
+msgstr "Datei nicht gefunden!"
+
+#: pronterface.py:1382
+msgid "mm of filament used in this print\n"
+msgstr "mm Filament in Druck genutzt\n"
+
+#: pronterface.py:1383
+msgid ""
+"mm in X\n"
+"and is"
+msgstr ""
+"mm in X\n"
+"und ist"
+
+#: pronterface.py:1383
+#: pronterface.py:1384
+msgid "mm wide\n"
+msgstr "mm breit\n"
+
+#: pronterface.py:1383
+#: pronterface.py:1384
+#: pronterface.py:1385
+msgid "mm to"
+msgstr "mm bis"
+
+#: pronterface.py:1383
+#: pronterface.py:1384
+#: pronterface.py:1385
+msgid "the print goes from"
+msgstr "Der Druck verläuft von"
+
+#: pronterface.py:1384
+msgid ""
+"mm in Y\n"
+"and is"
+msgstr ""
+"mm in Y\n"
+"und ist"
+
+#: pronterface.py:1385
+msgid "mm high\n"
+msgstr "mm hoch\n"
+
+#: pronterface.py:1385
+msgid ""
+"mm in Z\n"
+"and is"
+msgstr ""
+"mm in Z\n"
+"und ist"
+
+#: pronterface.py:1386
+msgid "Estimated duration (pessimistic): "
+msgstr "Geschätze Dauer (pessimistisch):"
+
+#: pronterface.py:1410
+msgid "No file loaded. Please use load first."
+msgstr "Keine Datei geladen. Benutze zuerst laden."
+
+#: pronterface.py:1421
+msgid "Restart"
+msgstr "Neustart"
+
+#: pronterface.py:1425
+msgid "File upload complete"
+msgstr "Datei Upload komplett"
+
+#: pronterface.py:1444
+msgid "Pick SD filename"
+msgstr "Wähle SD Dateiname"
+
+#: pronterface.py:1452
+msgid "Paused."
+msgstr "Pausiert."
+
+#: pronterface.py:1462
+msgid "Resume"
+msgstr "Fortsetzen"
+
+#: pronterface.py:1478
+msgid "Connecting..."
+msgstr "Verbinde..."
+
+#: pronterface.py:1509
+msgid "Disconnected."
+msgstr "Getrennt."
+
+#: pronterface.py:1536
+msgid "Reset."
+msgstr "Zurücksetzen."
+
+#: pronterface.py:1537
+msgid "Are you sure you want to reset the printer?"
+msgstr "Möchten Sie den Drucker wirklich zurücksetzen?"
+
+#: pronterface.py:1537
+msgid "Reset?"
+msgstr "Zurücksetzen?"
+
+#: pronterface.py:1583
+msgid "Save"
+msgstr "Speichern"
+
+#: pronterface.py:1639
+msgid "Edit settings"
+msgstr "Einstellungen bearbeiten"
+
+#: pronterface.py:1641
+msgid "Defaults"
+msgstr "Standardwerte"
+
+#: pronterface.py:1670
+msgid "Custom button"
+msgstr "Individueller Button"
+
+#: pronterface.py:1675
+msgid "Button title"
+msgstr "Button Titel"
+
+#: pronterface.py:1678
+msgid "Command"
+msgstr "Kommando"
+
+#: pronterface.py:1687
+msgid "Color"
+msgstr "Farbe"
+
diff --git a/locale/plater.pot b/locale/plater.pot
new file mode 100644
index 000000000..c4daabdad
--- /dev/null
+++ b/locale/plater.pot
@@ -0,0 +1,93 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR ORGANIZATION
+# FIRST AUTHOR , YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2012-01-09 15:07+CET\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: ENCODING\n"
+"Generated-By: pygettext.py 1.5\n"
+
+
+#: plater.py:223
+msgid "Plate building tool"
+msgstr ""
+
+#: plater.py:229
+msgid "Clear"
+msgstr ""
+
+#: plater.py:230
+msgid "Load"
+msgstr ""
+
+#: plater.py:232
+msgid "Export"
+msgstr ""
+
+#: plater.py:235
+msgid "Done"
+msgstr ""
+
+#: plater.py:237
+msgid "Cancel"
+msgstr ""
+
+#: plater.py:239
+msgid "Snap to Z = 0"
+msgstr ""
+
+#: plater.py:240
+msgid "Put at 100, 100"
+msgstr ""
+
+#: plater.py:241
+msgid "Delete"
+msgstr ""
+
+#: plater.py:242
+msgid "Auto"
+msgstr ""
+
+#: plater.py:266
+msgid "Autoplating"
+msgstr ""
+
+#: plater.py:294
+msgid "Bed full, sorry sir :("
+msgstr ""
+
+#: plater.py:304
+msgid "Are you sure you want to clear the grid? All unsaved changes will be lost."
+msgstr ""
+
+#: plater.py:304
+msgid "Clear the grid?"
+msgstr ""
+
+#: plater.py:346
+msgid "Pick file to save to"
+msgstr ""
+
+#: plater.py:347
+msgid "STL files (;*.stl;)"
+msgstr ""
+
+#: plater.py:367
+msgid "wrote "
+msgstr ""
+
+#: plater.py:370
+msgid "Pick file to load"
+msgstr ""
+
+#: plater.py:371
+msgid "STL files (;*.stl;)|*.stl|OpenSCAD files (;*.scad;)|*.scad"
+msgstr ""
+
diff --git a/locale/pronterface.pot b/locale/pronterface.pot
index 7e0773765..3429d9ace 100644
--- a/locale/pronterface.pot
+++ b/locale/pronterface.pot
@@ -1,537 +1,654 @@
-# Pronterface Message Catalog Template
-# Copyright (C) 2011 Jonathan Marsden
-# Jonathan Marsden , 2011.
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR ORGANIZATION
+# FIRST AUTHOR , YEAR.
#
msgid ""
msgstr ""
-"Project-Id-Version: Pronterface jm1\n"
-"POT-Creation-Date: 2011-08-06 13:27+PDT\n"
-"PO-Revision-Date: 2011-08-06 13:27+PDT\n"
-"Last-Translator: Jonathan Marsden \n"
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2012-01-19 09:21+CET\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: UTF-8\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
+#: pronsole.py:250
+msgid "Communications Speed (default: 115200)"
+msgstr ""
+
+#: pronsole.py:251
+msgid "Heated Build Platform temp for ABS (default: 110 deg C)"
+msgstr ""
+
+#: pronsole.py:252
+msgid "Heated Build Platform temp for PLA (default: 60 deg C)"
+msgstr ""
+
+#: pronsole.py:253
+msgid "Feedrate for Control Panel Moves in Extrusions (default: 300mm/min)"
+msgstr ""
+
+#: pronsole.py:254
+msgid "Port used to communicate with printer"
+msgstr ""
+
+#: pronsole.py:255
+msgid ""
+"Slice command\n"
+" default:\n"
+" python skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_craft.py $s)"
+msgstr ""
+
+#: pronsole.py:256
+msgid ""
+"Slice settings command\n"
+" default:\n"
+" python skeinforge/skeinforge_application/skeinforge.py"
+msgstr ""
+
+#: pronsole.py:257
+msgid "Extruder temp for ABS (default: 230 deg C)"
+msgstr ""
+
+#: pronsole.py:258
+msgid "Extruder temp for PLA (default: 185 deg C)"
+msgstr ""
+
+#: pronsole.py:259
+msgid "Feedrate for Control Panel Moves in X and Y (default: 3000mm/min)"
+msgstr ""
+
+#: pronsole.py:260
+msgid "Feedrate for Control Panel Moves in Z (default: 200mm/min)"
+msgstr ""
+
#: pronterface.py:15
msgid "WX is not installed. This program requires WX to run."
msgstr ""
+#: pronterface.py:66
+msgid ""
+"Dimensions of Build Platform\n"
+" & optional offset of origin\n"
+"\n"
+"Examples:\n"
+" XXXxYYY\n"
+" XXX,YYY,ZZZ\n"
+" XXXxYYYxZZZ+OffX+OffY+OffZ"
+msgstr ""
+
#: pronterface.py:67
+msgid "Last Set Temperature for the Heated Print Bed"
+msgstr ""
+
+#: pronterface.py:68
+msgid "Folder of last opened file"
+msgstr ""
+
+#: pronterface.py:69
+msgid "Last Temperature of the Hot End"
+msgstr ""
+
+#: pronterface.py:70
+msgid "Width of Extrusion in Preview (default: 0.5)"
+msgstr ""
+
+#: pronterface.py:71
+msgid "Fine Grid Spacing (default: 10)"
+msgstr ""
+
+#: pronterface.py:72
+msgid "Coarse Grid Spacing (default: 50)"
+msgstr ""
+
+#: pronterface.py:73
+msgid "Pronterface background color (default: #FFFFFF)"
+msgstr ""
+
+#: pronterface.py:76
msgid "Printer Interface"
msgstr ""
-#: pronterface.py:80
+#: pronterface.py:93
msgid "Motors off"
msgstr ""
-#: pronterface.py:81
+#: pronterface.py:94
msgid "Check temp"
msgstr ""
-#: pronterface.py:82
+#: pronterface.py:95
msgid "Extrude"
msgstr ""
-#: pronterface.py:83
+#: pronterface.py:96
msgid "Reverse"
msgstr ""
-#: pronterface.py:99
+#: pronterface.py:114
msgid ""
"# I moved all your custom buttons into .pronsolerc.\n"
"# Please don't add them here any more.\n"
"# Backup of your old buttons is in custombtn.old\n"
msgstr ""
-#: pronterface.py:104
+#: pronterface.py:119
msgid "Note!!! You have specified custom buttons in both custombtn.txt and .pronsolerc"
msgstr ""
-#: pronterface.py:105
+#: pronterface.py:120
msgid "Ignoring custombtn.txt. Remove all current buttons to revert to custombtn.txt"
msgstr ""
-#: pronterface.py:130 pronterface.py:476 pronterface.py:1228
-#: pronterface.py:1279 pronterface.py:1396 pronterface.py:1428
-#: pronterface.py:1443
+#: pronterface.py:148 pronterface.py:499 pronterface.py:1319
+#: pronterface.py:1373 pronterface.py:1495 pronterface.py:1529
+#: pronterface.py:1544
msgid "Print"
msgstr ""
-#: pronterface.py:134
+#: pronterface.py:152
msgid "Printer is now online."
msgstr ""
-#: pronterface.py:188
+#: pronterface.py:212
msgid "Setting hotend temperature to "
msgstr ""
-#: pronterface.py:188 pronterface.py:224
+#: pronterface.py:212 pronterface.py:248
msgid " degrees Celsius."
msgstr ""
-#: pronterface.py:207 pronterface.py:242
+#: pronterface.py:231 pronterface.py:267 pronterface.py:325
msgid "Printer is not online."
msgstr ""
-#: pronterface.py:209
+#: pronterface.py:233
msgid "You cannot set negative temperatures. To turn the hotend off entirely, set its temperature to 0."
msgstr ""
-#: pronterface.py:224
+#: pronterface.py:248
msgid "Setting bed temperature to "
msgstr ""
-#: pronterface.py:244
+#: pronterface.py:269
msgid "You cannot set negative temperatures. To turn the bed off entirely, set its temperature to 0."
msgstr ""
-#: pronterface.py:246
+#: pronterface.py:271
msgid "You must enter a temperature."
msgstr ""
-#: pronterface.py:261
+#: pronterface.py:286
msgid "Do you want to erase the macro?"
msgstr ""
-#: pronterface.py:265
+#: pronterface.py:290
msgid "Cancelled."
msgstr ""
-#: pronterface.py:295
+#: pronterface.py:331
msgid " Opens file"
msgstr ""
-#: pronterface.py:295
+#: pronterface.py:331
msgid "&Open..."
msgstr ""
-#: pronterface.py:296
+#: pronterface.py:332
msgid " Edit open file"
msgstr ""
-#: pronterface.py:296
+#: pronterface.py:332
msgid "&Edit..."
msgstr ""
-#: pronterface.py:297
+#: pronterface.py:333
msgid " Clear output console"
msgstr ""
-#: pronterface.py:297
+#: pronterface.py:333
msgid "Clear console"
msgstr ""
-#: pronterface.py:298
+#: pronterface.py:334
+msgid " Project slices"
+msgstr ""
+
+#: pronterface.py:334
+msgid "Projector"
+msgstr ""
+
+#: pronterface.py:335
msgid " Closes the Window"
msgstr ""
-#: pronterface.py:298
+#: pronterface.py:335
msgid "E&xit"
msgstr ""
-#: pronterface.py:299
+#: pronterface.py:336
msgid "&File"
msgstr ""
-#: pronterface.py:304
+#: pronterface.py:341
msgid "&Macros"
msgstr ""
-#: pronterface.py:305
+#: pronterface.py:342
msgid "<&New...>"
msgstr ""
-#: pronterface.py:306
+#: pronterface.py:343
msgid " Options dialog"
msgstr ""
-#: pronterface.py:306
+#: pronterface.py:343
msgid "&Options"
msgstr ""
-#: pronterface.py:308
-msgid " Adjust SFACT settings"
+#: pronterface.py:345
+msgid " Adjust slicing settings"
msgstr ""
-#: pronterface.py:308
-msgid "SFACT Settings"
+#: pronterface.py:345
+msgid "Slicing Settings"
msgstr ""
-#: pronterface.py:311
-msgid " Quickly adjust SFACT settings for active profile"
-msgstr ""
-
-#: pronterface.py:311
-msgid "SFACT Quick Settings"
-msgstr ""
-
-#: pronterface.py:315
+#: pronterface.py:352
msgid "&Settings"
msgstr ""
-#: pronterface.py:331
+#: pronterface.py:368
msgid "Enter macro name"
msgstr ""
-#: pronterface.py:334
+#: pronterface.py:371
msgid "Macro name:"
msgstr ""
-#: pronterface.py:337
+#: pronterface.py:374
msgid "Ok"
msgstr ""
-#: pronterface.py:341 pronterface.py:1465
+#: pronterface.py:378 pronterface.py:1330 pronterface.py:1587
msgid "Cancel"
msgstr ""
-#: pronterface.py:359
+#: pronterface.py:396
msgid "' is being used by built-in command"
msgstr ""
-#: pronterface.py:359
+#: pronterface.py:396
msgid "Name '"
msgstr ""
-#: pronterface.py:362
+#: pronterface.py:399
msgid "Macro name may contain only alphanumeric symbols and underscores"
msgstr ""
-#: pronterface.py:411
+#: pronterface.py:448
msgid "Port"
msgstr ""
-#: pronterface.py:430
+#: pronterface.py:467
msgid "Connect"
msgstr ""
-#: pronterface.py:432
+#: pronterface.py:469
msgid "Connect to the printer"
msgstr ""
-#: pronterface.py:434
-msgid "Disconnect"
-msgstr ""
-
-#: pronterface.py:438
+#: pronterface.py:471
msgid "Reset"
msgstr ""
-#: pronterface.py:441 pronterface.py:687
+#: pronterface.py:474 pronterface.py:751
msgid "Mini mode"
msgstr ""
-#: pronterface.py:455
-msgid ""
-"Monitor\n"
-"printer"
+#: pronterface.py:478
+msgid "Monitor Printer"
msgstr ""
-#: pronterface.py:465
+#: pronterface.py:488
msgid "Load file"
msgstr ""
-#: pronterface.py:468
-msgid "SD Upload"
+#: pronterface.py:491
+msgid "Compose"
msgstr ""
-#: pronterface.py:472
-msgid "SD Print"
+#: pronterface.py:495
+msgid "SD"
msgstr ""
-#: pronterface.py:480 pronterface.py:1280 pronterface.py:1321
-#: pronterface.py:1370 pronterface.py:1395 pronterface.py:1427
-#: pronterface.py:1442
+#: pronterface.py:503 pronterface.py:1374 pronterface.py:1419
+#: pronterface.py:1469 pronterface.py:1494 pronterface.py:1528
+#: pronterface.py:1543
msgid "Pause"
msgstr ""
-#: pronterface.py:494
+#: pronterface.py:516
msgid "Send"
msgstr ""
-#: pronterface.py:502 pronterface.py:603
+#: pronterface.py:524 pronterface.py:625
msgid "mm/min"
msgstr ""
-#: pronterface.py:504
+#: pronterface.py:526
msgid "XY:"
msgstr ""
-#: pronterface.py:506
+#: pronterface.py:528
msgid "Z:"
msgstr ""
-#: pronterface.py:529
+#: pronterface.py:551 pronterface.py:632
msgid "Heater:"
msgstr ""
-#: pronterface.py:532 pronterface.py:552
+#: pronterface.py:554 pronterface.py:574
msgid "Off"
msgstr ""
-#: pronterface.py:544 pronterface.py:564
+#: pronterface.py:566 pronterface.py:586
msgid "Set"
msgstr ""
-#: pronterface.py:549
+#: pronterface.py:571 pronterface.py:634
msgid "Bed:"
msgstr ""
-#: pronterface.py:597
+#: pronterface.py:619
msgid "mm"
msgstr ""
-#: pronterface.py:636 pronterface.py:1099 pronterface.py:1315
+#: pronterface.py:677 pronterface.py:1182 pronterface.py:1413
msgid "Not connected to printer."
msgstr ""
-#: pronterface.py:694
+#: pronterface.py:706
+msgid "SD Upload"
+msgstr ""
+
+#: pronterface.py:710
+msgid "SD Print"
+msgstr ""
+
+#: pronterface.py:758
msgid "Full mode"
msgstr ""
-#: pronterface.py:719
+#: pronterface.py:783
msgid "Execute command: "
msgstr ""
-#: pronterface.py:730
+#: pronterface.py:794
msgid "click to add new custom button"
msgstr ""
-#: pronterface.py:751
+#: pronterface.py:813
msgid "Defines custom button. Usage: button \"title\" [/c \"colour\"] command"
msgstr ""
-#: pronterface.py:773
+#: pronterface.py:835
msgid "Custom button number should be between 0 and 63"
msgstr ""
-#: pronterface.py:865
+#: pronterface.py:927
msgid "Edit custom button '%s'"
msgstr ""
-#: pronterface.py:867
+#: pronterface.py:929
msgid "Move left <<"
msgstr ""
-#: pronterface.py:870
+#: pronterface.py:932
msgid "Move right >>"
msgstr ""
-#: pronterface.py:874
+#: pronterface.py:936
msgid "Remove custom button '%s'"
msgstr ""
-#: pronterface.py:877
+#: pronterface.py:939
msgid "Add custom button"
msgstr ""
-#: pronterface.py:1022
+#: pronterface.py:1084
msgid "event object missing"
msgstr ""
-#: pronterface.py:1050
+#: pronterface.py:1112
msgid "Invalid period given."
msgstr ""
-#: pronterface.py:1053
+#: pronterface.py:1115
msgid "Monitoring printer."
msgstr ""
-#: pronterface.py:1055
+#: pronterface.py:1117
msgid "Done monitoring."
msgstr ""
-#: pronterface.py:1077
+#: pronterface.py:1139
msgid "Printer is online. "
msgstr ""
-#: pronterface.py:1079 pronterface.py:1226 pronterface.py:1278
+#: pronterface.py:1141 pronterface.py:1317 pronterface.py:1372
msgid "Loaded "
msgstr ""
-#: pronterface.py:1082
+#: pronterface.py:1144
msgid "Bed"
msgstr ""
-#: pronterface.py:1082
+#: pronterface.py:1144
msgid "Hotend"
msgstr ""
-#: pronterface.py:1089
+#: pronterface.py:1154
msgid " SD printing:%04.2f %%"
msgstr ""
-#: pronterface.py:1091
-msgid " Printing:%04.2f %%"
+#: pronterface.py:1157
+msgid " Printing:%04.2f %% |"
+msgstr ""
+
+#: pronterface.py:1158
+msgid " Line# "
+msgstr ""
+
+#: pronterface.py:1158
+msgid " lines |"
+msgstr ""
+
+#: pronterface.py:1158
+msgid "of "
+msgstr ""
+
+#: pronterface.py:1163
+msgid " Est: "
msgstr ""
-#: pronterface.py:1149
+#: pronterface.py:1164
+msgid " of: "
+msgstr ""
+
+#: pronterface.py:1165
+msgid " Remaining | "
+msgstr ""
+
+#: pronterface.py:1166
+msgid " Z: %0.2f mm"
+msgstr ""
+
+#: pronterface.py:1233
msgid "Opening file failed."
msgstr ""
-#: pronterface.py:1155
+#: pronterface.py:1239
msgid "Starting print"
msgstr ""
-#: pronterface.py:1178
+#: pronterface.py:1262
msgid "Pick SD file"
msgstr ""
-#: pronterface.py:1178
+#: pronterface.py:1262
msgid "Select the file to print"
msgstr ""
-#: pronterface.py:1206
-msgid "Skeinforge execution failed."
+#: pronterface.py:1297
+msgid "Failed to execute slicing software: "
msgstr ""
-#: pronterface.py:1213
-msgid "Skeining..."
+#: pronterface.py:1304
+msgid "Slicing..."
msgstr ""
-#: pronterface.py:1226 pronterface.py:1278
+#: pronterface.py:1317 pronterface.py:1372
msgid ", %d lines"
msgstr ""
-#: pronterface.py:1235
-msgid "Skeining "
+#: pronterface.py:1324
+msgid "Load File"
msgstr ""
-#: pronterface.py:1237
-msgid ""
-"Skeinforge not found. \n"
-"Please copy Skeinforge into a directory named \"skeinforge\" in the same directory as this file."
+#: pronterface.py:1331
+msgid "Slicing "
msgstr ""
-#: pronterface.py:1256
+#: pronterface.py:1350
msgid "Open file to print"
msgstr ""
-#: pronterface.py:1257
+#: pronterface.py:1351
msgid "OBJ, STL, and GCODE files (;*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ;)"
msgstr ""
-#: pronterface.py:1264
+#: pronterface.py:1358
msgid "File not found!"
msgstr ""
-#: pronterface.py:1288
+#: pronterface.py:1382
msgid ""
"mm of filament used in this print\n"
msgstr ""
-#: pronterface.py:1289
+#: pronterface.py:1383
msgid ""
"mm in X\n"
"and is"
msgstr ""
-#: pronterface.py:1289 pronterface.py:1290
+#: pronterface.py:1383 pronterface.py:1384
msgid ""
"mm wide\n"
msgstr ""
-#: pronterface.py:1289 pronterface.py:1290 pronterface.py:1291
+#: pronterface.py:1383 pronterface.py:1384 pronterface.py:1385
msgid "mm to"
msgstr ""
-#: pronterface.py:1289 pronterface.py:1290 pronterface.py:1291
+#: pronterface.py:1383 pronterface.py:1384 pronterface.py:1385
msgid "the print goes from"
msgstr ""
-#: pronterface.py:1290
+#: pronterface.py:1384
msgid ""
"mm in Y\n"
"and is"
msgstr ""
-#: pronterface.py:1291
+#: pronterface.py:1385
msgid ""
"mm high\n"
msgstr ""
-#: pronterface.py:1291
+#: pronterface.py:1385
msgid ""
"mm in Z\n"
"and is"
msgstr ""
-#: pronterface.py:1292
+#: pronterface.py:1386
msgid "Estimated duration (pessimistic): "
msgstr ""
-#: pronterface.py:1312
+#: pronterface.py:1410
msgid "No file loaded. Please use load first."
msgstr ""
-#: pronterface.py:1323
+#: pronterface.py:1421
msgid "Restart"
msgstr ""
-#: pronterface.py:1327
+#: pronterface.py:1425
msgid "File upload complete"
msgstr ""
-#: pronterface.py:1346
+#: pronterface.py:1444
msgid "Pick SD filename"
msgstr ""
-#: pronterface.py:1353
+#: pronterface.py:1452
msgid "Paused."
msgstr ""
-#: pronterface.py:1363
+#: pronterface.py:1462
msgid "Resume"
msgstr ""
-#: pronterface.py:1379
+#: pronterface.py:1478
msgid "Connecting..."
msgstr ""
-#: pronterface.py:1410
+#: pronterface.py:1509
msgid "Disconnected."
msgstr ""
-#: pronterface.py:1435
+#: pronterface.py:1536
msgid "Reset."
msgstr ""
-#: pronterface.py:1436
+#: pronterface.py:1537
msgid "Are you sure you want to reset the printer?"
msgstr ""
-#: pronterface.py:1436
+#: pronterface.py:1537
msgid "Reset?"
msgstr ""
-#: pronterface.py:1461
+#: pronterface.py:1583
msgid "Save"
msgstr ""
-#: pronterface.py:1519
+#: pronterface.py:1639
msgid "Edit settings"
msgstr ""
-#: pronterface.py:1521
+#: pronterface.py:1641
msgid "Defaults"
msgstr ""
-#: pronterface.py:1543
+#: pronterface.py:1670
msgid "Custom button"
msgstr ""
-#: pronterface.py:1551
+#: pronterface.py:1675
msgid "Button title"
msgstr ""
-#: pronterface.py:1554
+#: pronterface.py:1678
msgid "Command"
msgstr ""
-#: pronterface.py:1563
+#: pronterface.py:1687
msgid "Color"
msgstr ""
diff --git a/plater.py b/plater.py
index 506cd9be5..28f4e5a0f 100755
--- a/plater.py
+++ b/plater.py
@@ -1,359 +1,490 @@
#!/usr/bin/env python
-import wx,time,random,threading,os,math
+
+# This file is part of the Printrun suite.
+#
+# Printrun is 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
+# (at your option) any later version.
+#
+# Printrun 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 Printrun. If not, see .
+
+# Set up Internationalization using gettext
+# searching for installed locales on /usr/share; uses relative folder if not found (windows)
+import os, gettext, Queue, re
+
+if os.path.exists('/usr/share/pronterface/locale'):
+ gettext.install('plater', '/usr/share/pronterface/locale', unicode=1)
+else:
+ gettext.install('plater', './locale', unicode=1)
+
+import wx
+import time
+import random
+import threading
+import math
+import sys
+
import stltool
-def translate(l): return l
+glview = False
+if "-nogl" not in sys.argv:
+ try:
+ import stlview
+ glview = True
+ except:
+ pass
-def rotate(l): return l
-def import_stl(s): return s
+def evalme(s):
+ return eval(s[s.find("(") + 1:s.find(")")])
+
class stlwrap:
- def __init__(self,obj,name=None):
- self.obj=obj
- self.name=name
+ def __init__(self, obj, name=None):
+ self.obj = obj
+ self.name = name
if name is None:
- self.name=obj.name
-
+ self.name = obj.name
+
def __repr__(self):
return self.name
-
+
class showstl(wx.Window):
- def __init__(self,parent,size,pos):
- wx.Window.__init__(self,parent,size=size,pos=pos)
- self.l=wx.ListBox(self,size=(300,180),pos=(0,size[1]-180))
- self.cl=wx.Button(self,label="Clear",pos=(300,size[1]-180))
- self.lb=wx.Button(self,label="Load",pos=(300,size[1]-155))
- self.eb=wx.Button(self,label="Export",pos=(300,size[1]-130))
- self.sb=wx.Button(self,label="Snap to Z=0",pos=(300,size[1]-105))
- self.cb=wx.Button(self,label="Put at 100,100",pos=(300,size[1]-80))
- self.db=wx.Button(self,label="Delete",pos=(300,size[1]-55))
- self.ab=wx.Button(self,label="Auto",pos=(300,size[1]-30))
- self.cl.Bind(wx.EVT_BUTTON,self.clear)
- self.lb.Bind(wx.EVT_BUTTON,self.right)
- self.eb.Bind(wx.EVT_BUTTON,self.export)
- self.sb.Bind(wx.EVT_BUTTON,self.snap)
- self.cb.Bind(wx.EVT_BUTTON,self.center)
- self.db.Bind(wx.EVT_BUTTON,self.delete)
- self.ab.Bind(wx.EVT_BUTTON,self.autoplate)
- #self.SetBackgroundColour((0,0,0))
- #wx.FutureCall(200,self.paint)
- self.i=0
- self.previ=0
- self.Bind(wx.EVT_MOUSEWHEEL,self.rot)
- self.Bind(wx.EVT_MOUSE_EVENTS,self.move)
- self.Bind(wx.EVT_PAINT,self.repaint)
- #self.s=stltool.stl("sphere.stl").scale([2,1,1])
- self.triggered=0
- self.models={}
- self.basedir="."
- self.initpos=None
- self.prevsel=-1
-
- def center(self,event):
- i=self.l.GetSelection()
- if i != -1:
- m=self.models[self.l.GetString(i)]
- m.offsets=[100,100,m.offsets[2]]
- self.Refresh()
+ def __init__(self, parent, size, pos):
+ wx.Window.__init__(self, parent, size=size, pos=pos)
+ #self.SetBackgroundColour((0, 0, 0))
+ #wx.FutureCall(200, self.paint)
+ self.i = 0
+ self.parent = parent
+ self.previ = 0
+ self.Bind(wx.EVT_MOUSEWHEEL, self.rot)
+ self.Bind(wx.EVT_MOUSE_EVENTS, self.move)
+ self.Bind(wx.EVT_PAINT, self.repaint)
+ self.Bind(wx.EVT_KEY_DOWN, self.keypress)
+ #self.s = stltool.stl("sphere.stl").scale([2, 1, 1])
+ self.triggered = 0
+ self.initpos = None
+ self.prevsel = -1
- def snap(self,event):
- i=self.l.GetSelection()
- if i != -1:
- m=self.models[self.l.GetString(i)]
- m.offsets[2]=-1.0*min(m.facetsminz)[0]
- #print m.offsets[2]
- self.Refresh()
+ def drawmodel(self, m, scale):
+ m.bitmap = wx.EmptyBitmap(800, 800, 32)
+ dc = wx.MemoryDC()
+ dc.SelectObject(m.bitmap)
+ dc.SetBackground(wx.Brush((0, 0, 0, 0)))
+ dc.SetBrush(wx.Brush((0, 0, 0, 255)))
+ #dc.DrawRectangle(-1, -1, 10000, 10000)
+ dc.SetBrush(wx.Brush(wx.Colour(128, 255, 128)))
+ dc.SetPen(wx.Pen(wx.Colour(128, 128, 128)))
+ #m.offsets = [10, 10, 0]
+ #print m.offsets, m.dims
+ for i in m.facets: # random.sample(m.facets, min(100000, len(m.facets))):
+ dc.DrawPolygon([wx.Point(400 + scale * p[0], (400 - scale * p[1])) for p in i[1]])
+ #if(time.time()-t)>5:
+ # break
+ dc.SelectObject(wx.NullBitmap)
+ m.bitmap.SetMask(wx.Mask(m.bitmap, wx.Colour(0, 0, 0, 255)))
- def delete(self,event):
- i=self.l.GetSelection()
- if i != -1:
- del self.models[self.l.GetString(i)]
- self.l.Delete(i)
- self.l.Select(self.l.GetCount()-1)
+ def move_shape(self, delta):
+ """moves shape (selected in l, which is list ListBox of shapes)
+ by an offset specified in tuple delta.
+ Positive numbers move to (rigt, down)"""
+ name = self.parent.l.GetSelection()
+ if name == wx.NOT_FOUND:
+ return False
+ name = self.parent.l.GetString(name)
+ model = self.parent.models[name]
+ model.offsets = [
+ model.offsets[0] + delta[0],
+ model.offsets[1] + delta[1],
+ model.offsets[2]
+ ]
+ self.Refresh()
+ return True
+
+ def move(self, event):
+ if event.ButtonUp(wx.MOUSE_BTN_LEFT):
+ if(self.initpos is not None):
+ currentpos = event.GetPositionTuple()
+ delta = (
+ 0.5 * (currentpos[0] - self.initpos[0]),
+ - 0.5 * (currentpos[1] - self.initpos[1])
+ )
+ self.move_shape(delta)
self.Refresh()
+ self.initpos = None
+ elif event.ButtonDown(wx.MOUSE_BTN_RIGHT):
+ self.parent.right(event)
+ elif event.Dragging():
+ if self.initpos is None:
+ self.initpos = event.GetPositionTuple()
+ self.Refresh()
+ dc = wx.ClientDC(self)
+ p = event.GetPositionTuple()
+ dc.DrawLine(self.initpos[0], self.initpos[1], p[0], p[1])
+ #print math.sqrt((p[0]-self.initpos[0])**2+(p[1]-self.initpos[1])**2)
- def export(self,event):
- dlg=wx.FileDialog(self,"Pick file to save to",self.basedir,style=wx.FD_SAVE)
- dlg.SetWildcard("STL files (;*.stl;)")
- if(dlg.ShowModal() == wx.ID_OK):
- name=dlg.GetPath()
- sf=open(name.replace(".","_")+".scad","w")
-
- facets=[]
- for i in self.models.values():
-
- r=i.rot
- o=i.offsets
- sf.write('translate([%s,%s,%s]) rotate([0,0,%s]) import_stl("%s");\n'%(str(o[0]),str(o[1]),str(o[2]),r,os.path.split(i.filename)[1]))
- if r != 0:
- i=i.rotate([0,0,-r])
- if o != [0,0,0]:
- i=i.translate([o[0],-o[1],o[2]])
- facets+=i.facets
- sf.close()
- stltool.emitstl(name,facets,"plater_export")
- print "wrote ",name
-
- def autoplate(self,event):
- print "Autoplating"
+ del dc
+ else:
+ event.Skip()
+
+ def rotate_shape(self, angle):
+ """rotates acive shape
+ positive angle is clockwise
+ """
+ self.i += angle
+ if not self.triggered:
+ self.triggered = 1
+ threading.Thread(target=self.cr).start()
+
+ def keypress(self, event):
+ """gets keypress events and moves/rotates acive shape"""
+ keycode = event.GetKeyCode()
+ #print keycode
+ step = 5
+ angle = 18
+ if event.ControlDown():
+ step = 1
+ angle = 1
+ #h
+ if keycode == 72:
+ self.move_shape((-step, 0))
+ #l
+ if keycode == 76:
+ self.move_shape((step, 0))
+ #j
+ if keycode == 75:
+ self.move_shape((0, step))
+ #k
+ if keycode == 74:
+ self.move_shape((0, -step))
+ #[
+ if keycode == 91:
+ self.rotate_shape(-angle)
+ #]
+ if keycode == 93:
+ self.rotate_shape(angle)
+ event.Skip()
+
+ def rotateafter(self):
+ if(self.i != self.previ):
+ i = self.parent.l.GetSelection()
+ if i != wx.NOT_FOUND:
+ #o = self.models[self.l.GetItemText(i)].offsets
+ self.parent.models[self.parent.l.GetString(i)].rot -= 5 * (self.i - self.previ)
+ #self.models[self.l.GetItemText(i)].offsets = o
+ self.previ = self.i
+ self.Refresh()
+
+ def cr(self):
+ time.sleep(0.01)
+ wx.CallAfter(self.rotateafter)
+ self.triggered = 0
+
+ def rot(self, event):
+ z = event.GetWheelRotation()
+ s = self.parent.l.GetSelection()
+ if self.prevsel != s:
+ self.i = 0
+ self.prevsel = s
+ if z < 0:
+ self.rotate_shape(-1)
+ else:
+ self.rotate_shape(1)
+
+ def repaint(self, event):
+ dc = wx.PaintDC(self)
+ self.paint(dc=dc)
+
+ def paint(self, coord1="x", coord2="y", dc=None):
+ coords = {"x": 0, "y": 1, "z": 2}
+ if dc is None:
+ dc = wx.ClientDC(self)
+ offset = [0, 0]
+ scale = 2
+ dc.SetPen(wx.Pen(wx.Colour(100, 100, 100)))
+ for i in xrange(20):
+ dc.DrawLine(0, i * scale * 10, 400, i * scale * 10)
+ dc.DrawLine(i * scale * 10, 0, i * scale * 10, 400)
+ dc.SetPen(wx.Pen(wx.Colour(0, 0, 0)))
+ for i in xrange(4):
+ dc.DrawLine(0, i * scale * 50, 400, i * scale * 50)
+ dc.DrawLine(i * scale * 50, 0, i * scale * 50, 400)
+ dc.SetBrush(wx.Brush(wx.Colour(128, 255, 128)))
+ dc.SetPen(wx.Pen(wx.Colour(128, 128, 128)))
+ t = time.time()
+ dcs = wx.MemoryDC()
+ for m in self.parent.models.values():
+ b = m.bitmap
+ #print b
+ im = b.ConvertToImage()
+ #print im
+ imgc = wx.Point(im.GetWidth() / 2, im.GetHeight() / 2)
+ #print math.radians(5*(self.i-self.previ))
+ im = im.Rotate(math.radians(m.rot), imgc, 0)
+ bm = wx.BitmapFromImage(im)
+ dcs.SelectObject(bm)
+ bsz = bm.GetSize()
+ dc.Blit(scale * m.offsets[0] - bsz[0] / 2, 400 - (scale * m.offsets[1] + bsz[1] / 2), bsz[0], bsz[1], dcs, 0, 0, useMask=1)
+ #for i in m.facets:#random.sample(m.facets, min(100000, len(m.facets))):
+ # dc.DrawPolygon([wx.Point(offset[0]+scale*m.offsets[0]+scale*p[0], 400-(offset[1]+scale*m.offsets[1]+scale*p[1])) for p in i[1]])
+ #if(time.time()-t)>5:
+ # break
+ del dc
+ #print time.time()-t
+ #s.export()
+
+
+class stlwin(wx.Frame):
+ def __init__(self, size=(800, 580), callback=None, parent=None):
+ wx.Frame.__init__(self, parent, title=_("Plate building tool"), size=size)
+ self.SetIcon(wx.Icon("plater.ico", wx.BITMAP_TYPE_ICO))
+ self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
+ self.panel = wx.Panel(self, -1, size=(150, 600), pos=(0, 0))
+ self.panel.SetBackgroundColour((10, 10, 10))
+ self.l = wx.ListBox(self.panel, size=(300, 180), pos=(0, 30))
+ self.cl = wx.Button(self.panel, label=_("Clear"), pos=(0, 205))
+ self.lb = wx.Button(self.panel, label=_("Load"), pos=(0, 0))
+ if(callback is None):
+ self.eb = wx.Button(self.panel, label=_("Export"), pos=(100, 0))
+ self.eb.Bind(wx.EVT_BUTTON, self.export)
+ else:
+ self.eb = wx.Button(self.panel, label=_("Done"), pos=(100, 0))
+ self.eb.Bind(wx.EVT_BUTTON, lambda e: self.done(e, callback))
+ self.eb = wx.Button(self.panel, label=_("Cancel"), pos=(200, 0))
+ self.eb.Bind(wx.EVT_BUTTON, lambda e: self.Destroy())
+ self.sb = wx.Button(self.panel, label=_("Snap to Z = 0"), pos=(00, 255))
+ self.cb = wx.Button(self.panel, label=_("Put at 100, 100"), pos=(0, 280))
+ self.db = wx.Button(self.panel, label=_("Delete"), pos=(0, 305))
+ self.ab = wx.Button(self.panel, label=_("Auto"), pos=(0, 330))
+ self.cl.Bind(wx.EVT_BUTTON, self.clear)
+ self.lb.Bind(wx.EVT_BUTTON, self.right)
+ self.sb.Bind(wx.EVT_BUTTON, self.snap)
+ self.cb.Bind(wx.EVT_BUTTON, self.center)
+ self.db.Bind(wx.EVT_BUTTON, self.delete)
+ self.ab.Bind(wx.EVT_BUTTON, self.autoplate)
+ self.basedir = "."
+ self.models = {}
+ self.SetBackgroundColour((10, 10, 10))
+ self.mainsizer.Add(self.panel)
+ #self.mainsizer.AddSpacer(10)
+ if glview:
+ self.s = stlview.TestGlPanel(self, (580, 580))
+ else:
+ self.s = showstl(self, (580, 580), (0, 0))
+ self.mainsizer.Add(self.s, 1, wx.EXPAND)
+ self.SetSizer(self.mainsizer)
+ #self.mainsizer.Fit(self)
+ self.Layout()
+
+ #self.SetClientSize(size)
+
+ def autoplate(self, event):
+ print _("Autoplating")
separation = 2
- bedsize = [200,200,100]
- cursor = [0,0,0]
+ bedsize = [200, 200, 100]
+ cursor = [0, 0, 0]
newrow = 0
- max = [0,0]
+ max = [0, 0]
for i in self.models:
- self.models[i].offsets[2]=-1.0*self.models[i].dims[4]
+ self.models[i].offsets[2] = -1.0 * self.models[i].dims[4]
x = abs(self.models[i].dims[0] - self.models[i].dims[1])
y = abs(self.models[i].dims[2] - self.models[i].dims[3])
- centre = [x/2, y/2]
+ centre = [x / 2, y / 2]
centreoffset = [self.models[i].dims[0] + centre[0], self.models[i].dims[2] + centre[1]]
- if (cursor[0]+x+separation) >= bedsize[0]:
+ if (cursor[0] + x + separation) >= bedsize[0]:
cursor[0] = 0
- cursor[1] += newrow+separation
+ cursor[1] += newrow + separation
newrow = 0
if (newrow == 0) or (newrow < y):
newrow = y
#To the person who works out why the offsets are applied differently here:
# Good job, it confused the hell out of me.
self.models[i].offsets[0] = cursor[0] + centre[0] - centreoffset[0]
- self.models[i].offsets[1] = cursor[1] + centre[1] + centreoffset[1]
- if (max[0] == 0) or (max[0] < (cursor[0]+x)):
- max[0] = cursor[0]+x
- if (max[1] == 0) or (max[1] < (cursor[1]+x)):
- max[1] = cursor[1]+x
- cursor[0] += x+separation
- if (cursor[1]+y) >= bedsize[1]:
- print "Bed full, sorry sir :("
+ self.models[i].offsets[1] = cursor[1] + centre[1] - centreoffset[1]
+ if (max[0] == 0) or (max[0] < (cursor[0] + x)):
+ max[0] = cursor[0] + x
+ if (max[1] == 0) or (max[1] < (cursor[1] + x)):
+ max[1] = cursor[1] + x
+ cursor[0] += x + separation
+ if (cursor[1] + y) >= bedsize[1]:
+ print _("Bed full, sorry sir :(")
self.Refresh()
return
- centreoffset = [(bedsize[0]-max[0])/2,(bedsize[1]-max[1])/2]
+ centreoffset = [(bedsize[0] - max[0]) / 2, (bedsize[1] - max[1]) / 2]
for i in self.models:
self.models[i].offsets[0] += centreoffset[0]
self.models[i].offsets[1] += centreoffset[1]
self.Refresh()
-
- def right(self,event):
- dlg=wx.FileDialog(self,"Pick file to load",self.basedir,style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
- dlg.SetWildcard("STL files (;*.stl;)|*.stl|OpenSCAD files (;*.scad;)|*.scad")
+
+ def clear(self, event):
+ result = wx.MessageBox(_('Are you sure you want to clear the grid? All unsaved changes will be lost.'), _('Clear the grid?'),
+ wx.YES_NO | wx.ICON_QUESTION)
+ if (result == 2):
+ self.models = {}
+ self.l.Clear()
+ self.Refresh()
+
+ def center(self, event):
+ i = self.l.GetSelection()
+ if i != -1:
+ m = self.models[self.l.GetString(i)]
+ m.offsets = [100, 100, m.offsets[2]]
+ self.Refresh()
+
+ def snap(self, event):
+ i = self.l.GetSelection()
+ if i != -1:
+ m = self.models[self.l.GetString(i)]
+ m.offsets[2] = -1.0 * min(m.facetsminz)[0]
+ #print m.offsets[2]
+ self.Refresh()
+
+ def delete(self, event):
+ i = self.l.GetSelection()
+ if i != -1:
+ del self.models[self.l.GetString(i)]
+ self.l.Delete(i)
+ self.l.Select(self.l.GetCount() - 1)
+ self.Refresh()
+
+ def done(self, event, cb):
+ try:
+ os.mkdir("tempstl")
+ except:
+ pass
+ name = "tempstl/" + str(int(time.time()) % 10000) + ".stl"
+ self.writefiles(name)
+ if cb is not None:
+ cb(name)
+ self.Destroy()
+
+ def export(self, event):
+ dlg = wx.FileDialog(self, _("Pick file to save to"), self.basedir, style=wx.FD_SAVE)
+ dlg.SetWildcard(_("STL files (;*.stl;*.STL;)"))
+ if(dlg.ShowModal() == wx.ID_OK):
+ name = dlg.GetPath()
+ self.writefiles(name)
+
+ def writefiles(self, name):
+ sf = open(name.replace(".", "_") + ".scad", "w")
+ facets = []
+ for i in self.models.values():
+
+ r = i.rot
+ o = i.offsets
+ sf.write('translate([%s, %s, %s]) rotate([0, 0, %s]) import_stl("%s");\n' % (str(o[0]), str(o[1]), str(o[2]), r, os.path.split(i.filename)[1]))
+ if r != 0:
+ i = i.rotate([0, 0, r])
+ if o != [0, 0, 0]:
+ i = i.translate([o[0], o[1], o[2]])
+ facets += i.facets
+ sf.close()
+ stltool.emitstl(name, facets, "plater_export")
+ print _("wrote "), name
+
+ def right(self, event):
+ dlg = wx.FileDialog(self, _("Pick file to load"), self.basedir, style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
+ dlg.SetWildcard(_("STL files (;*.stl;*.STL;)|*.stl|OpenSCAD files (;*.scad;)|*.scad"))
if(dlg.ShowModal() == wx.ID_OK):
- name=dlg.GetPath()
+ name = dlg.GetPath()
if (name.lower().endswith(".stl")):
- self.load_stl(event,name)
+ self.load_stl(event, name)
elif (name.lower().endswith(".scad")):
- self.load_scad(event,name)
-
- def load_scad(self,event,name):
- lf=open(name)
- s=[i.replace("\n","").replace("\r","").replace(";","") for i in lf]
+ self.load_scad(event, name)
+
+ def load_scad(self, event, name):
+ lf = open(name)
+ s = [i.replace("\n", "").replace("\r", "").replace(";", "") for i in lf if "stl" in i]
lf.close()
for i in s:
parts = i.split()
- translate_list = eval(parts[0])
- rotate_list = eval(parts[1])
- stl_file = eval(parts[2])
-
- newname=os.path.split(stl_file.lower())[1]
- c=1
+ for part in parts:
+ if 'translate' in part:
+ translate_list = evalme(part)
+ for part in parts:
+ if 'rotate' in part:
+ rotate_list = evalme(part)
+ for part in parts:
+ if 'import' in part:
+ stl_file = evalme(part)
+
+ newname = os.path.split(stl_file.lower())[1]
+ c = 1
while newname in self.models:
- newname=os.path.split(stl_file.lower())[1]
- newname=newname+"(%d)"%c
- c+=1
- stl_path = os.path.join(os.path.split(name)[0:len(os.path.split(stl_file))-1])
- stl_full_path = os.path.join(stl_path[0],str(stl_file))
- self.load_stl_into_model(stl_full_path,stl_file,translate_list,rotate_list[2])
-
- def load_stl(self,event,name):
+ newname = os.path.split(stl_file.lower())[1]
+ newname = newname + "(%d)" % c
+ c += 1
+ stl_path = os.path.join(os.path.split(name)[0:len(os.path.split(stl_file)) - 1])
+ stl_full_path = os.path.join(stl_path[0], str(stl_file))
+ self.load_stl_into_model(stl_full_path, stl_file, translate_list, rotate_list[2])
+
+ def load_stl(self, event, name):
if not(os.path.exists(name)):
return
path = os.path.split(name)[0]
- self.basedir=path
- t=time.time()
+ self.basedir = path
+ t = time.time()
#print name
if name.lower().endswith(".stl"):
#Filter out the path, just show the STL filename.
- self.load_stl_into_model(name,name)
+ self.load_stl_into_model(name, name)
self.Refresh()
#print time.time()-t
- def load_stl_into_model(self,path,name,offset=[0,0,0],rotation=0):
- newname=os.path.split(name.lower())[1]
- c=1
+ def load_stl_into_model(self, path, name, offset=[0, 0, 0], rotation=0, scale=[1.0, 1.0, 1.0]):
+ newname = os.path.split(name.lower())[1]
+ c = 1
while newname in self.models:
- newname=os.path.split(name.lower())[1]
- newname=newname+"(%d)"%c
- c+=1
- self.models[newname]=stltool.stl(path)
- self.models[newname].offsets=offset
- self.models[newname].rot=rotation
- self.models[newname].filename=name
- minx,miny,minz,maxx,maxy,maxz=(10000,10000,10000,0,0,0)
+ newname = os.path.split(name.lower())[1]
+ newname = newname + "(%d)" % c
+ c += 1
+ self.models[newname] = stltool.stl(path)
+ self.models[newname].offsets = offset
+ self.models[newname].rot = rotation
+ self.models[newname].scale = scale
+ self.models[newname].filename = name
+ minx, miny, minz, maxx, maxy, maxz = (10000, 10000, 10000, 0, 0, 0)
for i in self.models[newname].facets:
for j in i[1]:
- if j[0]maxx:
- maxx=j[0]
- if j[1]>maxy:
- maxy=j[1]
- if j[2]>maxz:
- maxz=j[2]
- self.models[newname].dims=[minx,maxx,miny,maxy,minz,maxz]
- #if minx<0:
- # self.models[newname].offsets[0]=-minx
- #if miny<0:
- # self.models[newname].offsets[1]=-miny
- self.models[newname].bitmap=wx.EmptyBitmap(800,800,32)
- dc=wx.MemoryDC()
- dc.SelectObject(self.models[newname].bitmap)
- dc.SetBackground(wx.Brush((0,0,0,0)))
- dc.SetBrush(wx.Brush((0,0,0,255)))
- #dc.DrawRectangle(-1,-1,10000,10000)
- dc.SetBrush(wx.Brush(wx.Colour(128,255,128)))
- dc.SetPen(wx.Pen(wx.Colour(128,128,128)))
- m=self.models[newname]
- #m.offsets=[10,10,0]
- print m.offsets,m.dims
- scale=2
- for i in m.facets:#random.sample(m.facets,min(100000,len(m.facets))):
- dc.DrawPolygon([wx.Point(400+scale*p[0],(400+scale*p[1])) for p in i[1]])
- #if(time.time()-t)>5:
- # break
- dc.SelectObject(wx.NullBitmap)
- m.bitmap.SetMask(wx.Mask(m.bitmap,wx.Colour(0,0,0,255)))
-
- #print time.time()-t
+ if j[0] < minx:
+ minx = j[0]
+ if j[1] < miny:
+ miny = j[1]
+ if j[2] < minz:
+ minz = j[2]
+ if j[0] > maxx:
+ maxx = j[0]
+ if j[1] > maxy:
+ maxy = j[1]
+ if j[2] > maxz:
+ maxz = j[2]
+ self.models[newname].dims = [minx, maxx, miny, maxy, minz, maxz]
+ #if minx < 0:
+ # self.models[newname].offsets[0] = -minx
+ #if miny < 0:
+ # self.models[newname].offsets[1] = -miny
+ self.s.drawmodel(self.models[newname], 2)
+
+ #print time.time() - t
self.l.Append(newname)
- i=self.l.GetSelection()
- if i==wx.NOT_FOUND:
+ i = self.l.GetSelection()
+ if i == wx.NOT_FOUND:
self.l.Select(0)
-
- self.l.Select(self.l.GetCount()-1)
-
- def clear(self,event):
- result = wx.MessageBox('Are you sure you want to clear the grid? All unsaved changes will be lost.', 'Clear the grid?',
- wx.YES_NO | wx.ICON_QUESTION)
- if (result == 2):
- self.models={}
- self.l.Clear()
- self.Refresh()
-
- def move(self,event):
- if event.ButtonUp(wx.MOUSE_BTN_LEFT):
- if(self.initpos is not None):
- i=self.l.GetSelection()
- if i != wx.NOT_FOUND:
- p=event.GetPositionTuple()
- #print (p[0]-self.initpos[0]),(p[1]-self.initpos[1])
- t=time.time()
- m=self.models[self.l.GetString(i)]
- m.offsets=[m.offsets[0]+0.5*(p[0]-self.initpos[0]),m.offsets[1]-0.5*(p[1]-self.initpos[1]),m.offsets[2]]
- #self.models[self.l.GetItemText(i)]=self.models[self.l.GetItemText(i)].translate([0.5*(p[0]-self.initpos[0]),0.5*(p[1]-self.initpos[1]),0])
- #print time.time()-t
- self.Refresh()
- self.initpos=None
- elif event.ButtonDown(wx.MOUSE_BTN_RIGHT):
- self.right(event)
- elif event.Dragging():
- if self.initpos is None:
- self.initpos=event.GetPositionTuple()
- self.Refresh()
- dc=wx.ClientDC(self)
- p=event.GetPositionTuple()
- dc.DrawLine(self.initpos[0],self.initpos[1],p[0],p[1])
- #print math.sqrt((p[0]-self.initpos[0])**2+(p[1]-self.initpos[1])**2)
-
- del dc
- else:
- event.Skip()
-
-
- def rotateafter(self):
- if(self.i!=self.previ):
- i=self.l.GetSelection()
- if i != wx.NOT_FOUND:
- #o=self.models[self.l.GetItemText(i)].offsets
- self.models[self.l.GetString(i)].rot+=5*(self.i-self.previ)
- #self.models[self.l.GetItemText(i)].offsets=o
- self.previ=self.i
- self.Refresh()
- def cr(self):
- time.sleep(0.01)
- wx.CallAfter(self.rotateafter)
- self.triggered=0
-
- def rot(self, event):
- z=event.GetWheelRotation()
- s=self.l.GetSelection()
- if self.prevsel!=s:
- self.i=0
- self.prevsel=s
- if z > 0:
- self.i-=1
- else:
- self.i+=1
- if not self.triggered:
- self.triggered=1
- threading.Thread(target=self.cr).start()
-
- def repaint(self,event):
- dc=wx.PaintDC(self)
- self.paint(dc=dc)
-
- def paint(self,coord1="x",coord2="y",dc=None):
- coords={"x":0,"y":1,"z":2}
- if dc is None:
- dc=wx.ClientDC(self)
- offset=[0,0]
- scale=2
- dc.SetPen(wx.Pen(wx.Colour(100,100,100)))
- for i in xrange(20):
- dc.DrawLine(0,i*scale*10,400,i*scale*10)
- dc.DrawLine(i*scale*10,0,i*scale*10,400)
- dc.SetPen(wx.Pen(wx.Colour(0,0,0)))
- for i in xrange(4):
- dc.DrawLine(0,i*scale*50,400,i*scale*50)
- dc.DrawLine(i*scale*50,0,i*scale*50,400)
- dc.SetBrush(wx.Brush(wx.Colour(128,255,128)))
- dc.SetPen(wx.Pen(wx.Colour(128,128,128)))
- t=time.time()
- dcs=wx.MemoryDC()
- for m in self.models.values():
- b=m.bitmap
- #print b
- im=b.ConvertToImage()
- #print im
- imgc = wx.Point( im.GetWidth()/2,im.GetHeight()/2 )
- #print math.radians(5*(self.i-self.previ))
- im= im.Rotate( math.radians(m.rot), imgc, 0)
- bm=wx.BitmapFromImage(im)
- dcs.SelectObject(bm)
- bsz=bm.GetSize()
- dc.Blit(scale*m.offsets[0]-bsz[0]/2,400-(scale*m.offsets[1]+bsz[1]/2),bsz[0],bsz[1],dcs,0,0,useMask=1)
- #for i in m.facets:#random.sample(m.facets,min(100000,len(m.facets))):
- # dc.DrawPolygon([wx.Point(offset[0]+scale*m.offsets[0]+scale*p[0],400-(offset[1]+scale*m.offsets[1]+scale*p[1])) for p in i[1]])
- #if(time.time()-t)>5:
- # break
- del dc
- #print time.time()-t
- #s.export()
-
-class stlwin(wx.Frame):
- def __init__(self,size=(400,580)):
- wx.Frame.__init__(self,None,title="Right-click to add a file",size=size)
- self.SetIcon(wx.Icon("plater.ico",wx.BITMAP_TYPE_ICO))
- self.SetClientSize(size)
- self.s=showstl(self,(400,580),(0,0))
-
+
+ self.l.Select(self.l.GetCount() - 1)
+
+
if __name__ == '__main__':
app = wx.App(False)
main = stlwin()
main.Show()
app.MainLoop()
-
diff --git a/printcore.py b/printcore.py
index 124d92b8b..cadbc0e22 100755
--- a/printcore.py
+++ b/printcore.py
@@ -1,5 +1,19 @@
#!/usr/bin/env python
-# Licensed under GPLv3
+
+# This file is part of the Printrun suite.
+#
+# Printrun is 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
+# (at your option) any later version.
+#
+# Printrun 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 Printrun. If not, see .
from serial import Serial
from threading import Thread
@@ -124,11 +138,11 @@ def _listen(self):
pass
#callback for errors
pass
- if "resend" in line.lower() or "rs" in line:
+ if line.lower().startswith("resend") or line.startswith("rs"):
try:
toresend=int(line.replace("N:"," ").replace("N"," ").replace(":"," ").split()[-1])
except:
- if "rs" in line:
+ if line.startswith("rs"):
toresend=int(line.split()[1])
self.resendfrom=toresend
self.clear=True
@@ -205,6 +219,8 @@ def _print(self):
pass
while(self.printing and self.printer and self.online):
self._sendnext()
+ self.log=[]
+ self.sent=[]
if self.endcb is not None:
try:
self.endcb()
@@ -225,6 +241,7 @@ def _sendnext(self):
self._send(self.sentlines[self.resendfrom],self.resendfrom,False)
self.resendfrom+=1
return
+ self.sentlines={}
self.resendfrom=-1
for i in self.priqueue[:]:
self._send(i)
diff --git a/projectlayer.py b/projectlayer.py
new file mode 100644
index 000000000..e50ce8b77
--- /dev/null
+++ b/projectlayer.py
@@ -0,0 +1,155 @@
+# This file is part of the Printrun suite.
+#
+# Printrun is 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
+# (at your option) any later version.
+#
+# Printrun 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 Printrun. If not, see .
+
+import xml.etree.ElementTree
+import wx
+import time
+
+def parsesvg(name):
+ et= xml.etree.ElementTree.ElementTree(file=name)
+ zlast=0
+ zdiff=0
+ ol=[]
+ for i in et.findall("{http://www.w3.org/2000/svg}g")[0].findall("{http://www.w3.org/2000/svg}g"):
+ z=float(i.get('id').split("z:")[-1])
+ zdiff=z-zlast
+ zlast=z
+ path=i.find('{http://www.w3.org/2000/svg}path')
+ ol+=[(path.get("d").split("z"))[:-1]]
+ return ol,zdiff
+
+
+class dispframe(wx.Frame):
+ def __init__(self, parent, title, res=(1600,1200),printer=None):
+ wx.Frame.__init__(self, parent=parent, title=title)
+ self.p=printer
+ self.pic=wx.StaticBitmap(self)
+ self.bitmap=wx.EmptyBitmap(*res)
+ self.SetBackgroundColour("black")
+ self.pic.Hide()
+ self.pen=wx.Pen("white")
+ self.brush=wx.Brush("white")
+ self.SetDoubleBuffered(True)
+ self.Show()
+ def drawlayer(self,svg):
+ try:
+ dc=wx.MemoryDC()
+ dc.SelectObject(self.bitmap)
+ dc.SetBackground(wx.Brush("black"))
+ dc.Clear()
+ dc.SetPen(self.pen)
+ dc.SetBrush(self.brush)
+ for i in svg:
+ #print i
+ points=[wx.Point(*map(lambda x:int(round(float(x)*self.scale)),j.strip().split())) for j in i.strip().split("M")[1].split("L")]
+ dc.DrawPolygon(points,self.size[0]/2,self.size[1]/2)
+
+
+ dc.SelectObject(wx.NullBitmap)
+ self.pic.SetBitmap(self.bitmap)
+ self.pic.Show()
+ self.Refresh()
+ except:
+ pass
+
+ def nextimg(self,event):
+ if self.index.
+
import cmd, printcore, sys
import glob, os, time
import sys, subprocess
import math
from math import sqrt
+import gettext
+if os.path.exists('/usr/share/pronterface/locale'):
+ gettext.install('pronterface', '/usr/share/pronterface/locale', unicode=1)
+else:
+ gettext.install('pronterface', './locale', unicode=1)
if os.name=="nt":
try:
@@ -108,6 +129,7 @@ def estimate_duration(g):
# calculate the maximum move duration accounting for above ;)
# print ".... estimating ...."
for i in g:
+ i=i.split(";")[0]
if "G4" in i or "G1" in i:
if "G4" in i:
parts = i.split(" ")
@@ -136,7 +158,7 @@ def estimate_duration(g):
currenttravel = hypot3d(x, y, z, lastx, lasty, lastz)
distance = 2* ((lastf+f) * (f-lastf) * 0.5 ) / acceleration #2x because we have to accelerate and decelerate
- if distance <= currenttravel:
+ if distance <= currenttravel and ( lastf + f )!=0 and f!=0:
moveduration = 2 * distance / ( lastf + f )
currenttravel -= distance
moveduration += currenttravel/f
@@ -170,13 +192,16 @@ def __init__(self):
# the initial value determines the type
self.port = ""
self.baudrate = 115200
- self.temperature_pla = 185
- self.temperature_abs = 230
- self.bedtemp_pla = 60
self.bedtemp_abs = 110
+ self.bedtemp_pla = 60
+ self.temperature_abs = 230
+ self.temperature_pla = 185
self.xy_feedrate = 3000
self.z_feedrate = 200
self.e_feedrate = 300
+ self.slicecommand="python skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_craft.py $s"
+ self.sliceoptscommand="python skeinforge/skeinforge_application/skeinforge.py"
+
def _set(self,key,value):
try:
value = getattr(self,"_%s_alias"%key)()[value]
@@ -237,6 +262,19 @@ def __init__(self):
self.settings._bedtemp_abs_cb = self.set_temp_preset
self.settings._bedtemp_pla_cb = self.set_temp_preset
self.monitoring=0
+ self.helpdict = {}
+ self.helpdict["baudrate"] = _("Communications Speed (default: 115200)")
+ self.helpdict["bedtemp_abs"] = _("Heated Build Platform temp for ABS (default: 110 deg C)")
+ self.helpdict["bedtemp_pla"] = _("Heated Build Platform temp for PLA (default: 60 deg C)")
+ self.helpdict["e_feedrate"] = _("Feedrate for Control Panel Moves in Extrusions (default: 300mm/min)")
+ self.helpdict["port"] = _("Port used to communicate with printer")
+ self.helpdict["slicecommand"] = _("Slice command\n default:\n python skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_craft.py $s)")
+ self.helpdict["sliceoptscommand"] = _("Slice settings command\n default:\n python skeinforge/skeinforge_application/skeinforge.py")
+ self.helpdict["temperature_abs"] = _("Extruder temp for ABS (default: 230 deg C)")
+ self.helpdict["temperature_pla"] = _("Extruder temp for PLA (default: 185 deg C)")
+ self.helpdict["xy_feedrate"] = _("Feedrate for Control Panel Moves in X and Y (default: 3000mm/min)")
+ self.helpdict["z_feedrate"] = _("Feedrate for Control Panel Moves in Z (default: 200mm/min)")
+
def set_temp_preset(self,key,value):
if not key.startswith("bed"):
@@ -1094,6 +1132,9 @@ def help_monitor(self):
print "monitor - Reports temperature and SD print status (if SD printing) every 5 seconds"
print "monitor 2 - Reports temperature and SD print status (if SD printing) every 2 seconds"
+ def expandcommand(self,c):
+ return c.replace("$python",sys.executable)
+
def do_skein(self,l):
l=l.split()
if len(l)==0:
@@ -1107,30 +1148,17 @@ def do_skein(self,l):
if not(os.path.exists(l[0])):
print "File not found!"
return
- if not os.path.exists("/usr/lib/python2.6/dist-packages/skeinforge/__init__.py"):
- if not os.path.exists("skeinforge"):
- print _("Skeinforge not found. \nPlease copy Skeinforge into a directory named \"skeinforge\" in the same directory as this file.")
- return
- if not os.path.exists("skeinforge/__init__.py"):
- f=open("skeinforge/__init__.py","w")
- f.close()
try:
- from skeinforge.skeinforge_application.skeinforge_utilities import skeinforge_craft
- from skeinforge.skeinforge_application import skeinforge
+ import shlex
if(settings):
- param = "/usr/lib/python2.6/dist-packages/skeinforge/skeinforge_application/skeinforge.py"
- if not os.path.exists(param):
- param = "skeinforge/skeinforge_application/skeinforge.py"
- print "Entering skeinforge settings: ",sys.executable," ",param
- subprocess.call([sys.executable,param])
+ param = self.expandcommand(self.settings.sliceoptscommand).replace("\\","\\\\").encode()
+ print "Entering skeinforge settings: ",param
+ subprocess.call(shlex.split(param))
else:
- if(len(l)>1):
- if(l[1] == "view"):
- skeinforge_craft.writeOutput(l[0],True)
- else:
- skeinforge_craft.writeOutput(l[0],False)
- else:
- skeinforge_craft.writeOutput(l[0],False)
+ param = self.expandcommand(self.settings.slicecommand).encode()
+ print "Slicing: ",param
+ params=[i.replace("$s",l[0]).replace("$o",l[0].replace(".stl","_export.gcode").replace(".STL","_export.gcode")).encode() for i in shlex.split(param.replace("\\","\\\\").encode())]
+ subprocess.call(params)
print "Loading skeined file."
self.do_load(l[0].replace(".stl","_export.gcode"))
except Exception,e:
diff --git a/pronterface.py b/pronterface.py
index 406697ffa..cad6ec50a 100755
--- a/pronterface.py
+++ b/pronterface.py
@@ -1,8 +1,23 @@
#!/usr/bin/env python
+# This file is part of the Printrun suite.
+#
+# Printrun is 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
+# (at your option) any later version.
+#
+# Printrun 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 Printrun. If not, see .
+
# Set up Internationalization using gettext
# searching for installed locales on /usr/share; uses relative folder if not found (windows)
-import os, gettext
+import os, gettext, Queue, re
if os.path.exists('/usr/share/pronterface/locale'):
gettext.install('pronterface', '/usr/share/pronterface/locale', unicode=1)
@@ -14,11 +29,12 @@
except:
print _("WX is not installed. This program requires WX to run.")
raise
-import printcore, sys, glob, time, threading, traceback, StringIO, gviz, traceback, cStringIO
+import printcore, sys, glob, time, threading, traceback, gviz, traceback, cStringIO, subprocess
try:
os.chdir(os.path.split(__file__)[0])
except:
pass
+StringIO=cStringIO
thread=threading.Thread
winsize=(800,500)
@@ -46,7 +62,7 @@ def __del__(self):
sys.stdout = self.stdout
def write(self, data):
self.target(data)
- self.stdout.write(data)
+ self.stdout.write(data.encode("utf-8"))
def flush(self):
self.stdout.flush()
@@ -54,25 +70,37 @@ def flush(self):
class PronterWindow(wx.Frame,pronsole.pronsole):
def __init__(self, filename=None,size=winsize):
pronsole.pronsole.__init__(self)
+ self.settings.build_dimensions = '200x200x100+0+0+0' #default build dimensions are 200x200x100 with 0,0,0 in the corner of the bed
+ self.settings.last_bed_temperature = 0.0
self.settings.last_file_path = ""
self.settings.last_temperature = 0.0
- self.settings.last_bed_temperature = 0.0
- self.settings.bed_size_x = 200.
- self.settings.bed_size_y = 200.
+ self.settings.preview_extrusion_width = 0.5
self.settings.preview_grid_step1 = 10.
self.settings.preview_grid_step2 = 50.
- self.settings.preview_extrusion_width = 0.5
+ self.settings.bgcolor = "#FFFFFF"
+ self.helpdict["build_dimensions"] = _("Dimensions of Build Platform\n & optional offset of origin\n\nExamples:\n XXXxYYY\n XXX,YYY,ZZZ\n XXXxYYYxZZZ+OffX+OffY+OffZ")
+ self.helpdict["last_bed_temperature"] = _("Last Set Temperature for the Heated Print Bed")
+ self.helpdict["last_file_path"] = _("Folder of last opened file")
+ self.helpdict["last_temperature"] = _("Last Temperature of the Hot End")
+ self.helpdict["preview_extrusion_width"] = _("Width of Extrusion in Preview (default: 0.5)")
+ self.helpdict["preview_grid_step1"] = _("Fine Grid Spacing (default: 10)")
+ self.helpdict["preview_grid_step2"] = _("Coarse Grid Spacing (default: 50)")
+ self.helpdict["bgcolor"] = _("Pronterface background color (default: #FFFFFF)")
self.filename=filename
os.putenv("UBUNTU_MENUPROXY","0")
wx.Frame.__init__(self,None,title=_("Printer Interface"),size=size);
self.SetIcon(wx.Icon("P-face.ico",wx.BITMAP_TYPE_ICO))
self.panel=wx.Panel(self,-1,size=size)
- self.panel.SetBackgroundColour("white")
+
self.statuscheck=False
+ self.capture_skip=[]
self.tempreport=""
self.monitor=0
+ self.f=None
+ self.skeinp=None
self.monitor_interval=3
self.paused=False
+ self.sentlines=Queue.Queue(30)
xcol=(245,245,108)
ycol=(180,180,255)
zcol=(180,255,180)
@@ -85,6 +113,8 @@ def __init__(self, filename=None,size=winsize):
self.custombuttons=[]
self.btndict={}
self.parse_cmdline(sys.argv[1:])
+ self.build_dimensions_list = self.get_build_dimensions(self.settings.build_dimensions)
+ self.panel.SetBackgroundColour(self.settings.bgcolor)
customdict={}
try:
execfile("custombtn.txt",customdict)
@@ -110,6 +140,7 @@ def __init__(self, filename=None,size=winsize):
self.popwindow()
self.t=Tee(self.catchprint)
self.stdout=sys.stdout
+ self.skeining=0
self.mini=False
self.p.sendcb=self.sentcb
self.p.startcb=self.startcb
@@ -134,7 +165,9 @@ def endcb(self):
def online(self):
print _("Printer is now online.")
- wx.CallAfter(self.connectbtn.Disable)
+ self.connectbtn.SetLabel("Disconnect")
+ self.connectbtn.Bind(wx.EVT_BUTTON,self.disconnect)
+
for i in self.printerControls:
wx.CallAfter(i.Enable)
@@ -157,7 +190,11 @@ def sentcb(self,line):
threading.Thread(target=wx.CallAfter,args=(self.gviz.setlayer,layer)).start()
except:
pass
- threading.Thread(target=self.gviz.addgcode,args=(line,1)).start()
+ try:
+ self.sentlines.put_nowait(line)
+ except:
+ pass
+ #threading.Thread(target=self.gviz.addgcode,args=(line,1)).start()
#self.gwindow.p.addgcode(line,hilight=1)
def do_extrude(self,l=""):
@@ -189,22 +226,22 @@ def do_settemp(self,l=""):
self.p.send_now("M104 S"+l)
print _("Setting hotend temperature to "),f,_(" degrees Celsius.")
self.hsetpoint=f
- #self.tgauge.SetTarget(int(f))
+ self.hottgauge.SetTarget(int(f))
if f>0:
- self.htemp.SetValue(l)
+ wx.CallAfter(self.htemp.SetValue,l)
self.set("last_temperature",str(f))
- self.settoff.SetBackgroundColour("")
- self.settoff.SetForegroundColour("")
- self.settbtn.SetBackgroundColour("#FFAA66")
- self.settbtn.SetForegroundColour("#660000")
- self.htemp.SetBackgroundColour("#FFDABB")
+ wx.CallAfter(self.settoff.SetBackgroundColour,"")
+ wx.CallAfter(self.settoff.SetForegroundColour,"")
+ wx.CallAfter(self.settbtn.SetBackgroundColour,"#FFAA66")
+ wx.CallAfter(self.settbtn.SetForegroundColour,"#660000")
+ wx.CallAfter(self.htemp.SetBackgroundColour,"#FFDABB")
else:
- self.settoff.SetBackgroundColour("#0044CC")
- self.settoff.SetForegroundColour("white")
- self.settbtn.SetBackgroundColour("")
- self.settbtn.SetForegroundColour("")
- self.htemp.SetBackgroundColour("white")
- self.htemp.Refresh()
+ wx.CallAfter(self.settoff.SetBackgroundColour,"#0044CC")
+ wx.CallAfter(self.settoff.SetForegroundColour,"white")
+ wx.CallAfter(self.settbtn.SetBackgroundColour,"")
+ wx.CallAfter(self.settbtn.SetForegroundColour,"")
+ wx.CallAfter(self.htemp.SetBackgroundColour,"white")
+ wx.CallAfter(self.htemp.Refresh)
else:
print _("Printer is not online.")
else:
@@ -225,21 +262,22 @@ def do_bedtemp(self,l=""):
self.p.send_now("M140 S"+l)
print _("Setting bed temperature to "),f,_(" degrees Celsius.")
self.bsetpoint=f
+ self.bedtgauge.SetTarget(int(f))
if f>0:
- self.btemp.SetValue(l)
+ wx.CallAfter(self.btemp.SetValue,l)
self.set("last_bed_temperature",str(f))
- self.setboff.SetBackgroundColour("")
- self.setboff.SetForegroundColour("")
- self.setbbtn.SetBackgroundColour("#FFAA66")
- self.setbbtn.SetForegroundColour("#660000")
- self.btemp.SetBackgroundColour("#FFDABB")
+ wx.CallAfter(self.setboff.SetBackgroundColour,"")
+ wx.CallAfter(self.setboff.SetForegroundColour,"")
+ wx.CallAfter(self.setbbtn.SetBackgroundColour,"#FFAA66")
+ wx.CallAfter(self.setbbtn.SetForegroundColour,"#660000")
+ wx.CallAfter(self.btemp.SetBackgroundColour,"#FFDABB")
else:
- self.setboff.SetBackgroundColour("#0044CC")
- self.setboff.SetForegroundColour("white")
- self.setbbtn.SetBackgroundColour("")
- self.setbbtn.SetForegroundColour("")
- self.btemp.SetBackgroundColour("white")
- self.btemp.Refresh()
+ wx.CallAfter(self.setboff.SetBackgroundColour,"#0044CC")
+ wx.CallAfter(self.setboff.SetForegroundColour,"white")
+ wx.CallAfter(self.setbbtn.SetBackgroundColour,"")
+ wx.CallAfter(self.setbbtn.SetForegroundColour,"")
+ wx.CallAfter(self.btemp.SetBackgroundColour,"white")
+ wx.CallAfter(self.btemp.Refresh)
else:
print _("Printer is not online.")
else:
@@ -274,6 +312,10 @@ def cb(definition):
pronsole.pronsole.start_macro(self,macro_name,old_macro_definition)
def catchprint(self,l):
+ for pat in self.capture_skip:
+ if pat.match(l):
+ self.capture_skip.remove(pat)
+ return
wx.CallAfter(self.logbox.AppendText,l)
def scanserial(self):
@@ -290,6 +332,13 @@ def scanserial(self):
pass
return baselist+glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*') +glob.glob("/dev/tty.*")+glob.glob("/dev/cu.*")+glob.glob("/dev/rfcomm*")
+ def project(self,event):
+ import projectlayer
+ if(self.p.online):
+ projectlayer.setframe(self,self.p).Show()
+ else:
+ print _("Printer is not online.")
+
def popmenu(self):
self.menustrip = wx.MenuBar()
# File menu
@@ -297,6 +346,7 @@ def popmenu(self):
self.Bind(wx.EVT_MENU, self.loadfile, m.Append(-1,_("&Open..."),_(" Opens file")))
self.Bind(wx.EVT_MENU, self.do_editgcode, m.Append(-1,_("&Edit..."),_(" Edit open file")))
self.Bind(wx.EVT_MENU, self.clearOutput, m.Append(-1,_("Clear console"),_(" Clear output console")))
+ self.Bind(wx.EVT_MENU, self.project, m.Append(-1,_("Projector"),_(" Project slices")))
self.Bind(wx.EVT_MENU, self.OnExit, m.Append(wx.ID_EXIT,_("E&xit"),_(" Closes the Window")))
self.menustrip.Append(m,_("&File"))
@@ -307,12 +357,12 @@ def popmenu(self):
self.Bind(wx.EVT_MENU, self.new_macro, self.macros_menu.Append(-1, _("<&New...>")))
self.Bind(wx.EVT_MENU, lambda *e:options(self), m.Append(-1,_("&Options"),_(" Options dialog")))
- self.Bind(wx.EVT_MENU, lambda x:threading.Thread(target=lambda :self.do_skein("set")).start(), m.Append(-1,_("SFACT Settings"),_(" Adjust SFACT settings")))
- try:
- from SkeinforgeQuickEditDialog import SkeinforgeQuickEditDialog
- self.Bind(wx.EVT_MENU, lambda *e:SkeinforgeQuickEditDialog(self), m.Append(-1,_("SFACT Quick Settings"),_(" Quickly adjust SFACT settings for active profile")))
- except:
- pass
+ self.Bind(wx.EVT_MENU, lambda x:threading.Thread(target=lambda :self.do_skein("set")).start(), m.Append(-1,_("Slicing Settings"),_(" Adjust slicing settings")))
+ #try:
+ # from SkeinforgeQuickEditDialog import SkeinforgeQuickEditDialog
+ # self.Bind(wx.EVT_MENU, lambda *e:SkeinforgeQuickEditDialog(self), m.Append(-1,_("SFACT Quick Settings"),_(" Quickly adjust SFACT settings for active profile")))
+ #except:
+ # pass
self.menustrip.Append(m,_("&Settings"))
self.update_macros_menu()
@@ -410,103 +460,88 @@ def popwindow(self):
#lower section contains the rest of the window - manual controls, console, visualizations
#TOP ROW:
uts=self.uppertopsizer=wx.BoxSizer(wx.HORIZONTAL)
- self.rescanbtn=wx.Button(self.panel,-1,_("Port"),pos=(380,0))
+ self.rescanbtn=wx.Button(self.panel,-1,_("Port"))
self.rescanbtn.Bind(wx.EVT_BUTTON,self.rescanports)
- uts.Add(self.rescanbtn,wx.TOP|wx.LEFT,0)
+ uts.Add(self.rescanbtn,0,wx.TOP|wx.LEFT,0)
self.serialport = wx.ComboBox(self.panel, -1,
choices=self.scanserial(),
- style=wx.CB_DROPDOWN, pos=(50,0))
+ style=wx.CB_DROPDOWN)
self.rescanports()
uts.Add(self.serialport)
- uts.Add(wx.StaticText(self.panel,-1,"@",pos=(250,5)),wx.RIGHT,5)
+ uts.Add(wx.StaticText(self.panel,-1,"@"),0,wx.RIGHT|wx.ALIGN_CENTER,0)
self.baud = wx.ComboBox(self.panel, -1,
choices=["2400", "9600", "19200", "38400", "57600", "115200", "250000"],
- style=wx.CB_DROPDOWN, size=(110,30),pos=(275,0))
+ style=wx.CB_DROPDOWN)
try:
self.baud.SetValue("115200")
self.baud.SetValue(str(self.settings.baudrate))
except:
pass
uts.Add(self.baud)
- self.connectbtn=wx.Button(self.panel,-1,_("Connect"),pos=(380,0))
+ self.connectbtn=wx.Button(self.panel,-1,_("Connect"))
uts.Add(self.connectbtn)
self.connectbtn.SetToolTipString(_("Connect to the printer"))
self.connectbtn.Bind(wx.EVT_BUTTON,self.connect)
- self.disconnectbtn=wx.Button(self.panel,-1,_("Disconnect"),pos=(470,0))
- self.disconnectbtn.Bind(wx.EVT_BUTTON,self.disconnect)
- self.printerControls.append(self.disconnectbtn)
- uts.Add(self.disconnectbtn)
- self.resetbtn=wx.Button(self.panel,-1,_("Reset"),pos=(560,0))
+ self.resetbtn=wx.Button(self.panel,-1,_("Reset"))
self.resetbtn.Bind(wx.EVT_BUTTON,self.reset)
uts.Add(self.resetbtn)
- self.minibtn=wx.Button(self.panel,-1,_("Mini mode"),pos=(690,0))
+ self.minibtn=wx.Button(self.panel,-1,_("Mini mode"))
self.minibtn.Bind(wx.EVT_BUTTON,self.toggleview)
- #self.tgauge=TempGauge(self.panel,size=(300,24))
- #def scroll_setpoint(e):
- # if e.GetWheelRotation()>0:
- # self.do_settemp(str(self.hsetpoint+1))
- # elif e.GetWheelRotation()<0:
- # self.do_settemp(str(max(0,self.hsetpoint-1)))
- #self.tgauge.Bind(wx.EVT_MOUSEWHEEL,scroll_setpoint)
- uts.Add((10,-1))
- self.monitorbox=wx.CheckBox(self.panel,-1,"",pos=(450,37))
- uts.Add((15,-1))
- uts.Add(self.monitorbox)
- uts.Add(wx.StaticText(self.panel,-1,_("Monitor\nprinter"),pos=(470,37)))
+ uts.Add((25,-1))
+ self.monitorbox=wx.CheckBox(self.panel,-1,_("Monitor Printer"))
+ uts.Add(self.monitorbox,0,wx.ALIGN_CENTER)
self.monitorbox.Bind(wx.EVT_CHECKBOX,self.setmonitor)
uts.Add((15,-1),flag=wx.EXPAND)
- uts.Add(self.minibtn)
- #uts.Add(self.tgauge)
+ uts.Add(self.minibtn,0,wx.ALIGN_CENTER)
#SECOND ROW
ubs=self.upperbottomsizer=wx.BoxSizer(wx.HORIZONTAL)
- self.loadbtn=wx.Button(self.panel,-1,_("Load file"),pos=(0,40))
+ self.loadbtn=wx.Button(self.panel,-1,_("Load file"))
self.loadbtn.Bind(wx.EVT_BUTTON,self.loadfile)
ubs.Add(self.loadbtn)
- self.uploadbtn=wx.Button(self.panel,-1,_("SD Upload"),pos=(90,40))
- self.uploadbtn.Bind(wx.EVT_BUTTON,self.upload)
- self.printerControls.append(self.uploadbtn)
- ubs.Add(self.uploadbtn)
- self.sdprintbtn=wx.Button(self.panel,-1,_("SD Print"),pos=(180,40))
- self.sdprintbtn.Bind(wx.EVT_BUTTON,self.sdprintfile)
- self.printerControls.append(self.sdprintbtn)
- ubs.Add(self.sdprintbtn)
- self.printbtn=wx.Button(self.panel,-1,_("Print"),pos=(270,40))
+ self.platebtn=wx.Button(self.panel,-1,_("Compose"))
+ self.platebtn.Bind(wx.EVT_BUTTON,self.plate)
+ #self.printerControls.append(self.uploadbtn)
+ ubs.Add(self.platebtn)
+ self.sdbtn=wx.Button(self.panel,-1,_("SD"))
+ self.sdbtn.Bind(wx.EVT_BUTTON,self.sdmenu)
+ self.printerControls.append(self.sdbtn)
+ ubs.Add(self.sdbtn)
+ self.printbtn=wx.Button(self.panel,-1,_("Print"))
self.printbtn.Bind(wx.EVT_BUTTON,self.printfile)
self.printbtn.Disable()
ubs.Add(self.printbtn)
- self.pausebtn=wx.Button(self.panel,-1,_("Pause"),pos=(360,40))
+ self.pausebtn=wx.Button(self.panel,-1,_("Pause"))
self.pausebtn.Bind(wx.EVT_BUTTON,self.pause)
ubs.Add(self.pausebtn)
- ubs.Add((50,-1),flag=wx.EXPAND)
#Right full view
lrs=self.lowerrsizer=wx.BoxSizer(wx.VERTICAL)
- self.logbox=wx.TextCtrl(self.panel,size=(350,340),pos=(440,75),style = wx.TE_MULTILINE)
+ self.logbox=wx.TextCtrl(self.panel,style = wx.TE_MULTILINE,size=(350,-1))
self.logbox.SetEditable(0)
- lrs.Add(self.logbox)
+ lrs.Add(self.logbox,1,wx.EXPAND)
lbrs=wx.BoxSizer(wx.HORIZONTAL)
- self.commandbox=wx.TextCtrl(self.panel,size=(295,30),pos=(440,420),style = wx.TE_PROCESS_ENTER)
+ self.commandbox=wx.TextCtrl(self.panel,style = wx.TE_PROCESS_ENTER)
self.commandbox.Bind(wx.EVT_TEXT_ENTER,self.sendline)
#self.printerControls.append(self.commandbox)
- lbrs.Add(self.commandbox)
- self.sendbtn=wx.Button(self.panel,-1,_("Send"),size=(55,28), pos=(700,420))
+ lbrs.Add(self.commandbox,1)
+ self.sendbtn=wx.Button(self.panel,-1,_("Send"))
self.sendbtn.Bind(wx.EVT_BUTTON,self.sendline)
#self.printerControls.append(self.sendbtn)
lbrs.Add(self.sendbtn)
- lrs.Add(lbrs)
+ lrs.Add(lbrs,0,wx.EXPAND)
#left pane
lls=self.lowerlsizer=wx.GridBagSizer()
- lls.Add(wx.StaticText(self.panel,-1,_("mm/min"),pos=(60,69)),pos=(0,4),span=(1,4))
- self.xyfeedc=wx.SpinCtrl(self.panel,-1,str(self.settings.xy_feedrate),min=0,max=50000,size=(70,25),pos=(25,83))
- lls.Add(wx.StaticText(self.panel,-1,_("XY:"),pos=(2,90-2)),pos=(1,3),span=(1,1), flag=wx.ALIGN_CENTER)
+ lls.Add(wx.StaticText(self.panel,-1,_("mm/min")),pos=(0,4),span=(1,4))
+ self.xyfeedc=wx.SpinCtrl(self.panel,-1,str(self.settings.xy_feedrate),min=0,max=50000,size=(70,-1))
+ lls.Add(wx.StaticText(self.panel,-1,_("XY:")),pos=(1,3),span=(1,1), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
lls.Add(self.xyfeedc,pos=(1,4),span=(1,2))
- lls.Add(wx.StaticText(self.panel,-1,_("Z:"),pos=(90,90-2)),pos=(1,6),span=(1,1), flag=wx.ALIGN_CENTER)
- self.zfeedc=wx.SpinCtrl(self.panel,-1,str(self.settings.z_feedrate),min=0,max=50000,size=(70,25),pos=(105,83))
+ lls.Add(wx.StaticText(self.panel,-1,_("Z:")),pos=(1,6),span=(1,1), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ self.zfeedc=wx.SpinCtrl(self.panel,-1,str(self.settings.z_feedrate),min=0,max=50000,size=(70,-1))
lls.Add(self.zfeedc,pos=(1,7),span=(1,3))
#lls.Add((200,375))
@@ -518,7 +553,7 @@ def popwindow(self):
wx.CallAfter(self.xyb.SetFocus)
for i in self.cpbuttons:
- btn=wx.Button(self.panel,-1,i[0])#,size=(60,-1))
+ btn=wx.Button(self.panel,-1,i[0])#)
btn.SetBackgroundColour(i[3])
btn.SetForegroundColour("black")
btn.properties=i
@@ -528,10 +563,10 @@ def popwindow(self):
lls.Add(btn,pos=i[2],span=i[4])
- lls.Add(wx.StaticText(self.panel,-1,_("Heater:"),pos=(0,343)),pos=(3,0),span=(1,1),flag=wx.ALIGN_CENTER)
+ lls.Add(wx.StaticText(self.panel,-1,_("Heater:")),pos=(3,0),span=(1,1),flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT)
htemp_choices=[self.temps[i]+" ("+i+")" for i in sorted(self.temps.keys(),key=lambda x:self.temps[x])]
- self.settoff=wx.Button(self.panel,-1,_("Off"),size=(36,-1),pos=(45,335))
+ self.settoff=wx.Button(self.panel,-1,_("Off"),size=(36,-1))
self.settoff.Bind(wx.EVT_BUTTON,lambda e:self.do_settemp("off"))
self.printerControls.append(self.settoff)
lls.Add(self.settoff,pos=(3,1),span=(1,1))
@@ -539,19 +574,19 @@ def popwindow(self):
if self.settings.last_temperature not in map(float,self.temps.values()):
htemp_choices = [str(self.settings.last_temperature)] + htemp_choices
self.htemp=wx.ComboBox(self.panel, -1,
- choices=htemp_choices,style=wx.CB_DROPDOWN, size=(80,25),pos=(45,337))
+ choices=htemp_choices,style=wx.CB_DROPDOWN, size=(80,-1))
self.htemp.Bind(wx.EVT_COMBOBOX,self.htemp_change)
lls.Add(self.htemp,pos=(3,2),span=(1,2))
- self.settbtn=wx.Button(self.panel,-1,_("Set"),size=(36,-1),pos=(125,335))
+ self.settbtn=wx.Button(self.panel,-1,_("Set"),size=(38,-1))
self.settbtn.Bind(wx.EVT_BUTTON,self.do_settemp)
self.printerControls.append(self.settbtn)
lls.Add(self.settbtn,pos=(3,4),span=(1,1))
- lls.Add(wx.StaticText(self.panel,-1,_("Bed:"),pos=(0,343)),pos=(4,0),span=(1,1),flag=wx.ALIGN_CENTER)
+ lls.Add(wx.StaticText(self.panel,-1,_("Bed:")),pos=(4,0),span=(1,1),flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT)
btemp_choices=[self.bedtemps[i]+" ("+i+")" for i in sorted(self.bedtemps.keys(),key=lambda x:self.temps[x])]
- self.setboff=wx.Button(self.panel,-1,_("Off"),size=(36,-1),pos=(135,335))
+ self.setboff=wx.Button(self.panel,-1,_("Off"),size=(36,-1))
self.setboff.Bind(wx.EVT_BUTTON,lambda e:self.do_bedtemp("off"))
self.printerControls.append(self.setboff)
lls.Add(self.setboff,pos=(4,1),span=(1,1))
@@ -559,14 +594,14 @@ def popwindow(self):
if self.settings.last_bed_temperature not in map(float,self.bedtemps.values()):
btemp_choices = [str(self.settings.last_bed_temperature)] + btemp_choices
self.btemp=wx.ComboBox(self.panel, -1,
- choices=btemp_choices,style=wx.CB_DROPDOWN, size=(80,25),pos=(135,367))
+ choices=btemp_choices,style=wx.CB_DROPDOWN, size=(80,-1))
self.btemp.Bind(wx.EVT_COMBOBOX,self.btemp_change)
lls.Add(self.btemp,pos=(4,2),span=(1,2))
- self.setbbtn=wx.Button(self.panel,-1,_("Set"),size=(38,-1),pos=(135,365))
+ self.setbbtn=wx.Button(self.panel,-1,_("Set"),size=(38,-1))
self.setbbtn.Bind(wx.EVT_BUTTON,self.do_bedtemp)
self.printerControls.append(self.setbbtn)
- lls.Add(self.setbbtn,pos=(4,4),span=(1,2))
+ lls.Add(self.setbbtn,pos=(4,4),span=(1,1))
self.btemp.SetValue(str(self.settings.last_bed_temperature))
self.htemp.SetValue(str(self.settings.last_temperature))
@@ -590,38 +625,56 @@ def popwindow(self):
#lls.Add(self.btemp,pos=(4,1),span=(1,3))
#lls.Add(self.setbbtn,pos=(4,4),span=(1,2))
self.tempdisp=wx.StaticText(self.panel,-1,"")
- lls.Add(self.tempdisp,pos=(4,6),span=(1,3))
+ lls.Add(self.tempdisp,pos=(4,5),span=(1,3))
- self.edist=wx.SpinCtrl(self.panel,-1,"5",min=0,max=1000,size=(60,25),pos=(70,398))
+ self.edist=wx.SpinCtrl(self.panel,-1,"5",min=0,max=1000,size=(60,-1))
self.edist.SetBackgroundColour((225,200,200))
self.edist.SetForegroundColour("black")
lls.Add(self.edist,pos=(5,2),span=(1,1))
- lls.Add(wx.StaticText(self.panel,-1,_("mm"),pos=(130,407)),pos=(5,3),span=(1,2))
- self.efeedc=wx.SpinCtrl(self.panel,-1,str(self.settings.e_feedrate),min=0,max=50000,size=(60,25),pos=(70,397+28))
+ lls.Add(wx.StaticText(self.panel,-1,_("mm")),pos=(5,3),span=(1,2))
+ self.efeedc=wx.SpinCtrl(self.panel,-1,str(self.settings.e_feedrate),min=0,max=50000,size=(60,-1))
self.efeedc.SetBackgroundColour((225,200,200))
self.efeedc.SetForegroundColour("black")
self.efeedc.Bind(wx.EVT_SPINCTRL,self.setfeeds)
lls.Add(self.efeedc,pos=(6,2),span=(1,1))
- lls.Add(wx.StaticText(self.panel,-1,_("mm/min"),pos=(130,407+27)),pos=(6,3),span=(1,2))
+ lls.Add(wx.StaticText(self.panel,-1,_("mm/min")),pos=(6,3),span=(1,2))
self.xyfeedc.Bind(wx.EVT_SPINCTRL,self.setfeeds)
self.zfeedc.Bind(wx.EVT_SPINCTRL,self.setfeeds)
self.zfeedc.SetBackgroundColour((180,255,180))
self.zfeedc.SetForegroundColour("black")
# lls.Add((10,0),pos=(0,11),span=(1,1))
+
+ self.hottgauge=TempGauge(self.panel,size=(300,24),title=_("Heater:"),maxval=230)
+ lls.Add(self.hottgauge,pos=(7,0),span=(1,8))
+ self.bedtgauge=TempGauge(self.panel,size=(300,24),title=_("Bed:"),maxval=130)
+ lls.Add(self.bedtgauge,pos=(8,0),span=(1,8))
+ #def scroll_setpoint(e):
+ # if e.GetWheelRotation()>0:
+ # self.do_settemp(str(self.hsetpoint+1))
+ # elif e.GetWheelRotation()<0:
+ # self.do_settemp(str(max(0,self.hsetpoint-1)))
+ #self.tgauge.Bind(wx.EVT_MOUSEWHEEL,scroll_setpoint)
+
self.gviz=gviz.gviz(self.panel,(300,300),
- bedsize=(self.settings.bed_size_x,self.settings.bed_size_y),
+ build_dimensions=self.build_dimensions_list,
grid=(self.settings.preview_grid_step1,self.settings.preview_grid_step2),
extrusion_width=self.settings.preview_extrusion_width)
self.gviz.showall=1
- self.gwindow=gviz.window([],
- bedsize=(self.settings.bed_size_x,self.settings.bed_size_y),
+ try:
+ raise ""
+ import stlview
+ self.gwindow=stlview.GCFrame(None, wx.ID_ANY, 'Gcode view, shift to move view, mousewheel to set layer', size=(600,600))
+ except:
+ self.gwindow=gviz.window([],
+ build_dimensions=self.build_dimensions_list,
grid=(self.settings.preview_grid_step1,self.settings.preview_grid_step2),
extrusion_width=self.settings.preview_extrusion_width)
self.gviz.Bind(wx.EVT_LEFT_DOWN,self.showwin)
self.gwindow.Bind(wx.EVT_CLOSE,lambda x:self.gwindow.Hide())
+ vcs=wx.BoxSizer(wx.VERTICAL)
+ vcs.Add(self.gviz,1,flag=wx.SHAPED)
cs=self.centersizer=wx.GridBagSizer()
- cs.Add(self.gviz,pos=(0,0),span=(1,3))
- lls.Add(cs,pos=(0,10),span=(8,1))
+ vcs.Add(cs,0,flag=wx.EXPAND)
self.uppersizer=wx.BoxSizer(wx.VERTICAL)
self.uppersizer.Add(self.uppertopsizer)
@@ -629,15 +682,17 @@ def popwindow(self):
self.lowersizer=wx.BoxSizer(wx.HORIZONTAL)
self.lowersizer.Add(lls)
- self.lowersizer.Add(lrs)
+ self.lowersizer.Add(vcs,1,wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL)
+ self.lowersizer.Add(lrs,0,wx.EXPAND)
self.topsizer=wx.BoxSizer(wx.VERTICAL)
self.topsizer.Add(self.uppersizer)
- self.topsizer.Add(self.lowersizer)
+ self.topsizer.Add(self.lowersizer,1,wx.EXPAND)
self.panel.SetSizer(self.topsizer)
self.status=self.CreateStatusBar()
self.status.SetStatusText(_("Not connected to printer."))
self.panel.Bind(wx.EVT_MOUSE_EVENTS,self.editbutton)
self.Bind(wx.EVT_CLOSE, self.kill)
+
self.topsizer.Layout()
self.topsizer.Fit(self)
@@ -649,7 +704,28 @@ def popwindow(self):
#self.panel.Fit()
#uts.Layout()
self.cbuttons_reload()
+
+ def plate(self,e):
+ import plater
+ print "plate function activated"
+ plater.stlwin(size=(800,580),callback=self.platecb,parent=self).Show()
+
+ def platecb(self,name):
+ print "plated: "+name
+ self.loadfile(None,name)
+
+ def sdmenu(self,e):
+ obj = e.GetEventObject()
+ popupmenu=wx.Menu()
+ item = popupmenu.Append(-1,_("SD Upload"))
+ if not self.f or not len(self.f):
+ item.Enable(False)
+ self.Bind(wx.EVT_MENU,self.upload,id=item.GetId())
+ item = popupmenu.Append(-1,_("SD Print"))
+ self.Bind(wx.EVT_MENU,self.sdprintfile,id=item.GetId())
+ self.panel.PopupMenu(popupmenu, obj.GetPosition())
+
def htemp_change(self,event):
if self.hsetpoint > 0:
self.do_settemp("")
@@ -662,8 +738,9 @@ def btemp_change(self,event):
def showwin(self,event):
if(self.f is not None):
- self.gwindow.Show()
-
+ self.gwindow.Show(True)
+ self.gwindow.Raise()
+
def setfeeds(self,e):
self.feedrates_changed = True
try:
@@ -732,9 +809,7 @@ def cbuttons_reload(self):
b.SetToolTip(wx.ToolTip(_("click to add new custom button")))
b.Bind(wx.EVT_BUTTON,self.cbutton_edit)
else:
- b=wx.StaticText(self.panel,-1,"",size=(72,22),style=wx.ALIGN_CENTRE+wx.ST_NO_AUTORESIZE) #+wx.SIMPLE_BORDER
- #b.Freeze()
- b.Disable()
+ continue
b.custombutton=i
b.properties=btndef
if btndef is not None:
@@ -746,7 +821,7 @@ def cbuttons_reload(self):
if i<4:
ubs.Add(b)
else:
- cs.Add(b,pos=(1+(i-4)/3,(i-4)%3),span=(1,1))
+ cs.Add(b,pos=((i-4)/3,(i-4)%3))
self.topsizer.Layout()
def help_button(self):
@@ -1043,11 +1118,11 @@ def do_monitor(self,l=""):
if l.strip()=="":
self.monitorbox.SetValue(not self.monitorbox.GetValue())
elif l.strip()=="off":
- self.monitorbox.SetValue(False)
+ wx.CallAfter(self.monitorbox.SetValue,False)
else:
try:
self.monitor_interval=float(l)
- self.monitorbox.SetValue(self.monitor_interval>0)
+ wx.CallAfter(self.monitorbox.SetValue,self.monitor_interval>0)
except:
print _("Invalid period given.")
self.setmonitor(None)
@@ -1083,10 +1158,11 @@ def statuschecker(self):
pass
string+=(self.tempreport.replace("\r","").replace("T",_("Hotend")).replace("B",_("Bed")).replace("\n","").replace("ok ",""))+" "
wx.CallAfter(self.tempdisp.SetLabel,self.tempreport.strip().replace("ok ",""))
- #try:
- # self.tgauge.SetValue(int(filter(lambda x:x.startswith("T:"),self.tempreport.split())[0].split(":")[1]))
- #except:
- # pass
+ try:
+ self.hottgauge.SetValue(float(filter(lambda x:x.startswith("T:"),self.tempreport.split())[0].split(":")[1]))
+ self.bedtgauge.SetValue(float(filter(lambda x:x.startswith("B:"),self.tempreport.split())[0].split(":")[1]))
+ except:
+ pass
fractioncomplete = 0.0
if self.sdprinting:
fractioncomplete = float(self.percentdone/100.0)
@@ -1108,8 +1184,16 @@ def statuschecker(self):
if(self.monitor and self.p.online):
if self.sdprinting:
self.p.send_now("M27")
+ self.capture_skip.append(re.compile(r"ok T:[\d\.]+( B:[\d\.]+)?( @:[\d\.]+)?\s*"))
+ self.capture_skip.append(re.compile(r"\n"))
self.p.send_now("M105")
time.sleep(self.monitor_interval)
+ while not self.sentlines.empty():
+ try:
+ gc=self.sentlines.get_nowait()
+ wx.CallAfter(self.gviz.addgcode,gc,1)
+ except:
+ break
wx.CallAfter(self.status.SetStatusText,_("Not connected to printer."))
except:
pass #if window has been closed
@@ -1136,10 +1220,11 @@ def recvcb(self,l):
if "T:" in l:
self.tempreport=l
wx.CallAfter(self.tempdisp.SetLabel,self.tempreport.strip().replace("ok ",""))
- #try:
- # self.tgauge.SetValue(int(filter(lambda x:x.startswith("T:"),self.tempreport.split())[0].split(":")[1]))
- #except:
- # pass
+ try:
+ self.hottgauge.SetValue(float(filter(lambda x:x.startswith("T:"),self.tempreport.split())[0].split(":")[1]))
+ self.bedtgauge.SetValue(float(filter(lambda x:x.startswith("B:"),self.tempreport.split())[0].split(":")[1]))
+ except:
+ pass
tstring=l.rstrip()
#print tstring
if(tstring!="ok"):
@@ -1211,21 +1296,27 @@ def getfiles(self):
def skein_func(self):
try:
- from skeinforge.skeinforge_application.skeinforge_utilities import skeinforge_craft
- from skeinforge.skeinforge_application import skeinforge
- from skeinforge.fabmetheus_utilities import settings
- skeinforge_craft.writeOutput(self.filename,False)
- #print len(self.cout.getvalue().split())
+ import shlex
+ param = self.expandcommand(self.settings.slicecommand).encode()
+ print "Slicing: ",param
+ pararray=[i.replace("$s",self.filename).replace("$o",self.filename.replace(".stl","_export.gcode").replace(".STL","_export.gcode")).encode() for i in shlex.split(param.replace("\\","\\\\").encode())]
+ #print pararray
+ self.skeinp=subprocess.Popen(pararray,stderr=subprocess.STDOUT,stdout=subprocess.PIPE)
+ while True:
+ o = self.skeinp.stdout.read(1)
+ if o == '' and self.skeinp.poll() != None: break
+ sys.stdout.write(o)
+ self.skeinp.wait()
self.stopsf=1
except:
- print _("Skeinforge execution failed.")
+ print _("Failed to execute slicing software: ")
self.stopsf=1
traceback.print_exc(file=sys.stdout)
def skein_monitor(self):
while(not self.stopsf):
try:
- wx.CallAfter(self.status.SetStatusText,_("Skeining..."))#+self.cout.getvalue().split("\n")[-1])
+ wx.CallAfter(self.status.SetStatusText,_("Slicing..."))#+self.cout.getvalue().split("\n")[-1])
except:
pass
time.sleep(0.1)
@@ -1245,23 +1336,25 @@ def skein_monitor(self):
threading.Thread(target=self.loadviz).start()
except:
self.filename=fn
+ wx.CallAfter(self.loadbtn.SetLabel,_("Load File"))
+ self.skeining=0
+ self.skeinp=None
+
def skein(self,filename):
- print _("Skeining ") + filename
- if not os.path.exists("/usr/lib/python2.6/dist-packages/skeinforge/__init__.py"):
- if not os.path.exists("skeinforge"):
- print _("Skeinforge not found. \nPlease copy Skeinforge into a directory named \"skeinforge\" in the same directory as this file.")
- return
- if not os.path.exists("skeinforge/__init__.py"):
- f=open("skeinforge/__init__.py","w")
- f.close()
+ wx.CallAfter(self.loadbtn.SetLabel,_("Cancel"))
+ print _("Slicing ") + filename
self.cout=StringIO.StringIO()
self.filename=filename
self.stopsf=0
+ self.skeining=1
thread(target=self.skein_func).start()
thread(target=self.skein_monitor).start()
def loadfile(self,event,filename=None):
+ if self.skeining and self.skeinp is not None:
+ self.skeinp.terminate()
+ return
basedir=self.settings.last_file_path
if not os.path.exists(basedir):
basedir = "."
@@ -1306,11 +1399,15 @@ def loadviz(self):
print _("the print goes from"),Ymin,_("mm to"),Ymax,_("mm in Y\nand is"),Ytot,_("mm wide\n")
print _("the print goes from"),Zmin,_("mm to"),Zmax,_("mm in Z\nand is"),Ztot,_("mm high\n")
print _("Estimated duration (pessimistic): "), pronsole.estimate_duration(self.f)
+ #import time
+ #t0=time.time()
self.gviz.clear()
self.gwindow.p.clear()
- for i in self.f:
- self.gviz.addgcode(i)
- self.gwindow.p.addgcode(i)
+ self.gviz.addfile(self.f)
+ #print "generated 2d view in %f s"%(time.time()-t0)
+ #t0=time.time()
+ self.gwindow.p.addfile(self.f)
+ #print "generated 3d view in %f s"%(time.time()-t0)
self.gviz.showall=1
wx.CallAfter(self.gviz.Refresh)
@@ -1355,7 +1452,7 @@ def uploadtrigger(self,l):
self.recvlisteners.remove(self.uploadtrigger)
def upload(self,event):
- if not len(self.f):
+ if not self.f or not len(self.f):
return
if not self.p.online:
return
@@ -1427,8 +1524,10 @@ def disconnect(self,event):
print _("Disconnected.")
self.p.disconnect()
self.statuscheck=False
-
- wx.CallAfter(self.connectbtn.Enable);
+
+ self.connectbtn.SetLabel("Connect")
+ self.connectbtn.Bind(wx.EVT_BUTTON,self.connect)
+
wx.CallAfter(self.printbtn.Disable);
wx.CallAfter(self.pausebtn.Disable);
for i in self.printerControls:
@@ -1459,7 +1558,28 @@ def reset(self,event):
wx.CallAfter(self.pausebtn.SetLabel, _("Pause"))
wx.CallAfter(self.printbtn.SetLabel, _("Print"))
self.paused=0
-
+
+ def get_build_dimensions(self,bdim):
+ import re
+ # a string containing up to six numbers delimited by almost anything
+ # first 0-3 numbers specify the build volume, no sign, always positive
+ # remaining 0-3 numbers specify the coordinates of the "southwest" corner of the build platform
+ # "XXX,YYY"
+ # "XXXxYYY+xxx-yyy"
+ # "XXX,YYY,ZZZ+xxx+yyy-zzz"
+ # etc
+ bdl = re.match(
+ "[^\d+-]*(\d+)?" + # X build size
+ "[^\d+-]*(\d+)?" + # Y build size
+ "[^\d+-]*(\d+)?" + # Z build size
+ "[^\d+-]*([+-]\d+)?" + # X corner coordinate
+ "[^\d+-]*([+-]\d+)?" + # Y corner coordinate
+ "[^\d+-]*([+-]\d+)?" # Z corner coordinate
+ ,bdim).groups()
+ defaults = [200, 200, 100, 0, 0, 0]
+ bdl_float = [float(value) if value else defaults[i] for i, value in enumerate(bdl)]
+ return bdl_float
+
class macroed(wx.Dialog):
"""Really simple editor to edit macro definitions"""
def __init__(self,macro_name,definition,callback,gcode=False):
@@ -1504,7 +1624,6 @@ def save(self,ev):
def close(self,ev):
self.Destroy()
def unindent(self,text):
- import re
self.indent_chars = text[:len(text)-len(text.lstrip())]
if len(self.indent_chars)==0:
self.indent_chars=" "
@@ -1520,7 +1639,6 @@ def unindent(self,text):
unindented += line + "\n"
return unindented
def reindent(self,text):
- import re
lines = re.split(r"(?:\r\n?|\n)",text)
if len(lines) <= 1:
return text
@@ -1529,29 +1647,36 @@ def reindent(self,text):
if line.strip() != "":
reindented += self.indent_chars + line + "\n"
return reindented
-
+
class options(wx.Dialog):
"""Options editor"""
def __init__(self,pronterface):
- wx.Dialog.__init__(self, None, title=_("Edit settings"))
+ wx.Dialog.__init__(self, None, title=_("Edit settings"), style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
topsizer=wx.BoxSizer(wx.VERTICAL)
vbox=wx.StaticBoxSizer(wx.StaticBox(self, label=_("Defaults")) ,wx.VERTICAL)
topsizer.Add(vbox,1,wx.ALL+wx.EXPAND)
- grid=wx.GridSizer(rows=0,cols=2,hgap=8,vgap=2)
+ grid=wx.FlexGridSizer(rows=0,cols=2,hgap=8,vgap=2)
+ grid.SetFlexibleDirection( wx.BOTH )
+ grid.AddGrowableCol( 1 )
+ grid.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )
vbox.Add(grid,0,wx.EXPAND)
ctrls = {}
- for k,v in pronterface.settings._all_settings().items():
- grid.Add(wx.StaticText(self,-1,k),0,wx.BOTTOM+wx.RIGHT)
- ctrls[k] = wx.TextCtrl(self,-1,str(v))
- grid.Add(ctrls[k],1,wx.EXPAND)
+ for k,v in sorted(pronterface.settings._all_settings().items()):
+ ctrls[k,0] = wx.StaticText(self,-1,k)
+ ctrls[k,1] = wx.TextCtrl(self,-1,str(v))
+ if k in pronterface.helpdict:
+ ctrls[k,0].SetToolTipString(pronterface.helpdict.get(k))
+ ctrls[k,1].SetToolTipString(pronterface.helpdict.get(k))
+ grid.Add(ctrls[k,0],0,wx.ALIGN_CENTER_VERTICAL|wx.ALL|wx.ALIGN_RIGHT)
+ grid.Add(ctrls[k,1],1,wx.ALIGN_CENTER_VERTICAL|wx.ALL|wx.EXPAND)
topsizer.Add(self.CreateSeparatedButtonSizer(wx.OK+wx.CANCEL),0,wx.EXPAND)
self.SetSizer(topsizer)
topsizer.Layout()
topsizer.Fit(self)
if self.ShowModal()==wx.ID_OK:
for k,v in pronterface.settings._all_settings().items():
- if ctrls[k].GetValue() != str(v):
- pronterface.set(k,str(ctrls[k].GetValue()))
+ if ctrls[k,1].GetValue() != str(v):
+ pronterface.set(k,str(ctrls[k,1].GetValue()))
self.Destroy()
class ButtonEdit(wx.Dialog):
@@ -1560,15 +1685,12 @@ def __init__(self,pronterface):
wx.Dialog.__init__(self, None, title=_("Custom button"),style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
self.pronterface=pronterface
topsizer=wx.BoxSizer(wx.VERTICAL)
- vbox=wx.StaticBoxSizer(wx.StaticBox(self,label=""),wx.VERTICAL)
- topsizer.Add(vbox,1,wx.ALL+wx.EXPAND)
grid=wx.FlexGridSizer(rows=0,cols=2,hgap=4,vgap=2)
grid.AddGrowableCol(1,1)
- vbox.Add(grid,0,wx.EXPAND)
- grid.Add(wx.StaticText(self,-1, _("Button title")), 0, wx.BOTTOM+wx.RIGHT)
+ grid.Add(wx.StaticText(self,-1, _("Button title")), 0, wx.BOTTOM|wx.RIGHT)
self.name=wx.TextCtrl(self,-1,"")
grid.Add(self.name,1,wx.EXPAND)
- grid.Add(wx.StaticText(self, -1, _("Command")), 0, wx.BOTTOM+wx.RIGHT)
+ grid.Add(wx.StaticText(self, -1, _("Command")), 0, wx.BOTTOM|wx.RIGHT)
self.command=wx.TextCtrl(self,-1,"")
xbox=wx.BoxSizer(wx.HORIZONTAL)
xbox.Add(self.command,1,wx.EXPAND)
@@ -1576,14 +1698,14 @@ def __init__(self,pronterface):
self.macrob=wx.Button(self,-1,"..",style=wx.BU_EXACTFIT)
self.macrob.Bind(wx.EVT_BUTTON,self.macrob_handler)
xbox.Add(self.macrob,0)
- grid.Add(xbox)
- grid.Add(wx.StaticText(self,-1, _("Color")),0,wx.BOTTOM+wx.RIGHT)
+ grid.Add(xbox,1,wx.EXPAND)
+ grid.Add(wx.StaticText(self,-1, _("Color")),0,wx.BOTTOM|wx.RIGHT)
self.color=wx.TextCtrl(self,-1,"")
grid.Add(self.color,1,wx.EXPAND)
- topsizer.Add(self.CreateSeparatedButtonSizer(wx.OK+wx.CANCEL),0,wx.EXPAND)
- self.SetSizer(topsizer)
- topsizer.Layout()
- topsizer.Fit(self)
+ topsizer.Add(grid,0,wx.EXPAND)
+ topsizer.Add( (0,0),1)
+ topsizer.Add(self.CreateStdDialogButtonSizer(wx.OK|wx.CANCEL),0,wx.ALIGN_CENTER)
+ self.SetSizer(topsizer)
def macrob_enabler(self,e):
macro = self.command.GetValue()
valid = False
@@ -1606,18 +1728,21 @@ def macrob_handler(self,e):
self.name.SetValue(macro)
class TempGauge(wx.Panel):
- def __init__(self,parent,size=(200,22)):
+ def __init__(self,parent,size=(200,22),title="",maxval=240,gaugeColour=None):
wx.Panel.__init__(self,parent,-1,size=size)
self.Bind(wx.EVT_PAINT,self.paint)
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
self.width,self.height=size
+ self.title=title
+ self.max=maxval
+ self.gaugeColour=gaugeColour
self.value=0
self.setpoint=0
self.recalc()
def recalc(self):
- self.max=max(int(self.setpoint*1.05),240)
- self.scale=float(self.width-2)/float(self.max)
- self.ypt=int(self.scale*max(self.setpoint,40))
+ mmax=max(int(self.setpoint*1.05),self.max)
+ self.scale=float(self.width-2)/float(mmax)
+ self.ypt=max(16,int(self.scale*max(self.setpoint,self.max/6)))
def SetValue(self,value):
self.value=value
wx.CallAfter(self.Refresh)
@@ -1625,13 +1750,24 @@ def SetTarget(self,value):
self.setpoint=value
self.recalc()
wx.CallAfter(self.Refresh)
+ def interpolatedColour(self,val,vmin,vmid,vmax,cmin,cmid,cmax):
+ if val < vmin: return cmin
+ if val > vmax: return cmax
+ if val <= vmid:
+ lo,hi,val,valhi = cmin,cmid,val-vmin,vmid-vmin
+ else:
+ lo,hi,val,valhi = cmid,cmax,val-vmid,vmax-vmid
+ vv = float(val)/valhi
+ rgb=lo.Red()+(hi.Red()-lo.Red())*vv,lo.Green()+(hi.Green()-lo.Green())*vv,lo.Blue()+(hi.Blue()-lo.Blue())*vv
+ rgb=map(lambda x:x*0.8,rgb)
+ return wx.Colour(*map(int,rgb))
def paint(self,ev):
x0,y0,x1,y1,xE,yE = 1,1,self.ypt+1,1,self.width+1-2,20
dc=wx.PaintDC(self)
dc.SetBackground(wx.Brush((255,255,255)))
dc.Clear()
cold,medium,hot = wx.Colour(0,167,223),wx.Colour(239,233,119),wx.Colour(210,50.100)
- gauge1,gauge2 = wx.Colour(255,255,210),wx.Colour(234,82,0)
+ gauge1,gauge2 = wx.Colour(255,255,210),(self.gaugeColour or wx.Colour(234,82,0))
shadow1,shadow2 = wx.Colour(110,110,110),wx.Colour(255,255,255)
gc = wx.GraphicsContext.Create(dc)
# draw shadow first
@@ -1653,12 +1789,13 @@ def paint(self,ev):
gc.SetBrush(gc.CreateLinearGradientBrush(x1-2,y1,xE,y1,medium,hot))
gc.DrawRoundedRectangle(x1-2,y1,xE-x1,yE,6)
# draw gauge
- gc.SetBrush(gc.CreateLinearGradientBrush(x0,y0+3,x0,y0+15,gauge1,gauge2))
- #gc.SetBrush(gc.CreateLinearGradientBrush(0,3,0,15,wx.Colour(255,255,255),wx.Colour(255,90,32)))
width=12
w1=y0+9-width/2
w2=w1+width
value=x0+max(10,min(self.width+1-2,int(self.value*self.scale)))
+ #gc.SetBrush(gc.CreateLinearGradientBrush(x0,y0+3,x0,y0+15,gauge1,gauge2))
+ #gc.SetBrush(gc.CreateLinearGradientBrush(0,3,0,15,wx.Colour(255,255,255),wx.Colour(255,90,32)))
+ gc.SetBrush(gc.CreateLinearGradientBrush(x0,y0+3,x0,y0+15,gauge1,self.interpolatedColour(value,x0,x1,xE,cold,medium,hot)))
val_path = gc.CreatePath()
val_path.MoveToPoint(x0,w1)
val_path.AddLineToPoint(value,w1)
@@ -1684,9 +1821,11 @@ def paint(self,ev):
#gc.SetFont(gc.CreateFont(wx.Font(12,wx.FONTFAMILY_DEFAULT,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_BOLD),wx.WHITE))
#gc.DrawText(text,29,-2)
gc.SetFont(gc.CreateFont(wx.Font(10,wx.FONTFAMILY_DEFAULT,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_BOLD),wx.WHITE))
- gc.DrawText(text,x0+31,y0+1)
+ gc.DrawText(self.title,x0+19,y0+1)
+ gc.DrawText(text, x0+153,y0+1)
gc.SetFont(gc.CreateFont(wx.Font(10,wx.FONTFAMILY_DEFAULT,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_BOLD)))
- gc.DrawText(text,x0+30,y0+0)
+ gc.DrawText(self.title,x0+18,y0+0)
+ gc.DrawText(text, x0+152,y0+0)
if __name__ == '__main__':
app = wx.App(False)
diff --git a/stltool.py b/stltool.py
index 3573215d7..d54ac02d8 100644
--- a/stltool.py
+++ b/stltool.py
@@ -1,3 +1,18 @@
+# This file is part of the Printrun suite.
+#
+# Printrun is 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
+# (at your option) any later version.
+#
+# Printrun 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 Printrun. If not, see .
+
import sys, struct, math
def cross(v1,v2):
diff --git a/stlview.py b/stlview.py
index d6cd9123d..fe0bab647 100644
--- a/stlview.py
+++ b/stlview.py
@@ -1,18 +1,35 @@
#!/usr/bin/python
+
+# This file is part of the Printrun suite.
+#
+# Printrun is 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
+# (at your option) any later version.
+#
+# Printrun 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 Printrun. If not, see .
+
import os
-import wx,math,stltool
+import math
+import stltool
+import wx
from wx import glcanvas
import time
import threading
-
+
import pyglet
pyglet.options['shadow_window'] = False
pyglet.options['debug_gl'] = False
-from pyglet import gl
from pyglet.gl import *
-class GLPanel(wx.Panel):
+class GLPanel(wx.Panel):
'''A simple class for using OpenGL with wxPython.'''
def __init__(self, parent, id, pos=wx.DefaultPosition,
@@ -24,9 +41,9 @@ def __init__(self, parent, id, pos=wx.DefaultPosition,
#init gl canvas data
self.GLinitialized = False
- attribList = (glcanvas.WX_GL_RGBA, # RGBA
- glcanvas.WX_GL_DOUBLEBUFFER, # Double Buffered
- glcanvas.WX_GL_DEPTH_SIZE, 24) # 24 bit
+ attribList = (glcanvas.WX_GL_RGBA, # RGBA
+ glcanvas.WX_GL_DOUBLEBUFFER, # Double Buffered
+ glcanvas.WX_GL_DEPTH_SIZE, 24) # 24 bit
# Create the canvas
self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.canvas = glcanvas.GLCanvas(self, attribList=attribList)
@@ -34,7 +51,7 @@ def __init__(self, parent, id, pos=wx.DefaultPosition,
self.SetSizer(self.sizer)
#self.sizer.Fit(self)
self.Layout()
-
+
# bind events
self.canvas.Bind(wx.EVT_ERASE_BACKGROUND, self.processEraseBackgroundEvent)
self.canvas.Bind(wx.EVT_SIZE, self.processSizeEvent)
@@ -56,7 +73,7 @@ def SwapBuffers(self):
#==========================================================================
def processEraseBackgroundEvent(self, event):
'''Process the erase background event.'''
- pass # Do nothing, to avoid flashing on MSWin
+ pass # Do nothing, to avoid flashing on MSWin
def processSizeEvent(self, event):
'''Process the resize event.'''
@@ -74,15 +91,15 @@ def processSizeEvent(self, event):
def processPaintEvent(self, event):
'''Process the drawing event.'''
self.canvas.SetCurrent()
-
+
# This is a 'perfect' time to initialize OpenGL ... only if we need to
if not self.GLinitialized:
self.OnInitGL()
self.GLinitialized = True
-
+
self.OnDraw()
event.Skip()
-
+
def Destroy(self):
#clean up the pyglet OpenGL context
#self.pygletcontext.destroy()
@@ -95,55 +112,53 @@ def Destroy(self):
def OnInitGL(self):
'''Initialize OpenGL for use in the window.'''
#create a pyglet context for this panel
- self.pmat=(GLdouble * 16)()
- self.mvmat=(GLdouble * 16)()
+ self.pmat = (GLdouble * 16)()
+ self.mvmat = (GLdouble * 16)()
self.pygletcontext = Context(current_context)
self.pygletcontext.set_current()
- self.dist=1000
- self.vpmat=None
+ self.dist = 1000
+ self.vpmat = None
#normal gl init
- glClearColor(0, 0, 0, 0.5)
+ glClearColor(0, 0, 0, 1)
glColor3f(1, 0, 0)
glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
# Uncomment this line for a wireframe view
#glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
-
+
# Simple light setup. On Windows GL_LIGHT0 is enabled by default,
- # but this is not the case on Linux or Mac, so remember to always
+ # but this is not the case on Linux or Mac, so remember to always
# include it.
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_LIGHT1)
-
+
# Define a simple function to create ctypes arrays of floats:
def vec(*args):
return (GLfloat * len(args))(*args)
-
+
glLightfv(GL_LIGHT0, GL_POSITION, vec(.5, .5, 1, 0))
glLightfv(GL_LIGHT0, GL_SPECULAR, vec(.5, .5, 1, 1))
glLightfv(GL_LIGHT0, GL_DIFFUSE, vec(1, 1, 1, 1))
glLightfv(GL_LIGHT1, GL_POSITION, vec(1, 0, .5, 0))
glLightfv(GL_LIGHT1, GL_DIFFUSE, vec(.5, .5, .5, 1))
glLightfv(GL_LIGHT1, GL_SPECULAR, vec(1, 1, 1, 1))
-
+
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, vec(0.5, 0, 0.3, 1))
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vec(1, 1, 1, 1))
- glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 200)
- glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, vec(0,0.1,0,0.9))
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50)
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, vec(0, 0.1, 0, 0.9))
#create objects to draw
#self.create_objects()
-
-
-
+
def OnReshape(self, width, height):
'''Reshape the OpenGL viewport based on the dimensions of the window.'''
-
+
if not self.GLinitialized:
self.OnInitGL()
self.GLinitialized = True
- self.pmat=(GLdouble * 16)()
- self.mvmat=(GLdouble * 16)()
+ self.pmat = (GLdouble * 16)()
+ self.mvmat = (GLdouble * 16)()
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
@@ -151,43 +166,43 @@ def OnReshape(self, width, height):
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
#pyglet stuff
- self.vpmat=(GLint * 4)(0,0,*list(self.GetClientSize()))
- glGetDoublev(GL_PROJECTION_MATRIX,self.pmat)
- glGetDoublev(GL_MODELVIEW_MATRIX,self.mvmat)
+ self.vpmat = (GLint * 4)(0, 0, *list(self.GetClientSize()))
+ glGetDoublev(GL_PROJECTION_MATRIX, self.pmat)
+ glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat)
#glMatrixMode(GL_PROJECTION)
-
-
+
# Wrap text to the width of the window
if self.GLinitialized:
self.pygletcontext.set_current()
self.update_object_resize()
-
+
def OnDraw(self, *args, **kwargs):
"""Draw the window."""
#clear the context
self.canvas.SetCurrent()
self.pygletcontext.set_current()
- glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
#draw objects
self.draw_objects()
#update screen
self.SwapBuffers()
-
+
#==========================================================================
# To be implemented by a sub class
#==========================================================================
def create_objects(self):
'''create opengl objects when opengl is initialized'''
pass
-
+
def update_object_resize(self):
'''called when the window recieves only if opengl is initialized'''
pass
-
+
def draw_objects(self):
'''called in the middle of ondraw after the buffer has been cleared'''
pass
-
+
+
class stlview(object):
def __init__(self, facets, batch):
# Create the vertex and normal arrays.
@@ -200,232 +215,249 @@ def __init__(self, facets, batch):
normals.extend(i[0])
# Create a list of triangle indices.
- indices = range(3*len(facets))#[[3*i,3*i+1,3*i+2] for i in xrange(len(facets))]
+ indices = range(3 * len(facets)) # [[3*i,3*i+1,3*i+2] for i in xrange(len(facets))]
#print indices[:10]
- self.vertex_list = batch.add_indexed(len(vertices)//3,
+ self.vertex_list = batch.add_indexed(len(vertices) // 3,
GL_TRIANGLES,
- None,#group,
+ None, # group,
indices,
('v3f/static', vertices),
('n3f/static', normals))
-
+
def delete(self):
self.vertex_list.delete()
+
+def vdiff(v, o):
+ return [x[0] - x[1] for x in zip(v, o)]
+
+
class gcview(object):
def __init__(self, lines, batch, w=0.5, h=0.5):
# Create the vertex and normal arrays.
vertices = []
normals = []
- self.prev=[0.001,0.001,0.001,0.001]
- self.fline=1
- f=open("20cube_export.gcode")
- lines=list(f)
- f.close()
- self.layers={}
- lines=[self.transform(i) for i in lines]
- lines=[i for i in lines if i is not None]
- layertemp={}
- lasth=None
+ self.prev = [0.001, 0.001, 0.001, 0.001]
+ self.fline = 1
+ self.vlists = []
+ self.layers = {}
+ t0 = time.time()
+ lines = [self.transform(i) for i in lines]
+ lines = [i for i in lines if i is not None]
+ print "transformed lines in %fs" % (time.time() - t0)
+ t0 = time.time()
+ layertemp = {}
+ lasth = None
+ counter = 0
+ if len(lines) == 0:
+ return
for i in lines:
+ counter += 1
if i[0][2] not in layertemp:
- layertemp[i[0][2]]=[[],[]]
+ layertemp[i[0][2]] = [[], []]
if lasth is not None:
- self.layers[lasth]=pyglet.graphics.Batch()
- indices = range(len(layertemp[lasth][0]))#[[3*i,3*i+1,3*i+2] for i in xrange(len(facets))]
- self.layers[lasth].add_indexed(len(layertemp[lasth][0])//3,
+ self.layers[lasth] = pyglet.graphics.Batch()
+ lt = layertemp[lasth][0]
+ indices = range(len(layertemp[lasth][0]) // 3) # [[3*i,3*i+1,3*i+2] for i in xrange(len(facets))]
+ self.vlists.append(self.layers[lasth].add_indexed(len(layertemp[lasth][0]) // 3,
GL_TRIANGLES,
- None,#group,
+ None, # group,
indices,
('v3f/static', layertemp[lasth][0]),
- ('n3f/static', layertemp[lasth][1]))
- lasth=i[0][2]
- def vdiff(v,o):
- return map(lambda x,y:x-y,v,o)
-
- spoints,epoints,S,E=self.genline(i,h,w)
- for j in xrange(8):
-
- layertemp[i[0][2]][0].extend(spoints[(j+1)%8])
- layertemp[i[0][2]][1].extend(vdiff(spoints[(j+1)%8],S))
- layertemp[i[0][2]][0].extend(epoints[(j)%8])
- layertemp[i[0][2]][1].extend(vdiff(epoints[(j)%8],E))
- layertemp[i[0][2]][0].extend(spoints[j])
- layertemp[i[0][2]][1].extend(vdiff(spoints[j],S))
- layertemp[i[0][2]][0].extend(epoints[(j)])
- layertemp[i[0][2]][1].extend(vdiff(epoints[(j)],E))
- layertemp[i[0][2]][0].extend(spoints[(j+1)%8])
- layertemp[i[0][2]][1].extend(vdiff(spoints[j],S))
- layertemp[i[0][2]][0].extend(epoints[(j+1)%8])
- layertemp[i[0][2]][1].extend(vdiff(epoints[(j+1)%8],E))
-
- vertices.extend(spoints[(j+1)%8])
- normals.extend(vdiff(spoints[(j+1)%8],S))
- vertices.extend(epoints[(j)%8])
- normals.extend(vdiff(epoints[(j)%8],E))
- vertices.extend(spoints[j])
- normals.extend(vdiff(spoints[j],S))
- vertices.extend(epoints[(j)])
- normals.extend(vdiff(epoints[(j)],E))
- vertices.extend(spoints[(j+1)%8])
- normals.extend(vdiff(spoints[j],S))
- vertices.extend(epoints[(j+1)%8])
- normals.extend(vdiff(epoints[(j+1)%8],E))
+ ('n3f/static', layertemp[lasth][1])))
+
+ lasth = i[0][2]
+
+ spoints, epoints, S, E = self.genline(i, h, w)
+
+ verticestoadd = [[
+ spoints[(j + 1) % 8],
+ epoints[(j) % 8],
+ spoints[j],
+ epoints[j],
+ spoints[(j + 1) % 8],
+ epoints[(j + 1) % 8]
+ ] for j in xrange(8)]
+ normalstoadd = [map(vdiff, v, [S, E, S, E, S, E]) for v in verticestoadd]
+ v1 = []
+ map(v1.extend, verticestoadd)
+ v2 = []
+ map(v2.extend, v1)
+ n1 = []
+ map(n1.extend, normalstoadd)
+ n2 = []
+ map(n2.extend, n1)
+
+ layertemp[i[0][2]][0] += v2
+ vertices += v2
+ layertemp[i[0][2]][1] += n2
+ normals += n2
+ print "appended lines in %fs" % (time.time() - t0)
+ t0 = time.time()
+
# Create a list of triangle indices.
- indices = range(3*16*len(lines))#[[3*i,3*i+1,3*i+2] for i in xrange(len(facets))]
- #print indices[:10]
- self.vertex_list = batch.add_indexed(len(vertices)//3,
+ indices = range(3 * 16 * len(lines)) # [[3*i,3*i+1,3*i+2] for i in xrange(len(facets))]
+ self.vlists.append(batch.add_indexed(len(vertices) // 3,
GL_TRIANGLES,
- None,#group,
+ None, # group,
indices,
('v3f/static', vertices),
- ('n3f/static', normals))
+ ('n3f/static', normals)))
if lasth is not None:
- self.layers[lasth]=pyglet.graphics.Batch()
- indices = range(len(layertemp[lasth][0]))#[[3*i,3*i+1,3*i+2] for i in xrange(len(facets))]
- self.layers[lasth].add_indexed(len(layertemp[lasth][0])//3,
+ self.layers[lasth] = pyglet.graphics.Batch()
+ indices = range(len(layertemp[lasth][0])) # [[3*i,3*i+1,3*i+2] for i in xrange(len(facets))]
+ self.vlists.append(self.layers[lasth].add_indexed(len(layertemp[lasth][0]) // 3,
GL_TRIANGLES,
- None,#group,
+ None, # group,
indices,
('v3f/static', layertemp[lasth][0]),
- ('n3f/static', layertemp[lasth][1]))
-
-
- def genline(self,i,h,w):
- S=i[0][:3]
- E=i[1][:3]
- v=map(lambda x,y:x-y,E,S)
- vlen=math.sqrt(float(sum(map(lambda a:a*a, v[:3]))))
-
- if vlen==0:
- vlen=0.01
- sq2=math.sqrt(2.0)/2.0
- htw=float(h)/w
- d=w/2.0
- if i[1][3]==i[0][3]:
- d=0.05
- points=[[d,0,0],
- [sq2*d,sq2*d,0],
- [0,d,0],
- [-sq2*d,sq2*d,0],
- [-d,0,0],
- [-sq2*d,-sq2*d,0],
- [0,-d,0],
- [sq2*d,-sq2*d,0]
- ]
- axis=stltool.cross([0,0,1],v)
- alen=math.sqrt(float(sum(map(lambda a:a*a, v[:3]))))
- if alen>0:
- axis=map(lambda m:m/alen,axis)
- angle=math.acos(v[2]/vlen)
- def vrot(v,axis,angle):
- kxv=stltool.cross(axis,v)
- kdv=sum(map(lambda x,y:x*y,axis,v))
- return map(lambda x,y,z:x*math.cos(angle)+y*math.sin(angle)+z*kdv*(1.0-math.cos(angle)),v,kxv,axis)
- points=map(lambda x:vrot(x,axis,angle),points)
- points=map(lambda x:[x[0],x[1],htw*x[2]],points)
-
- def vadd(v,o):
- return map(lambda x,y:x+y,v,o)
- spoints=map(lambda x:vadd(S,x),points)
- epoints=map(lambda x:vadd(E,x),points)
- return spoints,epoints,S,E
-
- def transform(self,line):
- line=line.split(";")[0]
- cur=self.prev[:]
- if len(line)>0:
+ ('n3f/static', layertemp[lasth][1])))
+
+ def genline(self, i, h, w):
+ S = i[0][:3]
+ E = i[1][:3]
+ v = map(lambda x, y: x - y, E, S)
+ vlen = math.sqrt(float(sum(map(lambda a: a * a, v[:3]))))
+
+ if vlen == 0:
+ vlen = 0.01
+ sq2 = math.sqrt(2.0) / 2.0
+ htw = float(h) / w
+ d = w / 2.0
+ if i[1][3] == i[0][3]:
+ d = 0.05
+ points = [[d, 0, 0],
+ [sq2 * d, sq2 * d, 0],
+ [0, d, 0],
+ [-sq2 * d, sq2 * d, 0],
+ [-d, 0, 0],
+ [-sq2 * d, -sq2 * d, 0],
+ [0, -d, 0],
+ [sq2 * d, -sq2 * d, 0]
+ ]
+ axis = stltool.cross([0, 0, 1], v)
+ alen = math.sqrt(float(sum(map(lambda a: a * a, v[:3]))))
+ if alen > 0:
+ axis = map(lambda m: m / alen, axis)
+ angle = math.acos(v[2] / vlen)
+
+ def vrot(v, axis, angle):
+ kxv = stltool.cross(axis, v)
+ kdv = sum(map(lambda x, y: x * y, axis, v))
+ return map(lambda x, y, z: x * math.cos(angle) + y * math.sin(angle) + z * kdv * (1.0 - math.cos(angle)), v, kxv, axis)
+
+ points = map(lambda x: vrot(x, axis, angle), points)
+ points = map(lambda x: [x[0], x[1], htw * x[2]], points)
+
+ def vadd(v, o):
+ return map(sum, zip(v, o))
+ spoints = map(lambda x: vadd(S, x), points)
+ epoints = map(lambda x: vadd(E, x), points)
+ return spoints, epoints, S, E
+
+ def transform(self, line):
+ line = line.split(";")[0]
+ cur = self.prev[:]
+ if len(line) > 0:
if "G1" in line or "G0" in line or "G92" in line:
if("X" in line):
- cur[0]=float(line.split("X")[1].split(" ")[0])
+ cur[0] = float(line.split("X")[1].split(" ")[0])
if("Y" in line):
- cur[1]=float(line.split("Y")[1].split(" ")[0])
+ cur[1] = float(line.split("Y")[1].split(" ")[0])
if("Z" in line):
- cur[2]=float(line.split("Z")[1].split(" ")[0])
+ cur[2] = float(line.split("Z")[1].split(" ")[0])
if("E" in line):
- cur[3]=float(line.split("E")[1].split(" ")[0])
- if self.prev==cur:
+ cur[3] = float(line.split("E")[1].split(" ")[0])
+ if self.prev == cur:
return None
if self.fline or "G92" in line:
- self.prev=cur
- self.fline=0
+ self.prev = cur
+ self.fline = 0
return None
else:
- r=[self.prev,cur]
- self.prev=cur
+ r = [self.prev, cur]
+ self.prev = cur
return r
-
-
+
def delete(self):
- self.vertex_list.delete()
+ for i in self.vlists:
+ i.delete()
+ self.vlists = []
def trackball(p1x, p1y, p2x, p2y, r):
- TRACKBALLSIZE=r
+ TRACKBALLSIZE = r
#float a[3]; /* Axis of rotation */
#float phi; /* how much to rotate about axis */
#float p1[3], p2[3], d[3];
#float t;
if (p1x == p2x and p1y == p2y):
- return [0.0,0.0,0.0,1.0]
+ return [0.0, 0.0, 0.0, 1.0]
- p1=[p1x,p1y,project_to_sphere(TRACKBALLSIZE,p1x,p1y)]
- p2=[p2x,p2y,project_to_sphere(TRACKBALLSIZE,p2x,p2y)]
- a=stltool.cross(p2,p1)
-
- d=map(lambda x,y:x-y,p1,p2)
- t = math.sqrt(sum(map(lambda x:x*x, d))) / (2.0*TRACKBALLSIZE)
+ p1 = [p1x, p1y, project_to_sphere(TRACKBALLSIZE, p1x, p1y)]
+ p2 = [p2x, p2y, project_to_sphere(TRACKBALLSIZE, p2x, p2y)]
+ a = stltool.cross(p2, p1)
- if (t > 1.0): t = 1.0
- if (t < -1.0): t = -1.0
+ d = map(lambda x, y: x - y, p1, p2)
+ t = math.sqrt(sum(map(lambda x: x * x, d))) / (2.0 * TRACKBALLSIZE)
+
+ if (t > 1.0):
+ t = 1.0
+ if (t < -1.0):
+ t = -1.0
phi = 2.0 * math.asin(t)
- return axis_to_quat(a,phi)
+ return axis_to_quat(a, phi)
+
def vec(*args):
return (GLfloat * len(args))(*args)
-
-def axis_to_quat(a,phi):
+
+
+def axis_to_quat(a, phi):
#print a, phi
- lena=math.sqrt(sum(map(lambda x:x*x, a)))
- q=map(lambda x:x*(1/lena),a)
- q=map(lambda x:x*math.sin(phi/2.0),q)
- q.append(math.cos(phi/2.0))
+ lena = math.sqrt(sum(map(lambda x: x * x, a)))
+ q = map(lambda x: x * (1 / lena), a)
+ q = map(lambda x: x * math.sin(phi / 2.0), q)
+ q.append(math.cos(phi / 2.0))
return q
-
+
+
def build_rotmatrix(q):
- m=(GLdouble * 16)()
+ m = (GLdouble * 16)()
m[0] = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2])
- m[1] = 2.0 * (q[0] * q[1] - q[2] * q[3]);
- m[2] = 2.0 * (q[2] * q[0] + q[1] * q[3]);
- m[3] = 0.0;
-
- m[4] = 2.0 * (q[0] * q[1] + q[2] * q[3]);
- m[5]= 1.0 - 2.0 * (q[2] * q[2] + q[0] * q[0]);
- m[6] = 2.0 * (q[1] * q[2] - q[0] * q[3]);
- m[7] = 0.0;
-
- m[8] = 2.0 * (q[2] * q[0] - q[1] * q[3]);
- m[9] = 2.0 * (q[1] * q[2] + q[0] * q[3]);
- m[10] = 1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]);
- m[11] = 0.0;
-
- m[12] = 0.0;
- m[13] = 0.0;
- m[14] = 0.0;
- m[15] = 1.0;
+ m[1] = 2.0 * (q[0] * q[1] - q[2] * q[3])
+ m[2] = 2.0 * (q[2] * q[0] + q[1] * q[3])
+ m[3] = 0.0
+
+ m[4] = 2.0 * (q[0] * q[1] + q[2] * q[3])
+ m[5] = 1.0 - 2.0 * (q[2] * q[2] + q[0] * q[0])
+ m[6] = 2.0 * (q[1] * q[2] - q[0] * q[3])
+ m[7] = 0.0
+
+ m[8] = 2.0 * (q[2] * q[0] - q[1] * q[3])
+ m[9] = 2.0 * (q[1] * q[2] + q[0] * q[3])
+ m[10] = 1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0])
+ m[11] = 0.0
+
+ m[12] = 0.0
+ m[13] = 0.0
+ m[14] = 0.0
+ m[15] = 1.0
return m
+
def project_to_sphere(r, x, y):
- d = math.sqrt(x*x + y*y)
+ d = math.sqrt(x * x + y * y)
if (d < r * 0.70710678118654752440):
- return math.sqrt(r*r - d*d)
+ return math.sqrt(r * r - d * d)
else:
t = r / 1.41421356237309504880
- return t*t / d
-
-def mulquat(q1,rq):
+ return t * t / d
+
+
+def mulquat(q1, rq):
return [q1[3] * rq[0] + q1[0] * rq[3] + q1[1] * rq[2] - q1[2] * rq[1],
q1[3] * rq[1] + q1[1] * rq[3] + q1[2] * rq[0] - q1[0] * rq[2],
q1[3] * rq[2] + q1[2] * rq[3] + q1[0] * rq[1] - q1[1] * rq[0],
@@ -433,207 +465,272 @@ def mulquat(q1,rq):
class TestGlPanel(GLPanel):
-
- def __init__(self, parent, size,id=wx.ID_ANY,):
+
+ def __init__(self, parent, size, id=wx.ID_ANY):
super(TestGlPanel, self).__init__(parent, id, wx.DefaultPosition, size, 0)
- self.batches=[]
- self.rot=0
- self.canvas.Bind(wx.EVT_MOUSE_EVENTS,self.move)
- self.canvas.Bind(wx.EVT_LEFT_DCLICK,self.double)
- self.initialized=1
- self.canvas.Bind(wx.EVT_MOUSEWHEEL,self.wheel)
- self.parent=parent
- self.initp=None
- self.dist=200
- self.bedsize=[200,200]
- self.transv=[0, 0, -self.dist]
- self.basequat=[0,0,0,1]
+ self.batches = []
+ self.rot = 0
+ self.canvas.Bind(wx.EVT_MOUSE_EVENTS, self.move)
+ self.canvas.Bind(wx.EVT_LEFT_DCLICK, self.double)
+ self.initialized = 1
+ self.canvas.Bind(wx.EVT_MOUSEWHEEL, self.wheel)
+ self.parent = parent
+ self.initpos = None
+ self.dist = 200
+ self.bedsize = [200, 200]
+ self.transv = [0, 0, -self.dist]
+ self.basequat = [0, 0, 0, 1]
wx.CallAfter(self.forceresize)
- self.mousepos=[0,0]
-
+ self.mousepos = [0, 0]
+
def double(self, event):
- p=event.GetPositionTuple()
- sz=self.GetClientSize()
- v=map(lambda m,w,b:b*m/w,p,sz,self.bedsize)
- v[1]=self.bedsize[1]-v[1]
- v+=[300]
+ p = event.GetPositionTuple()
+ sz = self.GetClientSize()
+ v = map(lambda m, w, b: b * m / w, p, sz, self.bedsize)
+ v[1] = self.bedsize[1] - v[1]
+ v += [300]
print v
- self.add_file("../prusa/metric-prusa/x-end-idler.stl",v)
-
-
+ self.add_file("../prusa/metric-prusa/x-end-idler.stl", v)
+
def forceresize(self):
- self.SetClientSize((self.GetClientSize()[0],self.GetClientSize()[1]+1))
- self.SetClientSize((self.GetClientSize()[0],self.GetClientSize()[1]-1))
+ self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] + 1))
+ self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] - 1))
threading.Thread(target=self.update).start()
- self.initialized=0
-
+ self.initialized = 0
+
+ def move_shape(self, delta):
+ """moves shape (selected in l, which is list ListBox of shapes)
+ by an offset specified in tuple delta.
+ Positive numbers move to (rigt, down)"""
+ name = self.parent.l.GetSelection()
+ if name == wx.NOT_FOUND:
+ return False
+
+ name = self.parent.l.GetString(name)
+
+ model = self.parent.models[name]
+ model.offsets = [
+ model.offsets[0] + delta[0],
+ model.offsets[1] + delta[1],
+ model.offsets[2]
+ ]
+ self.Refresh()
+ return True
+
def move(self, event):
+ """react to mouse actions:
+ no mouse: show red mousedrop
+ LMB: move active object,
+ with shift rotate viewport
+ RMB: nothing
+ with shift move viewport
+ """
if event.Dragging() and event.LeftIsDown():
- if self.initp==None:
- self.initp=event.GetPositionTuple()
+ if self.initpos == None:
+ self.initpos = event.GetPositionTuple()
else:
if not event.ShiftDown():
- i=self.parent.l.GetSelection()
- if i<0:
- return
- p1=list(self.initp)
- p1[1]*=-1
- self.initp=None
- p2=list(event.GetPositionTuple())
- p2[1]*=-1
- m=self.parent.models[self.parent.l.GetString(i)]
- m.offsets=map(lambda old,new,original:original+(new-old), list(p1)+[0],list(p2)+[0],m.offsets)
+ currentpos = event.GetPositionTuple()
+ delta = (
+ (currentpos[0] - self.initpos[0]),
+ -(currentpos[1] - self.initpos[1])
+ )
+ self.move_shape(delta)
+ self.initpos = None
return
- #print self.initp
- p1=self.initp
- self.initp=None
- p2=event.GetPositionTuple()
- sz=self.GetClientSize()
- p1x=(float(p1[0])-sz[0]/2)/(sz[0]/2)
- p1y=-(float(p1[1])-sz[1]/2)/(sz[1]/2)
- p2x=(float(p2[0])-sz[0]/2)/(sz[0]/2)
- p2y=-(float(p2[1])-sz[1]/2)/(sz[1]/2)
+ #print self.initpos
+ p1 = self.initpos
+ self.initpos = None
+ p2 = event.GetPositionTuple()
+ sz = self.GetClientSize()
+ p1x = (float(p1[0]) - sz[0] / 2) / (sz[0] / 2)
+ p1y = -(float(p1[1]) - sz[1] / 2) / (sz[1] / 2)
+ p2x = (float(p2[0]) - sz[0] / 2) / (sz[0] / 2)
+ p2y = -(float(p2[1]) - sz[1] / 2) / (sz[1] / 2)
#print p1x,p1y,p2x,p2y
- quat=trackball(p1x, p1y, p2x, p2y, -self.transv[2]/250.0)
+ quat = trackball(p1x, p1y, p2x, p2y, -self.transv[2] / 250.0)
if self.rot:
- self.basequat=mulquat(self.basequat,quat)
+ self.basequat = mulquat(self.basequat, quat)
#else:
- glGetDoublev(GL_MODELVIEW_MATRIX,self.mvmat)
- #self.basequat=quatx
- mat=build_rotmatrix(self.basequat)
+ glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat)
+ #self.basequat = quatx
+ mat = build_rotmatrix(self.basequat)
glLoadIdentity()
- glTranslatef(self.transv[0],self.transv[1],0)
- glTranslatef(0,0,self.transv[2])
+ glTranslatef(self.transv[0], self.transv[1], 0)
+ glTranslatef(0, 0, self.transv[2])
glMultMatrixd(mat)
- glGetDoublev(GL_MODELVIEW_MATRIX,self.mvmat)
- self.rot=1
-
+ glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat)
+ self.rot = 1
+
elif event.ButtonUp(wx.MOUSE_BTN_LEFT):
- if self.initp is not None:
- self.initp=None
+ if self.initpos is not None:
+ self.initpos = None
elif event.ButtonUp(wx.MOUSE_BTN_RIGHT):
- if self.initp is not None:
- self.initp=None
-
-
+ if self.initpos is not None:
+ self.initpos = None
+
elif event.Dragging() and event.RightIsDown() and event.ShiftDown():
- if self.initp is None:
- self.initp=event.GetPositionTuple()
+ if self.initpos is None:
+ self.initpos = event.GetPositionTuple()
else:
- p1=self.initp
- p2=event.GetPositionTuple()
- sz=self.GetClientSize()
- p1=list(p1)
- p2=list(p2)
- p1[1]*=-1
- p2[1]*=-1
-
- self.transv=map(lambda x,y,z,c:c-self.dist*(x-y)/z, list(p1)+[0], list(p2)+[0], list(sz)+[1], self.transv)
-
+ p1 = self.initpos
+ p2 = event.GetPositionTuple()
+ sz = self.GetClientSize()
+ p1 = list(p1)
+ p2 = list(p2)
+ p1[1] *= -1
+ p2[1] *= -1
+
+ self.transv = map(lambda x, y, z, c: c - self.dist * (x - y) / z, list(p1) + [0], list(p2) + [0], list(sz) + [1], self.transv)
+
glLoadIdentity()
- glTranslatef(self.transv[0],self.transv[1],0)
- glTranslatef(0,0,self.transv[2])
+ glTranslatef(self.transv[0], self.transv[1], 0)
+ glTranslatef(0, 0, self.transv[2])
if(self.rot):
glMultMatrixd(build_rotmatrix(self.basequat))
- glGetDoublev(GL_MODELVIEW_MATRIX,self.mvmat)
- self.rot=1
- self.initp=None
+ glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat)
+ self.rot = 1
+ self.initpos = None
else:
#mouse is moving without a button press
- p=event.GetPositionTuple()
- sz=self.GetClientSize()
- v=map(lambda m,w,b:b*m/w,p,sz,self.bedsize)
- v[1]=self.bedsize[1]-v[1]
- self.mousepos=v
-
- def wheel(self,event):
- z=event.GetWheelRotation()
- delta=10
+ p = event.GetPositionTuple()
+ sz = self.GetClientSize()
+ v = map(lambda m, w, b: b * m / w, p, sz, self.bedsize)
+ v[1] = self.bedsize[1] - v[1]
+ self.mousepos = v
+
+ def rotate_shape(self, angle):
+ """rotates acive shape
+ positive angle is clockwise
+ """
+ name = self.parent.l.GetSelection()
+ if name == wx.NOT_FOUND:
+ return False
+ name = self.parent.l.GetString(name)
+ model = self.parent.models[name]
+ model.rot += angle
+
+ def wheel(self, event):
+ """react to mouse wheel actions:
+ rotate object
+ with shift zoom viewport
+ """
+ z = event.GetWheelRotation()
+ angle = 10
if not event.ShiftDown():
- i=self.parent.l.GetSelection()
-
- if i<0:
+ i = self.parent.l.GetSelection()
+
+ if i < 0:
+ try:
+ self.parent.setlayerindex(z)
+ except:
+ pass
return
- m=self.parent.models[self.parent.l.GetString(i)]
-
+
if z > 0:
- m.rot+=delta/2
+ self.rotate_shape(angle / 2)
else:
- m.rot-=delta/2
+ self.rotate_shape(-angle / 2)
return
if z > 0:
- self.transv[2]+=delta
+ self.transv[2] += angle
else:
- self.transv[2]-=delta
-
+ self.transv[2] -= angle
+
glLoadIdentity()
glTranslatef(*self.transv)
if(self.rot):
glMultMatrixd(build_rotmatrix(self.basequat))
- glGetDoublev(GL_MODELVIEW_MATRIX,self.mvmat)
- self.rot=1
-
-
+ glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat)
+ self.rot = 1
+
+ def keypress(self, event):
+ """gets keypress events and moves/rotates acive shape"""
+ keycode = event.GetKeyCode()
+ print keycode
+ step = 5
+ angle = 18
+ if event.ControlDown():
+ step = 1
+ angle = 1
+ #h
+ if keycode == 72:
+ self.move_shape((-step, 0))
+ #l
+ if keycode == 76:
+ self.move_shape((step, 0))
+ #j
+ if keycode == 75:
+ self.move_shape((0, step))
+ #k
+ if keycode == 74:
+ self.move_shape((0, -step))
+ #[
+ if keycode == 91:
+ self.rotate_shape(-angle)
+ #]
+ if keycode == 93:
+ self.rotate_shape(angle)
+ event.Skip()
+
def update(self):
while(1):
- dt=0.05
+ dt = 0.05
time.sleep(0.05)
try:
wx.CallAfter(self.Refresh)
except:
return
-
- def anim(self,obj):
- g=50*9.8
- v=20
- dt=0.05
- basepos=obj.offsets[2]
- obj.offsets[2]+=obj.animoffset
- while obj.offsets[2]>-1:
+
+ def anim(self, obj):
+ g = 50 * 9.8
+ v = 20
+ dt = 0.05
+ basepos = obj.offsets[2]
+ obj.offsets[2] += obj.animoffset
+ while obj.offsets[2] > -1:
time.sleep(dt)
- obj.offsets[2]-=v*dt
- v+=g*dt
- if(obj.offsets[2]<0):
- obj.scale[2]*=1-3*dt
+ obj.offsets[2] -= v * dt
+ v += g * dt
+ if(obj.offsets[2] < 0):
+ obj.scale[2] *= 1 - 3 * dt
#return
- v=v/4
- while obj.offsets[2] 0 and self.modelindex < len(mlk) - 1:
+ self.modelindex += 1
+ if z < 0 and self.modelindex > 0:
+ self.modelindex -= 1
+ m.curlayer = mlk[self.modelindex]
+ wx.CallAfter(self.SetTitle, "Gcode view, shift to move. Layer %d, Z = %f" % (self.modelindex, m.curlayer))
+
+
+def main():
app = wx.App(redirect=False)
- frame = TestFrame(None, wx.ID_ANY, 'GL Window', size=(400,400))
- #frame = wx.Frame(None, -1, "GL Window", size=(400,400))
+ frame = GCFrame(None, wx.ID_ANY, 'Gcode view, shift to move view, mousewheel to set layer', size=(400, 400))
+ frame.addfile(list(open("carriage dump_export.gcode")))
+ #frame = wx.Frame(None, -1, "GL Window", size=(400, 400))
#panel = TestGlPanel(frame)
- frame.Show(True)
- app.MainLoop()
+ #frame.Show(True)
+ #app.MainLoop()
app.Destroy()
-
+
+if __name__ == "__main__":
+ import cProfile
+ print cProfile.run("main()")
diff --git a/xybuttons.py b/xybuttons.py
index 50b5575cf..8b29adf0f 100644
--- a/xybuttons.py
+++ b/xybuttons.py
@@ -1,9 +1,28 @@
+# This file is part of the Printrun suite.
+#
+# Printrun is 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
+# (at your option) any later version.
+#
+# Printrun 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 Printrun. If not, see .
+
import wx, os, math
from bufferedcanvas import *
-def imagefile(filename):
- return os.path.join(os.path.dirname(__file__), "images", filename)
+def imagefile(filename):
+ if os.path.exists(os.path.join(os.path.dirname(__file__), "images", filename)):
+ return os.path.join(os.path.dirname(__file__), "images", filename)
+ else:
+ return os.path.join(os.path.split(os.path.split(__file__)[0])[0], "images", filename)
+
def sign(n):
if n < 0: return -1
elif n > 0: return 1
@@ -38,9 +57,8 @@ def __init__(self, parent, moveCallback=None, cornerCallback=None, ID=-1):
self.moveCallback = moveCallback
self.cornerCallback = cornerCallback
self.enabled = False
-
+
BufferedCanvas.__init__(self, parent, ID)
-
self.SetSize(self.bg_bmp.GetSize())
# Set up mouse and keyboard event capture
@@ -192,8 +210,9 @@ def draw(self, dc, w, h):
gc = wx.GraphicsContext.Create(dc)
center = wx.Point(XYButtons.center[0], XYButtons.center[1])
- w, h = (self.bg_bmp.GetWidth(), self.bg_bmp.GetHeight())
- gc.DrawBitmap(self.bg_bmp, 0, 0, w, h)
+ if self.bg_bmp:
+ w, h = (self.bg_bmp.GetWidth(), self.bg_bmp.GetHeight())
+ gc.DrawBitmap(self.bg_bmp, 0, 0, w, h)
if self.enabled:
# Brush and pen for grey overlay when mouse hovers over
@@ -254,6 +273,8 @@ def OnKey(self, evt):
self.quadrant = 2
elif evt.GetKeyCode() == wx.WXK_RIGHT:
self.quadrant = 0
+ elif evt.GetKeyCode() == wx.WXK_SPACE:
+ pass
else:
evt.Skip()
return
@@ -327,4 +348,4 @@ def OnLeftDown(self, event):
def OnLeaveWindow(self, evt):
self.quadrant = None
self.concentric = None
- self.update()
\ No newline at end of file
+ self.update()
diff --git a/zbuttons.py b/zbuttons.py
index c5e0887f5..5638e6f2a 100644
--- a/zbuttons.py
+++ b/zbuttons.py
@@ -1,8 +1,28 @@
+# This file is part of the Printrun suite.
+#
+# Printrun is 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
+# (at your option) any later version.
+#
+# Printrun 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 Printrun. If not, see .
+
import wx, os, math
from bufferedcanvas import *
def imagefile(filename):
- return os.path.join(os.path.dirname(__file__), "images", filename)
+ if os.path.exists(os.path.join(os.path.dirname(__file__), "images", filename)):
+ return os.path.join(os.path.dirname(__file__), "images", filename)
+ else:
+ return os.path.join(os.path.split(os.path.split(__file__)[0])[0], "images", filename)
+
+
def sign(n):
if n < 0: return -1
@@ -75,9 +95,9 @@ def getRangeDir(self, pos):
def draw(self, dc, w, h):
dc.Clear()
gc = wx.GraphicsContext.Create(dc)
- w, h = (self.bg_bmp.GetWidth(), self.bg_bmp.GetHeight())
-
- gc.DrawBitmap(self.bg_bmp, 0, 0, w, h)
+ if self.bg_bmp:
+ w, h = (self.bg_bmp.GetWidth(), self.bg_bmp.GetHeight())
+ gc.DrawBitmap(self.bg_bmp, 0, 0, w, h)
if self.enabled:
# Draw label overlays
diff --git a/zscaper.py b/zscaper.py
index 6d4a96a77..25d7a19ad 100644
--- a/zscaper.py
+++ b/zscaper.py
@@ -1,3 +1,18 @@
+# This file is part of the Printrun suite.
+#
+# Printrun is 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
+# (at your option) any later version.
+#
+# Printrun 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 Printrun. If not, see .
+
import wx,math
from stltool import *
a=wx.App()