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()