Commit b69e28ad authored by sumpfralle's avatar sumpfralle

added conventional/climb settings to the GUI

updated Changelog


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@705 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent c60d883e
Version 0.3.1 - UNRELEASED Version 0.3.1 - UNRELEASED
* added automatic support grid positioning for contour models * added automatic support grid positioning for contour models
* added an improved contour toolpath strategy (ContourFollow)
* see http://fab.senselab.org/node/43
* added options for conventional/climb milling
* allow to reverse the direction of a 2D contour model * allow to reverse the direction of a 2D contour model
* added optional "orthogonal" view (instead of perspective) * added optional "orthogonal" view (instead of perspective)
* added a "recent files" item to the file menu * added a "recent files" item to the file menu
......
...@@ -10,8 +10,8 @@ ...@@ -10,8 +10,8 @@
xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="910.52441" width="967.52997"
height="2845.2439" height="2821.4348"
id="svg2" id="svg2"
version="1.1" version="1.1"
inkscape:version="0.47 r22583" inkscape:version="0.47 r22583"
...@@ -20,6 +20,67 @@ ...@@ -20,6 +20,67 @@
id="title4292">Sketches for Push-Follow toolpath strategy</title> id="title4292">Sketches for Push-Follow toolpath strategy</title>
<defs <defs
id="defs4"> id="defs4">
<inkscape:path-effect
effect="spiro"
id="path-effect5592"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect5350"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect5146"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect4952"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect4948"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect4944"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect4940"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect4936"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect4138"
is_visible="true" />
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart"
style="overflow:visible">
<path
id="path3687"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(0.8,0,0,0.8,10,0)" />
</marker>
<inkscape:path-effect
effect="spiro"
id="path-effect2910"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect2906"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect2902"
is_visible="true" />
<linearGradient <linearGradient
id="linearGradient3644"> id="linearGradient3644">
<stop <stop
...@@ -123,10 +184,17 @@ ...@@ -123,10 +184,17 @@
y1="883.64081" y1="883.64081"
x2="381.3631" x2="381.3631"
y2="883.64081" /> y2="883.64081" />
<inkscape:perspective
id="perspective4920"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient <linearGradient
inkscape:collect="always" inkscape:collect="always"
xlink:href="#linearGradient3644" xlink:href="#linearGradient3644"
id="linearGradient4240" id="linearGradient5778"
gradientUnits="userSpaceOnUse" gradientUnits="userSpaceOnUse"
gradientTransform="translate(-274.73686,-694.75982)" gradientTransform="translate(-274.73686,-694.75982)"
x1="287.60236" x1="287.60236"
...@@ -141,9 +209,9 @@ ...@@ -141,9 +209,9 @@
borderopacity="1.0" borderopacity="1.0"
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="0.35306407" inkscape:zoom="0.499308"
inkscape:cx="379.0174" inkscape:cx="898.5398"
inkscape:cy="872.93317" inkscape:cy="243.40248"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="false" showgrid="false"
...@@ -160,8 +228,8 @@ ...@@ -160,8 +228,8 @@
inkscape:window-y="0" inkscape:window-y="0"
inkscape:window-maximized="1" inkscape:window-maximized="1"
inkscape:object-paths="true" inkscape:object-paths="true"
inkscape:snap-intersection-paths="true" inkscape:snap-intersection-paths="false"
inkscape:object-nodes="false" inkscape:object-nodes="true"
inkscape:snap-smooth-nodes="false" inkscape:snap-smooth-nodes="false"
inkscape:snap-nodes="false"> inkscape:snap-nodes="false">
<inkscape:grid <inkscape:grid
...@@ -298,45 +366,6 @@ ...@@ -298,45 +366,6 @@
x="-1419.0509" x="-1419.0509"
sodipodi:role="line">above the cutter level.</tspan></text> sodipodi:role="line">above the cutter level.</tspan></text>
</g> </g>
<g
id="g3852"
transform="translate(1.9550781,0)"
inkscape:export-filename="/home/lars/subversion/pycam/trunk/artwork/pics/case1a.png"
inkscape:export-xdpi="40"
inkscape:export-ydpi="40">
<g
transform="translate(-1160,0)"
id="g3844">
<path
sodipodi:nodetypes="csaacccc"
id="path3676"
d="m -406.1415,39.399761 c 0,0 14.3721,-9.70579 21.46016,-3.70003 8.92695,7.56386 16.03483,9.82794 24.42021,14.06011 7.69164,3.88203 15.07588,10.80419 23.68019,10.36008 8.49429,-0.43843 22.20018,-12.5801 22.20018,-12.5801 l 0,252.342049 -91.76074,0 0,-260.482109 z"
style="fill:url(#linearGradient4226);fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="cccc"
id="path3680"
d="m -236.6722,331.72503 119.56148,49.09019 -149.86704,149.94979 30.30556,-199.03998 z"
style="fill:#2e980b;fill-opacity:1;stroke:none" />
</g>
<text
id="text3686"
y="588.5863"
x="-1421.2794"
style="font-size:28px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
id="tspan3690"
y="588.5863"
x="-1421.2794"
sodipodi:role="line">Case 1a</tspan><tspan
id="tspan3692"
y="623.5863"
x="-1421.2794"
sodipodi:role="line">The triangle is completely</tspan><tspan
id="tspan3732"
y="658.5863"
x="-1421.2794"
sodipodi:role="line">below the cutter level.</tspan></text>
</g>
<g <g
id="g4282" id="g4282"
inkscape:export-filename="/home/lars/subversion/pycam/trunk/artwork/pics/case2a.png" inkscape:export-filename="/home/lars/subversion/pycam/trunk/artwork/pics/case2a.png"
...@@ -394,7 +423,7 @@ ...@@ -394,7 +423,7 @@
sodipodi:nodetypes="csaacccc" sodipodi:nodetypes="csaacccc"
id="rect3642" id="rect3642"
d="m 13.865497,39.399761 c 0,0 14.3721,-9.70579 21.46016,-3.70003 8.92695,7.56386 16.03483,9.82794 24.42021,14.06011 7.691642,3.88203 15.075882,10.80419 23.680192,10.36008 8.49429,-0.43843 22.200181,-12.5801 22.200181,-12.5801 l 0,252.342049 -91.760743,0 0,-260.482109 z" d="m 13.865497,39.399761 c 0,0 14.3721,-9.70579 21.46016,-3.70003 8.92695,7.56386 16.03483,9.82794 24.42021,14.06011 7.691642,3.88203 15.075882,10.80419 23.680192,10.36008 8.49429,-0.43843 22.200181,-12.5801 22.200181,-12.5801 l 0,252.342049 -91.760743,0 0,-260.482109 z"
style="fill:url(#linearGradient4240);fill-opacity:1;stroke:none" /> style="fill:url(#linearGradient5778);fill-opacity:1;stroke:none" />
<text <text
id="text3660" id="text3660"
y="478.15857" y="478.15857"
...@@ -517,16 +546,261 @@ ...@@ -517,16 +546,261 @@
<text <text
xml:space="preserve" xml:space="preserve"
style="font-size:28px;font-style:normal;font-weight:normal;text-align:start;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans" style="font-size:28px;font-style:normal;font-weight:normal;text-align:start;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="-1195.6948" x="-1207.0242"
y="2281.3574" y="2207.7163"
id="text2894"><tspan id="text2894"><tspan
sodipodi:role="line" sodipodi:role="line"
id="tspan2896" id="tspan2896"
x="-1195.6948" x="-1207.0242"
y="2281.3574">see the related blog posting:</tspan><tspan y="2207.7163">see the related blog posting:</tspan><tspan
sodipodi:role="line" sodipodi:role="line"
x="-1195.6948" x="-1207.0242"
y="2316.3574" y="2242.7163"
id="tspan2898">http://fab.senselab.org/node/43</tspan></text> id="tspan2898">http://fab.senselab.org/node/43</tspan></text>
<g
id="g4339"
inkscape:export-filename="/home/lars/subversion/pycam/trunk/artwork/pics/case1a.png"
inkscape:export-xdpi="40"
inkscape:export-ydpi="40">
<g
transform="translate(-1158.0449,0)"
id="g3844">
<path
sodipodi:nodetypes="csaacccc"
id="path3676"
d="m -406.1415,39.399761 c 0,0 14.3721,-9.70579 21.46016,-3.70003 8.92695,7.56386 16.03483,9.82794 24.42021,14.06011 7.69164,3.88203 15.07588,10.80419 23.68019,10.36008 8.49429,-0.43843 22.20018,-12.5801 22.20018,-12.5801 l 0,252.342049 -91.76074,0 0,-260.482109 z"
style="fill:url(#linearGradient4226);fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="cccc"
id="path3680"
d="m -236.6722,331.72503 119.56148,49.09019 -149.86704,149.94979 30.30556,-199.03998 z"
style="fill:#2e980b;fill-opacity:1;stroke:none" />
</g>
<text
id="text3686"
y="588.5863"
x="-1419.3243"
style="font-size:28px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
id="tspan3690"
y="588.5863"
x="-1419.3243"
sodipodi:role="line">Case 1a</tspan><tspan
id="tspan3692"
y="623.5863"
x="-1419.3243"
sodipodi:role="line">The triangle is completely</tspan><tspan
id="tspan3732"
y="658.5863"
x="-1419.3243"
sodipodi:role="line">below the cutter level.</tspan></text>
<path
transform="translate(-1603.5528,33.73877)"
inkscape:original-d="m 148.69822,96.45102 c 113.29389,-59.479289 -2.83234,4.24852 0,0 z"
inkscape:path-effect="#path-effect2902"
id="path2900"
d="m 148.69822,96.45102 0,0"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
transform="translate(-1603.5528,33.73877)"
inkscape:original-d="M 138.78501,86.537805 222.33925,45.468772 138.78501,86.537805 z"
inkscape:path-effect="#path-effect2910"
id="path2908"
d="M 138.78501,86.537805 222.33925,45.468772 138.78501,86.537805"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstart)" />
<text
id="text4132"
y="86.288414"
x="-1340.468"
style="font-size:28px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:22px"
y="86.288414"
x="-1340.468"
id="tspan4134"
sodipodi:role="line">Cutter</tspan></text>
<path
transform="translate(-1603.5528,33.73877)"
inkscape:original-d="m 263.40828,307.46088 5.6647,-69.3925 -5.6647,69.3925 z"
inkscape:path-effect="#path-effect4138"
id="path4136"
d="m 263.40828,307.46088 5.6647,-69.3925 -5.6647,69.3925"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstart)" />
<text
id="text4324"
y="210.31602"
x="-1330.7284"
style="font-size:28px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:22px"
y="210.31602"
x="-1330.7284"
id="tspan4326"
sodipodi:role="line">One triangle</tspan><tspan
style="font-size:22px"
id="tspan4328"
y="237.81602"
x="-1330.7284"
sodipodi:role="line">of the solid 3D</tspan><tspan
style="font-size:22px"
id="tspan4330"
y="265.31604"
x="-1330.7284"
sodipodi:role="line">trimesh model.</tspan></text>
</g>
<g
id="g5875"
inkscape:export-filename="/home/lars/subversion/pycam/trunk/artwork/pics/corners.png"
inkscape:export-xdpi="40"
inkscape:export-ydpi="40">
<g
id="g5780">
<path
style="opacity:0.67041201;fill:#a1af9c;fill-opacity:1;stroke:#000000;stroke-opacity:1"
d="m -965.74222,2727.1351 -56.76808,-78.8764 -85.7763,29.3263 -50.1352,-142.3395 229.95363,-145.1493 90.34061,256.487 -127.61466,80.5519 z"
id="path2897"
sodipodi:nodetypes="ccccccc" />
<path
id="path5873"
d="m -898.0403,2376.9594 -12.5,-35.5625 c 0,0 -1.3e-4,10e-5 -2e-4,2e-4 -9.80861,7.8487 -31.8438,20.1562 -31.8438,20.1562 l -2.0937,1.3125 -0.031,0.031"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:none;stroke:#e50000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1,2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans;stroke-dashoffset:0" />
<path
id="path5871"
d="m -810.97214,2624.3428 c -29.04832,-82.4521 -58.08796,-164.9073 -87.06816,-247.3834"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:none;stroke:#e50000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans" />
<path
id="path5869"
d="m -1179.2278,2511.0531 -20.25,12.7813 7.9687,22.5625"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:none;stroke:#e50000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1,2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans;stroke-dashoffset:0" />
<path
id="path5867"
d="m -944.509,2362.8968 c -78.2368,49.3906 -156.4793,98.7754 -234.7188,148.1563"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:none;stroke:#e50000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans" />
<path
id="path5865"
d="m -1139.0403,2695.4906 9.8437,27.9688 28.0938,-9.5313"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:none;stroke:#e50000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1,2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans;stroke-dashoffset:0" />
<path
id="path5863"
d="m -1191.5091,2546.3969 c 17.504,49.6955 34.9761,99.3967 52.4688,149.0937"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:none;stroke:#e50000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans" />
<path
id="path5861"
d="m -991.1341,2752.9281 16.4688,22.9063 23.875,-15.0625"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:none;stroke:#e50000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1,2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans;stroke-dashoffset:0" />
<path
id="path5859"
d="m -1101.1028,2713.9281 c 21.9899,-7.4481 43.8611,-14.9884 65.75,-22.5 14.7458,20.4976 29.4867,41.0159 44.2187,61.5"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:none;stroke:#e50000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans" />
<path
id="path5857"
d="m -950.7903,2760.7719 120.95798,-76.3509"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:none;stroke:#e50000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans" />
<path
id="path4357"
d="m -829.83232,2684.421 c 23.74503,-19.1043 27.7063,-34.969 18.86018,-60.0782"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:none;stroke:#e50000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1,2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans;stroke-dashoffset:0" />
<path
style="opacity:0.33000004;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m -838.12756,2646.5832 -184.38274,1.6755 -135.9115,-113.0132 320.29424,111.3377"
id="path4946"
inkscape:path-effect="#path-effect4948"
inkscape:original-d="m -838.12756,2646.5832 -184.38274,1.6755 -135.9115,-113.0132 320.29424,111.3377 z" />
<path
style="fill:none;stroke:#000000;stroke-width:1.21528423px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstart)"
d="m -1100.9885,2445.7916 -22.9943,-71.8056 22.9943,71.8056"
id="path4950"
inkscape:path-effect="#path-effect4952"
inkscape:original-d="m -1100.9885,2445.7916 -22.9943,-71.8056 22.9943,71.8056 z" />
<text
xml:space="preserve"
style="font-size:22px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="-1112.4302"
y="2334.2952"
id="text5138"><tspan
sodipodi:role="line"
id="tspan5140"
x="-1112.4302"
y="2334.2952">extended shifted</tspan><tspan
sodipodi:role="line"
x="-1112.4302"
y="2361.7952"
id="tspan5142">collision line</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstart)"
d="m -1044.7795,2700.736 -67.0928,78.1081 67.0928,-78.1081"
id="path5144"
inkscape:path-effect="#path-effect5146"
inkscape:original-d="m -1044.7795,2700.736 -67.0928,78.1081 67.0928,-78.1081 z"
sodipodi:nodetypes="ccc" />
<text
xml:space="preserve"
style="font-size:22px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="-1126.8904"
y="2799.8621"
id="text5332"><tspan
sodipodi:role="line"
id="tspan5334"
x="-1126.8904"
y="2799.8621">shortened</tspan><tspan
sodipodi:role="line"
x="-1126.8904"
y="2827.3621"
id="tspan5336">lines at</tspan><tspan
sodipodi:role="line"
x="-1126.8904"
y="2854.8621"
id="tspan5338">concave corner</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstart)"
d="m -965.66996,2781.8483 58.08038,31.0429 -58.08038,-31.0429"
id="path5348"
inkscape:path-effect="#path-effect5350"
inkscape:original-d="m -965.66996,2781.8483 58.08038,31.0429 -58.08038,-31.0429 z" />
<text
xml:space="preserve"
style="font-size:22px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="-815.1947"
y="2817.2107"
id="text5536"><tspan
sodipodi:role="line"
id="tspan5538"
x="-815.1947"
y="2817.2107">extended lines</tspan><tspan
sodipodi:role="line"
x="-815.1947"
y="2844.7107"
id="tspan5540">at convex corner</tspan></text>
<text
xml:space="preserve"
style="font-size:22px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="-737.35394"
y="2440.3757"
id="text5576"><tspan
sodipodi:role="line"
x="-737.35394"
y="2440.3757"
id="tspan5580">connecting a</tspan><tspan
id="tspan5806"
sodipodi:role="line"
x="-737.35394"
y="2467.8757">convex corner</tspan><tspan
sodipodi:role="line"
x="-737.35394"
y="2495.3757"
id="tspan5582">with an arc</tspan><tspan
sodipodi:role="line"
x="-737.35394"
y="2522.8757"
id="tspan5586">(not implemented)</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstart)"
d="M 804.1129,2599.9043 860.19051,2497.763 804.1129,2599.9043"
id="path5590"
inkscape:path-effect="#path-effect5592"
inkscape:original-d="M 804.1129,2599.9043 860.19051,2497.763 804.1129,2599.9043 z"
transform="translate(-1603.5528,33.73877)" />
</g>
</g>
</g> </g>
</svg> </svg>
...@@ -414,10 +414,12 @@ if __name__ == "__main__": ...@@ -414,10 +414,12 @@ if __name__ == "__main__":
"contour": "ContourCutter", "contour": "ContourCutter",
"polygon": "PolygonCutter", "polygon": "PolygonCutter",
}[opts.process_path_postprocessor] }[opts.process_path_postprocessor]
# TODO: add the miling_style option
tps.set_process_settings(path_generator, postprocessor, tps.set_process_settings(path_generator, postprocessor,
opts.process_path_direction, opts.process_material_allowance, opts.process_path_direction, reverse=False,
opts.safety_height, opts.process_overlap_percent / 100.0, material_allowance=opts.process_material_allowance,
opts.process_step_down, opts.process_engrave_offset) overlap=opts.process_overlap_percent / 100.0,
step_down=opts.process_step_down, engrave_offset=opts.process_engrave_offset)
# set locations of external programs # set locations of external programs
program_locations = {} program_locations = {}
if opts.external_program_inkscape: if opts.external_program_inkscape:
......
...@@ -2427,10 +2427,8 @@ This can be useful if the imported model is technically broken (sometimes this h ...@@ -2427,10 +2427,8 @@ This can be useful if the imported model is technically broken (sometimes this h
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkTable" id="table6"> <object class="GtkHBox" id="hbox29">
<property name="visible">True</property> <property name="visible">True</property>
<property name="n_rows">3</property>
<property name="n_columns">3</property>
<child> <child>
<object class="GtkFrame" id="frame8"> <object class="GtkFrame" id="frame8">
<property name="visible">True</property> <property name="visible">True</property>
...@@ -2441,19 +2439,18 @@ This can be useful if the imported model is technically broken (sometimes this h ...@@ -2441,19 +2439,18 @@ This can be useful if the imported model is technically broken (sometimes this h
<property name="visible">True</property> <property name="visible">True</property>
<property name="left_padding">12</property> <property name="left_padding">12</property>
<child> <child>
<object class="GtkVBox" id="vbox15"> <object class="GtkVBox" id="vbox21">
<property name="visible">True</property> <property name="visible">True</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="spacing">1</property> <property name="spacing">1</property>
<child> <child>
<object class="GtkRadioButton" id="DropCutter"> <object class="GtkRadioButton" id="PushRemoveStrategy">
<property name="label" translatable="yes">Drop Cutter</property> <property name="label" translatable="yes">Slice removal</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">False</property> <property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">The Drop Cutter goes down to the lowest possible point at any location within the working area. <property name="tooltip_text" translatable="yes">Slice the model at different levels of z. Remove all material along a fixed grid.
This is suitable for finishing processes after removing the material above.</property> This operation is not supposed to follow the shape of the model accurately. Use a contour or surface toolpath strategy for the finish.</property>
<property name="active">True</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>
</object> </object>
<packing> <packing>
...@@ -2462,16 +2459,15 @@ This is suitable for finishing processes after removing the material above.</pro ...@@ -2462,16 +2459,15 @@ This is suitable for finishing processes after removing the material above.</pro
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkRadioButton" id="PushCutter"> <object class="GtkRadioButton" id="ContourPolygonStrategy">
<property name="label" translatable="yes">Push Cutter</property> <property name="label" translatable="yes">Contour (polygon)</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">False</property> <property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">The Push Cutter removes material in multiple layers down to the bottom of the working area. <property name="tooltip_text" translatable="yes">This contour toolpath strategy is based on a grid of collisions for slices of the model. The collisions are combined and form polygons around each model piece.
This is suitable for roughly processing the material. The algorithm does not work properly under all circumstances. Maybe you want try the new (experimental) "Contour (follow)" strategy instead.</property>
It will spare some material close to the model (depending on the "step down" value).</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>
<property name="group">DropCutter</property> <property name="group">PushRemoveStrategy</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
...@@ -2479,14 +2475,16 @@ It will spare some material close to the model (depending on the "step down" val ...@@ -2479,14 +2475,16 @@ It will spare some material close to the model (depending on the "step down" val
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkRadioButton" id="EngraveCutter"> <object class="GtkRadioButton" id="ContourFollowStrategy">
<property name="label" translatable="yes">Engraving</property> <property name="label" translatable="yes">Contour (follow)</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">False</property> <property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Engraving is only applicable to contour models (e.g. DXF files).</property> <property name="tooltip_text" translatable="yes">The Contour-&gt;Follow strategy slices the model at various z levels. It computes the exact paths of the model's contour. Thus it should be preferred over the "Contour (polygon)" strategy.
This code is very new and thus quite experimental.
The results are only accurate for a cylindrical tool.</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>
<property name="group">DropCutter</property> <property name="group">PushRemoveStrategy</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
...@@ -2494,85 +2492,36 @@ It will spare some material close to the model (depending on the "step down" val ...@@ -2494,85 +2492,36 @@ It will spare some material close to the model (depending on the "step down" val
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkRadioButton" id="WaterlineCutter"> <object class="GtkRadioButton" id="SurfaceStrategy">
<property name="label" translatable="yes">Waterlines</property> <property name="label" translatable="yes">Surface</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">DropCutter</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">3</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="Path Generator">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Path Generator&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkFrame" id="frame11">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment17">
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
<object class="GtkHBox" id="hbox13">
<property name="visible">True</property>
<property name="spacing">6</property>
<child>
<object class="GtkRadioButton" id="PathDirectionX">
<property name="label" translatable="yes">x</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">False</property> <property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Compute the height of the model at each point of a fixed grid (depending on the "Overlap" setting).
Currently vertical moves will never occour. Increase the overlap value to improve the accuracy of vertical edges.</property>
<property name="active">True</property> <property name="active">True</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>
<property name="group">PushRemoveStrategy</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="position">0</property> <property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="PathDirectionY">
<property name="label" translatable="yes">y</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">PathDirectionX</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkRadioButton" id="PathDirectionXY"> <object class="GtkRadioButton" id="EngraveStrategy">
<property name="label" translatable="yes">xy</property> <property name="label" translatable="yes">Engraving</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">False</property> <property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Follow the contour of a 2D drawing (in DXF or SVG format).
Use the "Engrave Offset" to shift the position of the tool to the outside (positive value) or inside (negative).</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>
<property name="group">PathDirectionX</property> <property name="group">PushRemoveStrategy</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="position">2</property> <property name="position">4</property>
</packing> </packing>
</child> </child>
</object> </object>
...@@ -2580,121 +2529,27 @@ It will spare some material close to the model (depending on the "step down" val ...@@ -2580,121 +2529,27 @@ It will spare some material close to the model (depending on the "step down" val
</object> </object>
</child> </child>
<child type="label"> <child type="label">
<object class="GtkLabel" id="PathDirectionLabel"> <object class="GtkLabel" id="ToolpathStrategy">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Path Direction&lt;/b&gt;</property> <property name="label" translatable="yes">&lt;b&gt;Path Strategy&lt;/b&gt;</property>
<property name="use_markup">True</property> <property name="use_markup">True</property>
</object> </object>
</child> </child>
</object> </object>
<packing> <packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="frame7">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment15">
<property name="visible">True</property>
<property name="top_padding">3</property>
<property name="bottom_padding">3</property>
<property name="left_padding">12</property>
<child>
<object class="GtkVBox" id="vbox21">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">1</property>
<child>
<object class="GtkRadioButton" id="PathAccumulator">
<property name="label" translatable="yes">Path Accumulator</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property> <property name="position">0</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkRadioButton" id="ZigZagCutter"> <object class="GtkVSeparator" id="vseparator9">
<property name="label" translatable="yes">ZigZag Cutter</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="orientation">vertical</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">PathAccumulator</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="position">1</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkRadioButton" id="SimpleCutter">
<property name="label" translatable="yes">Simple Cutter</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">PathAccumulator</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="PolygonCutter">
<property name="label" translatable="yes">Polygon Cutter</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">PathAccumulator</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="ContourCutter">
<property name="label" translatable="yes">Contour Cutter</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">PathAccumulator</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">4</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="PostProcessorLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Postprocessor&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child> <child>
<object class="GtkFrame" id="PathSettingsFrame"> <object class="GtkFrame" id="PathSettingsFrame">
<property name="visible">True</property> <property name="visible">True</property>
...@@ -2726,9 +2581,9 @@ It will spare some material close to the model (depending on the "step down" val ...@@ -2726,9 +2581,9 @@ It will spare some material close to the model (depending on the "step down" val
<object class="GtkSpinButton" id="OverlapPercentControl"> <object class="GtkSpinButton" id="OverlapPercentControl">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">The distance between two neighbouring drill positions is based on the overlap value. <property name="tooltip_text" translatable="yes">Overlapping percentage for grid-based toolpath strategies.
Use high values for fine-grained toolpaths.</property> Higher values increase accuracy and processing time.</property>
<property name="invisible_char">&#x2022;</property> <property name="invisible_char">&#x25CF;</property>
<property name="adjustment">OverlapPercentValue</property> <property name="adjustment">OverlapPercentValue</property>
<property name="numeric">True</property> <property name="numeric">True</property>
</object> </object>
...@@ -2757,11 +2612,9 @@ Use high values for fine-grained toolpaths.</property> ...@@ -2757,11 +2612,9 @@ Use high values for fine-grained toolpaths.</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Material allowance determines the minimum distance that should be preserved between the tool and the model. <property name="tooltip_text" translatable="yes">Material allowance determines the minimum distance that should be preserved between the tool and the model.
This value should be greater than zero for the first roughing operation. This value should be greater than zero for the first roughing operation or for inaccurate tools.
The last finishing operation should have zero material allowance. The last finishing operation should have zero material allowance.</property>
<property name="invisible_char">&#x25CF;</property>
This operation is not available for engraving.</property>
<property name="invisible_char">&#x2022;</property>
<property name="adjustment">MaterialAllowanceValue</property> <property name="adjustment">MaterialAllowanceValue</property>
<property name="digits">2</property> <property name="digits">2</property>
<property name="numeric">True</property> <property name="numeric">True</property>
...@@ -2779,8 +2632,8 @@ This operation is not available for engraving.</property> ...@@ -2779,8 +2632,8 @@ This operation is not available for engraving.</property>
<object class="GtkSpinButton" id="MaxStepDownControl"> <object class="GtkSpinButton" id="MaxStepDownControl">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">This value determines the maximum height of each PushCutter slice.</property> <property name="tooltip_text" translatable="yes">The maximum height of each layer for all slicing toolpath strategies.</property>
<property name="invisible_char">&#x2022;</property> <property name="invisible_char">&#x25CF;</property>
<property name="adjustment">MaxStepDownValue</property> <property name="adjustment">MaxStepDownValue</property>
<property name="digits">2</property> <property name="digits">2</property>
<property name="numeric">True</property> <property name="numeric">True</property>
...@@ -2824,6 +2677,8 @@ This operation is not available for engraving.</property> ...@@ -2824,6 +2677,8 @@ This operation is not available for engraving.</property>
<object class="GtkSpinButton" id="EngraveOffsetControl"> <object class="GtkSpinButton" id="EngraveOffsetControl">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Shift the position of the tool towards the outside (positive value) or inside (negative).
Usually you will want to use the cutter radius here to cut around the outline.</property>
<property name="invisible_char">&#x25CF;</property> <property name="invisible_char">&#x25CF;</property>
<property name="adjustment">EngraveOffsetValue</property> <property name="adjustment">EngraveOffsetValue</property>
<property name="digits">2</property> <property name="digits">2</property>
...@@ -2851,10 +2706,14 @@ This operation is not available for engraving.</property> ...@@ -2851,10 +2706,14 @@ This operation is not available for engraving.</property>
</child> </child>
</object> </object>
<packing> <packing>
<property name="left_attach">2</property> <property name="position">2</property>
<property name="right_attach">3</property> </packing>
<property name="top_attach">2</property> </child>
<property name="bottom_attach">3</property> </object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -2862,19 +2721,86 @@ This operation is not available for engraving.</property> ...@@ -2862,19 +2721,86 @@ This operation is not available for engraving.</property>
<property name="visible">True</property> <property name="visible">True</property>
</object> </object>
<packing> <packing>
<property name="top_attach">1</property> <property name="expand">False</property>
<property name="bottom_attach">2</property> <property name="position">4</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkHSeparator" id="hseparator5"> <object class="GtkFrame" id="frame11">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment17">
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
<object class="GtkHBox" id="hbox13">
<property name="visible">True</property>
<child>
<object class="GtkHBox" id="hbox31">
<property name="visible">True</property> <property name="visible">True</property>
<property name="spacing">4</property>
<child>
<object class="GtkLabel" id="GridDirectionLabel">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="yalign">0</property>
<property name="label" translatable="yes">Grid direction:</property>
</object> </object>
<packing> <packing>
<property name="left_attach">2</property> <property name="position">0</property>
<property name="right_attach">3</property> </packing>
<property name="top_attach">1</property> </child>
<property name="bottom_attach">2</property> <child>
<object class="GtkVBox" id="vbox15">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkRadioButton" id="GridDirectionX">
<property name="label" translatable="yes">x</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="GridDirectionY">
<property name="label" translatable="yes">y</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">GridDirectionX</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="GridDirectionXY">
<property name="label" translatable="yes">both </property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">GridDirectionX</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="position">1</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -2883,28 +2809,94 @@ This operation is not available for engraving.</property> ...@@ -2883,28 +2809,94 @@ This operation is not available for engraving.</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="expand">False</property>
<property name="right_attach">2</property> <property name="position">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkVSeparator" id="vseparator9"> <object class="GtkLabel" id="MillingStyleLabel">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="yalign">0</property>
<property name="label" translatable="yes">Milling Style:</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="vbox33">
<property name="visible">True</property> <property name="visible">True</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<child>
<object class="GtkRadioButton" id="MillingStyleConventional">
<property name="label" translatable="yes">conventional / up</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="expand">False</property>
<property name="right_attach">2</property> <property name="fill">False</property>
<property name="position">0</property>
</packing> </packing>
</child> </child>
<child> <child>
<placeholder/> <object class="GtkRadioButton" id="MillingStyleClimb">
<property name="label" translatable="yes">climb / down</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">MillingStyleConventional</property>
</object>
<packing>
<property name="position">1</property>
</packing>
</child> </child>
<child>
<object class="GtkRadioButton" id="MillingStyleIgnore">
<property name="label" translatable="yes">ignore</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">MillingStyleConventional</property>
</object> </object>
<packing> <packing>
<property name="position">3</property> <property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="position">4</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="PathDirectionFrameLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Path Direction&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="position">5</property>
</packing> </packing>
</child> </child>
</object> </object>
......
...@@ -545,17 +545,20 @@ class ProjectGui: ...@@ -545,17 +545,20 @@ class ProjectGui:
self.gui.get_object(name).connect("clicked", self.handle_tool_settings_change) self.gui.get_object(name).connect("clicked", self.handle_tool_settings_change)
self.gui.get_object("ToolName").connect("changed", self.handle_tool_settings_change) self.gui.get_object("ToolName").connect("changed", self.handle_tool_settings_change)
# connect the "consistency check" and the update-handler with all toolpath settings # connect the "consistency check" and the update-handler with all toolpath settings
for objname in ("PathAccumulator", "SimpleCutter", "ZigZagCutter", for objname in ("PushRemoveStrategy", "ContourPolygonStrategy",
"PolygonCutter", "ContourCutter", "DropCutter", "PushCutter", "ContourFollowStrategy", "SurfaceStrategy",
"EngraveCutter", "WaterlineCutter", "PathDirectionX", "EngraveStrategy", "GridDirectionX",
"PathDirectionY", "PathDirectionXY", "SettingEnableODE"): "GridDirectionY", "GridDirectionXY"):
self.gui.get_object(objname).connect("toggled", self.update_process_controls) self.gui.get_object(objname).connect("toggled",
if objname != "SettingEnableODE": self.update_process_controls)
self.gui.get_object(objname).connect("toggled", self.handle_process_settings_change) self.gui.get_object(objname).connect("toggled",
self.handle_process_settings_change)
for objname in ("OverlapPercentControl", "MaterialAllowanceControl", for objname in ("OverlapPercentControl", "MaterialAllowanceControl",
"MaxStepDownControl", "EngraveOffsetControl"): "MaxStepDownControl", "EngraveOffsetControl"):
self.gui.get_object(objname).connect("value-changed", self.handle_process_settings_change) self.gui.get_object(objname).connect("value-changed",
self.gui.get_object("ProcessSettingName").connect("changed", self.handle_process_settings_change) self.handle_process_settings_change)
self.gui.get_object("ProcessSettingName").connect("changed",
self.handle_process_settings_change)
# get/set functions for the current tool/process/bounds/task # get/set functions for the current tool/process/bounds/task
def get_current_item(table, item_list): def get_current_item(table, item_list):
index = self._treeview_get_active_index(table, item_list) index = self._treeview_get_active_index(table, item_list)
...@@ -970,7 +973,6 @@ class ProjectGui: ...@@ -970,7 +973,6 @@ class ProjectGui:
self.gui.get_object("SupportGridPositionManualShiftBox").set_sensitive( self.gui.get_object("SupportGridPositionManualShiftBox").set_sensitive(
self.grid_adjustment_selector.get_active() >= 0) self.grid_adjustment_selector.get_active() >= 0)
def update_support_grid_manual_adjust(self, widget=None, data1=None, def update_support_grid_manual_adjust(self, widget=None, data1=None,
data2=None): data2=None):
new_value = self.grid_adjustment_value.get_value() new_value = self.grid_adjustment_value.get_value()
...@@ -1164,13 +1166,14 @@ class ProjectGui: ...@@ -1164,13 +1166,14 @@ class ProjectGui:
tool_desc += "(%.4f%s / %.4f%s)" % ( 2 * tool["tool_radius"], unit, 2 * tool["torus_radius"], unit) tool_desc += "(%.4f%s / %.4f%s)" % ( 2 * tool["tool_radius"], unit, 2 * tool["torus_radius"], unit)
lines.append(tool_desc) lines.append(tool_desc)
lines.append("Spindle speed: %drpm / Feedrate: %d%s/minute" % (tool["speed"], tool["feedrate"], unit)) lines.append("Spindle speed: %drpm / Feedrate: %d%s/minute" % (tool["speed"], tool["feedrate"], unit))
lines.append("Path: %s / %s" % (process["path_generator"], process["path_postprocessor"])) lines.append("Strategy: %s" % process["path_strategy"])
if process["path_generator"] == "EngraveCutter": if process["path_strategy"] == "EngraveStrategy":
lines.append("Engrave offset: %.3f" % process["engrave_offset"]) lines.append("Engrave offset: %.3f" % process["engrave_offset"])
else: else:
lines.append("Overlap: %d%%" % process["overlap_percent"]) lines.append("Overlap: %d%%" % process["overlap_percent"])
lines.append("Milling style: %s" % process["milling_style"])
lines.append("Material allowance: %.2f%s" % (process["material_allowance"], unit)) lines.append("Material allowance: %.2f%s" % (process["material_allowance"], unit))
if process["path_generator"] != "DropCutter": if process["path_strategy"] != "SurfaceStrategy":
lines.append("Maximum step down: %.2f%s" % (process["step_down"], unit)) lines.append("Maximum step down: %.2f%s" % (process["step_down"], unit))
else: else:
lines.append("No task selected") lines.append("No task selected")
...@@ -1308,45 +1311,38 @@ class ProjectGui: ...@@ -1308,45 +1311,38 @@ class ProjectGui:
# possible dependencies of the DropCutter # possible dependencies of the DropCutter
get_obj = self.gui.get_object get_obj = self.gui.get_object
cutter_name = None cutter_name = None
for one_cutter in ("DropCutter", "PushCutter", "EngraveCutter", for one_cutter in ("PushRemoveStrategy", "ContourPolygonStrategy",
"WaterlineCutter"): "ContourFollowStrategy", "SurfaceStrategy", "EngraveStrategy"):
if get_obj(one_cutter).get_active(): if get_obj(one_cutter).get_active():
cutter_name = one_cutter cutter_name = one_cutter
if cutter_name == "DropCutter": break
if get_obj("PathDirectionXY").get_active(): else:
get_obj("PathDirectionX").set_active(True) raise ValueError("Invalid cutter selected")
if not (get_obj("PathAccumulator").get_active() or get_obj("ZigZagCutter").get_active()): if cutter_name == "SurfaceStrategy" \
get_obj("PathAccumulator").set_active(True) and get_obj("GridDirectionXY").get_active():
elif cutter_name == "PushCutter": get_obj("GridDirectionX").set_active(True)
if not (get_obj("SimpleCutter").get_active() \ all_controls = ("GridDirectionX", "GridDirectionY", "GridDirectionXY",
or get_obj("PolygonCutter").get_active() \ "MillingStyleConventional", "MillingStyleClimb",
or get_obj("ContourCutter").get_active()): "MillingStyleIgnore", "MaxStepDownControl",
get_obj("SimpleCutter").set_active(True)
elif cutter_name == "EngraveCutter":
if not get_obj("SimpleCutter").get_active():
get_obj("SimpleCutter").set_active(True)
elif cutter_name == "WaterlineCutter":
if not get_obj("PathAccumulator").get_active():
get_obj("PathAccumulator").set_active(True)
else:
raise ValueError("Invalid cutter selected: %s" % str(cutter_name))
all_controls = ("PathDirectionX", "PathDirectionY", "PathDirectionXY",
"SimpleCutter", "PolygonCutter", "ContourCutter",
"PathAccumulator", "ZigZagCutter", "MaxStepDownControl",
"MaterialAllowanceControl", "OverlapPercentControl", "MaterialAllowanceControl", "OverlapPercentControl",
"EngraveOffsetControl") "EngraveOffsetControl")
active_controls = { active_controls = {
"DropCutter": ("PathAccumulator", "ZigZagCutter", "PathDirectionX", "PushRemoveStrategy": ("GridDirectionX", "GridDirectionY",
"PathDirectionY", "MaterialAllowanceControl", "GridDirectionXY", "MaxStepDownControl",
"OverlapPercentControl"), "MaterialAllowanceControl", "OverlapPercentControl"),
"PushCutter": ("SimpleCutter", "PolygonCutter", "ContourCutter", "ContourPolygonStrategy": ("GridDirectionX", "GridDirectionY",
"PathDirectionX", "PathDirectionY", "PathDirectionXY", "GridDirectionXY", "MillingStyleConventional",
"MillingStyleClimb", "MillingStyleIgnore",
"MaxStepDownControl", "MaterialAllowanceControl", "MaxStepDownControl", "MaterialAllowanceControl",
"OverlapPercentControl"), "OverlapPercentControl"),
"EngraveCutter": ("SimpleCutter", "MaxStepDownControl", "ContourFollowStrategy": ("MillingStyleConventional",
"EngraveOffsetControl"), "MillingStyleClimb", "MillingStyleIgnore",
"WaterlineCutter": ("PathAccumulator", "MaterialAllowanceControl",
"MaxStepDownControl"), "MaxStepDownControl"),
"SurfaceStrategy": ("GridDirectionX", "GridDirectionY",
"MillingStyleConventional", "MillingStyleClimb",
"MillingStyleIgnore", "MaterialAllowanceControl",
"OverlapPercentControl"),
"EngraveStrategy": ("MaxStepDownControl", "EngraveOffsetControl"),
} }
for one_control in all_controls: for one_control in all_controls:
get_obj(one_control).set_sensitive(one_control in active_controls[cutter_name]) get_obj(one_control).set_sensitive(one_control in active_controls[cutter_name])
...@@ -2300,28 +2296,71 @@ class ProjectGui: ...@@ -2300,28 +2296,71 @@ class ProjectGui:
self.update_bounds_table(self.bounds_list.index(new_settings)) self.update_bounds_table(self.bounds_list.index(new_settings))
self._put_bounds_settings_to_gui(new_settings) self._put_bounds_settings_to_gui(new_settings)
def _get_process_details(self, strategy, direction, milling_style):
STRATEGY_GENERATORS = {
"PushRemoveStrategy": "PushCutter",
"ContourPolygonStrategy": "PushCutter",
"ContourFollowStrategy": "ContourFollow",
"SurfaceStrategy": "DropCutter",
"EngraveStrategy": "EngraveCutter"}
generator = STRATEGY_GENERATORS[strategy]
if strategy in ("PushRemoveStrategy", "SurfaceStrategy"):
if strategy == "PushRemoveStrategy":
# TODO: implement "conventional/climb" for PolygonCutter
processor = "PolygonCutter"
elif milling_style in ("conventional", "climb"):
processor = "PathAccumulator"
else:
processor = "ZigZagCutter"
if milling_style == "conventional":
reverse = False
else:
reverse_counter = 0
if direction == "y":
reverse_counter += 1
if milling_style == "conventional":
reverse_counter += 1
reverse = (reverse_counter % 1) == 1
elif strategy in ("ContourPolygonStrategy", "ContourFollowStrategy"):
if strategy == "ContourPolygonStrategy":
processor = "ContourCutter"
else:
processor = "PathAccumulator"
reverse = milling_style in ("climb", "ignore")
elif strategy == "EngraveStrategy":
processor = "SimpleCutter"
reverse = False
else:
pass
return generator, processor, reverse
def _load_process_settings_from_gui(self, settings=None): def _load_process_settings_from_gui(self, settings=None):
if settings is None: if settings is None:
settings = {} settings = {}
settings["name"] = self.gui.get_object("ProcessSettingName").get_text() settings["name"] = self.gui.get_object("ProcessSettingName").get_text()
# path generator # path generator
def get_path_generator(): for key in ("PushRemoveStrategy", "ContourPolygonStrategy",
for name in ("DropCutter", "PushCutter", "EngraveCutter", "ContourFollowStrategy", "SurfaceStrategy", "EngraveStrategy"):
"WaterlineCutter"): if self.gui.get_object(key).get_active():
if self.gui.get_object(name).get_active(): strategy = key
return name break
settings["path_generator"] = get_path_generator() settings["path_strategy"] = strategy
# path direction # path direction
def get_path_direction(): for obj, value in (("GridDirectionX", "x"), ("GridDirectionY", "y"),
for obj, value in (("PathDirectionX", "x"), ("PathDirectionY", "y"), ("PathDirectionXY", "xy")): ("GridDirectionXY", "xy")):
if self.gui.get_object(obj).get_active(): if self.gui.get_object(obj).get_active():
return value direction = value
settings["path_direction"] = get_path_direction() break
def get_path_postprocessor(): # milling style
for name in ("PathAccumulator", "SimpleCutter", "ZigZagCutter", "PolygonCutter", "ContourCutter"): for obj, value in (("MillingStyleConventional", "conventional"),
if self.gui.get_object(name).get_active(): ("MillingStyleClimb", "climb"),
return name ("MillingStyleIgnore", "ignore")):
settings["path_postprocessor"] = get_path_postprocessor() if self.gui.get_object(obj).get_active():
milling_style = value
break
# post_processor and reverse
settings["milling_style"] = milling_style
settings["path_direction"] = direction
for objname, key in (("OverlapPercentControl", "overlap_percent"), for objname, key in (("OverlapPercentControl", "overlap_percent"),
("MaterialAllowanceControl", "material_allowance"), ("MaterialAllowanceControl", "material_allowance"),
("MaxStepDownControl", "step_down"), ("MaxStepDownControl", "step_down"),
...@@ -2331,20 +2370,24 @@ class ProjectGui: ...@@ -2331,20 +2370,24 @@ class ProjectGui:
def _put_process_settings_to_gui(self, settings): def _put_process_settings_to_gui(self, settings):
self.gui.get_object("ProcessSettingName").set_text(settings["name"]) self.gui.get_object("ProcessSettingName").set_text(settings["name"])
def set_path_generator(value):
self.gui.get_object(value).set_active(True)
set_path_generator(settings["path_generator"])
# path direction # path direction
def set_path_direction(direction): def set_path_direction(direction):
for obj, value in (("PathDirectionX", "x"), ("PathDirectionY", "y"), ("PathDirectionXY", "xy")): for obj, value in (("GridDirectionX", "x"), ("GridDirectionY", "y"),
("GridDirectionXY", "xy")):
if value == direction: if value == direction:
self.gui.get_object(obj).set_active(True) self.gui.get_object(obj).set_active(True)
return return
set_path_direction(settings["path_direction"]) set_path_direction(settings["path_direction"])
# path postprocessor def set_path_strategy(value):
def set_path_postprocessor(value):
self.gui.get_object(value).set_active(True) self.gui.get_object(value).set_active(True)
set_path_postprocessor(settings["path_postprocessor"]) set_path_strategy(settings["path_strategy"])
# milling style
def set_milling_style(style):
STYLES = {"conventional": "MillingStyleConventional",
"climb": "MillingStyleClimb",
"ignore": "MillingStyleIgnore"}
self.gui.get_object(STYLES[style]).set_active(True)
set_milling_style(settings["milling_style"])
for objname, key in (("OverlapPercentControl", "overlap_percent"), for objname, key in (("OverlapPercentControl", "overlap_percent"),
("MaterialAllowanceControl", "material_allowance"), ("MaterialAllowanceControl", "material_allowance"),
("MaxStepDownControl", "step_down"), ("MaxStepDownControl", "step_down"),
...@@ -2791,12 +2834,15 @@ class ProjectGui: ...@@ -2791,12 +2834,15 @@ class ProjectGui:
# unit size # unit size
toolpath_settings.set_unit_size(self.settings.get("unit")) toolpath_settings.set_unit_size(self.settings.get("unit"))
generator, postprocessor, reverse = self._get_process_details(
process_settings["path_strategy"],
process_settings["path_direction"],
process_settings["milling_style"])
# process settings # process settings
toolpath_settings.set_process_settings( toolpath_settings.set_process_settings(
process_settings["path_generator"], generator, postprocessor, process_settings["path_direction"],
process_settings["path_postprocessor"], reverse, process_settings["material_allowance"],
process_settings["path_direction"],
process_settings["material_allowance"],
process_settings["overlap_percent"] / 100.0, process_settings["overlap_percent"] / 100.0,
process_settings["step_down"], process_settings["step_down"],
process_settings["engrave_offset"]) process_settings["engrave_offset"])
......
...@@ -130,11 +130,11 @@ speed: 1000 ...@@ -130,11 +130,11 @@ speed: 1000
[ProcessDefault] [ProcessDefault]
name: Remove material name: Remove material
path_direction: x
engrave_offset: 0.0 engrave_offset: 0.0
path_generator: PushCutter path_strategy: PushCutter
path_postprocessor: PolygonCutter path_direction: x
material_allowance: 0.5 milling_style: ignore
material_allowance: 0.0
step_down: 3.0 step_down: 3.0
overlap_percent: 0 overlap_percent: 0
...@@ -180,37 +180,35 @@ tool_radius: 0.5 ...@@ -180,37 +180,35 @@ tool_radius: 0.5
[ProcessDefault] [ProcessDefault]
path_direction: x path_direction: x
path_strategy: SurfaceStrategy
milling_style: ignore
engrave_offset: 0.0 engrave_offset: 0.0
step_down: 3.0
material_allowance: 0.0
[Process0] [Process0]
name: Remove material name: Remove material
path_generator: PushCutter path_strategy: PushRemoveStrategy
path_postprocessor: PolygonCutter
material_allowance: 0.5 material_allowance: 0.5
step_down: 3.0 step_down: 3.0
overlap_percent: 0 overlap_percent: 0
[Process1] [Process1]
name: Carve contour name: Carve contour
path_generator: PushCutter path_strategy: ContourFollowStrategy
path_postprocessor: ContourCutter
material_allowance: 0.2 material_allowance: 0.2
step_down: 1.5 step_down: 1.5
overlap_percent: 20 overlap_percent: 20
[Process2] [Process2]
name: Cleanup name: Cleanup
path_generator: DropCutter path_strategy: SurfaceStrategy
path_postprocessor: ZigZagCutter
material_allowance: 0.0 material_allowance: 0.0
step_down: 1.0
overlap_percent: 60 overlap_percent: 60
[Process3] [Process3]
name: Gravure name: Gravure
path_generator: EngraveCutter path_strategy: EngraveStrategy
path_postprocessor: SimpleCutter
material_allowance: 0.0
step_down: 1.0 step_down: 1.0
overlap_percent: 50 overlap_percent: 50
...@@ -267,9 +265,9 @@ process: 3 ...@@ -267,9 +265,9 @@ process: 3
"torus_radius": float, "torus_radius": float,
"speed": float, "speed": float,
"feedrate": float, "feedrate": float,
"path_strategy": str,
"path_direction": str, "path_direction": str,
"path_generator": str, "milling_style": str,
"path_postprocessor": str,
"material_allowance": float, "material_allowance": float,
"overlap_percent": int, "overlap_percent": int,
"step_down": float, "step_down": float,
...@@ -290,8 +288,8 @@ process: 3 ...@@ -290,8 +288,8 @@ process: 3
CATEGORY_KEYS = { CATEGORY_KEYS = {
"tool": ("name", "shape", "tool_radius", "torus_radius", "feedrate", "tool": ("name", "shape", "tool_radius", "torus_radius", "feedrate",
"speed"), "speed"),
"process": ("name", "path_generator", "path_postprocessor", "process": ("name", "path_strategy", "path_direction",
"path_direction", "material_allowance", "milling_style", "material_allowance",
"overlap_percent", "step_down", "engrave_offset"), "overlap_percent", "step_down", "engrave_offset"),
"bounds": ("name", "type", "x_low", "x_high", "y_low", "bounds": ("name", "type", "x_low", "x_high", "y_low",
"y_high", "z_low", "z_high"), "y_high", "z_low", "z_high"),
...@@ -588,6 +586,7 @@ class ToolpathSettings: ...@@ -588,6 +586,7 @@ class ToolpathSettings:
"generator": str, "generator": str,
"postprocessor": str, "postprocessor": str,
"path_direction": str, "path_direction": str,
"reverse": bool,
"material_allowance": float, "material_allowance": float,
"overlap": float, "overlap": float,
"step_down": float, "step_down": float,
...@@ -699,12 +698,16 @@ class ToolpathSettings: ...@@ -699,12 +698,16 @@ class ToolpathSettings:
return "mm" return "mm"
def set_process_settings(self, generator, postprocessor, path_direction, def set_process_settings(self, generator, postprocessor, path_direction,
material_allowance=0.0, overlap=0.0, reverse=False, material_allowance=0.0, overlap=0.0,
step_down=1.0, engrave_offset=0.0): step_down=1.0, engrave_offset=0.0):
# TODO: this hack should be somewhere else, I guess
if generator in ("ContourFollow", "EngraveCutter"):
material_allowance = 0.0
self.process_settings = { self.process_settings = {
"generator": generator, "generator": generator,
"postprocessor": postprocessor, "postprocessor": postprocessor,
"path_direction": path_direction, "path_direction": path_direction,
"reverse": reverse,
"material_allowance": material_allowance, "material_allowance": material_allowance,
"overlap": overlap, "overlap": overlap,
"step_down": step_down, "step_down": step_down,
......
...@@ -20,7 +20,8 @@ You should have received a copy of the GNU General Public License ...@@ -20,7 +20,8 @@ You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>. along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
""" """
from pycam.PathGenerators import DropCutter, PushCutter, EngraveCutter, Waterline from pycam.PathGenerators import DropCutter, PushCutter, EngraveCutter, \
ContourFollow
from pycam.Geometry.utils import number from pycam.Geometry.utils import number
import pycam.PathProcessors import pycam.PathProcessors
import pycam.Cutters import pycam.Cutters
...@@ -33,7 +34,8 @@ log = pycam.Utils.log.get_logger() ...@@ -33,7 +34,8 @@ log = pycam.Utils.log.get_logger()
DIRECTIONS = frozenset(("x", "y", "xy")) DIRECTIONS = frozenset(("x", "y", "xy"))
PATH_GENERATORS = frozenset(("DropCutter", "PushCutter", "EngraveCutter", "WaterlineCutter")) PATH_GENERATORS = frozenset(("DropCutter", "PushCutter", "EngraveCutter",
"ContourFollow"))
PATH_POSTPROCESSORS = frozenset(("ContourCutter", "PathAccumulator", PATH_POSTPROCESSORS = frozenset(("ContourCutter", "PathAccumulator",
"PolygonCutter", "SimpleCutter", "ZigZagCutter")) "PolygonCutter", "SimpleCutter", "ZigZagCutter"))
CALCULATION_BACKENDS = frozenset((None, "ODE")) CALCULATION_BACKENDS = frozenset((None, "ODE"))
...@@ -48,6 +50,7 @@ def generate_toolpath_from_settings(model, tp_settings, callback=None): ...@@ -48,6 +50,7 @@ def generate_toolpath_from_settings(model, tp_settings, callback=None):
return generate_toolpath(model, tp_settings.get_tool_settings(), return generate_toolpath(model, tp_settings.get_tool_settings(),
bounds_low, bounds_high, process["path_direction"], bounds_low, bounds_high, process["path_direction"],
process["generator"], process["postprocessor"], process["generator"], process["postprocessor"],
process["reverse"],
process["material_allowance"], process["overlap"], process["material_allowance"], process["overlap"],
process["step_down"], process["engrave_offset"], process["step_down"], process["engrave_offset"],
grid["type"], grid["distance_x"], grid["distance_y"], grid["type"], grid["distance_x"], grid["distance_y"],
...@@ -59,6 +62,7 @@ def generate_toolpath_from_settings(model, tp_settings, callback=None): ...@@ -59,6 +62,7 @@ def generate_toolpath_from_settings(model, tp_settings, callback=None):
def generate_toolpath(model, tool_settings=None, def generate_toolpath(model, tool_settings=None,
bounds_low=None, bounds_high=None, direction="x", bounds_low=None, bounds_high=None, direction="x",
path_generator="DropCutter", path_postprocessor="ZigZagCutter", path_generator="DropCutter", path_postprocessor="ZigZagCutter",
reverse=False,
material_allowance=0, overlap=0, step_down=0, engrave_offset=0, material_allowance=0, overlap=0, step_down=0, engrave_offset=0,
support_grid_type=None, support_grid_distance_x=None, support_grid_type=None, support_grid_distance_x=None,
support_grid_distance_y=None, support_grid_thickness=None, support_grid_distance_y=None, support_grid_thickness=None,
...@@ -255,7 +259,7 @@ def generate_toolpath(model, tool_settings=None, ...@@ -255,7 +259,7 @@ def generate_toolpath(model, tool_settings=None,
for next_model in trimesh_models[1:]: for next_model in trimesh_models[1:]:
combined_models += next_model combined_models += next_model
generator = _get_pathgenerator_instance(combined_models, contour_model, generator = _get_pathgenerator_instance(combined_models, contour_model,
cutter, path_generator, path_postprocessor, physics) cutter, path_generator, path_postprocessor, reverse, physics)
if isinstance(generator, basestring): if isinstance(generator, basestring):
return generator return generator
if (overlap < 0) or (overlap >= 1): if (overlap < 0) or (overlap >= 1):
...@@ -298,7 +302,7 @@ def generate_toolpath(model, tool_settings=None, ...@@ -298,7 +302,7 @@ def generate_toolpath(model, tool_settings=None,
dz = maxz - minz dz = maxz - minz
toolpath = generator.GenerateToolPath(minz, maxz, stepping, dz, toolpath = generator.GenerateToolPath(minz, maxz, stepping, dz,
callback) callback)
elif path_generator == "WaterlineCutter": elif path_generator == "ContourFollow":
if step_down > 0: if step_down > 0:
dz = step_down dz = step_down
else: else:
...@@ -313,12 +317,13 @@ def generate_toolpath(model, tool_settings=None, ...@@ -313,12 +317,13 @@ def generate_toolpath(model, tool_settings=None,
return toolpath return toolpath
def _get_pathgenerator_instance(trimesh_model, contour_model, cutter, def _get_pathgenerator_instance(trimesh_model, contour_model, cutter,
pathgenerator, pathprocessor, physics): pathgenerator, pathprocessor, reverse, physics):
if pathgenerator == "DropCutter": if pathgenerator == "DropCutter":
if pathprocessor == "ZigZagCutter": if pathprocessor == "ZigZagCutter":
processor = pycam.PathProcessors.PathAccumulator(zigzag=True) processor = pycam.PathProcessors.PathAccumulator(zigzag=True,
reverse=reverse)
elif pathprocessor == "PathAccumulator": elif pathprocessor == "PathAccumulator":
processor = pycam.PathProcessors.PathAccumulator() processor = pycam.PathProcessors.PathAccumulator(reverse=reverse)
else: else:
return ("Invalid postprocessor (%s) for 'DropCutter': only " \ return ("Invalid postprocessor (%s) for 'DropCutter': only " \
+ "'ZigZagCutter' or 'PathAccumulator' are allowed") \ + "'ZigZagCutter' or 'PathAccumulator' are allowed") \
...@@ -327,15 +332,15 @@ def _get_pathgenerator_instance(trimesh_model, contour_model, cutter, ...@@ -327,15 +332,15 @@ def _get_pathgenerator_instance(trimesh_model, contour_model, cutter,
physics=physics) physics=physics)
elif pathgenerator == "PushCutter": elif pathgenerator == "PushCutter":
if pathprocessor == "PathAccumulator": if pathprocessor == "PathAccumulator":
processor = pycam.PathProcessors.PathAccumulator() processor = pycam.PathProcessors.PathAccumulator(reverse=reverse)
elif pathprocessor == "SimpleCutter": elif pathprocessor == "SimpleCutter":
processor = pycam.PathProcessors.SimpleCutter() processor = pycam.PathProcessors.SimpleCutter(reverse=reverse)
elif pathprocessor == "ZigZagCutter": elif pathprocessor == "ZigZagCutter":
processor = pycam.PathProcessors.ZigZagCutter() processor = pycam.PathProcessors.ZigZagCutter(reverse=reverse)
elif pathprocessor == "PolygonCutter": elif pathprocessor == "PolygonCutter":
processor = pycam.PathProcessors.PolygonCutter() processor = pycam.PathProcessors.PolygonCutter(reverse=reverse)
elif pathprocessor == "ContourCutter": elif pathprocessor == "ContourCutter":
processor = pycam.PathProcessors.ContourCutter() processor = pycam.PathProcessors.ContourCutter(reverse=reverse)
else: else:
return ("Invalid postprocessor (%s) for 'PushCutter' - it should " \ return ("Invalid postprocessor (%s) for 'PushCutter' - it should " \
+ "be one of these: %s") % (processor, PATH_POSTPROCESSORS) + "be one of these: %s") % (processor, PATH_POSTPROCESSORS)
...@@ -343,7 +348,7 @@ def _get_pathgenerator_instance(trimesh_model, contour_model, cutter, ...@@ -343,7 +348,7 @@ def _get_pathgenerator_instance(trimesh_model, contour_model, cutter,
physics=physics) physics=physics)
elif pathgenerator == "EngraveCutter": elif pathgenerator == "EngraveCutter":
if pathprocessor == "SimpleCutter": if pathprocessor == "SimpleCutter":
processor = pycam.PathProcessors.SimpleCutter() processor = pycam.PathProcessors.SimpleCutter(reverse=reverse)
else: else:
return ("Invalid postprocessor (%s) for 'EngraveCutter' - it " \ return ("Invalid postprocessor (%s) for 'EngraveCutter' - it " \
+ "should be one of these: %s") \ + "should be one of these: %s") \
...@@ -353,14 +358,14 @@ def _get_pathgenerator_instance(trimesh_model, contour_model, cutter, ...@@ -353,14 +358,14 @@ def _get_pathgenerator_instance(trimesh_model, contour_model, cutter,
+ "DXF file)." + "DXF file)."
return EngraveCutter.EngraveCutter(cutter, trimesh_model, return EngraveCutter.EngraveCutter(cutter, trimesh_model,
contour_model, processor, physics=physics) contour_model, processor, physics=physics)
elif pathgenerator == "WaterlineCutter": elif pathgenerator == "ContourFollow":
if pathprocessor == "PathAccumulator": if pathprocessor == "PathAccumulator":
processor = pycam.PathProcessors.PathAccumulator() processor = pycam.PathProcessors.PathAccumulator(reverse=reverse)
else: else:
return ("Invalid postprocessor (%s) for 'WaterlineCutter' - it " \ return ("Invalid postprocessor (%s) for 'ContourFollow' - it " \
+ "should be one of these: %s") \ + "should be one of these: %s") \
% (processor, PATH_POSTPROCESSORS) % (processor, PATH_POSTPROCESSORS)
return Waterline.Waterline(cutter, trimesh_model, processor, return ContourFollow.ContourFollow(cutter, trimesh_model, processor,
physics=physics) physics=physics)
else: else:
return "Invalid path generator (%s): not one of %s" \ return "Invalid path generator (%s): not one of %s" \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment