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
* 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
* added optional "orthogonal" view (instead of perspective)
* added a "recent files" item to the file menu
......
......@@ -10,8 +10,8 @@
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="910.52441"
height="2845.2439"
width="967.52997"
height="2821.4348"
id="svg2"
version="1.1"
inkscape:version="0.47 r22583"
......@@ -20,6 +20,67 @@
id="title4292">Sketches for Push-Follow toolpath strategy</title>
<defs
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
id="linearGradient3644">
<stop
......@@ -123,10 +184,17 @@
y1="883.64081"
x2="381.3631"
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
inkscape:collect="always"
xlink:href="#linearGradient3644"
id="linearGradient4240"
id="linearGradient5778"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-274.73686,-694.75982)"
x1="287.60236"
......@@ -141,9 +209,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35306407"
inkscape:cx="379.0174"
inkscape:cy="872.93317"
inkscape:zoom="0.499308"
inkscape:cx="898.5398"
inkscape:cy="243.40248"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
......@@ -160,8 +228,8 @@
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:object-paths="true"
inkscape:snap-intersection-paths="true"
inkscape:object-nodes="false"
inkscape:snap-intersection-paths="false"
inkscape:object-nodes="true"
inkscape:snap-smooth-nodes="false"
inkscape:snap-nodes="false">
<inkscape:grid
......@@ -298,45 +366,6 @@
x="-1419.0509"
sodipodi:role="line">above the cutter level.</tspan></text>
</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
id="g4282"
inkscape:export-filename="/home/lars/subversion/pycam/trunk/artwork/pics/case2a.png"
......@@ -394,7 +423,7 @@
sodipodi:nodetypes="csaacccc"
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"
style="fill:url(#linearGradient4240);fill-opacity:1;stroke:none" />
style="fill:url(#linearGradient5778);fill-opacity:1;stroke:none" />
<text
id="text3660"
y="478.15857"
......@@ -517,16 +546,261 @@
<text
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"
x="-1195.6948"
y="2281.3574"
x="-1207.0242"
y="2207.7163"
id="text2894"><tspan
sodipodi:role="line"
id="tspan2896"
x="-1195.6948"
y="2281.3574">see the related blog posting:</tspan><tspan
x="-1207.0242"
y="2207.7163">see the related blog posting:</tspan><tspan
sodipodi:role="line"
x="-1195.6948"
y="2316.3574"
x="-1207.0242"
y="2242.7163"
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>
</svg>
......@@ -414,10 +414,12 @@ if __name__ == "__main__":
"contour": "ContourCutter",
"polygon": "PolygonCutter",
}[opts.process_path_postprocessor]
# TODO: add the miling_style option
tps.set_process_settings(path_generator, postprocessor,
opts.process_path_direction, opts.process_material_allowance,
opts.safety_height, opts.process_overlap_percent / 100.0,
opts.process_step_down, opts.process_engrave_offset)
opts.process_path_direction, reverse=False,
material_allowance=opts.process_material_allowance,
overlap=opts.process_overlap_percent / 100.0,
step_down=opts.process_step_down, engrave_offset=opts.process_engrave_offset)
# set locations of external programs
program_locations = {}
if opts.external_program_inkscape:
......
......@@ -2427,10 +2427,8 @@ This can be useful if the imported model is technically broken (sometimes this h
</packing>
</child>
<child>
<object class="GtkTable" id="table6">
<object class="GtkHBox" id="hbox29">
<property name="visible">True</property>
<property name="n_rows">3</property>
<property name="n_columns">3</property>
<child>
<object class="GtkFrame" id="frame8">
<property name="visible">True</property>
......@@ -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="left_padding">12</property>
<child>
<object class="GtkVBox" id="vbox15">
<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="DropCutter">
<property name="label" translatable="yes">Drop Cutter</property>
<object class="GtkRadioButton" id="PushRemoveStrategy">
<property name="label" translatable="yes">Slice removal</property>
<property name="visible">True</property>
<property name="can_focus">True</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.
This is suitable for finishing processes after removing the material above.</property>
<property name="active">True</property>
<property name="tooltip_text" translatable="yes">Slice the model at different levels of z. Remove all material along a fixed grid.
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="draw_indicator">True</property>
</object>
<packing>
......@@ -2462,16 +2459,15 @@ This is suitable for finishing processes after removing the material above.</pro
</packing>
</child>
<child>
<object class="GtkRadioButton" id="PushCutter">
<property name="label" translatable="yes">Push Cutter</property>
<object class="GtkRadioButton" id="ContourPolygonStrategy">
<property name="label" translatable="yes">Contour (polygon)</property>
<property name="visible">True</property>
<property name="can_focus">True</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.
This is suitable for roughly processing the material.
It will spare some material close to the model (depending on the "step down" value).</property>
<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.
The algorithm does not work properly under all circumstances. Maybe you want try the new (experimental) "Contour (follow)" strategy instead.</property>
<property name="draw_indicator">True</property>
<property name="group">DropCutter</property>
<property name="group">PushRemoveStrategy</property>
</object>
<packing>
<property name="expand">False</property>
......@@ -2479,14 +2475,16 @@ It will spare some material close to the model (depending on the "step down" val
</packing>
</child>
<child>
<object class="GtkRadioButton" id="EngraveCutter">
<property name="label" translatable="yes">Engraving</property>
<object class="GtkRadioButton" id="ContourFollowStrategy">
<property name="label" translatable="yes">Contour (follow)</property>
<property name="visible">True</property>
<property name="can_focus">True</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="group">DropCutter</property>
<property name="group">PushRemoveStrategy</property>
</object>
<packing>
<property name="expand">False</property>
......@@ -2494,85 +2492,36 @@ It will spare some material close to the model (depending on the "step down" val
</packing>
</child>
<child>
<object class="GtkRadioButton" id="WaterlineCutter">
<property name="label" translatable="yes">Waterlines</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>
<object class="GtkRadioButton" id="SurfaceStrategy">
<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="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="draw_indicator">True</property>
<property name="group">PushRemoveStrategy</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</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>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="PathDirectionXY">
<property name="label" translatable="yes">xy</property>
<object class="GtkRadioButton" id="EngraveStrategy">
<property name="label" translatable="yes">Engraving</property>
<property name="visible">True</property>
<property name="can_focus">True</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="group">PathDirectionX</property>
<property name="group">PushRemoveStrategy</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
<property name="position">4</property>
</packing>
</child>
</object>
......@@ -2580,121 +2529,27 @@ It will spare some material close to the model (depending on the "step down" val
</object>
</child>
<child type="label">
<object class="GtkLabel" id="PathDirectionLabel">
<object class="GtkLabel" id="ToolpathStrategy">
<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>
</object>
</child>
</object>
<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>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="ZigZagCutter">
<property name="label" translatable="yes">ZigZag Cutter</property>
<object class="GtkVSeparator" id="vseparator9">
<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>
<property name="orientation">vertical</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</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>
<object class="GtkFrame" id="PathSettingsFrame">
<property name="visible">True</property>
......@@ -2726,9 +2581,9 @@ It will spare some material close to the model (depending on the "step down" val
<object class="GtkSpinButton" id="OverlapPercentControl">
<property name="visible">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.
Use high values for fine-grained toolpaths.</property>
<property name="invisible_char">&#x2022;</property>
<property name="tooltip_text" translatable="yes">Overlapping percentage for grid-based toolpath strategies.
Higher values increase accuracy and processing time.</property>
<property name="invisible_char">&#x25CF;</property>
<property name="adjustment">OverlapPercentValue</property>
<property name="numeric">True</property>
</object>
......@@ -2757,11 +2612,9 @@ Use high values for fine-grained toolpaths.</property>
<property name="visible">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.
This value should be greater than zero for the first roughing operation.
The last finishing operation should have zero material allowance.
This operation is not available for engraving.</property>
<property name="invisible_char">&#x2022;</property>
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.</property>
<property name="invisible_char">&#x25CF;</property>
<property name="adjustment">MaterialAllowanceValue</property>
<property name="digits">2</property>
<property name="numeric">True</property>
......@@ -2779,8 +2632,8 @@ This operation is not available for engraving.</property>
<object class="GtkSpinButton" id="MaxStepDownControl">
<property name="visible">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="invisible_char">&#x2022;</property>
<property name="tooltip_text" translatable="yes">The maximum height of each layer for all slicing toolpath strategies.</property>
<property name="invisible_char">&#x25CF;</property>
<property name="adjustment">MaxStepDownValue</property>
<property name="digits">2</property>
<property name="numeric">True</property>
......@@ -2824,6 +2677,8 @@ This operation is not available for engraving.</property>
<object class="GtkSpinButton" id="EngraveOffsetControl">
<property name="visible">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="adjustment">EngraveOffsetValue</property>
<property name="digits">2</property>
......@@ -2851,10 +2706,14 @@ This operation is not available for engraving.</property>
</child>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
</packing>
</child>
<child>
......@@ -2862,19 +2721,86 @@ This operation is not available for engraving.</property>
<property name="visible">True</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="expand">False</property>
<property name="position">4</property>
</packing>
</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="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>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="position">0</property>
</packing>
</child>
<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>
</child>
<child>
......@@ -2883,28 +2809,94 @@ This operation is not available for engraving.</property>
<property name="orientation">vertical</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</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="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>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</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>
<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>
<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>
</child>
</object>
......
......@@ -545,17 +545,20 @@ class ProjectGui:
self.gui.get_object(name).connect("clicked", 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
for objname in ("PathAccumulator", "SimpleCutter", "ZigZagCutter",
"PolygonCutter", "ContourCutter", "DropCutter", "PushCutter",
"EngraveCutter", "WaterlineCutter", "PathDirectionX",
"PathDirectionY", "PathDirectionXY", "SettingEnableODE"):
self.gui.get_object(objname).connect("toggled", self.update_process_controls)
if objname != "SettingEnableODE":
self.gui.get_object(objname).connect("toggled", self.handle_process_settings_change)
for objname in ("PushRemoveStrategy", "ContourPolygonStrategy",
"ContourFollowStrategy", "SurfaceStrategy",
"EngraveStrategy", "GridDirectionX",
"GridDirectionY", "GridDirectionXY"):
self.gui.get_object(objname).connect("toggled",
self.update_process_controls)
self.gui.get_object(objname).connect("toggled",
self.handle_process_settings_change)
for objname in ("OverlapPercentControl", "MaterialAllowanceControl",
"MaxStepDownControl", "EngraveOffsetControl"):
self.gui.get_object(objname).connect("value-changed", self.handle_process_settings_change)
self.gui.get_object("ProcessSettingName").connect("changed", self.handle_process_settings_change)
self.gui.get_object(objname).connect("value-changed",
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
def get_current_item(table, item_list):
index = self._treeview_get_active_index(table, item_list)
......@@ -970,7 +973,6 @@ class ProjectGui:
self.gui.get_object("SupportGridPositionManualShiftBox").set_sensitive(
self.grid_adjustment_selector.get_active() >= 0)
def update_support_grid_manual_adjust(self, widget=None, data1=None,
data2=None):
new_value = self.grid_adjustment_value.get_value()
......@@ -1164,13 +1166,14 @@ class ProjectGui:
tool_desc += "(%.4f%s / %.4f%s)" % ( 2 * tool["tool_radius"], unit, 2 * tool["torus_radius"], unit)
lines.append(tool_desc)
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"]))
if process["path_generator"] == "EngraveCutter":
lines.append("Strategy: %s" % process["path_strategy"])
if process["path_strategy"] == "EngraveStrategy":
lines.append("Engrave offset: %.3f" % process["engrave_offset"])
else:
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))
if process["path_generator"] != "DropCutter":
if process["path_strategy"] != "SurfaceStrategy":
lines.append("Maximum step down: %.2f%s" % (process["step_down"], unit))
else:
lines.append("No task selected")
......@@ -1308,45 +1311,38 @@ class ProjectGui:
# possible dependencies of the DropCutter
get_obj = self.gui.get_object
cutter_name = None
for one_cutter in ("DropCutter", "PushCutter", "EngraveCutter",
"WaterlineCutter"):
for one_cutter in ("PushRemoveStrategy", "ContourPolygonStrategy",
"ContourFollowStrategy", "SurfaceStrategy", "EngraveStrategy"):
if get_obj(one_cutter).get_active():
cutter_name = one_cutter
if cutter_name == "DropCutter":
if get_obj("PathDirectionXY").get_active():
get_obj("PathDirectionX").set_active(True)
if not (get_obj("PathAccumulator").get_active() or get_obj("ZigZagCutter").get_active()):
get_obj("PathAccumulator").set_active(True)
elif cutter_name == "PushCutter":
if not (get_obj("SimpleCutter").get_active() \
or get_obj("PolygonCutter").get_active() \
or get_obj("ContourCutter").get_active()):
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",
break
else:
raise ValueError("Invalid cutter selected")
if cutter_name == "SurfaceStrategy" \
and get_obj("GridDirectionXY").get_active():
get_obj("GridDirectionX").set_active(True)
all_controls = ("GridDirectionX", "GridDirectionY", "GridDirectionXY",
"MillingStyleConventional", "MillingStyleClimb",
"MillingStyleIgnore", "MaxStepDownControl",
"MaterialAllowanceControl", "OverlapPercentControl",
"EngraveOffsetControl")
active_controls = {
"DropCutter": ("PathAccumulator", "ZigZagCutter", "PathDirectionX",
"PathDirectionY", "MaterialAllowanceControl",
"OverlapPercentControl"),
"PushCutter": ("SimpleCutter", "PolygonCutter", "ContourCutter",
"PathDirectionX", "PathDirectionY", "PathDirectionXY",
"PushRemoveStrategy": ("GridDirectionX", "GridDirectionY",
"GridDirectionXY", "MaxStepDownControl",
"MaterialAllowanceControl", "OverlapPercentControl"),
"ContourPolygonStrategy": ("GridDirectionX", "GridDirectionY",
"GridDirectionXY", "MillingStyleConventional",
"MillingStyleClimb", "MillingStyleIgnore",
"MaxStepDownControl", "MaterialAllowanceControl",
"OverlapPercentControl"),
"EngraveCutter": ("SimpleCutter", "MaxStepDownControl",
"EngraveOffsetControl"),
"WaterlineCutter": ("PathAccumulator", "MaterialAllowanceControl",
"ContourFollowStrategy": ("MillingStyleConventional",
"MillingStyleClimb", "MillingStyleIgnore",
"MaxStepDownControl"),
"SurfaceStrategy": ("GridDirectionX", "GridDirectionY",
"MillingStyleConventional", "MillingStyleClimb",
"MillingStyleIgnore", "MaterialAllowanceControl",
"OverlapPercentControl"),
"EngraveStrategy": ("MaxStepDownControl", "EngraveOffsetControl"),
}
for one_control in all_controls:
get_obj(one_control).set_sensitive(one_control in active_controls[cutter_name])
......@@ -2300,28 +2296,71 @@ class ProjectGui:
self.update_bounds_table(self.bounds_list.index(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):
if settings is None:
settings = {}
settings["name"] = self.gui.get_object("ProcessSettingName").get_text()
# path generator
def get_path_generator():
for name in ("DropCutter", "PushCutter", "EngraveCutter",
"WaterlineCutter"):
if self.gui.get_object(name).get_active():
return name
settings["path_generator"] = get_path_generator()
for key in ("PushRemoveStrategy", "ContourPolygonStrategy",
"ContourFollowStrategy", "SurfaceStrategy", "EngraveStrategy"):
if self.gui.get_object(key).get_active():
strategy = key
break
settings["path_strategy"] = strategy
# path direction
def get_path_direction():
for obj, value in (("PathDirectionX", "x"), ("PathDirectionY", "y"), ("PathDirectionXY", "xy")):
for obj, value in (("GridDirectionX", "x"), ("GridDirectionY", "y"),
("GridDirectionXY", "xy")):
if self.gui.get_object(obj).get_active():
return value
settings["path_direction"] = get_path_direction()
def get_path_postprocessor():
for name in ("PathAccumulator", "SimpleCutter", "ZigZagCutter", "PolygonCutter", "ContourCutter"):
if self.gui.get_object(name).get_active():
return name
settings["path_postprocessor"] = get_path_postprocessor()
direction = value
break
# milling style
for obj, value in (("MillingStyleConventional", "conventional"),
("MillingStyleClimb", "climb"),
("MillingStyleIgnore", "ignore")):
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"),
("MaterialAllowanceControl", "material_allowance"),
("MaxStepDownControl", "step_down"),
......@@ -2331,20 +2370,24 @@ class ProjectGui:
def _put_process_settings_to_gui(self, settings):
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
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:
self.gui.get_object(obj).set_active(True)
return
set_path_direction(settings["path_direction"])
# path postprocessor
def set_path_postprocessor(value):
def set_path_strategy(value):
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"),
("MaterialAllowanceControl", "material_allowance"),
("MaxStepDownControl", "step_down"),
......@@ -2791,12 +2834,15 @@ class ProjectGui:
# unit size
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
toolpath_settings.set_process_settings(
process_settings["path_generator"],
process_settings["path_postprocessor"],
process_settings["path_direction"],
process_settings["material_allowance"],
generator, postprocessor, process_settings["path_direction"],
reverse, process_settings["material_allowance"],
process_settings["overlap_percent"] / 100.0,
process_settings["step_down"],
process_settings["engrave_offset"])
......
......@@ -130,11 +130,11 @@ speed: 1000
[ProcessDefault]
name: Remove material
path_direction: x
engrave_offset: 0.0
path_generator: PushCutter
path_postprocessor: PolygonCutter
material_allowance: 0.5
path_strategy: PushCutter
path_direction: x
milling_style: ignore
material_allowance: 0.0
step_down: 3.0
overlap_percent: 0
......@@ -180,37 +180,35 @@ tool_radius: 0.5
[ProcessDefault]
path_direction: x
path_strategy: SurfaceStrategy
milling_style: ignore
engrave_offset: 0.0
step_down: 3.0
material_allowance: 0.0
[Process0]
name: Remove material
path_generator: PushCutter
path_postprocessor: PolygonCutter
path_strategy: PushRemoveStrategy
material_allowance: 0.5
step_down: 3.0
overlap_percent: 0
[Process1]
name: Carve contour
path_generator: PushCutter
path_postprocessor: ContourCutter
path_strategy: ContourFollowStrategy
material_allowance: 0.2
step_down: 1.5
overlap_percent: 20
[Process2]
name: Cleanup
path_generator: DropCutter
path_postprocessor: ZigZagCutter
path_strategy: SurfaceStrategy
material_allowance: 0.0
step_down: 1.0
overlap_percent: 60
[Process3]
name: Gravure
path_generator: EngraveCutter
path_postprocessor: SimpleCutter
material_allowance: 0.0
path_strategy: EngraveStrategy
step_down: 1.0
overlap_percent: 50
......@@ -267,9 +265,9 @@ process: 3
"torus_radius": float,
"speed": float,
"feedrate": float,
"path_strategy": str,
"path_direction": str,
"path_generator": str,
"path_postprocessor": str,
"milling_style": str,
"material_allowance": float,
"overlap_percent": int,
"step_down": float,
......@@ -290,8 +288,8 @@ process: 3
CATEGORY_KEYS = {
"tool": ("name", "shape", "tool_radius", "torus_radius", "feedrate",
"speed"),
"process": ("name", "path_generator", "path_postprocessor",
"path_direction", "material_allowance",
"process": ("name", "path_strategy", "path_direction",
"milling_style", "material_allowance",
"overlap_percent", "step_down", "engrave_offset"),
"bounds": ("name", "type", "x_low", "x_high", "y_low",
"y_high", "z_low", "z_high"),
......@@ -588,6 +586,7 @@ class ToolpathSettings:
"generator": str,
"postprocessor": str,
"path_direction": str,
"reverse": bool,
"material_allowance": float,
"overlap": float,
"step_down": float,
......@@ -699,12 +698,16 @@ class ToolpathSettings:
return "mm"
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):
# TODO: this hack should be somewhere else, I guess
if generator in ("ContourFollow", "EngraveCutter"):
material_allowance = 0.0
self.process_settings = {
"generator": generator,
"postprocessor": postprocessor,
"path_direction": path_direction,
"reverse": reverse,
"material_allowance": material_allowance,
"overlap": overlap,
"step_down": step_down,
......
......@@ -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/>.
"""
from pycam.PathGenerators import DropCutter, PushCutter, EngraveCutter, Waterline
from pycam.PathGenerators import DropCutter, PushCutter, EngraveCutter, \
ContourFollow
from pycam.Geometry.utils import number
import pycam.PathProcessors
import pycam.Cutters
......@@ -33,7 +34,8 @@ log = pycam.Utils.log.get_logger()
DIRECTIONS = frozenset(("x", "y", "xy"))
PATH_GENERATORS = frozenset(("DropCutter", "PushCutter", "EngraveCutter", "WaterlineCutter"))
PATH_GENERATORS = frozenset(("DropCutter", "PushCutter", "EngraveCutter",
"ContourFollow"))
PATH_POSTPROCESSORS = frozenset(("ContourCutter", "PathAccumulator",
"PolygonCutter", "SimpleCutter", "ZigZagCutter"))
CALCULATION_BACKENDS = frozenset((None, "ODE"))
......@@ -48,6 +50,7 @@ def generate_toolpath_from_settings(model, tp_settings, callback=None):
return generate_toolpath(model, tp_settings.get_tool_settings(),
bounds_low, bounds_high, process["path_direction"],
process["generator"], process["postprocessor"],
process["reverse"],
process["material_allowance"], process["overlap"],
process["step_down"], process["engrave_offset"],
grid["type"], grid["distance_x"], grid["distance_y"],
......@@ -59,6 +62,7 @@ def generate_toolpath_from_settings(model, tp_settings, callback=None):
def generate_toolpath(model, tool_settings=None,
bounds_low=None, bounds_high=None, direction="x",
path_generator="DropCutter", path_postprocessor="ZigZagCutter",
reverse=False,
material_allowance=0, overlap=0, step_down=0, engrave_offset=0,
support_grid_type=None, support_grid_distance_x=None,
support_grid_distance_y=None, support_grid_thickness=None,
......@@ -255,7 +259,7 @@ def generate_toolpath(model, tool_settings=None,
for next_model in trimesh_models[1:]:
combined_models += next_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):
return generator
if (overlap < 0) or (overlap >= 1):
......@@ -298,7 +302,7 @@ def generate_toolpath(model, tool_settings=None,
dz = maxz - minz
toolpath = generator.GenerateToolPath(minz, maxz, stepping, dz,
callback)
elif path_generator == "WaterlineCutter":
elif path_generator == "ContourFollow":
if step_down > 0:
dz = step_down
else:
......@@ -313,12 +317,13 @@ def generate_toolpath(model, tool_settings=None,
return toolpath
def _get_pathgenerator_instance(trimesh_model, contour_model, cutter,
pathgenerator, pathprocessor, physics):
pathgenerator, pathprocessor, reverse, physics):
if pathgenerator == "DropCutter":
if pathprocessor == "ZigZagCutter":
processor = pycam.PathProcessors.PathAccumulator(zigzag=True)
processor = pycam.PathProcessors.PathAccumulator(zigzag=True,
reverse=reverse)
elif pathprocessor == "PathAccumulator":
processor = pycam.PathProcessors.PathAccumulator()
processor = pycam.PathProcessors.PathAccumulator(reverse=reverse)
else:
return ("Invalid postprocessor (%s) for 'DropCutter': only " \
+ "'ZigZagCutter' or 'PathAccumulator' are allowed") \
......@@ -327,15 +332,15 @@ def _get_pathgenerator_instance(trimesh_model, contour_model, cutter,
physics=physics)
elif pathgenerator == "PushCutter":
if pathprocessor == "PathAccumulator":
processor = pycam.PathProcessors.PathAccumulator()
processor = pycam.PathProcessors.PathAccumulator(reverse=reverse)
elif pathprocessor == "SimpleCutter":
processor = pycam.PathProcessors.SimpleCutter()
processor = pycam.PathProcessors.SimpleCutter(reverse=reverse)
elif pathprocessor == "ZigZagCutter":
processor = pycam.PathProcessors.ZigZagCutter()
processor = pycam.PathProcessors.ZigZagCutter(reverse=reverse)
elif pathprocessor == "PolygonCutter":
processor = pycam.PathProcessors.PolygonCutter()
processor = pycam.PathProcessors.PolygonCutter(reverse=reverse)
elif pathprocessor == "ContourCutter":
processor = pycam.PathProcessors.ContourCutter()
processor = pycam.PathProcessors.ContourCutter(reverse=reverse)
else:
return ("Invalid postprocessor (%s) for 'PushCutter' - it should " \
+ "be one of these: %s") % (processor, PATH_POSTPROCESSORS)
......@@ -343,7 +348,7 @@ def _get_pathgenerator_instance(trimesh_model, contour_model, cutter,
physics=physics)
elif pathgenerator == "EngraveCutter":
if pathprocessor == "SimpleCutter":
processor = pycam.PathProcessors.SimpleCutter()
processor = pycam.PathProcessors.SimpleCutter(reverse=reverse)
else:
return ("Invalid postprocessor (%s) for 'EngraveCutter' - it " \
+ "should be one of these: %s") \
......@@ -353,14 +358,14 @@ def _get_pathgenerator_instance(trimesh_model, contour_model, cutter,
+ "DXF file)."
return EngraveCutter.EngraveCutter(cutter, trimesh_model,
contour_model, processor, physics=physics)
elif pathgenerator == "WaterlineCutter":
elif pathgenerator == "ContourFollow":
if pathprocessor == "PathAccumulator":
processor = pycam.PathProcessors.PathAccumulator()
processor = pycam.PathProcessors.PathAccumulator(reverse=reverse)
else:
return ("Invalid postprocessor (%s) for 'WaterlineCutter' - it " \
return ("Invalid postprocessor (%s) for 'ContourFollow' - it " \
+ "should be one of these: %s") \
% (processor, PATH_POSTPROCESSORS)
return Waterline.Waterline(cutter, trimesh_model, processor,
return ContourFollow.ContourFollow(cutter, trimesh_model, processor,
physics=physics)
else:
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