Drilling handles multiple locations
Jog rates started Automatically create default tool in new job.
This commit is contained in:
parent
e790963a45
commit
2f04ea9586
|
@ -5,6 +5,7 @@
|
|||
<file>icons/Path-Compound.svg</file>
|
||||
<file>icons/Path-Shape.svg</file>
|
||||
<file>icons/Path-Profile.svg</file>
|
||||
<file>icons/Path-Contour.svg</file>
|
||||
<file>icons/Path-Pocket.svg</file>
|
||||
<file>icons/Path-Drilling.svg</file>
|
||||
<file>icons/Path-Job.svg</file>
|
||||
|
|
565
src/Mod/Path/Gui/Resources/icons/Path-Contour.svg
Normal file
565
src/Mod/Path/Gui/Resources/icons/Path-Contour.svg
Normal file
|
@ -0,0 +1,565 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
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="64px"
|
||||
height="64px"
|
||||
id="svg2816"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="Path-Profile.svg">
|
||||
<defs
|
||||
id="defs2818">
|
||||
<linearGradient
|
||||
id="linearGradient4513">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4515" />
|
||||
<stop
|
||||
style="stop-color:#999999;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4517" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3681">
|
||||
<stop
|
||||
id="stop3697"
|
||||
offset="0"
|
||||
style="stop-color:#fff110;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#cf7008;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3685" />
|
||||
</linearGradient>
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 32 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="64 : 32 : 1"
|
||||
inkscape:persp3d-origin="32 : 21.333333 : 1"
|
||||
id="perspective2824" />
|
||||
<inkscape:perspective
|
||||
id="perspective3622"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3622-9"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3653"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3675"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3697"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3720"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3742"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3764"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3785"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3806"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3806-3"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3835"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3614"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3614-8"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3643"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3643-3"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3672"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3672-5"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3701"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3701-8"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective3746"
|
||||
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" />
|
||||
<pattern
|
||||
patternTransform="matrix(0.67643728,-0.81829155,2.4578314,1.8844554,-26.450606,18.294947)"
|
||||
id="pattern5231"
|
||||
xlink:href="#Strips1_1-4"
|
||||
inkscape:collect="always" />
|
||||
<inkscape:perspective
|
||||
id="perspective5224"
|
||||
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" />
|
||||
<pattern
|
||||
inkscape:stockid="Stripes 1:1"
|
||||
id="Strips1_1-4"
|
||||
patternTransform="matrix(0.66772843,-1.0037085,2.4261878,2.3114548,3.4760987,3.534923)"
|
||||
height="1"
|
||||
width="2"
|
||||
patternUnits="userSpaceOnUse"
|
||||
inkscape:collect="always">
|
||||
<rect
|
||||
id="rect4483-4"
|
||||
height="2"
|
||||
width="1"
|
||||
y="-0.5"
|
||||
x="0"
|
||||
style="fill:black;stroke:none" />
|
||||
</pattern>
|
||||
<inkscape:perspective
|
||||
id="perspective5224-9"
|
||||
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" />
|
||||
<pattern
|
||||
patternTransform="matrix(0.66772843,-1.0037085,2.4261878,2.3114548,39.618381,8.9692804)"
|
||||
id="pattern5231-4"
|
||||
xlink:href="#Strips1_1-6"
|
||||
inkscape:collect="always" />
|
||||
<inkscape:perspective
|
||||
id="perspective5224-3"
|
||||
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" />
|
||||
<pattern
|
||||
inkscape:stockid="Stripes 1:1"
|
||||
id="Strips1_1-6"
|
||||
patternTransform="matrix(0.66772843,-1.0037085,2.4261878,2.3114548,3.4760987,3.534923)"
|
||||
height="1"
|
||||
width="2"
|
||||
patternUnits="userSpaceOnUse"
|
||||
inkscape:collect="always">
|
||||
<rect
|
||||
id="rect4483-0"
|
||||
height="2"
|
||||
width="1"
|
||||
y="-0.5"
|
||||
x="0"
|
||||
style="fill:black;stroke:none" />
|
||||
</pattern>
|
||||
<pattern
|
||||
patternTransform="matrix(0.66513382,-1.0631299,2.4167603,2.4482973,-49.762569,2.9546807)"
|
||||
id="pattern5296"
|
||||
xlink:href="#pattern5231-3"
|
||||
inkscape:collect="always" />
|
||||
<inkscape:perspective
|
||||
id="perspective5288"
|
||||
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" />
|
||||
<pattern
|
||||
patternTransform="matrix(0.66772843,-1.0037085,2.4261878,2.3114548,-26.336284,10.887197)"
|
||||
id="pattern5231-3"
|
||||
xlink:href="#Strips1_1-4-3"
|
||||
inkscape:collect="always" />
|
||||
<pattern
|
||||
inkscape:stockid="Stripes 1:1"
|
||||
id="Strips1_1-4-3"
|
||||
patternTransform="matrix(0.66772843,-1.0037085,2.4261878,2.3114548,3.4760987,3.534923)"
|
||||
height="1"
|
||||
width="2"
|
||||
patternUnits="userSpaceOnUse"
|
||||
inkscape:collect="always">
|
||||
<rect
|
||||
id="rect4483-4-6"
|
||||
height="2"
|
||||
width="1"
|
||||
y="-0.5"
|
||||
x="0"
|
||||
style="fill:black;stroke:none" />
|
||||
</pattern>
|
||||
<pattern
|
||||
patternTransform="matrix(0.42844886,-0.62155849,1.5567667,1.431396,27.948414,13.306456)"
|
||||
id="pattern5330"
|
||||
xlink:href="#Strips1_1-9"
|
||||
inkscape:collect="always" />
|
||||
<inkscape:perspective
|
||||
id="perspective5323"
|
||||
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" />
|
||||
<pattern
|
||||
inkscape:stockid="Stripes 1:1"
|
||||
id="Strips1_1-9"
|
||||
patternTransform="matrix(0.66772843,-1.0037085,2.4261878,2.3114548,3.4760987,3.534923)"
|
||||
height="1"
|
||||
width="2"
|
||||
patternUnits="userSpaceOnUse"
|
||||
inkscape:collect="always">
|
||||
<rect
|
||||
id="rect4483-3"
|
||||
height="2"
|
||||
width="1"
|
||||
y="-0.5"
|
||||
x="0"
|
||||
style="fill:black;stroke:none" />
|
||||
</pattern>
|
||||
<inkscape:perspective
|
||||
id="perspective5361"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective5383"
|
||||
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" />
|
||||
<inkscape:perspective
|
||||
id="perspective5411"
|
||||
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="#linearGradient3681"
|
||||
id="linearGradient3687"
|
||||
x1="37.89756"
|
||||
y1="41.087898"
|
||||
x2="4.0605712"
|
||||
y2="40.168594"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(127.27273,-51.272729)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3681"
|
||||
id="linearGradient3695"
|
||||
x1="37.894287"
|
||||
y1="40.484772"
|
||||
x2="59.811455"
|
||||
y2="43.558987"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(127.27273,-51.272729)" />
|
||||
<linearGradient
|
||||
id="linearGradient3681-3">
|
||||
<stop
|
||||
id="stop3697-3"
|
||||
offset="0"
|
||||
style="stop-color:#fff110;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#cf7008;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3685-4" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="43.558987"
|
||||
x2="59.811455"
|
||||
y1="40.484772"
|
||||
x1="37.894287"
|
||||
gradientTransform="translate(-37.00068,-20.487365)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3608"
|
||||
xlink:href="#linearGradient3681-3"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient4513-2">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4515-2" />
|
||||
<stop
|
||||
style="stop-color:#999999;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4517-4" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="23.634638"
|
||||
fy="7.9319997"
|
||||
fx="32.151962"
|
||||
cy="7.9319997"
|
||||
cx="32.151962"
|
||||
gradientTransform="matrix(1,0,0,1.1841158,-8.5173246,-3.4097568)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient4538"
|
||||
xlink:href="#linearGradient4513-2"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient4513-1">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4515-8" />
|
||||
<stop
|
||||
style="stop-color:#999999;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4517-6" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="23.634638"
|
||||
fy="7.9319997"
|
||||
fx="32.151962"
|
||||
cy="7.9319997"
|
||||
cx="32.151962"
|
||||
gradientTransform="matrix(1,0,0,1.1841158,-8.5173246,-3.4097568)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient4538-6"
|
||||
xlink:href="#linearGradient4513-1"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient4513-1-3">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4515-8-7" />
|
||||
<stop
|
||||
style="stop-color:#999999;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4517-6-5" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="23.634638"
|
||||
fy="35.869175"
|
||||
fx="32.151962"
|
||||
cy="35.869175"
|
||||
cx="32.151962"
|
||||
gradientTransform="matrix(0.39497909,0,0,1.1841158,-2.716491,-26.067007)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient3069"
|
||||
xlink:href="#linearGradient4513-1-3"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient4513-1-2">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4515-8-6" />
|
||||
<stop
|
||||
style="stop-color:#999999;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4517-6-6" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="23.634638"
|
||||
fy="35.869175"
|
||||
fx="32.151962"
|
||||
cy="35.869175"
|
||||
cx="32.151962"
|
||||
gradientTransform="matrix(0.39497909,0,0,1.1841158,-2.716491,-26.067007)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient3102"
|
||||
xlink:href="#linearGradient4513-1-2"
|
||||
inkscape:collect="always" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4513-1"
|
||||
id="radialGradient3132"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.39497909,0,0,1.1841158,41.188465,-8.5177184)"
|
||||
cx="32.151962"
|
||||
cy="27.950663"
|
||||
fx="32.151962"
|
||||
fy="27.950663"
|
||||
r="23.634638" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="7.7781745"
|
||||
inkscape:cx="34.742778"
|
||||
inkscape:cy="31.569873"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1053"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata2821">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<path
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:#008b00;stroke-width:7.83772373;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
d="M 47.244934,13.041648 38.27355,11.532207 c -1.462847,-0.245405 -3.091123,-0.08644 -4.656553,0.377436 -2.609051,0.77312 -5.06659,2.419881 -6.488655,4.518817 L 7.215204,45.770884 c -2.275305,3.358296 -0.955689,6.602055 2.945235,7.256469"
|
||||
id="rect3083-0-3-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccsccc" />
|
||||
<path
|
||||
style="fill:#001748;fill-rule:nonzero;stroke:#000000;stroke-width:2.69342875;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;marker:none;filter-blend-mode:normal;filter-gaussianBlur-deviation:0;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 41.878715,34.330654 0.575831,27.30571 16.090909,-24.545455 0.363637,-25.545455 z"
|
||||
id="path4899"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#001748;fill-rule:nonzero;stroke:#000000;stroke-width:2.69342875;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;marker:none;filter-blend-mode:normal;filter-gaussianBlur-deviation:0;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 18.515689,30.416682 -0.333871,31.219682 24.272728,0 -0.575831,-27.30571 z"
|
||||
id="path4892"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:#008b00;stroke-width:7.83772373;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
d="m 10.160439,53.027353 15.662892,2.766775 14.351542,2.41586 c 3.900924,0.654414 8.869902,-1.537955 11.145208,-4.896251 l 6.006956,-8.880001"
|
||||
id="rect3083-0-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#0047ff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.82336974;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
d="M 33.872593,7.732496 18.515689,30.416682 41.878715,34.330654 52.152296,19.197791 49.663299,10.388809 33.872593,7.732496 Z"
|
||||
id="rect3083"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:#008b00;stroke-width:7.83772373;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
d="M 26.439693,2.779375 6.5265548,32.121799 C 4.25125,35.480095 5.5708656,38.723854 9.4717895,39.378268 l 28.7030835,4.83172 c 3.900924,0.654414 8.869902,-1.537955 11.145208,-4.896251 l 6.006956,-8.880001"
|
||||
id="rect3083-0"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
<path
|
||||
style="color:#000000;fill:url(#radialGradient3132);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.97430003;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 44.892106,2.9767791 0,17.4659099 c 0,0 0,1.310757 0,8.59375 l 17.34375,-8.59375 0,-1.90625 0,-15.5596599 z m 17.34375,22.5596599 -17.34375,8.5625 0,7.03125 17.34375,-8.59375 z m 0,12.09375 -14.5625,7.21875 5.9375,3.90625 8.625,-5.71875 z"
|
||||
id="rect4417"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccccccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 21 KiB |
|
@ -106,30 +106,6 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="Tool">
|
||||
<attribute name="icon">
|
||||
<iconset resource="../Path.qrc">
|
||||
<normaloff>:/icons/Path-LoadTool.svg</normaloff>:/icons/Path-LoadTool.svg</iconset>
|
||||
</attribute>
|
||||
<attribute name="label">
|
||||
<string>Tool Settings</string>
|
||||
</attribute>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>10</y>
|
||||
<width>301</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QComboBox" name="cboToolController"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="Depths">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>398</width>
|
||||
<height>534</height>
|
||||
<width>396</width>
|
||||
<height>517</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
|
@ -19,7 +19,7 @@
|
|||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>533</height>
|
||||
<height>400</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -42,8 +42,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>380</width>
|
||||
<height>426</height>
|
||||
<width>378</width>
|
||||
<height>409</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="icon">
|
||||
|
@ -56,6 +56,12 @@
|
|||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QWidget" name="widget_2" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
|
@ -110,7 +116,7 @@
|
|||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QListWidget" name="PathsList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
|
@ -132,11 +138,6 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QGridLayout" name="gridLayout_2"/>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="Stock">
|
||||
|
@ -144,8 +145,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>380</width>
|
||||
<height>426</height>
|
||||
<width>451</width>
|
||||
<height>349</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="icon">
|
||||
|
@ -214,8 +215,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>380</width>
|
||||
<height>426</height>
|
||||
<width>451</width>
|
||||
<height>349</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="icon">
|
||||
|
|
|
@ -6,22 +6,22 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>320</width>
|
||||
<height>503</height>
|
||||
<width>308</width>
|
||||
<height>389</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Tool Control</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="tcoName">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
|
@ -57,7 +57,7 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
|
@ -86,10 +86,38 @@
|
|||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="vertFeed"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Horiz Rapid</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="horizRapid">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Vert Rapid</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="vertRapid">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_3">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
|
|
|
@ -67,13 +67,14 @@ class PathWorkbench (Workbench):
|
|||
from PathScripts import PathRemote
|
||||
from PathScripts import PathSanity
|
||||
from PathScripts import DragknifeDressup
|
||||
from PathScripts import PathContour
|
||||
|
||||
# build commands list
|
||||
projcmdlist = ["Path_Job", "Path_Post", "Path_Inspect", "Path_Sanity"]
|
||||
projcmdlist = ["Path_Job", "Path_Post","Separator", "Path_Inspect", "Path_Sanity"]
|
||||
toolcmdlist = ["Path_ToolLibraryEdit", "Path_LoadTool"]
|
||||
prepcmdlist = ["Path_Plane", "Path_Fixture", "Path_ToolLenOffset", "Path_Comment",
|
||||
"Path_Stop", "Path_FaceProfile", "Path_FacePocket", "Path_Custom", "Path_FromShape"]
|
||||
opcmdlist = ["Path_Profile", "Path_Pocket",
|
||||
opcmdlist = ["Path_Contour", "Path_Profile", "Path_Pocket",
|
||||
"Path_Drilling", "Path_Engrave", "Path_Surfacing"]
|
||||
modcmdlist = ["Path_Copy", "Path_CompoundExtended", "Path_Array",
|
||||
"Path_SimpleCopy" ]
|
||||
|
|
635
src/Mod/Path/PathScripts/PathContour.py
Normal file
635
src/Mod/Path/PathScripts/PathContour.py
Normal file
|
@ -0,0 +1,635 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
import FreeCAD
|
||||
import Path
|
||||
import numpy
|
||||
from FreeCAD import Vector
|
||||
from PathScripts import PathUtils
|
||||
from PathScripts.PathUtils import depth_params
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore, QtGui
|
||||
# Qt tanslation handling
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
def translate(context, text, disambig=None):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def translate(context, text, disambig=None):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
else:
|
||||
def translate(ctxt, txt):
|
||||
return txt
|
||||
|
||||
__title__ = "Path Contour Operation"
|
||||
__author__ = "sliptonic (Brad Collette)"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
"""Path Contour object and FreeCAD command"""
|
||||
|
||||
class ObjectContour:
|
||||
|
||||
def __init__(self, obj):
|
||||
obj.addProperty("App::PropertyBool", "Active", "Path", "Make False, to prevent operation from generating code")
|
||||
obj.addProperty("App::PropertyString", "Comment", "Path", "An optional comment for this Contour")
|
||||
obj.addProperty("App::PropertyString", "UserLabel", "Path", "User Assigned Label")
|
||||
|
||||
obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", "The tool number in use")
|
||||
obj.ToolNumber = (0, 0, 1000, 1)
|
||||
obj.setEditorMode('ToolNumber', 1) # make this read only
|
||||
obj.addProperty("App::PropertyString", "ToolDescription", "Tool", "The description of the tool ")
|
||||
obj.setEditorMode('ToolDescription', 1) # make this read only
|
||||
|
||||
# Depth Properties
|
||||
obj.addProperty("App::PropertyDistance", "ClearanceHeight", "Depth", "The height needed to clear clamps and obstructions")
|
||||
obj.addProperty("App::PropertyDistance", "SafeHeight", "Depth", "Rapid Safety Height between locations.")
|
||||
obj.addProperty("App::PropertyFloatConstraint", "StepDown", "Depth", "Incremental Step Down of Tool")
|
||||
obj.StepDown = (1, 0.01, 1000, 0.5)
|
||||
obj.addProperty("App::PropertyDistance", "StartDepth", "Depth", "Starting Depth of Tool- first cut depth in Z")
|
||||
obj.addProperty("App::PropertyDistance", "FinalDepth", "Depth", "Final Depth of Tool- lowest value in Z")
|
||||
|
||||
# Start Point Properties
|
||||
obj.addProperty("App::PropertyVector", "StartPoint", "Start Point", "The start point of this path")
|
||||
obj.addProperty("App::PropertyBool", "UseStartPoint", "Start Point", "make True, if specifying a Start Point")
|
||||
obj.addProperty("App::PropertyLength", "ExtendAtStart", "Start Point", "extra length of tool path before start of part edge")
|
||||
obj.addProperty("App::PropertyLength", "LeadInLineLen", "Start Point", "length of straight segment of toolpath that comes in at angle to first part edge")
|
||||
|
||||
# End Point Properties
|
||||
obj.addProperty("App::PropertyBool", "UseEndPoint", "End Point", "make True, if specifying an End Point")
|
||||
obj.addProperty("App::PropertyLength", "ExtendAtEnd", "End Point", "extra length of tool path after end of part edge")
|
||||
obj.addProperty("App::PropertyLength", "LeadOutLineLen", "End Point", "length of straight segment of toolpath that comes in at angle to last part edge")
|
||||
obj.addProperty("App::PropertyVector", "EndPoint", "End Point", "The end point of this path")
|
||||
|
||||
# Contour Properties
|
||||
obj.addProperty("App::PropertyEnumeration", "Direction", "Contour", "The direction that the toolpath should go around the part ClockWise CW or CounterClockWise CCW")
|
||||
obj.Direction = ['CW', 'CCW'] # this is the direction that the Contour runs
|
||||
obj.addProperty("App::PropertyBool", "UseComp", "Contour", "make True, if using Cutter Radius Compensation")
|
||||
|
||||
obj.addProperty("App::PropertyDistance", "RollRadius", "Contour", "Radius at start and end")
|
||||
obj.addProperty("App::PropertyDistance", "OffsetExtra", "Contour", "Extra value to stay away from final Contour- good for roughing toolpath")
|
||||
obj.addProperty("App::PropertyLength", "SegLen", "Contour", "Tesselation value for tool paths made from beziers, bsplines, and ellipses")
|
||||
obj.addProperty("App::PropertyAngle", "PlungeAngle", "Contour", "Plunge angle with which the tool enters the work piece. Straight down is 90 degrees, if set small enough or zero the tool will descent exactly one layer depth down per turn")
|
||||
|
||||
obj.addProperty("App::PropertyVectorList", "locs", "Tags", "List of holding tag locations")
|
||||
|
||||
obj.addProperty("App::PropertyFloatList", "angles", "Tags", "List of angles for the holding tags")
|
||||
obj.addProperty("App::PropertyFloatList", "heights", "Tags", "List of angles for the holding tags")
|
||||
obj.addProperty("App::PropertyFloatList", "lengths", "Tags", "List of angles for the holding tags")
|
||||
locations = []
|
||||
angles = []
|
||||
lengths = []
|
||||
heights = []
|
||||
|
||||
obj.locs = locations
|
||||
obj.angles = angles
|
||||
obj.lengths = lengths
|
||||
obj.heights = heights
|
||||
|
||||
obj.Proxy = self
|
||||
|
||||
def __getstate__(self):
|
||||
return None
|
||||
|
||||
def __setstate__(self, state):
|
||||
return None
|
||||
|
||||
def onChanged(self, obj, prop):
|
||||
if prop == "UserLabel":
|
||||
obj.Label = obj.UserLabel + " :" + obj.ToolDescription
|
||||
|
||||
def setDepths(proxy, obj):
|
||||
parentJob = PathUtils.findParentJob(obj)
|
||||
if parentJob is None:
|
||||
return
|
||||
baseobject = parentJob.Base
|
||||
if baseobject is None:
|
||||
return
|
||||
|
||||
try:
|
||||
bb = baseobject.Shape.BoundBox # parent boundbox
|
||||
obj.StartDepth = bb.ZMax
|
||||
obj.ClearanceHeight = bb.ZMax + 5.0
|
||||
obj.SafeHeight = bb.ZMax + 3.0
|
||||
|
||||
except:
|
||||
obj.StartDepth = 5.0
|
||||
obj.ClearanceHeight = 10.0
|
||||
obj.SafeHeight = 8.0
|
||||
|
||||
def _buildPathLibarea(self, obj, edgelist):
|
||||
import PathScripts.PathKurveUtils as PathKurveUtils
|
||||
import math
|
||||
import area
|
||||
output = ""
|
||||
if obj.Comment != "":
|
||||
output += '(' + str(obj.Comment)+')\n'
|
||||
|
||||
if obj.StartPoint and obj.UseStartPoint:
|
||||
startpoint = obj.StartPoint
|
||||
else:
|
||||
startpoint = None
|
||||
|
||||
if obj.EndPoint and obj.UseEndPoint:
|
||||
endpoint = obj.EndPoint
|
||||
else:
|
||||
endpoint = None
|
||||
|
||||
PathKurveUtils.output('mem')
|
||||
PathKurveUtils.feedrate_hv(self.horizFeed, self.vertFeed)
|
||||
|
||||
output = ""
|
||||
output += "G0 Z" + str(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) + "\n"
|
||||
curve = PathKurveUtils.makeAreaCurve(edgelist, obj.Direction, startpoint, endpoint)
|
||||
|
||||
roll_radius = 2.0
|
||||
extend_at_start = 0.0
|
||||
extend_at_end = 0.0
|
||||
lead_in_line_len = 0.0
|
||||
lead_out_line_len = 0.0
|
||||
|
||||
if obj.UseComp is False:
|
||||
side = 'On'
|
||||
else:
|
||||
if obj.Direction == 'CW':
|
||||
side = 'Left'
|
||||
else:
|
||||
side = 'Right'
|
||||
|
||||
PathKurveUtils.clear_tags()
|
||||
for i in range(len(obj.locs)):
|
||||
tag = obj.locs[i]
|
||||
h = obj.heights[i]
|
||||
l = obj.lengths[i]
|
||||
a = math.radians(obj.angles[i])
|
||||
PathKurveUtils.add_tag(area.Point(tag.x, tag.y), l, a, h)
|
||||
|
||||
depthparams = depth_params(
|
||||
obj.ClearanceHeight.Value,
|
||||
obj.SafeHeight.Value, obj.StartDepth.Value, obj.StepDown, 0.0,
|
||||
obj.FinalDepth.Value, None)
|
||||
|
||||
PathKurveUtils.profile2(
|
||||
curve, side, self.radius, self.vertFeed, self.horizFeed,
|
||||
self.vertRapid, self.horizRapid, obj.OffsetExtra.Value, roll_radius,
|
||||
None, None, depthparams, extend_at_start, extend_at_end,
|
||||
lead_in_line_len, lead_out_line_len)
|
||||
|
||||
output += PathKurveUtils.retrieve_gcode()
|
||||
return output
|
||||
|
||||
def execute(self, obj):
|
||||
import Part # math #DraftGeomUtils
|
||||
output = ""
|
||||
|
||||
toolLoad = PathUtils.getLastToolLoad(obj)
|
||||
|
||||
if toolLoad is None or toolLoad.ToolNumber == 0:
|
||||
self.vertFeed = 100
|
||||
self.horizFeed = 100
|
||||
self.vertRapid = 100
|
||||
self.horizRapid = 100
|
||||
self.radius = 0.25
|
||||
obj.ToolNumber = 0
|
||||
obj.ToolDescription = "UNDEFINED"
|
||||
else:
|
||||
self.vertFeed = toolLoad.VertFeed.Value
|
||||
self.horizFeed = toolLoad.HorizFeed.Value
|
||||
self.vertRapid = toolLoad.VertRapid.Value
|
||||
self.horizRapid = toolLoad.HorizRapid.Value
|
||||
tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
|
||||
if tool.Diameter == 0:
|
||||
self.radius = 0.25
|
||||
else:
|
||||
self.radius = tool.Diameter/2
|
||||
obj.ToolNumber = toolLoad.ToolNumber
|
||||
obj.ToolDescription = toolLoad.Name
|
||||
|
||||
if obj.UserLabel == "":
|
||||
obj.Label = obj.Name + " :" + obj.ToolDescription
|
||||
else:
|
||||
obj.Label = obj.UserLabel + " :" + obj.ToolDescription
|
||||
|
||||
output += "(" + obj.Label + ")"
|
||||
if not obj.UseComp:
|
||||
output += "(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")"
|
||||
else:
|
||||
output += "(Uncompensated Tool Path)"
|
||||
|
||||
parentJob = PathUtils.findParentJob(obj)
|
||||
if parentJob is None:
|
||||
return
|
||||
baseobject = parentJob.Base
|
||||
if baseobject is None:
|
||||
return
|
||||
print "base object: " + baseobject.Name
|
||||
contourwire = PathUtils.silhouette(baseobject)
|
||||
|
||||
edgelist = contourwire.Edges
|
||||
edgelist = Part.__sortEdges__(edgelist)
|
||||
output += self._buildPathLibarea(obj, edgelist)
|
||||
if obj.Active:
|
||||
path = Path.Path(output)
|
||||
obj.Path = path
|
||||
obj.ViewObject.Visibility = True
|
||||
|
||||
else:
|
||||
path = Path.Path("(inactive operation)")
|
||||
obj.Path = path
|
||||
obj.ViewObject.Visibility = False
|
||||
|
||||
|
||||
class _ViewProviderContour:
|
||||
|
||||
def __init__(self, vobj):
|
||||
vobj.Proxy = self
|
||||
|
||||
def attach(self, vobj):
|
||||
self.Object = vobj.Object
|
||||
return
|
||||
|
||||
def setEdit(self, vobj, mode=0):
|
||||
FreeCADGui.Control.closeDialog()
|
||||
taskd = TaskPanel()
|
||||
taskd.obj = vobj.Object
|
||||
FreeCADGui.Control.showDialog(taskd)
|
||||
taskd.setupUi()
|
||||
return True
|
||||
|
||||
def getIcon(self):
|
||||
return ":/icons/Path-Contour.svg"
|
||||
|
||||
def __getstate__(self):
|
||||
return None
|
||||
|
||||
def __setstate__(self, state):
|
||||
return None
|
||||
|
||||
|
||||
class _CommandAddTag:
|
||||
def GetResources(self):
|
||||
return {'Pixmap': 'Path-Holding',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Contour", "Add Holding Tag"),
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Contour", "Add Holding Tag")}
|
||||
|
||||
def IsActive(self):
|
||||
return FreeCAD.ActiveDocument is not None
|
||||
|
||||
def setpoint(self, point, o):
|
||||
obj = FreeCADGui.Selection.getSelection()[0]
|
||||
obj.StartPoint.x = point.x
|
||||
obj.StartPoint.y = point.y
|
||||
loc = obj.locs
|
||||
h = obj.heights
|
||||
l = obj.lengths
|
||||
a = obj.angles
|
||||
|
||||
x = point.x
|
||||
y = point.y
|
||||
z = float(0.0)
|
||||
loc.append(Vector(x, y, z))
|
||||
h.append(4.0)
|
||||
l.append(5.0)
|
||||
a.append(45.0)
|
||||
|
||||
obj.locs = loc
|
||||
obj.heights = h
|
||||
obj.lengths = l
|
||||
obj.angles = a
|
||||
|
||||
def Activated(self):
|
||||
|
||||
FreeCADGui.Snapper.getPoint(callback=self.setpoint)
|
||||
|
||||
|
||||
class _CommandSetStartPoint:
|
||||
def GetResources(self):
|
||||
return {'Pixmap': 'Path-Holding',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Contour", "Pick Start Point"),
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Contour", "Pick Start Point")}
|
||||
|
||||
def IsActive(self):
|
||||
return FreeCAD.ActiveDocument is not None
|
||||
|
||||
def setpoint(self, point, o):
|
||||
obj = FreeCADGui.Selection.getSelection()[0]
|
||||
obj.StartPoint.x = point.x
|
||||
obj.StartPoint.y = point.y
|
||||
|
||||
def Activated(self):
|
||||
|
||||
FreeCADGui.Snapper.getPoint(callback=self.setpoint)
|
||||
|
||||
|
||||
class _CommandSetEndPoint:
|
||||
def GetResources(self):
|
||||
return {'Pixmap': 'Path-Holding',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Contour", "Pick End Point"),
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Contour", "Pick End Point")}
|
||||
|
||||
def IsActive(self):
|
||||
return FreeCAD.ActiveDocument is not None
|
||||
|
||||
def setpoint(self, point, o):
|
||||
obj = FreeCADGui.Selection.getSelection()[0]
|
||||
obj.EndPoint.x = point.x
|
||||
obj.EndPoint.y = point.y
|
||||
|
||||
def Activated(self):
|
||||
|
||||
FreeCADGui.Snapper.getPoint(callback=self.setpoint)
|
||||
|
||||
|
||||
class CommandPathContour:
|
||||
def GetResources(self):
|
||||
return {'Pixmap': 'Path-Contour',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("PathContour", "Contour"),
|
||||
'Accel': "P, P",
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathContour", "Creates a Path Contour object from selected faces")}
|
||||
|
||||
def IsActive(self):
|
||||
if FreeCAD.ActiveDocument is not None:
|
||||
for o in FreeCAD.ActiveDocument.Objects:
|
||||
if o.Name[:3] == "Job":
|
||||
return True
|
||||
return False
|
||||
|
||||
def Activated(self):
|
||||
ztop = 10.0
|
||||
zbottom = 0.0
|
||||
|
||||
FreeCAD.ActiveDocument.openTransaction(translate("Path", "Create a Contour"))
|
||||
FreeCADGui.addModule("PathScripts.PathContour")
|
||||
FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "Contour")')
|
||||
FreeCADGui.doCommand('PathScripts.PathContour.ObjectContour(obj)')
|
||||
FreeCADGui.doCommand('PathScripts.PathContour._ViewProviderContour(obj.ViewObject)')
|
||||
|
||||
FreeCADGui.doCommand('obj.Active = True')
|
||||
|
||||
FreeCADGui.doCommand('obj.ClearanceHeight = ' + str(ztop + 10.0))
|
||||
FreeCADGui.doCommand('obj.StepDown = 1.0')
|
||||
FreeCADGui.doCommand('obj.StartDepth= ' + str(ztop))
|
||||
FreeCADGui.doCommand('obj.FinalDepth=' + str(zbottom))
|
||||
|
||||
FreeCADGui.doCommand('obj.SafeHeight = ' + str(ztop + 2.0))
|
||||
FreeCADGui.doCommand('obj.OffsetExtra = 0.0')
|
||||
FreeCADGui.doCommand('obj.Direction = "CW"')
|
||||
FreeCADGui.doCommand('obj.UseComp = True')
|
||||
FreeCADGui.doCommand('obj.PlungeAngle = 90.0')
|
||||
FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
|
||||
|
||||
FreeCADGui.doCommand('PathScripts.PathContour.ObjectContour.setDepths(obj.Proxy, obj)')
|
||||
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
FreeCADGui.doCommand('obj.ViewObject.startEditing()')
|
||||
|
||||
|
||||
class TaskPanel:
|
||||
def __init__(self):
|
||||
#self.form = FreeCADGui.PySideUic.loadUi(":/panels/ContourEdit.ui")
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/ContourEdit.ui")
|
||||
self.updating = False
|
||||
|
||||
def accept(self):
|
||||
self.getFields()
|
||||
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCADGui.Control.closeDialog()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
FreeCADGui.Selection.removeObserver(self.s)
|
||||
|
||||
def reject(self):
|
||||
FreeCADGui.Control.closeDialog()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
FreeCADGui.Selection.removeObserver(self.s)
|
||||
|
||||
def getFields(self):
|
||||
if self.obj:
|
||||
if hasattr(self.obj, "StartDepth"):
|
||||
self.obj.StartDepth = self.form.startDepth.text()
|
||||
if hasattr(self.obj, "FinalDepth"):
|
||||
self.obj.FinalDepth = self.form.finalDepth.text()
|
||||
if hasattr(self.obj, "SafeHeight"):
|
||||
self.obj.SafeHeight = self.form.safeHeight.text()
|
||||
if hasattr(self.obj, "ClearanceHeight"):
|
||||
self.obj.ClearanceHeight = self.form.clearanceHeight.text()
|
||||
if hasattr(self.obj, "StepDown"):
|
||||
self.obj.StepDown = self.form.stepDown.value()
|
||||
if hasattr(self.obj, "OffsetExtra"):
|
||||
self.obj.OffsetExtra = self.form.extraOffset.value()
|
||||
if hasattr(self.obj, "SegLen"):
|
||||
self.obj.SegLen = self.form.segLen.value()
|
||||
if hasattr(self.obj, "RollRadius"):
|
||||
self.obj.RollRadius = self.form.rollRadius.value()
|
||||
if hasattr(self.obj, "PlungeAngle"):
|
||||
self.obj.PlungeAngle = str(self.form.plungeAngle.value())
|
||||
if hasattr(self.obj, "UseComp"):
|
||||
self.obj.UseComp = self.form.useCompensation.isChecked()
|
||||
if hasattr(self.obj, "UseStartPoint"):
|
||||
self.obj.UseStartPoint = self.form.useStartPoint.isChecked()
|
||||
if hasattr(self.obj, "UseEndPoint"):
|
||||
self.obj.UseEndPoint = self.form.useEndPoint.isChecked()
|
||||
if hasattr(self.obj, "Direction"):
|
||||
self.obj.Direction = str(self.form.direction.currentText())
|
||||
self.obj.Proxy.execute(self.obj)
|
||||
|
||||
def setFields(self):
|
||||
self.form.startDepth.setText(str(self.obj.StartDepth.Value))
|
||||
self.form.finalDepth.setText(str(self.obj.FinalDepth.Value))
|
||||
self.form.safeHeight.setText(str(self.obj.SafeHeight.Value))
|
||||
self.form.clearanceHeight.setText(str(self.obj.ClearanceHeight.Value))
|
||||
self.form.stepDown.setValue(self.obj.StepDown)
|
||||
self.form.extraOffset.setValue(self.obj.OffsetExtra.Value)
|
||||
self.form.segLen.setValue(self.obj.SegLen.Value)
|
||||
self.form.rollRadius.setValue(self.obj.RollRadius.Value)
|
||||
self.form.plungeAngle.setValue(self.obj.PlungeAngle.Value)
|
||||
self.form.useCompensation.setChecked(self.obj.UseComp)
|
||||
self.form.useStartPoint.setChecked(self.obj.UseStartPoint)
|
||||
self.form.useEndPoint.setChecked(self.obj.UseEndPoint)
|
||||
|
||||
index = self.form.direction.findText(
|
||||
self.obj.Direction, QtCore.Qt.MatchFixedString)
|
||||
if index >= 0:
|
||||
self.form.direction.setCurrentIndex(index)
|
||||
|
||||
for i in range(len(self.obj.locs)):
|
||||
item = QtGui.QTreeWidgetItem(self.form.tagTree)
|
||||
item.setText(0, str(i+1))
|
||||
l = self.obj.locs[i]
|
||||
item.setText(1, str(l.x)+", " + str(l.y) + ", " + str(l.z))
|
||||
item.setText(2, str(self.obj.heights[i]))
|
||||
item.setText(3, str(self.obj.lengths[i]))
|
||||
item.setText(4, str(self.obj.angles[i]))
|
||||
item.setFlags(item.flags() | QtCore.Qt.ItemIsEditable)
|
||||
item.setTextAlignment(0, QtCore.Qt.AlignLeft)
|
||||
|
||||
def open(self):
|
||||
self.s = SelObserver()
|
||||
# install the function mode resident
|
||||
FreeCADGui.Selection.addObserver(self.s)
|
||||
|
||||
|
||||
def getStandardButtons(self):
|
||||
return int(QtGui.QDialogButtonBox.Ok)
|
||||
|
||||
def edit(self, item, column):
|
||||
if not self.updating:
|
||||
self.resetObject()
|
||||
|
||||
def resetObject(self, remove=None):
|
||||
"transfers the values from the widget to the object"
|
||||
loc = []
|
||||
h = []
|
||||
l = []
|
||||
a = []
|
||||
|
||||
for i in range(self.form.tagTree.topLevelItemCount()):
|
||||
it = self.form.tagTree.findItems(
|
||||
str(i+1), QtCore.Qt.MatchExactly, 0)[0]
|
||||
if (remove is None) or (remove != i):
|
||||
if it.text(1):
|
||||
x = float(it.text(1).split()[0].rstrip(","))
|
||||
y = float(it.text(1).split()[1].rstrip(","))
|
||||
z = float(it.text(1).split()[2].rstrip(","))
|
||||
loc.append(Vector(x, y, z))
|
||||
|
||||
else:
|
||||
loc.append(0.0)
|
||||
if it.text(2):
|
||||
h.append(float(it.text(2)))
|
||||
else:
|
||||
h.append(4.0)
|
||||
if it.text(3):
|
||||
l.append(float(it.text(3)))
|
||||
else:
|
||||
l.append(5.0)
|
||||
if it.text(4):
|
||||
a.append(float(it.text(4)))
|
||||
else:
|
||||
a.append(45.0)
|
||||
|
||||
self.obj.locs = loc
|
||||
self.obj.heights = h
|
||||
self.obj.lengths = l
|
||||
self.obj.angles = a
|
||||
|
||||
self.obj.touch()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
def addElement(self):
|
||||
self.updating = True
|
||||
|
||||
item = QtGui.QTreeWidgetItem(self.form.tagTree)
|
||||
item.setText(0, str(self.form.tagTree.topLevelItemCount()))
|
||||
item.setText(1, "0.0, 0.0, 0.0")
|
||||
item.setText(2, str(float(4.0)))
|
||||
item.setText(3, str(float(10.0)))
|
||||
item.setText(4, str(float(45.0)))
|
||||
item.setFlags(item.flags() | QtCore.Qt.ItemIsEditable)
|
||||
self.updating = False
|
||||
|
||||
self.resetObject()
|
||||
|
||||
def removeElement(self):
|
||||
it = self.form.tagTree.currentItem()
|
||||
if it:
|
||||
nr = int(it.text(0))-1
|
||||
self.resetObject(remove=nr)
|
||||
self.update()
|
||||
|
||||
def update(self):
|
||||
'fills the treewidget'
|
||||
self.updating = True
|
||||
self.form.tagTree.clear()
|
||||
if self.obj:
|
||||
for i in range(len(self.obj.locs)):
|
||||
item = QtGui.QTreeWidgetItem(self.form.tagTree)
|
||||
item.setText(0, str(i+1))
|
||||
l = self.obj.locs[i]
|
||||
item.setText(1, str(l.x) + ", " + str(l.y) + ", " + str(l.z))
|
||||
item.setText(2, str(self.obj.heights[i]))
|
||||
item.setText(3, str(self.obj.lengths[i]))
|
||||
item.setText(4, str(self.obj.angles[i]))
|
||||
item.setFlags(item.flags() | QtCore.Qt.ItemIsEditable)
|
||||
item.setTextAlignment(0, QtCore.Qt.AlignLeft)
|
||||
self.updating = False
|
||||
return
|
||||
|
||||
|
||||
def setupUi(self):
|
||||
|
||||
# Connect Signals and Slots
|
||||
# Depths
|
||||
self.form.startDepth.editingFinished.connect(self.getFields)
|
||||
self.form.finalDepth.editingFinished.connect(self.getFields)
|
||||
self.form.stepDown.editingFinished.connect(self.getFields)
|
||||
|
||||
# Heights
|
||||
self.form.safeHeight.editingFinished.connect(self.getFields)
|
||||
self.form.clearanceHeight.editingFinished.connect(self.getFields)
|
||||
|
||||
# operation
|
||||
self.form.direction.currentIndexChanged.connect(self.getFields)
|
||||
self.form.useCompensation.clicked.connect(self.getFields)
|
||||
self.form.useStartPoint.clicked.connect(self.getFields)
|
||||
self.form.useEndPoint.clicked.connect(self.getFields)
|
||||
self.form.extraOffset.editingFinished.connect(self.getFields)
|
||||
self.form.segLen.editingFinished.connect(self.getFields)
|
||||
self.form.rollRadius.editingFinished.connect(self.getFields)
|
||||
|
||||
# Tag Form
|
||||
QtCore.QObject.connect(
|
||||
self.form.tagTree,
|
||||
QtCore.SIGNAL("itemChanged(QTreeWidgetItem *, int)"),
|
||||
self.edit)
|
||||
self.form.addTag.clicked.connect(self.addElement)
|
||||
self.form.deleteTag.clicked.connect(self.removeElement)
|
||||
|
||||
self.setFields()
|
||||
|
||||
|
||||
class SelObserver:
|
||||
def __init__(self):
|
||||
import PathScripts.PathSelection as PST
|
||||
PST.contourselect()
|
||||
|
||||
def __del__(self):
|
||||
import PathScripts.PathSelection as PST
|
||||
PST.clear()
|
||||
|
||||
def addSelection(self, doc, obj, sub, pnt):
|
||||
FreeCADGui.doCommand('Gui.Selection.addSelection(FreeCAD.ActiveDocument.' + obj + ')')
|
||||
FreeCADGui.updateGui()
|
||||
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
# register the FreeCAD command
|
||||
FreeCADGui.addCommand('Path_Contour', CommandPathContour())
|
||||
FreeCADGui.addCommand('Add_Tag', _CommandAddTag())
|
||||
FreeCADGui.addCommand('Set_StartPoint', _CommandSetStartPoint())
|
||||
FreeCADGui.addCommand('Set_EndPoint', _CommandSetEndPoint())
|
||||
|
||||
FreeCAD.Console.PrintLog("Loading PathContour... done\n")
|
|
@ -60,7 +60,7 @@ class ObjectDrilling:
|
|||
obj.addProperty("App::PropertyDistance", "FinalDepth", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property","Final Depth of Tool- lowest value in Z"))
|
||||
obj.addProperty("App::PropertyDistance", "SafeHeight", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property","Height to clear top of materil"))
|
||||
obj.addProperty("App::PropertyDistance", "RetractHeight", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property","The height where feed starts and height during retract tool when path is finished"))
|
||||
|
||||
obj.addProperty("App::PropertyFloat", "DwellTime", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property","The time to dwell between peck cycles"))
|
||||
# Tool Properties
|
||||
obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", QtCore.QT_TRANSLATE_NOOP("App::Property","The tool number in use"))
|
||||
obj.ToolNumber = (0, 0, 1000, 1)
|
||||
|
@ -90,15 +90,21 @@ class ObjectDrilling:
|
|||
if toolLoad is None or toolLoad.ToolNumber == 0:
|
||||
self.vertFeed = 100
|
||||
self.horizFeed = 100
|
||||
self.vertRapid = 100
|
||||
self.horizRapid = 100
|
||||
self.radius = 0.25
|
||||
obj.ToolNumber = 0
|
||||
obj.ToolDescription = "UNDEFINED"
|
||||
|
||||
else:
|
||||
self.vertFeed = toolLoad.VertFeed.Value
|
||||
self.horizFeed = toolLoad.HorizFeed.Value
|
||||
self.vertRapid = toolLoad.VertRapid.Value
|
||||
self.horizRapid = toolLoad.HorizRapid.Value
|
||||
tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
|
||||
self.radius = tool.Diameter/2
|
||||
if tool.Diameter == 0:
|
||||
self.radius = 0.25
|
||||
else:
|
||||
self.radius = tool.Diameter/2
|
||||
obj.ToolNumber = toolLoad.ToolNumber
|
||||
obj.ToolDescription = toolLoad.Name
|
||||
|
||||
|
@ -111,7 +117,9 @@ class ObjectDrilling:
|
|||
output = "(Begin Drilling)\n"
|
||||
if obj.Base:
|
||||
for loc in obj.Base:
|
||||
#print loc
|
||||
for sub in loc[1]:
|
||||
#locations.append(self._findDrillingVector(loc))
|
||||
|
||||
if "Face" in sub or "Edge" in sub:
|
||||
s = getattr(loc[0].Shape, sub)
|
||||
|
@ -136,23 +144,27 @@ class ObjectDrilling:
|
|||
|
||||
output += "G90 G98\n"
|
||||
# rapid to clearance height
|
||||
output += "G0 Z" + str(obj.ClearanceHeight.Value)
|
||||
output += "G0 Z" + str(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) + "\n"
|
||||
# rapid to first hole location, with spindle still retracted:
|
||||
p0 = locations[0]
|
||||
output += "G0 X" + fmt(p0.x) + " Y" + fmt(p0.y) + "\n"
|
||||
output += "G0 X" + fmt(p0.x) + " Y" + fmt(p0.y) + "F " + PathUtils.fmt(self.horizRapid) + "\n"
|
||||
# move tool to clearance plane
|
||||
output += "G0 Z" + fmt(obj.ClearanceHeight.Value) + "\n"
|
||||
output += "G0 Z" + fmt(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) + "\n"
|
||||
pword = ""
|
||||
qword = ""
|
||||
if obj.PeckDepth.Value > 0:
|
||||
cmd = "G83"
|
||||
qword = " Q" + fmt(obj.PeckDepth.Value)
|
||||
elif obj.DwellTime > 0:
|
||||
cmd = "G82"
|
||||
pword = " P" + fmt(obj.DwellTime)
|
||||
else:
|
||||
cmd = "G81"
|
||||
qword = ""
|
||||
for p in locations:
|
||||
output += cmd + \
|
||||
" X" + fmt(p.x) + \
|
||||
" Y" + fmt(p.y) + \
|
||||
" Z" + fmt(obj.FinalDepth.Value) + qword + \
|
||||
" Z" + fmt(obj.FinalDepth.Value) + qword + pword + \
|
||||
" R" + str(obj.RetractHeight.Value) + \
|
||||
" F" + str(self.vertFeed) + "\n" \
|
||||
|
||||
|
@ -174,20 +186,22 @@ class ObjectDrilling:
|
|||
|
||||
|
||||
def checkdrillable(self, obj, sub):
|
||||
print "in checkdrillable"
|
||||
drillable = False
|
||||
if obj.ShapeType == 'Vertex':
|
||||
drillable = True
|
||||
elif obj.ShapeType == 'Solid':
|
||||
if sub[0:4] == 'Face':
|
||||
subobj = obj.getElement(sub)
|
||||
drillable = isinstance(subobj.Edges[0].Curve, Part.Circle)
|
||||
if isinstance(subobj.Edges[0].Curve, Part.Circle):
|
||||
drillable = True
|
||||
if str(subobj.Surface) == "<Cylinder object>":
|
||||
drillable = True
|
||||
|
||||
if len(subobj.Edges[0].Vertexes) > 1:
|
||||
drillable = False
|
||||
if sub[0:4] == 'Edge':
|
||||
o = obj.getElement(sub)
|
||||
drillable = isinstance(o.Curve, Part.Circle)
|
||||
if isinstance(o.Curve, Part.Circle) and len(o.Vertexes) == 1:
|
||||
drillable = True
|
||||
|
||||
return drillable
|
||||
|
||||
|
@ -213,16 +227,38 @@ class ObjectDrilling:
|
|||
obj.ClearanceHeight = 10.0
|
||||
obj.SafeHeight = 8.0
|
||||
obj.RetractHeight = 6.0
|
||||
if self.checkdrillable(ss.Shape,sub):
|
||||
|
||||
if item in baselist:
|
||||
FreeCAD.Console.PrintWarning("Drillable location already in the list" + "\n")
|
||||
else:
|
||||
baselist.append(item)
|
||||
if not self.checkdrillable(ss.Shape,sub):
|
||||
FreeCAD.Console.PrintError("Selected element is not a drillable location" + "\n")
|
||||
return
|
||||
|
||||
if sub[0:4] == 'Face':
|
||||
# Check for other drillable faces and give user the option
|
||||
drillableFaces = []
|
||||
|
||||
for i in range(len(ss.Shape.Faces)):
|
||||
if self.checkdrillable(ss.Shape, "Face" + str(i+1)):
|
||||
drillableFaces.append("Face" + str(i+1))
|
||||
if len(drillableFaces) > 1:
|
||||
reply = QtGui.QMessageBox.question(None,"","Multiple drillable faces found. Drill them all?",
|
||||
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.No)
|
||||
if reply == QtGui.QMessageBox.Yes:
|
||||
for i in drillableFaces:
|
||||
if i in baselist:
|
||||
FreeCAD.Console.PrintWarning("Drillable location already in the list" + "\n")
|
||||
continue
|
||||
else:
|
||||
newitem = (ss, i)
|
||||
baselist.append(newitem)
|
||||
else:
|
||||
if item in baselist:
|
||||
FreeCAD.Console.PrintWarning("Drillable location already in the list" + "\n")
|
||||
else:
|
||||
baselist.append(item)
|
||||
print baselist
|
||||
obj.Base = baselist
|
||||
self.execute(obj)
|
||||
|
||||
|
||||
class _ViewProviderDrill:
|
||||
def __init__(self, obj):
|
||||
obj.Proxy = self
|
||||
|
|
|
@ -91,29 +91,36 @@ class ObjectPathEngrave:
|
|||
if obj.Comment != "":
|
||||
output += '(' + str(obj.Comment)+')\n'
|
||||
|
||||
myJob = PathUtils.findMyJob(obj)
|
||||
if myJob is not None:
|
||||
controllers = myJob.Proxy.getToolControllers(myJob)
|
||||
if len(controllers) >= 1:
|
||||
mlist = []
|
||||
for c in controllers:
|
||||
mlist.append(c.Name)
|
||||
else:
|
||||
mlist = ["None"]
|
||||
obj.ToolController = mlist
|
||||
# myJob = PathUtils.findParentJob(obj)
|
||||
# if myJob is not None:
|
||||
# controllers = myJob.Proxy.getToolControllers(myJob)
|
||||
# if len(controllers) >= 1:
|
||||
# mlist = []
|
||||
# for c in controllers:
|
||||
# mlist.append(c.Name)
|
||||
# else:
|
||||
# mlist = ["None"]
|
||||
# obj.ToolController = mlist
|
||||
|
||||
toolLoad = PathUtils.getLastToolLoad(obj)
|
||||
if toolLoad is None or toolLoad.ToolNumber == 0:
|
||||
self.vertFeed = 100
|
||||
self.horizFeed = 100
|
||||
self.vertRapid = 100
|
||||
self.horizRapid = 100
|
||||
self.radius = 0.25
|
||||
obj.ToolNumber = 0
|
||||
obj.ToolDescription = "UNDEFINED"
|
||||
else:
|
||||
self.vertFeed = toolLoad.VertFeed.Value
|
||||
self.horizFeed = toolLoad.HorizFeed.Value
|
||||
self.vertRapid = toolLoad.VertRapid.Value
|
||||
self.horizRapid = toolLoad.HorizRapid.Value
|
||||
tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
|
||||
self.radius = tool.Diameter/2
|
||||
if tool.Diameter == 0:
|
||||
self.radius = 0.25
|
||||
else:
|
||||
self.radius = tool.Diameter/2
|
||||
obj.ToolNumber = toolLoad.ToolNumber
|
||||
obj.ToolDescription = toolLoad.Name
|
||||
|
||||
|
@ -123,7 +130,7 @@ class ObjectPathEngrave:
|
|||
obj.Label = obj.UserLabel + " :" + obj.ToolDescription
|
||||
|
||||
if obj.Base:
|
||||
output += "G0 Z" + PathUtils.fmt(obj.ClearanceHeight.Value)+"\n"
|
||||
output += "G0 Z" + PathUtils.fmt(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) + "\n"
|
||||
|
||||
wires = []
|
||||
for o in obj.Base:
|
||||
|
@ -135,7 +142,7 @@ class ObjectPathEngrave:
|
|||
if obj.Algorithm == "OCC Native":
|
||||
output += self.buildpathocc(obj, wires)
|
||||
|
||||
output += "G0 Z" + PathUtils.fmt(obj.ClearanceHeight.Value)+"\n"
|
||||
output += "G0 Z" + PathUtils.fmt(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) +"\n"
|
||||
|
||||
|
||||
# print output
|
||||
|
@ -173,7 +180,7 @@ class ObjectPathEngrave:
|
|||
if not last:
|
||||
# we set the first move to our first point
|
||||
last = edge.Vertexes[0].Point
|
||||
output += "G0" + " X" + PathUtils.fmt(last.x) + " Y" + PathUtils.fmt(last.y) + " Z" + PathUtils.fmt(obj.SafeHeight.Value) # Rapid sto starting position
|
||||
output += "G0" + " X" + PathUtils.fmt(last.x) + " Y" + PathUtils.fmt(last.y) + " Z" + PathUtils.fmt(obj.SafeHeight.Value) + "F " + PathUtils.fmt(self.horizRapid) # Rapid sto starting position
|
||||
output += "G1" + " X" + PathUtils.fmt(last.x) + " Y" + PathUtils.fmt(last.y) + " Z" + PathUtils.fmt(obj.FinalDepth.Value) + "F " + PathUtils.fmt(self.vertFeed) + "\n" # Vertical feed to depth
|
||||
if isinstance(edge.Curve, Part.Circle):
|
||||
point = edge.Vertexes[-1].Point
|
||||
|
@ -294,6 +301,9 @@ class TaskPanel:
|
|||
def __init__(self):
|
||||
self.form = FreeCADGui.PySideUic.loadUi(":/panels/EngraveEdit.ui")
|
||||
|
||||
def __del__(self):
|
||||
FreeCADGui.Selection.removeObserver(self.s)
|
||||
|
||||
def accept(self):
|
||||
self.getFields()
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import Path
|
|||
from PySide import QtCore, QtGui
|
||||
import os
|
||||
import glob
|
||||
import PathLoadTool
|
||||
#import PathLoadTool
|
||||
import Draft
|
||||
|
||||
|
||||
|
@ -123,14 +123,14 @@ class ObjectPathJob:
|
|||
obj.Y_Min = current_post.CORNER_MIN['y']
|
||||
obj.Z_Min = current_post.CORNER_MIN['z']
|
||||
|
||||
def getToolControllers(self, obj):
|
||||
'''returns a list of ToolControllers for the current job'''
|
||||
controllers = []
|
||||
for o in obj.Group:
|
||||
if "Proxy" in o.PropertiesList:
|
||||
if isinstance(o.Proxy, PathLoadTool.LoadTool):
|
||||
controllers.append (o.Name)
|
||||
return controllers
|
||||
# def getToolControllers(self, obj):
|
||||
# '''returns a list of ToolControllers for the current job'''
|
||||
# controllers = []
|
||||
# for o in obj.Group:
|
||||
# if "Proxy" in o.PropertiesList:
|
||||
# if isinstance(o.Proxy, PathLoadTool.LoadTool):
|
||||
# controllers.append (o.Name)
|
||||
# return controllers
|
||||
|
||||
|
||||
def execute(self, obj):
|
||||
|
@ -204,19 +204,23 @@ class CommandJob:
|
|||
FreeCAD.ActiveDocument.openTransaction(translate("Path_Job", "Create Job"))
|
||||
FreeCADGui.addModule('PathScripts.PathUtils')
|
||||
FreeCADGui.addModule('PathScripts.PathLoadTool')
|
||||
FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeatureCompoundPython", "Job")')
|
||||
FreeCADGui.doCommand('PathScripts.PathJob.ObjectPathJob(obj)')
|
||||
FreeCADGui.doCommand('PathScripts.PathLoadTool.CommandPathLoadTool.Create(obj.Name)')
|
||||
FreeCADGui.doCommand('obj.ViewObject.startEditing()')
|
||||
# FreeCADGui.doCommand('tool = Path.Tool()')
|
||||
# FreeCADGui.doCommand('tool')
|
||||
# FreeCADGui.doCommand('tool.Diameter = 5.0')
|
||||
# FreeCADGui.doCommand('tool.Name = "Default Tool"')
|
||||
# FreeCADGui.doCommand('tool.cuttingEdgeHeight = 15.0')
|
||||
# FreeCADGui.doCommand('tool.ToolType = "EndMill"')
|
||||
# FreeCADGui.doCommand('tool.Material = "HighSpeedSteel"')
|
||||
# FreeCADGui.doCommand('obj.ToolTable.addTools(tool)')
|
||||
|
||||
snippet = '''
|
||||
import PathScripts.PathLoadTool as PathLoadTool
|
||||
obj = FreeCAD.ActiveDocument.addObject("Path::FeatureCompoundPython", "Job")
|
||||
PathScripts.PathJob.ObjectPathJob(obj)
|
||||
PathLoadTool.CommandPathLoadTool.Create(obj.Name)
|
||||
tl = obj.Group[0]
|
||||
obj.ViewObject.startEditing()
|
||||
tool = Path.Tool()
|
||||
tool.Diameter = 5.0
|
||||
tool.Name = "Default Tool"
|
||||
tool.CuttingEdgeHeight = 15.0
|
||||
tool.ToolType = "EndMill"
|
||||
tool.Material = "HighSpeedSteel"
|
||||
obj.Tooltable.addTools(tool)
|
||||
tl.ToolNumber = 1
|
||||
'''
|
||||
FreeCADGui.doCommand(snippet)
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ def profile(curve, side_of_line, radius=1.0, vertfeed=0.0, horizfeed=0.0, offset
|
|||
|
||||
output = ""
|
||||
output += "G0 Z" + str(clearance) + "\n"
|
||||
|
||||
print "in profile: 151"
|
||||
offset_curve = area.Curve(curve)
|
||||
if offset_curve.getNumVertices() <= 1:
|
||||
raise Exception, "Sketch has no elements!"
|
||||
|
@ -297,28 +297,32 @@ and have not been throughly optimized, understood, or tested for FreeCAD.'''
|
|||
|
||||
|
||||
def profile2(curve, direction="on", radius=1.0, vertfeed=0.0,
|
||||
horizfeed=0.0, offset_extra=0.0, roll_radius=2.0,
|
||||
roll_on=None, roll_off=None, depthparams=None,
|
||||
horizfeed=0.0, vertrapid=0.0, horizrapid=0.0, offset_extra=0.0,
|
||||
roll_radius=2.0, roll_on=None, roll_off=None, depthparams=None,
|
||||
extend_at_start=0.0, extend_at_end=0.0, lead_in_line_len=0.0,
|
||||
lead_out_line_len=0.0):
|
||||
|
||||
# print "direction: " + str(direction)
|
||||
# print "radius: " + str(radius)
|
||||
# print "vertfeed: " + str(vertfeed)
|
||||
# print "horizfeed: " + str(horizfeed)
|
||||
# print "offset_extra: " + str(offset_extra)
|
||||
# print "roll_radius: " + str(roll_radius)
|
||||
# print "roll_on: " + str(roll_on)
|
||||
# print "roll_off: " + str(roll_off)
|
||||
# print "depthparams: " + str(depthparams)
|
||||
# print "extend_at_start: " + str(extend_at_start)
|
||||
# print "extend_at_end: " + str(extend_at_end)
|
||||
# print "lead_in_line_len: " + str(lead_in_line_len)
|
||||
# print "lead_out_line_len: " + str(lead_out_line_len)
|
||||
print "direction: " + str(direction)
|
||||
print "radius: " + str(radius)
|
||||
print "vertfeed: " + str(vertfeed)
|
||||
print "horizfeed: " + str(horizfeed)
|
||||
print "offset_extra: " + str(offset_extra)
|
||||
print "roll_radius: " + str(roll_radius)
|
||||
print "roll_on: " + str(roll_on)
|
||||
print "roll_off: " + str(roll_off)
|
||||
print "depthparams: " + str(depthparams)
|
||||
print "extend_at_start: " + str(extend_at_start)
|
||||
print "extend_at_end: " + str(extend_at_end)
|
||||
print "lead_in_line_len: " + str(lead_in_line_len)
|
||||
print "lead_out_line_len: " + str(lead_out_line_len)
|
||||
print "in profile2: 318"
|
||||
|
||||
global tags
|
||||
direction = direction.lower()
|
||||
offset_curve = area.Curve(curve)
|
||||
print "curve: " , str(curve)
|
||||
print "result curve: ", offset_curve.__dict__
|
||||
|
||||
if direction == "on":
|
||||
use_CRC() == False
|
||||
|
||||
|
@ -340,8 +344,10 @@ def profile2(curve, direction="on", radius=1.0, vertfeed=0.0,
|
|||
using_area_for_offset = True
|
||||
a = area.Area()
|
||||
a.append(curve)
|
||||
print "curve, offset: " , str(curve), str(offset)
|
||||
a.Offset(-offset)
|
||||
for curve in a.getCurves():
|
||||
print "result curve: ", curve
|
||||
curve_cw = curve.IsClockwise()
|
||||
if cw != curve_cw:
|
||||
curve.Reverse()
|
||||
|
@ -424,15 +430,17 @@ def profile2(curve, direction="on", radius=1.0, vertfeed=0.0,
|
|||
# start point
|
||||
if (endpoint is None) or (endpoint != s):
|
||||
if use_CRC():
|
||||
rapid(crc_start_point.x, crc_start_point.y)
|
||||
rapid(crc_start_point.x, crc_start_point.y) + "F " + horizrapid + "\n"
|
||||
else:
|
||||
rapid(s.x, s.y)
|
||||
rapid(s.x, s.y) #+ "F " + str(horizrapid) + "\n"
|
||||
|
||||
# rapid down to just above the material
|
||||
if endpoint is None:
|
||||
rapid(z=mat_depth + depthparams.rapid_safety_space)
|
||||
rapid(z=mat_depth + depthparams.rapid_safety_space) #+ "F " + vertrapid + "\n"
|
||||
|
||||
else:
|
||||
rapid(z=mat_depth)
|
||||
rapid(z=mat_depth) #+ "F " + str(vertrapid) + "\n"
|
||||
|
||||
|
||||
# feed down to depth
|
||||
mat_depth = depth
|
||||
|
@ -481,7 +489,7 @@ def profile2(curve, direction="on", radius=1.0, vertfeed=0.0,
|
|||
add_CRC_end_line(offset_curve, roll_on_curve, roll_off_curve,
|
||||
radius, direction, crc_end_point, lead_out_line_len)
|
||||
if direction == "on":
|
||||
rapid(z=depthparams.clearance_height)
|
||||
rapid(z=depthparams.clearance_height) #+ "F " + vertrapid + "\n"
|
||||
else:
|
||||
feed(crc_end_point.x, crc_end_point.y)
|
||||
|
||||
|
@ -493,11 +501,11 @@ def profile2(curve, direction="on", radius=1.0, vertfeed=0.0,
|
|||
|
||||
if endpoint != s:
|
||||
# rapid up to the clearance height
|
||||
rapid(z=depthparams.clearance_height)
|
||||
rapid(z=depthparams.clearance_height)# + "F " + vertrapid + "\n"
|
||||
|
||||
prev_depth = depth
|
||||
|
||||
rapid(z=depthparams.clearance_height)
|
||||
rapid(z=depthparams.clearance_height)# + "F " + vertrapid + "\n"
|
||||
|
||||
del offset_curve
|
||||
|
||||
|
|
|
@ -50,7 +50,8 @@ class LoadTool():
|
|||
obj.SpindleDir = ['Forward', 'Reverse']
|
||||
obj.addProperty("App::PropertySpeed", "VertFeed", "Feed", QtCore.QT_TRANSLATE_NOOP("App::Property","Feed rate for vertical moves in Z"))
|
||||
obj.addProperty("App::PropertySpeed", "HorizFeed", "Feed", QtCore.QT_TRANSLATE_NOOP("App::Property","Feed rate for horizontal moves"))
|
||||
|
||||
obj.addProperty("App::PropertySpeed", "VertRapid", "Rapid", QtCore.QT_TRANSLATE_NOOP("App::Property", "Rapid rate for vertical moves in Z"))
|
||||
obj.addProperty("App::PropertySpeed", "HorizRapid", "Rapid", QtCore.QT_TRANSLATE_NOOP("App::Property", "Rapid rate for horizontal moves"))
|
||||
obj.Proxy = self
|
||||
mode = 2
|
||||
obj.setEditorMode('Placement', mode)
|
||||
|
@ -211,12 +212,17 @@ class TaskPanel:
|
|||
def getFields(self):
|
||||
if self.obj:
|
||||
|
||||
if hasattr(self.obj, "VertFeed"):
|
||||
if hasattr(self.obj, "Label"):
|
||||
self.obj.Label = self.form.tcoName.text()
|
||||
if hasattr(self.obj, "VertFeed"):
|
||||
self.obj.VertFeed = self.form.vertFeed.text()
|
||||
if hasattr(self.obj, "HorizFeed"):
|
||||
self.obj.HorizFeed = self.form.horizFeed.text()
|
||||
if hasattr(self.obj, "VertRapid"):
|
||||
self.obj.VertRapid = self.form.vertRapid.text()
|
||||
if hasattr(self.obj, "HorizRapid"):
|
||||
self.obj.HorizRapid = self.form.horizRapid.text()
|
||||
|
||||
if hasattr(self.obj, "SpindleSpeed"):
|
||||
self.obj.SpindleSpeed = self.form.spindleSpeed.value()
|
||||
if hasattr(self.obj, "SpindleDir"):
|
||||
|
@ -229,6 +235,9 @@ class TaskPanel:
|
|||
|
||||
self.form.vertFeed.setText(str(self.obj.VertFeed.Value))
|
||||
self.form.horizFeed.setText(str(self.obj.HorizFeed.Value))
|
||||
self.form.vertRapid.setText(str(self.obj.VertRapid.Value))
|
||||
self.form.horizRapid.setText(str(self.obj.HorizRapid.Value))
|
||||
|
||||
self.form.spindleSpeed.setValue(self.obj.SpindleSpeed)
|
||||
self.form.tcoName.setText(str(self.obj.Label))
|
||||
|
||||
|
|
|
@ -230,7 +230,7 @@ class ObjectPocket:
|
|||
output = ""
|
||||
if obj.Comment != "":
|
||||
output += '(' + str(obj.Comment)+')\n'
|
||||
output += 'G0 Z' + fmt(obj.ClearanceHeight.Value) + "\n"
|
||||
output += 'G0 Z' + fmt(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) + "\n"
|
||||
|
||||
offsets = []
|
||||
nextradius = self.radius + extraoffset
|
||||
|
@ -318,9 +318,9 @@ class ObjectPocket:
|
|||
else:
|
||||
print "WARNING: Straight-plunging... probably not good, but we didn't find a place to helix or ramp"
|
||||
startPoint = edge.Vertexes[0].Point
|
||||
output += "G0 Z" + fmt(obj.ClearanceHeight.Value) + "\n"
|
||||
output += "G0 Z" + fmt(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) + "\n"
|
||||
output += "G0 X" + fmt(startPoint.x) + " Y" + fmt(startPoint.y) +\
|
||||
" Z" + fmt(obj.ClearanceHeight.Value) + "\n"
|
||||
" Z" + fmt(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.horizRapid) + "\n"
|
||||
first = False
|
||||
# then move slow down to our starting point for our profile
|
||||
last = edge.Vertexes[0].Point
|
||||
|
@ -349,7 +349,7 @@ class ObjectPocket:
|
|||
last = point
|
||||
|
||||
# move back up
|
||||
output += "G0 Z" + fmt(obj.ClearanceHeight.Value) + "\n"
|
||||
output += "G0 Z" + fmt(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) + "\n"
|
||||
return output
|
||||
|
||||
# To reload this from FreeCAD, use: import PathScripts.PathPocket; reload(PathScripts.PathPocket)
|
||||
|
@ -359,12 +359,16 @@ class ObjectPocket:
|
|||
if toolLoad is None or toolLoad.ToolNumber == 0:
|
||||
self.vertFeed = 100
|
||||
self.horizFeed = 100
|
||||
self.vertRapid = 100
|
||||
self.horiRrapid = 100
|
||||
self.radius = 0.25
|
||||
obj.ToolNumber = 0
|
||||
obj.ToolDescription = "UNDEFINED"
|
||||
else:
|
||||
self.vertFeed = toolLoad.VertFeed.Value
|
||||
self.horizFeed = toolLoad.HorizFeed.Value
|
||||
self.vertRapid = toolLoad.VertRapid.Value
|
||||
self.horizRapid = toolLoad.HorizRapid.Value
|
||||
tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
|
||||
if tool.Diameter == 0:
|
||||
self.radius = 0.25
|
||||
|
|
|
@ -61,15 +61,11 @@ class ObjectProfile:
|
|||
obj.addProperty("App::PropertyEnumeration", "Algorithm", "Algorithm", QtCore.QT_TRANSLATE_NOOP("App::Property","The library or algorithm used to generate the path"))
|
||||
obj.Algorithm = ['OCC Native', 'libarea']
|
||||
|
||||
obj.addProperty("App::PropertyLink", "ActiveTC", "Tool", QtCore.QT_TRANSLATE_NOOP("App::Property","The tool controler in use"))
|
||||
obj.addProperty("App::PropertyEnumeration", "ToolControllers", QtCore.QT_TRANSLATE_NOOP("App::Property","The tool controller to use"))
|
||||
obj.Toolcontrollers = []
|
||||
|
||||
# obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", "The tool number in use")
|
||||
# obj.ToolNumber = (0, 0, 1000, 1)
|
||||
# obj.setEditorMode('ToolNumber', 1) # make this read only
|
||||
# obj.addProperty("App::PropertyString", "ToolDescription", "Tool", "The description of the tool ")
|
||||
# obj.setEditorMode('ToolDescription', 1) # make this read onlyt
|
||||
obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", "The tool number in use")
|
||||
obj.ToolNumber = (0, 0, 1000, 1)
|
||||
obj.setEditorMode('ToolNumber', 1) # make this read only
|
||||
obj.addProperty("App::PropertyString", "ToolDescription", "Tool", "The description of the tool ")
|
||||
obj.setEditorMode('ToolDescription', 1) # make this read onlyt
|
||||
|
||||
# Depth Properties
|
||||
obj.addProperty("App::PropertyDistance", "ClearanceHeight", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property","The height needed to clear clamps and obstructions"))
|
||||
|
@ -117,7 +113,7 @@ class ObjectProfile:
|
|||
obj.angles = angles
|
||||
obj.lengths = lengths
|
||||
obj.heights = heights
|
||||
obj.ToolDescription = "UNDEFINED"
|
||||
#obj.ToolDescription = "UNDEFINED"
|
||||
|
||||
obj.Proxy = self
|
||||
|
||||
|
@ -188,7 +184,8 @@ class ObjectProfile:
|
|||
wire, obj.Side, self.radius, clockwise,
|
||||
obj.ClearanceHeight.Value, obj.StepDown, obj.StartDepth.Value,
|
||||
obj.FinalDepth.Value, FirstEdge, PathClosed, obj.SegLen.Value,
|
||||
self.vertFeed, self.horizFeed, PlungeAngle=obj.PlungeAngle.Value)
|
||||
self.vertFeed, self.horizFeed, self.vertRapid, self.horizRapid,
|
||||
PlungeAngle=obj.PlungeAngle.Value)
|
||||
|
||||
return output
|
||||
|
||||
|
@ -214,7 +211,7 @@ class ObjectProfile:
|
|||
PathKurveUtils.feedrate_hv(self.horizFeed, self.vertFeed)
|
||||
|
||||
output = ""
|
||||
output += "G0 Z" + str(obj.ClearanceHeight.Value)
|
||||
output += "G0 Z" + str(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) + "\n"
|
||||
curve = PathKurveUtils.makeAreaCurve(edgelist, obj.Direction, startpoint, endpoint)
|
||||
|
||||
'''The following line uses a profile function written for use with FreeCAD. It's clean but incomplete. It doesn't handle
|
||||
|
@ -226,7 +223,8 @@ print "y - " + str(point.y)
|
|||
or probably other features in heekscnc'''
|
||||
# output += PathKurveUtils.profile(curve, side, radius, vf, hf, offset_extra, rapid_safety_space, clearance, start_depth, step_down, final_depth, use_CRC)
|
||||
|
||||
'''The following calls the original procedure from heekscnc profile function. This, in turn, calls many other procedures to modify the profile.
|
||||
'''The following calls the original procedure from h
|
||||
toolLoad = obj.activeTCeekscnc profile function. This, in turn, calls many other procedures to modify the profile.
|
||||
This procedure is hacked together from heekscnc and has not been thoroughly reviewed or understood for FreeCAD. It can probably be
|
||||
thoroughly optimized and improved but it'll take a smarter mind than mine to do it. -sliptonic Feb16'''
|
||||
roll_radius = 2.0
|
||||
|
@ -255,10 +253,10 @@ print "y - " + str(point.y)
|
|||
obj.FinalDepth.Value, None)
|
||||
|
||||
PathKurveUtils.profile2(
|
||||
curve, obj.Side, self.radius, self.vertFeed,
|
||||
self.horizFeed, obj.OffsetExtra.Value, roll_radius, None, None,
|
||||
depthparams, extend_at_start, extend_at_end, lead_in_line_len,
|
||||
lead_out_line_len)
|
||||
curve, obj.Side, self.radius, self.vertFeed, self.horizFeed,
|
||||
self.vertRapid, self.horizRapid, obj.OffsetExtra.Value, roll_radius,
|
||||
None, None, depthparams, extend_at_start, extend_at_end,
|
||||
lead_in_line_len, lead_out_line_len)
|
||||
|
||||
output += PathKurveUtils.retrieve_gcode()
|
||||
return output
|
||||
|
@ -267,17 +265,23 @@ print "y - " + str(point.y)
|
|||
import Part # math #DraftGeomUtils
|
||||
output = ""
|
||||
|
||||
#toolLoad = PathUtils.getLastToolLoad(obj)
|
||||
toolLoad = obj.activeTC
|
||||
toolLoad = PathUtils.getLastToolLoad(obj)
|
||||
# obj.ToolController = PathUtils.getToolControllers(obj)
|
||||
# toolLoad = PathUtils.getToolLoad(obj, obj.ToolController)
|
||||
|
||||
if toolLoad is None or toolLoad.ToolNumber == 0:
|
||||
self.vertFeed = 100
|
||||
self.horizFeed = 100
|
||||
self.vertRapid = 100
|
||||
self.horizRapid = 100
|
||||
self.radius = 0.25
|
||||
obj.ToolNumber = 0
|
||||
obj.ToolDescription = "UNDEFINED"
|
||||
else:
|
||||
self.vertFeed = toolLoad.VertFeed.Value
|
||||
self.horizFeed = toolLoad.HorizFeed.Value
|
||||
self.vertRapid = toolLoad.VertRapid.Value
|
||||
self.horizRapid = toolLoad.HorizRapid.Value
|
||||
tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
|
||||
if tool.Diameter == 0:
|
||||
self.radius = 0.25
|
||||
|
@ -485,6 +489,7 @@ class CommandPathProfile:
|
|||
FreeCADGui.doCommand('obj.Direction = "CW"')
|
||||
FreeCADGui.doCommand('obj.UseComp = False')
|
||||
FreeCADGui.doCommand('obj.PlungeAngle = 90.0')
|
||||
#FreeCADGui.doCommand('obj.ActiveTC = None')
|
||||
FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
|
||||
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
|
|
|
@ -174,6 +174,13 @@ class POCKETGate:
|
|||
|
||||
return pocketable
|
||||
|
||||
class CONTOURGate:
|
||||
def allow(self, doc, obj, sub):
|
||||
pass
|
||||
|
||||
def contourselect():
|
||||
FreeCADGui.Selection.addSelectionGate(CONTOURGate())
|
||||
FreeCAD.Console.PrintWarning("Contour Select Mode\n")
|
||||
|
||||
def fselect():
|
||||
FreeCADGui.Selection.addSelectionGate(FGate())
|
||||
|
|
401
src/Mod/Path/PathScripts/PathStrategy.py
Normal file
401
src/Mod/Path/PathScripts/PathStrategy.py
Normal file
|
@ -0,0 +1,401 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2016 sliptonic <shopinthewoods@gmail.com> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
import FreeCAD
|
||||
import Path
|
||||
from PathScripts import PathUtils
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore, QtGui
|
||||
|
||||
__title__ = "Path Surface Operation"
|
||||
__author__ = "sliptonic (Brad Collette)"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
"""Path surface object and FreeCAD command"""
|
||||
|
||||
# Qt tanslation handling
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
|
||||
def translate(context, text, disambig=None):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def translate(context, text, disambig=None):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
|
||||
|
||||
class ObjectStrategy:
|
||||
|
||||
def __init__(self, obj):
|
||||
obj.addProperty("App::PropertyLinkSubList", "Base", "Path", "The base geometry of this toolpath")
|
||||
obj.addProperty("App::PropertyBool", "Active", "Path", "Make False, to prevent operation from generating code")
|
||||
obj.addProperty("App::PropertyString", "Comment", "Path", "An optional comment for this profile")
|
||||
obj.addProperty("App::PropertyString", "UserLabel", "Path", "User Assigned Label")
|
||||
|
||||
obj.addProperty("App::PropertyEnumeration", "Algorithm", "Algorithm", "The library to use to generate the path")
|
||||
obj.Algorithm = ['OCL Dropcutter', 'OCL Waterline']
|
||||
|
||||
# Tool Properties
|
||||
obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", "The tool number in use")
|
||||
obj.ToolNumber = (0, 0, 1000, 0)
|
||||
obj.setEditorMode('ToolNumber', 1) # make this read only
|
||||
obj.addProperty("App::PropertyString", "ToolDescription", "Tool", "The description of the tool ")
|
||||
obj.setEditorMode('ToolDescription', 1) # make this read onlyt
|
||||
|
||||
# Depth Properties
|
||||
obj.addProperty("App::PropertyDistance", "ClearanceHeight", "Depth", "The height needed to clear clamps and obstructions")
|
||||
obj.addProperty("App::PropertyDistance", "SafeHeight", "Depth", "Rapid Safety Height between locations.")
|
||||
obj.addProperty("App::PropertyFloatConstraint", "StepDown", "Depth", "Incremental Step Down of Tool")
|
||||
obj.StepDown = (0.0, 0.01, 100.0, 0.5)
|
||||
obj.addProperty("App::PropertyDistance", "StartDepth", "Depth", "Starting Depth of Tool- first cut depth in Z")
|
||||
obj.addProperty("App::PropertyDistance", "FinalDepth", "Depth", "Final Depth of Tool- lowest value in Z")
|
||||
obj.addProperty("App::PropertyDistance", "FinishDepth", "Depth", "Maximum material removed on final pass.")
|
||||
|
||||
obj.Proxy = self
|
||||
|
||||
def addbase(self, obj, ss, sub=""):
|
||||
baselist = obj.Base
|
||||
if len(baselist) == 0: # When adding the first base object, guess at heights
|
||||
try:
|
||||
bb = ss.Shape.BoundBox # parent boundbox
|
||||
subobj = ss.Shape.getElement(sub)
|
||||
fbb = subobj.BoundBox # feature boundbox
|
||||
obj.StartDepth = bb.ZMax
|
||||
obj.ClearanceHeight = bb.ZMax + 5.0
|
||||
obj.SafeHeight = bb.ZMax + 3.0
|
||||
|
||||
if fbb.ZMax < bb.ZMax:
|
||||
obj.FinalDepth = fbb.ZMax
|
||||
else:
|
||||
obj.FinalDepth = bb.ZMin
|
||||
except:
|
||||
obj.StartDepth = 5.0
|
||||
obj.ClearanceHeight = 10.0
|
||||
obj.SafeHeight = 8.0
|
||||
|
||||
item = (ss, sub)
|
||||
if item in baselist:
|
||||
FreeCAD.Console.PrintWarning(
|
||||
"this object already in the list" + "\n")
|
||||
else:
|
||||
baselist.append(item)
|
||||
obj.Base = baselist
|
||||
self.execute(obj)
|
||||
|
||||
def __getstate__(self):
|
||||
return None
|
||||
|
||||
def __setstate__(self, state):
|
||||
return None
|
||||
|
||||
def onChanged(self, obj, prop):
|
||||
return None
|
||||
|
||||
def execute(self, obj):
|
||||
output = ""
|
||||
|
||||
toolLoad = PathUtils.getLastToolLoad(obj)
|
||||
if toolLoad is None or toolLoad.ToolNumber == 0:
|
||||
self.vertFeed = 100
|
||||
self.horizFeed = 100
|
||||
self.vertRapid = 100
|
||||
self.horizRapid = 100
|
||||
self.radius = 0.25
|
||||
obj.ToolNumber = 0
|
||||
obj.ToolDescription = "UNDEFINED"
|
||||
else:
|
||||
self.vertFeed = toolLoad.VertFeed.Value
|
||||
self.horizFeed = toolLoad.HorizFeed.Value
|
||||
self.vertRapid = toolLoad.VertRapid.Value
|
||||
self.horizRapid = toolLoad.HorizRapid.Value
|
||||
tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
|
||||
if tool.Diameter == 0:
|
||||
self.radius = 0.25
|
||||
else:
|
||||
self.radius = tool.Diameter/2
|
||||
obj.ToolNumber = toolLoad.ToolNumber
|
||||
obj.ToolDescription = toolLoad.Name
|
||||
|
||||
|
||||
output += "(" + obj.Label + ")"
|
||||
output += "(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")"
|
||||
|
||||
if obj.Active:
|
||||
path = Path.Path(output)
|
||||
obj.Path = path
|
||||
obj.ViewObject.Visibility = True
|
||||
|
||||
else:
|
||||
path = Path.Path("(inactive operation)")
|
||||
obj.Path = path
|
||||
obj.ViewObject.Visibility = False
|
||||
|
||||
class ViewProviderStrategy:
|
||||
|
||||
def __init__(self, obj): # mandatory
|
||||
# obj.addProperty("App::PropertyFloat","SomePropertyName","PropertyGroup","Description of this property")
|
||||
obj.Proxy = self
|
||||
|
||||
def __getstate__(self): # mandatory
|
||||
return None
|
||||
|
||||
def __setstate__(self, state): # mandatory
|
||||
return None
|
||||
|
||||
def getIcon(self): # optional
|
||||
return ":/icons/Path-Surfacing.svg"
|
||||
|
||||
def onChanged(self, obj, prop): # optional
|
||||
# this is executed when a property of the VIEW PROVIDER changes
|
||||
pass
|
||||
|
||||
def updateData(self, obj, prop): # optional
|
||||
# this is executed when a property of the APP OBJECT changes
|
||||
pass
|
||||
|
||||
def setEdit(self, vobj, mode=0):
|
||||
FreeCADGui.Control.closeDialog()
|
||||
taskd = TaskPanel()
|
||||
taskd.obj = vobj.Object
|
||||
FreeCADGui.Control.showDialog(taskd)
|
||||
taskd.setupUi()
|
||||
return True
|
||||
|
||||
def unsetEdit(self, vobj, mode): # optional
|
||||
# this is executed when the user cancels or terminates edit mode
|
||||
pass
|
||||
|
||||
|
||||
class CommandPathStrategy:
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap': 'Path-3DSurface',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Strategy", "Strategy"),
|
||||
'Accel': "P, D",
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Strategy", "Creates a Path Strategy object")}
|
||||
|
||||
def IsActive(self):
|
||||
if FreeCAD.ActiveDocument is not None:
|
||||
for o in FreeCAD.ActiveDocument.Objects:
|
||||
if o.Name[:3] == "Job":
|
||||
return True
|
||||
return False
|
||||
|
||||
def Activated(self):
|
||||
|
||||
ztop = 10
|
||||
zbottom = 0
|
||||
|
||||
FreeCAD.ActiveDocument.openTransaction(translate("Path_Strategy", "Create Strategy"))
|
||||
FreeCADGui.addModule("PathScripts.PathStrategy")
|
||||
FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Strategy")')
|
||||
FreeCADGui.doCommand('PathScripts.PathStrategy.ObjectStrategy(obj)')
|
||||
FreeCADGui.doCommand('obj.Active = True')
|
||||
FreeCADGui.doCommand('PathScripts.PathStrategy.ViewProviderStrategy(obj.ViewObject)')
|
||||
FreeCADGui.doCommand('from PathScripts import PathUtils')
|
||||
FreeCADGui.doCommand('obj.ClearanceHeight = ' + str(ztop + 2))
|
||||
FreeCADGui.doCommand('obj.StartDepth = ' + str(ztop))
|
||||
FreeCADGui.doCommand('obj.SafeHeight = ' + str(ztop + 2))
|
||||
FreeCADGui.doCommand('obj.StepDown = ' + str((ztop - zbottom) / 8))
|
||||
FreeCADGui.doCommand('obj.FinalDepth=' + str(zbottom))
|
||||
FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
FreeCADGui.doCommand('obj.ViewObject.startEditing()')
|
||||
|
||||
|
||||
class TaskPanel:
|
||||
|
||||
def __init__(self):
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/StrategyEdit.ui")
|
||||
#self.form = FreeCADGui.PySideUic.loadUi(":/panels/SurfaceEdit.ui")
|
||||
|
||||
def accept(self):
|
||||
self.getFields()
|
||||
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCADGui.Control.closeDialog()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
FreeCADGui.Selection.removeObserver(self.s)
|
||||
|
||||
def reject(self):
|
||||
FreeCADGui.Control.closeDialog()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
FreeCADGui.Selection.removeObserver(self.s)
|
||||
|
||||
def getFields(self):
|
||||
if self.obj:
|
||||
if hasattr(self.obj, "StartDepth"):
|
||||
self.obj.StartDepth = self.form.startDepth.text()
|
||||
if hasattr(self.obj, "FinalDepth"):
|
||||
self.obj.FinalDepth = self.form.finalDepth.text()
|
||||
if hasattr(self.obj, "FinishDepth"):
|
||||
self.obj.FinishDepth = self.form.finishDepth.text()
|
||||
if hasattr(self.obj, "StepDown"):
|
||||
self.obj.StepDown = self.form.stepDown.value()
|
||||
if hasattr(self.obj, "SafeHeight"):
|
||||
self.obj.SafeHeight = self.form.safeHeight.text()
|
||||
if hasattr(self.obj, "ClearanceHeight"):
|
||||
self.obj.ClearanceHeight = self.form.clearanceHeight.text()
|
||||
|
||||
self.obj.Proxy.execute(self.obj)
|
||||
|
||||
def setFields(self):
|
||||
self.form.startDepth.setText(str(self.obj.StartDepth.Value))
|
||||
self.form.finalDepth.setText(str(self.obj.FinalDepth.Value))
|
||||
self.form.finishDepth.setText(str(self.obj.FinishDepth.Value))
|
||||
self.form.stepDown.setValue(self.obj.StepDown)
|
||||
|
||||
self.form.safeHeight.setText(str(self.obj.SafeHeight.Value))
|
||||
self.form.clearanceHeight.setText(str(self.obj.ClearanceHeight.Value))
|
||||
|
||||
for i in self.obj.Base:
|
||||
self.form.baseList.addItem(i[0].Name)
|
||||
|
||||
def open(self):
|
||||
self.s = SelObserver()
|
||||
# install the function mode resident
|
||||
FreeCADGui.Selection.addObserver(self.s)
|
||||
|
||||
def addBase(self):
|
||||
# check that the selection contains exactly what we want
|
||||
selection = FreeCADGui.Selection.getSelectionEx()
|
||||
if len(selection) != 1:
|
||||
FreeCAD.Console.PrintError(translate(
|
||||
"PathSurface", "Please select a single solid object from the project tree\n"))
|
||||
return
|
||||
|
||||
if not len(selection[0].SubObjects) == 0:
|
||||
FreeCAD.Console.PrintError(translate(
|
||||
"PathSurface", "Please select a single solid object from the project tree\n"))
|
||||
return
|
||||
|
||||
sel = selection[0].Object
|
||||
# get type of object
|
||||
# if sel.TypeId.startswith('Mesh'):
|
||||
# # it is a mesh already
|
||||
# print 'was already mesh'
|
||||
|
||||
# elif sel.TypeId.startswith('Part') and \
|
||||
# (sel.Shape.BoundBox.XLength > 0) and \
|
||||
# (sel.Shape.BoundBox.YLength > 0) and \
|
||||
# (sel.Shape.BoundBox.ZLength > 0):
|
||||
# print 'this is a solid Part object'
|
||||
|
||||
# else:
|
||||
# FreeCAD.Console.PrintError(
|
||||
# translate("PathSurface", "Cannot work with this object\n"))
|
||||
# return
|
||||
|
||||
self.obj.Proxy.addbase(self.obj, sel)
|
||||
|
||||
self.setFields() # defaults may have changed. Reload.
|
||||
self.form.baseList.clear()
|
||||
for i in self.obj.Base:
|
||||
self.form.baseList.addItem(i[0].Name)
|
||||
|
||||
def deleteBase(self):
|
||||
dlist = self.form.baseList.selectedItems()
|
||||
for d in dlist:
|
||||
newlist = []
|
||||
for i in self.obj.Base:
|
||||
if not i[0].Name == d.text():
|
||||
newlist.append(i)
|
||||
self.obj.Base = newlist
|
||||
self.form.baseList.takeItem(self.form.baseList.row(d))
|
||||
self.obj.Proxy.execute(self.obj)
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
def itemActivated(self):
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
slist = self.form.baseList.selectedItems()
|
||||
for i in slist:
|
||||
o = FreeCAD.ActiveDocument.getObject(i.text())
|
||||
FreeCADGui.Selection.addSelection(o)
|
||||
FreeCADGui.updateGui()
|
||||
|
||||
def reorderBase(self):
|
||||
newlist = []
|
||||
for i in range(self.form.baseList.count()):
|
||||
s = self.form.baseList.item(i).text()
|
||||
obj = FreeCAD.ActiveDocument.getObject(s)
|
||||
newlist.append(obj)
|
||||
self.obj.Base = newlist
|
||||
self.obj.Proxy.execute(self.obj)
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
def getStandardButtons(self):
|
||||
return int(QtGui.QDialogButtonBox.Ok)
|
||||
|
||||
def setupUi(self):
|
||||
|
||||
# Connect Signals and Slots
|
||||
|
||||
#Base Geometry
|
||||
self.form.addBase.clicked.connect(self.addBase)
|
||||
self.form.deleteBase.clicked.connect(self.deleteBase)
|
||||
self.form.reorderBase.clicked.connect(self.reorderBase)
|
||||
self.form.baseList.itemSelectionChanged.connect(self.itemActivated)
|
||||
|
||||
# Depths
|
||||
self.form.startDepth.editingFinished.connect(self.getFields)
|
||||
self.form.finalDepth.editingFinished.connect(self.getFields)
|
||||
self.form.finishDepth.editingFinished.connect(self.getFields)
|
||||
self.form.stepDown.editingFinished.connect(self.getFields)
|
||||
|
||||
# Heights
|
||||
self.form.safeHeight.editingFinished.connect(self.getFields)
|
||||
self.form.clearanceHeight.editingFinished.connect(self.getFields)
|
||||
|
||||
sel = FreeCADGui.Selection.getSelectionEx()
|
||||
self.setFields()
|
||||
|
||||
if len(sel) != 0:
|
||||
self.addBase()
|
||||
|
||||
|
||||
class SelObserver:
|
||||
|
||||
def __init__(self):
|
||||
import PathScripts.PathSelection as PST
|
||||
PST.surfaceselect()
|
||||
|
||||
def __del__(self):
|
||||
import PathScripts.PathSelection as PST
|
||||
PST.clear()
|
||||
|
||||
def addSelection(self, doc, obj, sub, pnt): # Selection object
|
||||
FreeCADGui.doCommand(
|
||||
'Gui.Selection.addSelection(FreeCAD.ActiveDocument.' + obj + ')')
|
||||
FreeCADGui.updateGui()
|
||||
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
# register the FreeCAD command
|
||||
FreeCADGui.addCommand('Path_Strategy', CommandPathStrategy())
|
||||
|
||||
FreeCAD.Console.PrintLog("Loading PathStrategy... done\n")
|
|
@ -131,9 +131,9 @@ class ObjectSurface:
|
|||
for loop in loops:
|
||||
p = loop[0]
|
||||
loopstring = "(loop begin)" + "\n"
|
||||
loopstring += "G0 Z" + str(obj.SafeHeight.Value) + "\n"
|
||||
loopstring += "G0 Z" + str(obj.SafeHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) + "\n"
|
||||
loopstring += "G0 X" + \
|
||||
str(fmt(p.x)) + " Y" + str(fmt(p.y)) + "\n"
|
||||
str(fmt(p.x)) + " Y" + str(fmt(p.y)) + "F " + PathUtils.fmt(self.horizRapid) + "\n"
|
||||
loopstring += "G1 Z" + str(fmt(p.z)) + "\n"
|
||||
for p in loop[1:]:
|
||||
loopstring += "G1 X" + \
|
||||
|
@ -239,8 +239,8 @@ class ObjectSurface:
|
|||
|
||||
# generate the path commands
|
||||
output = ""
|
||||
output += "G0 Z" + str(obj.ClearanceHeight.Value) + "\n"
|
||||
output += "G0 X" + str(clp[0].x) + " Y" + str(clp[0].y) + "\n"
|
||||
output += "G0 Z" + str(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) + "\n"
|
||||
output += "G0 X" + str(clp[0].x) + " Y" + str(clp[0].y) + "F " + PathUtils.fmt(self.horizRapid) + "\n"
|
||||
output += "G1 Z" + str(clp[0].z) + " F" + str(self.vertFeed) + "\n"
|
||||
|
||||
for c in clp:
|
||||
|
@ -261,14 +261,21 @@ class ObjectSurface:
|
|||
if toolLoad is None or toolLoad.ToolNumber == 0:
|
||||
self.vertFeed = 100
|
||||
self.horizFeed = 100
|
||||
self.vertRapid = 100
|
||||
self.horizRapid = 100
|
||||
self.radius = 0.25
|
||||
obj.ToolNumber = 0
|
||||
obj.ToolDescription = "UNDEFINED"
|
||||
else:
|
||||
self.vertFeed = toolLoad.VertFeed.Value
|
||||
self.horizFeed = toolLoad.HorizFeed.Value
|
||||
self.vertRapid = toolLoad.VertRapid.Value
|
||||
self.horizRapid = toolLoad.HorizRapid.Value
|
||||
tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
|
||||
self.radius = tool.Diameter/2
|
||||
if tool.Diameter == 0:
|
||||
self.radius = 0.25
|
||||
else:
|
||||
self.radius = tool.Diameter/2
|
||||
obj.ToolNumber = toolLoad.ToolNumber
|
||||
obj.ToolDescription = toolLoad.Name
|
||||
|
||||
|
|
|
@ -1,79 +1,62 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* This program is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU Library General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU Library General Public *
|
||||
#* License along with this program; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
#* USA *
|
||||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
from PySide import QtCore, QtGui
|
||||
import FreeCAD,FreeCADGui
|
||||
from PySide import QtCore,QtGui
|
||||
|
||||
# Qt tanslation handling
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
|
||||
def translate(context, text, disambig=None):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def translate(context, text, disambig=None):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
|
||||
|
||||
class CommandPathToolTableEdit:
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap': 'Path-ToolTable',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_ToolTableEdit", "EditToolTable"),
|
||||
return {'Pixmap' : 'Path-ToolTable',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_ToolTableEdit","EditToolTable"),
|
||||
'Accel': "P, T",
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_ToolTableEdit", "Edits a Tool Table in a selected Project")}
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_ToolTableEdit","Edits a Tool Table in a selected Project")}
|
||||
|
||||
def IsActive(self):
|
||||
return FreeCAD.ActiveDocument is not None
|
||||
return not FreeCAD.ActiveDocument is None
|
||||
|
||||
def Activated(self):
|
||||
FreeCAD.ActiveDocument.openTransaction(
|
||||
translate("Path_ToolTableEdit", "Edits a Tool Table in a selected Project"))
|
||||
snippet = '''
|
||||
from PathScripts import TooltableEditor
|
||||
from PathScripts import PathUtils
|
||||
sel = Gui.Selection.getSelectionEx()[0]
|
||||
obj=sel.Object
|
||||
if "Tooltable" in obj.PropertiesList:
|
||||
TooltableEditor.edit(obj.Name)
|
||||
'''
|
||||
FreeCADGui.doCommand(snippet)
|
||||
|
||||
# FreeCADGui.doCommand("from PathScripts import TooltableEditor")
|
||||
# FreeCADGui.doCommand("from PathScripts import PathUtils")
|
||||
# FreeCADGui.doCommand("sel = Gui.Selection.getSelectionEx()[0]")
|
||||
# FreeCADGui.doCommand("obj=sel.Object")
|
||||
# FreeCADGui.doCommand('job = PathUtils.findParentJob(obj)')
|
||||
# FreeCADGui.doCommand('TooltableEditor.edit(job.Name)')
|
||||
FreeCAD.ActiveDocument.openTransaction(translate("Path_ToolTableEdit","Edits a Tool Table in a selected Project"))
|
||||
FreeCADGui.doCommand("from PathScripts import TooltableEditor")
|
||||
FreeCADGui.doCommand("from PathScripts import PathUtils")
|
||||
FreeCADGui.doCommand('machine = PathUtils.findMachine()')
|
||||
FreeCADGui.doCommand('TooltableEditor.edit(machine.Name)')
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
# register the FreeCAD command
|
||||
FreeCADGui.addCommand('Path_ToolTableEdit', CommandPathToolTableEdit())
|
||||
FreeCADGui.addCommand('Path_ToolTableEdit',CommandPathToolTableEdit())
|
||||
|
||||
|
||||
FreeCAD.Console.PrintLog("Loading PathToolTableEdit... done\n")
|
||||
|
||||
|
|
|
@ -26,14 +26,15 @@ import FreeCAD
|
|||
import FreeCADGui
|
||||
import Part
|
||||
import math
|
||||
import Draft
|
||||
import Path
|
||||
import TechDraw
|
||||
from DraftGeomUtils import geomType
|
||||
from DraftGeomUtils import findWires
|
||||
import DraftVecUtils
|
||||
import PathScripts
|
||||
from PathScripts import PathJob
|
||||
import itertools
|
||||
from PySide import QtGui
|
||||
|
||||
def cleanedges(splines, precision):
|
||||
'''cleanedges([splines],precision). Convert BSpline curves, Beziers, to arcs that can be used for cnc paths.
|
||||
|
@ -83,6 +84,9 @@ def curvetowire(obj, steps):
|
|||
# fixme set at 4 decimal places for testing
|
||||
def fmt(val): return format(val, '.4f')
|
||||
|
||||
def silhouette(obj):
|
||||
w = TechDraw.findOuterWire(obj.Shape.Edges)
|
||||
return w
|
||||
|
||||
def isSameEdge(e1, e2):
|
||||
"""isSameEdge(e1,e2): return True if the 2 edges are both lines or arcs/circles and have the same
|
||||
|
@ -147,6 +151,26 @@ def is_clockwise(obj):
|
|||
|
||||
return sum >= 0
|
||||
|
||||
def loopdetect(obj, edge1, edge2):
|
||||
'''
|
||||
Returns a loop wire that includes the two edges.
|
||||
Useful for detecting boundaries of negative space features ie 'holes'
|
||||
If a unique loop is not found, returns None
|
||||
'''
|
||||
candidates = []
|
||||
for wire in obj.Shape.Wires:
|
||||
for e in wire.Edges:
|
||||
if e.hashCode() == edge1.hashCode():
|
||||
candidates.append((wire.hashCode(),wire))
|
||||
if e.hashCode() == edge2.hashCode():
|
||||
candidates.append((wire.hashCode(),wire))
|
||||
loop = set([x for x in candidates if candidates.count(x) > 1]) #return the duplicate item
|
||||
if len(loop) != 1:
|
||||
return None
|
||||
loopwire = next(x for x in loop)[1]
|
||||
return loopwire
|
||||
|
||||
|
||||
def check_clockwise(poly):
|
||||
'''
|
||||
check_clockwise(poly) a function for returning a boolean if the selected wire is clockwise or counter clockwise
|
||||
|
@ -396,7 +420,9 @@ def SortPath(wire, Side, radius, clockwise, firstedge=None, SegLen=0.5):
|
|||
return offset
|
||||
|
||||
|
||||
def MakePath(wire, Side, radius, clockwise, ZClearance, StepDown, ZStart, ZFinalDepth, firstedge=None, PathClosed=True, SegLen=0.5, VertFeed=1.0, HorizFeed=2.0, PlungeAngle=90.0):
|
||||
def MakePath(wire, Side, radius, clockwise, ZClearance, StepDown, ZStart,
|
||||
ZFinalDepth, firstedge=None, PathClosed=True, SegLen=0.5,
|
||||
VertFeed=1.0, HorizFeed=2.0, VertJog=1.0, HorizJog = 2.0, PlungeAngle=90.0):
|
||||
''' makes the path - just a simple profile for now '''
|
||||
offset = SortPath(wire, Side, radius, clockwise, firstedge, SegLen=SegLen)
|
||||
if len(offset.Edges) == 0:
|
||||
|
@ -404,9 +430,9 @@ def MakePath(wire, Side, radius, clockwise, ZClearance, StepDown, ZStart, ZFinal
|
|||
|
||||
toolpath = offset.Edges[:]
|
||||
paths = ""
|
||||
paths += "G0 Z" + str(ZClearance) + "\n"
|
||||
paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog) + "\n"
|
||||
first = toolpath[0].Vertexes[0].Point
|
||||
paths += "G0 X" + str(fmt(first.x)) + "Y" + str(fmt(first.y)) + "\n"
|
||||
paths += "G0 X" + str(fmt(first.x)) + "Y" + str(fmt(first.y)) + "F " + fmt(HorizJog) + "\n"
|
||||
Zprevious = ZStart
|
||||
ZCurrent = ZStart - StepDown
|
||||
|
||||
|
@ -414,9 +440,9 @@ def MakePath(wire, Side, radius, clockwise, ZClearance, StepDown, ZStart, ZFinal
|
|||
paths += convert(toolpath, Z=ZCurrent, Zprevious=Zprevious, PlungeAngle=PlungeAngle,
|
||||
vf=VertFeed, hf=HorizFeed)
|
||||
if not PathClosed:
|
||||
paths += "G0 Z" + str(ZClearance)
|
||||
paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog)
|
||||
paths += "G0 X" + str(fmt(first.x)) + "Y" + \
|
||||
str(fmt(first.y)) + "\n"
|
||||
str(fmt(first.y)) + "F " + fmt(HorizJog) + "\n"
|
||||
Zprevious = ZCurrent
|
||||
ZCurrent = ZCurrent - abs(StepDown)
|
||||
|
||||
|
@ -434,7 +460,7 @@ def MakePath(wire, Side, radius, clockwise, ZClearance, StepDown, ZStart, ZFinal
|
|||
paths += convert(toolpath, Z=ZFinalDepth, Zprevious=Zprevious, StopLength=StopLength,
|
||||
vf=VertFeed, hf=HorizFeed)
|
||||
|
||||
paths += "G0 Z" + str(ZClearance)
|
||||
paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog) + "\n"
|
||||
return paths
|
||||
|
||||
# the next two functions are for automatically populating tool
|
||||
|
@ -456,13 +482,6 @@ def changeTool(obj, job):
|
|||
if g == obj:
|
||||
return tlnum
|
||||
|
||||
def getLastTool(obj):
|
||||
toolNum = obj.ToolNumber
|
||||
if obj.ToolNumber == 0:
|
||||
# find tool from previous toolchange
|
||||
job = findJob()
|
||||
toolNum = changeTool(obj, job)
|
||||
return getTool(obj, toolNum)
|
||||
|
||||
def getLastToolLoad(obj):
|
||||
# This walks up the hierarchy and tries to find the closest preceding
|
||||
|
@ -507,6 +526,22 @@ def getLastToolLoad(obj):
|
|||
continue
|
||||
return tc
|
||||
|
||||
def getToolControllers(obj):
|
||||
controllers = []
|
||||
try:
|
||||
parent = obj.InList[0]
|
||||
except:
|
||||
parent = None
|
||||
|
||||
if parent is not None:
|
||||
sibs = parent.Group
|
||||
for g in sibs:
|
||||
if isinstance(g.Proxy, PathScripts.PathLoadTool.LoadTool):
|
||||
controllers.append(g.Name)
|
||||
return controllers
|
||||
|
||||
|
||||
|
||||
def getTool(obj, number=0):
|
||||
"retrieves a tool from a hosting object with a tooltable, if any"
|
||||
for o in obj.InList:
|
||||
|
|
|
@ -207,8 +207,9 @@ def parse(pathobj):
|
|||
for param in params:
|
||||
if param in c.Parameters:
|
||||
if param == 'F':
|
||||
outstring.append(
|
||||
param + format(c.Parameters['F'], '.2f'))
|
||||
if c.Name not in ["G0", "G00"]: #linuxcnc doesn't use rapid speeds
|
||||
outstring.append(
|
||||
param + format(c.Parameters['F'], '.2f'))
|
||||
elif param == 'T':
|
||||
outstring.append(param + str(c.Parameters['T']))
|
||||
else:
|
||||
|
|
Loading…
Reference in New Issue
Block a user