Path: add vcarve operation using openvoronoi
This commit is contained in:
@@ -125,6 +125,8 @@ SET(PathScripts_SRCS
|
||||
PathScripts/PathUtil.py
|
||||
PathScripts/PathUtils.py
|
||||
PathScripts/PathUtilsGui.py
|
||||
PathScripts/PathVcarve.py
|
||||
PathScripts/PathVcarveGui.py
|
||||
PathScripts/PathWaterline.py
|
||||
PathScripts/PathWaterlineGui.py
|
||||
PathScripts/PostUtils.py
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
<file>icons/Path-ToolController.svg</file>
|
||||
<file>icons/Path-Toolpath.svg</file>
|
||||
<file>icons/Path-ToolTable.svg</file>
|
||||
<file>icons/Path-Vcarve.svg</file>
|
||||
<file>icons/Path-Waterline.svg</file>
|
||||
<file>icons/arrow-ccw.svg</file>
|
||||
<file>icons/arrow-cw.svg</file>
|
||||
@@ -111,6 +112,7 @@
|
||||
<file>panels/PageOpSlotEdit.ui</file>
|
||||
<file>panels/PageOpSurfaceEdit.ui</file>
|
||||
<file>panels/PageOpWaterlineEdit.ui</file>
|
||||
<file>panels/PageOpVcarveEdit.ui</file>
|
||||
<file>panels/PathEdit.ui</file>
|
||||
<file>panels/PointEdit.ui</file>
|
||||
<file>panels/SetupGlobal.ui</file>
|
||||
|
||||
664
src/Mod/Path/Gui/Resources/icons/Path-Vcarve.svg
Normal file
664
src/Mod/Path/Gui/Resources/icons/Path-Vcarve.svg
Normal file
@@ -0,0 +1,664 @@
|
||||
<?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.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="Path-Vcarve.svg">
|
||||
<defs
|
||||
id="defs2818">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3853">
|
||||
<stop
|
||||
style="stop-color:#204a87;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3855" />
|
||||
<stop
|
||||
style="stop-color:#729fcf;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3857" />
|
||||
</linearGradient>
|
||||
<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.39492727,-0.00639802,0.01748379,1.079213,34.386898,-11.189684)"
|
||||
cx="32.151962"
|
||||
cy="27.950663"
|
||||
fx="32.151962"
|
||||
fy="27.950663"
|
||||
r="23.634638" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4031"
|
||||
id="linearGradient4055"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(71.494719,-3.1982556)"
|
||||
x1="30.000002"
|
||||
y1="14"
|
||||
x2="36"
|
||||
y2="54.227272" />
|
||||
<linearGradient
|
||||
id="linearGradient4031">
|
||||
<stop
|
||||
id="stop4033"
|
||||
offset="0"
|
||||
style="stop-color:#d3d7cf;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop4035"
|
||||
offset="1"
|
||||
style="stop-color:#888a85;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3853"
|
||||
id="linearGradient3859"
|
||||
x1="36.573002"
|
||||
y1="5.1688194"
|
||||
x2="27.702478"
|
||||
y2="56.270748"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,-1,0,63.650913)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3898-8-9">
|
||||
<stop
|
||||
style="stop-color:#888a85;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3900-2-2" />
|
||||
<stop
|
||||
style="stop-color:#d3d7cf;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3902-4-7" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3898-8-9"
|
||||
id="linearGradient3143"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="35.05999"
|
||||
y1="53.008698"
|
||||
x2="27.286415"
|
||||
y2="7.311924"
|
||||
gradientTransform="matrix(0.97351465,0,0,1,14.847529,-9)" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="7.77"
|
||||
inkscape:cx="62.383362"
|
||||
inkscape:cy="22.520305"
|
||||
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="1165"
|
||||
inkscape:window-height="1047"
|
||||
inkscape:window-x="1829"
|
||||
inkscape:window-y="1050"
|
||||
inkscape:window-maximized="0"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:snap-global="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3366"
|
||||
empspacing="2"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
<sodipodi:guide
|
||||
position="0,62"
|
||||
orientation="0,1"
|
||||
id="guide128"
|
||||
inkscape:locked="false" />
|
||||
</sodipodi:namedview>
|
||||
<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 />
|
||||
<dc:title>Path-Engrave</dc:title>
|
||||
<dc:date>2016-02-24</dc:date>
|
||||
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<dc:identifier>FreeCAD/src/Mod/Path/Gui/Resources/icons/Path-Engrave.svg</dc:identifier>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD LGPL2+</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<cc:license>https://www.gnu.org/copyleft/lesser.html</cc:license>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>[agryson] Alexander Gryson</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<path
|
||||
style="fill:#73d216;stroke:#73d216;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 5,25 V 38 L 33,53 51,49 V 34 Z"
|
||||
id="path3865"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#8ae234;stroke:none"
|
||||
d="m 3,30 v 4 l 30,16 16,-4 v -4 l -14,4 z"
|
||||
id="path3867"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#172a04;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 3,23 V 37 L 33,53 51,49 V 35 Z"
|
||||
id="path3863"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient3859);fill-opacity:1;fill-rule:nonzero;stroke:#0b1521;stroke-width:2;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 61,61 H 3 V 35 L 33,51 49,47 V 37 L 35,41 3,25 V 5 h 58 z"
|
||||
id="rect3105"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccc" />
|
||||
<path
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:#729fcf;stroke-width:1.99999976;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 59,59 H 5 V 38.311295 L 33,53 51,48.586777 50.982782,34.327135 35,39 5,24 V 7 h 54 z"
|
||||
id="rect3105-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccc" />
|
||||
<g
|
||||
id="g131"
|
||||
transform="matrix(1.0065176,0,0,0.880385,-0.29981087,1.1805708)">
|
||||
<path
|
||||
sodipodi:nodetypes="cccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="rect4417-1-2"
|
||||
d="M 55,2 H 37 V 42 L 45.999998,47 55,41 C 55,28 55,15 55,2 Z"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient3143);fill-opacity:1;fill-rule:nonzero;stroke:#2e3436;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 22 KiB |
104
src/Mod/Path/Gui/Resources/panels/PageOpVcarveEdit.ui
Normal file
104
src/Mod/Path/Gui/Resources/panels/PageOpVcarveEdit.ui
Normal file
@@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>140</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>ToolController</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="toolController">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The tool and its settings to be used for this operation.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><br/></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Discretization Deflection</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="discretize">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>This value is used in discretizing arcs into segments. Smaller values will result in larger gcode. Larger values may cause unwanted segments in the medial line path.</p></body></html></string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -113,6 +113,7 @@ class PathWorkbench (Workbench):
|
||||
threedcmdgroup = threedopcmdlist
|
||||
if PathPreferences.experimentalFeaturesEnabled():
|
||||
projcmdlist.append("Path_Sanity")
|
||||
engravecmdlist.append("Path_Vcarve")
|
||||
prepcmdlist.append("Path_Shape")
|
||||
extracmdlist.extend(["Path_Area", "Path_Area_Workplane"])
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@ else:
|
||||
|
||||
Processed = False
|
||||
|
||||
|
||||
def Startup():
|
||||
global Processed # pylint: disable=global-statement
|
||||
if not Processed:
|
||||
@@ -82,6 +81,7 @@ def Startup():
|
||||
from PathScripts import PathToolLibraryEditor
|
||||
from PathScripts import PathUtilsGui
|
||||
# from PathScripts import PathWaterlineGui # Added in initGui.py due to OCL dependency
|
||||
from PathScripts import PathVcarveGui
|
||||
Processed = True
|
||||
else:
|
||||
PathLog.debug('Skipping PathGui initialisation')
|
||||
|
||||
@@ -47,6 +47,9 @@ class MESHGate(PathBaseGate):
|
||||
def allow(self, doc, obj, sub): # pylint: disable=unused-argument
|
||||
return obj.TypeId[0:4] == 'Mesh'
|
||||
|
||||
class VCARVEGate:
|
||||
def allow(self, doc, obj, sub):
|
||||
|
||||
|
||||
class ENGRAVEGate(PathBaseGate):
|
||||
def allow(self, doc, obj, sub): # pylint: disable=unused-argument
|
||||
@@ -300,6 +303,10 @@ def surfaceselect():
|
||||
FreeCADGui.Selection.addSelectionGate(gate)
|
||||
FreeCAD.Console.PrintWarning("Surfacing Select Mode\n")
|
||||
|
||||
def vcarveselect():
|
||||
FreeCADGui.Selection.addSelectionGate(VCARVEGate())
|
||||
FreeCAD.Console.PrintWarning("Vcarve Select Mode\n")
|
||||
|
||||
|
||||
def probeselect():
|
||||
FreeCADGui.Selection.addSelectionGate(PROBEGate())
|
||||
@@ -328,6 +335,7 @@ def select(op):
|
||||
opsel['Surface'] = surfaceselect
|
||||
opsel['Waterline'] = surfaceselect
|
||||
opsel['Adaptive'] = adaptiveselect
|
||||
opsel['Vcarve'] = vcarveselect
|
||||
opsel['Probe'] = probeselect
|
||||
opsel['Custom'] = customselect
|
||||
return opsel[op]
|
||||
|
||||
266
src/Mod/Path/PathScripts/PathVcarve.py
Normal file
266
src/Mod/Path/PathScripts/PathVcarve.py
Normal file
@@ -0,0 +1,266 @@
|
||||
# -*- 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 ArchPanel
|
||||
import FreeCAD
|
||||
import Part
|
||||
import Path
|
||||
import PathScripts.PathEngraveBase as PathEngraveBase
|
||||
import PathScripts.PathLog as PathLog
|
||||
import PathScripts.PathOp as PathOp
|
||||
import PathScripts.PathUtils as PathUtils
|
||||
import traceback
|
||||
import time
|
||||
import PathScripts.PathGeom as pg
|
||||
from PathScripts.PathOpTools import orientWire
|
||||
|
||||
|
||||
from PySide import QtCore
|
||||
|
||||
__doc__ = "Class and implementation of Path Vcarve operation"
|
||||
|
||||
if False:
|
||||
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
|
||||
PathLog.trackModule(PathLog.thisModule())
|
||||
else:
|
||||
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
||||
|
||||
# Qt tanslation handling
|
||||
def translate(context, text, disambig=None):
|
||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||
|
||||
class ObjectVcarve(PathEngraveBase.ObjectOp):
|
||||
'''Proxy class for Vcarve operation.'''
|
||||
|
||||
def opFeatures(self, obj):
|
||||
'''opFeatures(obj) ... return all standard features and edges based geomtries'''
|
||||
return PathOp.FeatureTool | PathOp.FeatureDepths | PathOp.FeatureHeights | PathOp.FeatureStepDown | PathOp.FeatureBaseFaces;
|
||||
|
||||
def setupAdditionalProperties(self, obj):
|
||||
if not hasattr(obj, 'BaseShapes'):
|
||||
obj.addProperty("App::PropertyLinkList", "BaseShapes", "Path", QtCore.QT_TRANSLATE_NOOP("PathVcarve", "Additional base objects to be engraved"))
|
||||
obj.setEditorMode('BaseShapes', 2) # hide
|
||||
if not hasattr(obj, 'BaseObject'):
|
||||
obj.addProperty("App::PropertyLink", "BaseObject", "Path", QtCore.QT_TRANSLATE_NOOP("PathVcarve", "Additional base objects to be engraved"))
|
||||
obj.setEditorMode('BaseObject', 2) # hide
|
||||
|
||||
def initOperation(self, obj):
|
||||
'''initOperation(obj) ... create vcarve specific properties.'''
|
||||
obj.addProperty("App::PropertyFloat", "Discretize", "Path", QtCore.QT_TRANSLATE_NOOP("PathVcarve", "The deflection value for discretizing arcs"))
|
||||
self.setupAdditionalProperties(obj)
|
||||
|
||||
def opOnDocumentRestored(self, obj):
|
||||
# upgrade ...
|
||||
self.setupAdditionalProperties(obj)
|
||||
|
||||
|
||||
def buildPathMedial(self, obj, Faces, zDepths, unitcircle):
|
||||
'''constructs a medial axis path using openvoronoi'''
|
||||
import openvoronoi as ovd
|
||||
|
||||
def insert_wire_points(vd, wire):
|
||||
pts=[]
|
||||
for p in wire.Vertexes:
|
||||
pts.append( ovd.Point( p.X, p.Y ) )
|
||||
print('p1 = FreeCAD.Vector(X:{} Y:{}'.format(p.X, p.Y))
|
||||
id_list = []
|
||||
print("inserting ",len(pts)," point-sites:")
|
||||
for p in pts:
|
||||
id_list.append( vd.addVertexSite( p ) )
|
||||
return id_list
|
||||
|
||||
def insert_wire_segments(vd,id_list):
|
||||
print('insert_polygon-segments')
|
||||
print('inserting {} segments'.format(len(id_list)))
|
||||
for n in range(len(id_list)):
|
||||
n_nxt = n+1
|
||||
if n==(len(id_list)-1):
|
||||
n_nxt=0
|
||||
vd.addLineSite( id_list[n], id_list[n_nxt])
|
||||
|
||||
def insert_many_wires(vd, wires):
|
||||
# print('inserting {} wires'.format(len(obj.Wires)))
|
||||
polygon_ids =[]
|
||||
t_before = time.time()
|
||||
for idx, wire in enumerate(wires):
|
||||
d = obj.Discretize
|
||||
print('discretize: {}'.format(d))
|
||||
d = 0.008
|
||||
pointList = wire.discretize(Deflection=d)
|
||||
segwire = Part.Wire([Part.makeLine(p[0],p[1]) for p in zip(pointList, pointList[1:] )])
|
||||
|
||||
if idx == 0:
|
||||
segwire = orientWire(segwire, forward=False)
|
||||
else:
|
||||
segwire = orientWire(segwire, forward=True)
|
||||
|
||||
poly_id = insert_wire_points(vd,segwire)
|
||||
polygon_ids.append(poly_id)
|
||||
t_after = time.time()
|
||||
pt_time = t_after-t_before
|
||||
|
||||
t_before = time.time()
|
||||
for ids in polygon_ids:
|
||||
insert_wire_segments(vd,ids)
|
||||
t_after = time.time()
|
||||
seg_time = t_after-t_before
|
||||
return [pt_time, seg_time]
|
||||
|
||||
|
||||
def buildMedial(vd):
|
||||
safeheight = 3.0
|
||||
path = []
|
||||
maw = ovd.MedialAxisWalk( vd.getGraph() )
|
||||
toolpath = maw.walk()
|
||||
for chain in toolpath:
|
||||
path.append(Path.Command("G0 Z{}".format(safeheight)))
|
||||
p = chain[0][0][0]
|
||||
z = -(chain[0][0][1])
|
||||
|
||||
path.append(Path.Command("G0 X{} Y{} Z{}".format(p.x, p.y, safeheight)))
|
||||
|
||||
for step in chain:
|
||||
for point in step:
|
||||
p = point[0]
|
||||
z = -(point[1])
|
||||
path.append(Path.Command("G1 X{} Y{} Z{}".format(p.x, p.y, z)))
|
||||
|
||||
path.append(Path.Command("G0 Z{}".format(safeheight)))
|
||||
|
||||
return path
|
||||
|
||||
pathlist = []
|
||||
bins = 120 # int bins = number of bins for grid-search (affects performance, should not affect correctness)
|
||||
for f in Faces:
|
||||
#unitcircle = f.BoundBox.DiagonalLength/2
|
||||
print('unitcircle: {}'.format(unitcircle))
|
||||
vd = ovd.VoronoiDiagram(200, bins)
|
||||
vd.set_silent(True) # suppress Warnings!
|
||||
wires = f.Wires
|
||||
insert_many_wires(vd, wires)
|
||||
pi = ovd.PolygonInterior( True )
|
||||
vd.filter_graph(pi)
|
||||
ma = ovd.MedialAxis()
|
||||
vd.filter_graph(ma)
|
||||
pathlist.extend(buildMedial( vd )) # the actual cutting g-code
|
||||
|
||||
self.commandlist = pathlist
|
||||
|
||||
|
||||
|
||||
def opExecute(self, obj):
|
||||
'''opExecute(obj) ... process engraving operation'''
|
||||
PathLog.track()
|
||||
# Openvoronoi must be installed
|
||||
try:
|
||||
import openvoronoi as ovd
|
||||
except:
|
||||
FreeCAD.Console.PrintError(
|
||||
translate("Path_Vcarve", "This operation requires OpenVoronoi to be installed.") + "\n")
|
||||
return
|
||||
|
||||
|
||||
job = PathUtils.findParentJob(obj)
|
||||
|
||||
jobshapes = []
|
||||
zValues = self.getZValues(obj)
|
||||
|
||||
|
||||
try:
|
||||
if len(self.model) == 1 and self.model[0].isDerivedFrom('Sketcher::SketchObject') or \
|
||||
self.model[0].isDerivedFrom('Part::Part2DObject'):
|
||||
PathLog.track()
|
||||
|
||||
# self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid}))
|
||||
|
||||
# we only consider the outer wire if this is a Face
|
||||
modelshape = self.model[0].Shape
|
||||
self.buildPathMedial(obj, modelshape.Faces, zValues, modelshape.BoundBox.DiagonalLength/2)
|
||||
# self.wires = wires
|
||||
|
||||
# elif obj.Base:
|
||||
# PathLog.track()
|
||||
# wires = []
|
||||
# for base, subs in obj.Base:
|
||||
# edges = []
|
||||
# basewires = []
|
||||
# for feature in subs:
|
||||
# sub = base.Shape.getElement(feature)
|
||||
# if type(sub) == Part.Edge:
|
||||
# edges.append(sub)
|
||||
# elif sub.Wires:
|
||||
# basewires.extend(sub.Wires)
|
||||
# else:
|
||||
# basewires.append(Part.Wire(sub.Edges))
|
||||
|
||||
# for edgelist in Part.sortEdges(edges):
|
||||
# basewires.append(Part.Wire(edgelist))
|
||||
|
||||
# wires.extend(basewires)
|
||||
# self.buildpathocc(obj, wires, zValues)
|
||||
# self.wires = wires
|
||||
# elif not obj.BaseShapes:
|
||||
# PathLog.track()
|
||||
# if not obj.Base and not obj.BaseShapes:
|
||||
# for base in self.model:
|
||||
# PathLog.track(base.Label)
|
||||
# if base.isDerivedFrom('Part::Part2DObject'):
|
||||
# jobshapes.append(base)
|
||||
|
||||
# if not jobshapes:
|
||||
# raise ValueError(translate('PathVcarve', "Unknown baseobject type for engraving (%s)") % (obj.Base))
|
||||
|
||||
# if obj.BaseShapes or jobshapes:
|
||||
# PathLog.track()
|
||||
# wires = []
|
||||
# for shape in obj.BaseShapes + jobshapes:
|
||||
# PathLog.track(shape.Label)
|
||||
# shapeWires = shape.Shape.Wires
|
||||
# self.buildpathocc(obj, shapeWires, zValues)
|
||||
# wires.extend(shapeWires)
|
||||
# self.wires = wires
|
||||
# # the last command is a move to clearance, which is automatically added by PathOp
|
||||
# if self.commandlist:
|
||||
# self.commandlist.pop()
|
||||
|
||||
except Exception as e:
|
||||
PathLog.error(e)
|
||||
traceback.print_exc()
|
||||
PathLog.error(translate('PathVcarve', 'The Job Base Object has no engraveable element. Engraving operation will produce no output.'))
|
||||
|
||||
def opUpdateDepths(self, obj, ignoreErrors=False):
|
||||
'''updateDepths(obj) ... engraving is always done at the top most z-value'''
|
||||
job = PathUtils.findParentJob(obj)
|
||||
self.opSetDefaultValues(obj, job)
|
||||
|
||||
def SetupProperties():
|
||||
return [ "Discretize" ]
|
||||
|
||||
def Create(name, obj = None):
|
||||
'''Create(name) ... Creates and returns a Vcarve operation.'''
|
||||
if obj is None:
|
||||
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
|
||||
proxy = ObjectVcarve(obj, name)
|
||||
return obj
|
||||
|
||||
148
src/Mod/Path/PathScripts/PathVcarveGui.py
Normal file
148
src/Mod/Path/PathScripts/PathVcarveGui.py
Normal file
@@ -0,0 +1,148 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2017 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 FreeCADGui
|
||||
import PathScripts.PathVcarve as PathVcarve
|
||||
import PathScripts.PathLog as PathLog
|
||||
import PathScripts.PathOpGui as PathOpGui
|
||||
import PathScripts.PathSelection as PathSelection
|
||||
import PathScripts.PathUtils as PathUtils
|
||||
|
||||
from PySide import QtCore, QtGui
|
||||
|
||||
__title__ = "Path Vcarve Operation UI"
|
||||
__author__ = "sliptonic (Brad Collette)"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
__doc__ = "Vcarve operation page controller and command implementation."
|
||||
|
||||
if False:
|
||||
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
|
||||
PathLog.trackModule(PathLog.thisModule())
|
||||
else:
|
||||
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
||||
|
||||
def translate(context, text, disambig=None):
|
||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||
|
||||
class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage):
|
||||
'''Enhanced base geometry page to also allow special base objects.'''
|
||||
|
||||
def super(self):
|
||||
return super(TaskPanelBaseGeometryPage, self)
|
||||
|
||||
def addBaseGeometry(self, selection):
|
||||
added = False
|
||||
shapes = self.obj.BaseShapes
|
||||
for sel in selection:
|
||||
job = PathUtils.findParentJob(self.obj)
|
||||
base = job.Proxy.resourceClone(job, sel.Object)
|
||||
if not base:
|
||||
PathLog.notice((translate("Path", "%s is not a Base Model object of the job %s")+"\n") % (sel.Object.Label, job.Label))
|
||||
continue
|
||||
if base in shapes:
|
||||
PathLog.notice((translate("Path", "Base shape %s already in the list")+"\n") % (sel.Object.Label))
|
||||
continue
|
||||
if base.isDerivedFrom('Part::Part2DObject'):
|
||||
if sel.HasSubObjects:
|
||||
# selectively add some elements of the drawing to the Base
|
||||
for sub in sel.SubElementNames:
|
||||
if 'Vertex' in sub:
|
||||
PathLog.info(translate("Path", "Ignoring vertex"))
|
||||
else:
|
||||
self.obj.Proxy.addBase(self.obj, base, sub)
|
||||
else:
|
||||
# when adding an entire shape to BaseShapes we can take its sub shapes out of Base
|
||||
self.obj.Base = [(p,el) for p,el in self.obj.Base if p != base]
|
||||
shapes.append(base)
|
||||
self.obj.BaseShapes = shapes
|
||||
added = True
|
||||
else:
|
||||
# user wants us to engrave an edge of face of a base model
|
||||
base = self.super().addBaseGeometry(selection)
|
||||
added = added or base
|
||||
|
||||
return added
|
||||
|
||||
def setFields(self, obj):
|
||||
self.super().setFields(obj)
|
||||
self.form.baseList.blockSignals(True)
|
||||
for shape in self.obj.BaseShapes:
|
||||
item = QtGui.QListWidgetItem(shape.Label)
|
||||
item.setData(self.super().DataObject, shape)
|
||||
item.setData(self.super().DataObjectSub, None)
|
||||
self.form.baseList.addItem(item)
|
||||
self.form.baseList.blockSignals(False)
|
||||
|
||||
def updateBase(self):
|
||||
PathLog.track()
|
||||
shapes = []
|
||||
for i in range(self.form.baseList.count()):
|
||||
item = self.form.baseList.item(i)
|
||||
obj = item.data(self.super().DataObject)
|
||||
sub = item.data(self.super().DataObjectSub)
|
||||
if not sub:
|
||||
shapes.append(obj)
|
||||
PathLog.debug("Setting new base shapes: %s -> %s" % (self.obj.BaseShapes, shapes))
|
||||
self.obj.BaseShapes = shapes
|
||||
return self.super().updateBase()
|
||||
|
||||
class TaskPanelOpPage(PathOpGui.TaskPanelPage):
|
||||
'''Page controller class for the Vcarve operation.'''
|
||||
|
||||
def getForm(self):
|
||||
'''getForm() ... returns UI'''
|
||||
return FreeCADGui.PySideUic.loadUi(":/panels/PageOpVcarveEdit.ui")
|
||||
|
||||
def getFields(self, obj):
|
||||
'''getFields(obj) ... transfers values from UI to obj's proprties'''
|
||||
# if obj.StartVertex != self.form.startVertex.value():
|
||||
# obj.StartVertex = self.form.startVertex.value()
|
||||
self.updateToolController(obj, self.form.toolController)
|
||||
|
||||
def setFields(self, obj):
|
||||
'''setFields(obj) ... transfers obj's property values to UI'''
|
||||
# self.form.startVertex.setValue(obj.StartVertex)
|
||||
self.setupToolController(obj, self.form.toolController)
|
||||
|
||||
def getSignalsForUpdate(self, obj):
|
||||
'''getSignalsForUpdate(obj) ... return list of signals for updating obj'''
|
||||
signals = []
|
||||
# signals.append(self.form.startVertex.editingFinished)
|
||||
signals.append(self.form.toolController.currentIndexChanged)
|
||||
return signals
|
||||
|
||||
def taskPanelBaseGeometryPage(self, obj, features):
|
||||
'''taskPanelBaseGeometryPage(obj, features) ... return page for adding base geometries.'''
|
||||
return TaskPanelBaseGeometryPage(obj, features)
|
||||
|
||||
Command = PathOpGui.SetupOperation('Vcarve',
|
||||
PathVcarve.Create,
|
||||
TaskPanelOpPage,
|
||||
'Path-Vcarve',
|
||||
QtCore.QT_TRANSLATE_NOOP("PathVcarve", "Vcarve"),
|
||||
QtCore.QT_TRANSLATE_NOOP("PathVcarve", "Creates a medial line engraving path"),
|
||||
PathVcarve.SetupProperties)
|
||||
|
||||
FreeCAD.Console.PrintLog("Loading PathVcarveGui... done\n")
|
||||
Reference in New Issue
Block a user