Code cleanup and additional work on panels

This commit is contained in:
sliptonic 2016-04-03 11:07:51 -05:00 committed by Yorik van Havre
parent 670ae854f3
commit 704cc23ab7
15 changed files with 1582 additions and 377 deletions

View File

@ -57,6 +57,8 @@ SET(PathScripts_SRCS
PathScripts/PathInspect.py
PathScripts/PathSimpleCopy.py
PathScripts/PathEngrave.py
PathScripts/PathSurface.py
)
SET(PathScripts_NC_SRCS

View File

@ -88,7 +88,7 @@ add_library(PathGui SHARED ${PathGui_SRCS})
target_link_libraries(PathGui ${PathGui_LIBS})
fc_target_copy_resource(PathGui
fc_target_copy_resource(PathGui
${CMAKE_SOURCE_DIR}/src/Mod/Path
${CMAKE_BINARY_DIR}/Mod/Path
InitGui.py)

View File

@ -98,8 +98,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>116</width>
<height>108</height>
<width>304</width>
<height>314</height>
</rect>
</property>
<attribute name="icon">
@ -159,8 +159,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>150</width>
<height>108</height>
<width>304</width>
<height>314</height>
</rect>
</property>
<attribute name="icon">
@ -220,13 +220,13 @@
<rect>
<x>0</x>
<y>0</y>
<width>234</width>
<height>50</height>
<width>304</width>
<height>314</height>
</rect>
</property>
<attribute name="icon">
<iconset resource="../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/FreeCAD-default/scalable/user.svg</normaloff>:/icons/FreeCAD-default/scalable/user.svg</iconset>
<iconset resource="Resources/Path.qrc">
<normaloff>:/icons/Path-Hamburger.svg</normaloff>:/icons/Path-Hamburger.svg</iconset>
</attribute>
<attribute name="label">
<string>Operation</string>
@ -263,6 +263,7 @@
</customwidgets>
<resources>
<include location="../../../Gui/Icons/resource.qrc"/>
<include location="Resources/Path.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -34,7 +34,7 @@
<x>0</x>
<y>0</y>
<width>304</width>
<height>314</height>
<height>284</height>
</rect>
</property>
<attribute name="icon">
@ -99,7 +99,7 @@
<x>0</x>
<y>0</y>
<width>304</width>
<height>314</height>
<height>284</height>
</rect>
</property>
<attribute name="icon">
@ -146,7 +146,7 @@
<x>0</x>
<y>0</y>
<width>304</width>
<height>314</height>
<height>284</height>
</rect>
</property>
<attribute name="icon">
@ -187,18 +187,65 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>304</width>
<height>284</height>
</rect>
</property>
<attribute name="icon">
<iconset resource="../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/FreeCAD-default/scalable/document-save-as.svg</normaloff>:/icons/FreeCAD-default/scalable/document-save-as.svg</iconset>
</attribute>
<attribute name="label">
<string>Speeds</string>
</attribute>
<layout class="QFormLayout" name="formLayout_4">
<item row="0" column="0">
<widget class="Gui::InputField" name="horizFeed">
<property name="unit" stdset="0">
<string>mm/(s)</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label">
<property name="text">
<string>Horiz Feed</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="Gui::InputField" name="vertFeed">
<property name="unit" stdset="0">
<string notr="true">mm/(s)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Vert Feed</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_3">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>304</width>
<height>314</height>
<height>284</height>
</rect>
</property>
<attribute name="icon">
<iconset resource="../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/FreeCAD-default/scalable/user.svg</normaloff>:/icons/FreeCAD-default/scalable/user.svg</iconset>
<iconset resource="Resources/Path.qrc">
<normaloff>:/icons/Path-Hamburger.svg</normaloff>:/icons/Path-Hamburger.svg</iconset>
</attribute>
<attribute name="label">
<string>Operation</string>
@ -235,6 +282,7 @@
</customwidgets>
<resources>
<include location="../../../Gui/Icons/resource.qrc"/>
<include location="Resources/Path.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -252,6 +252,14 @@
<layout class="QGridLayout" name="gridLayout_3"/>
</widget>
<widget class="QWidget" name="Pattern">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>334</width>
<height>327</height>
</rect>
</property>
<attribute name="label">
<string>Pattern</string>
</attribute>
@ -266,8 +274,8 @@
</rect>
</property>
<attribute name="icon">
<iconset resource="../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/FreeCAD-default/scalable/user.svg</normaloff>:/icons/FreeCAD-default/scalable/user.svg</iconset>
<iconset resource="Resources/Path.qrc">
<normaloff>:/icons/Path-Hamburger.svg</normaloff>:/icons/Path-Hamburger.svg</iconset>
</attribute>
<attribute name="label">
<string>Operation</string>
@ -368,6 +376,7 @@
</customwidgets>
<resources>
<include location="../../../Gui/Icons/resource.qrc"/>
<include location="Resources/Path.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -224,6 +224,14 @@
</layout>
</widget>
<widget class="QWidget" name="Holding">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>334</width>
<height>357</height>
</rect>
</property>
<attribute name="label">
<string>Holding</string>
</attribute>
@ -283,8 +291,8 @@
</rect>
</property>
<attribute name="icon">
<iconset resource="../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/FreeCAD-default/scalable/user.svg</normaloff>:/icons/FreeCAD-default/scalable/user.svg</iconset>
<iconset resource="Resources/Path.qrc">
<normaloff>:/icons/Path-Hamburger.svg</normaloff>:/icons/Path-Hamburger.svg</iconset>
</attribute>
<attribute name="label">
<string>Operation</string>
@ -445,6 +453,7 @@
</customwidgets>
<resources>
<include location="../../../Gui/Icons/resource.qrc"/>
<include location="Resources/Path.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -31,6 +31,8 @@
<file>icons/Path-ToolChange.svg</file>
<file>icons/Path-SimpleCopy.svg</file>
<file>icons/Path-Engrave.svg</file>
<file>icons/Path-Surfacing.svg</file>
<file>icons/Path-Hamburger.svg</file>
<file>translations/Path_de.qm</file>
<file>translations/Path_af.qm</file>
<file>translations/Path_zh-CN.qm</file>

View File

@ -0,0 +1,644 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
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-3D-Surface-Example.svg">
<defs
id="defs2818">
<linearGradient
id="linearGradient4668"
osb:paint="gradient">
<stop
style="stop-color:#009b00;stop-opacity:1;"
offset="0"
id="stop4670" />
<stop
style="stop-color:#009b00;stop-opacity:0;"
offset="1"
id="stop4672" />
</linearGradient>
<linearGradient
id="linearGradient4662"
osb:paint="solid">
<stop
style="stop-color:#008000;stop-opacity:1;"
offset="0"
id="stop4664" />
</linearGradient>
<linearGradient
id="linearGradient4529"
osb:paint="solid">
<stop
style="stop-color:#0047ff;stop-opacity:1;"
offset="0"
id="stop4531" />
</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.39497909,0,0,1.1841158,-76.294432,-34.372515)"
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="3.8890873"
inkscape:cx="19.509966"
inkscape:cy="28.766417"
inkscape:current-layer="layer2"
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="1440"
inkscape:window-height="850"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:snap-global="false" />
<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>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2">
<path
style="fill:#008000;fill-rule:evenodd;stroke:#009e00;stroke-width:7.80422115;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 12.067826,56.827639 59.41424,8.9316598"
id="path4333"
inkscape:connector-curvature="0" />
<ellipse
style="opacity:0.97000002;fill:#0047ff;fill-opacity:1;stroke:#001d00;stroke-width:3;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4493"
cx="24.526913"
cy="34.172947"
rx="17.532757"
ry="16.375673" />
<path
style="opacity:1;fill:#008000;fill-opacity:0;stroke:#009f00;stroke-width:7.43599987;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4493-7"
sodipodi:type="arc"
sodipodi:cx="37.555004"
sodipodi:cy="-29.174681"
sodipodi:rx="16.187691"
sodipodi:ry="14.653894"
sodipodi:start="0.72590969"
sodipodi:end="3.3728699"
d="M 49.661711,-19.44719 A 16.187691,14.653894 0 0 1 30.100069,-16.167246 16.187691,14.653894 0 0 1 21.79832,-32.53366"
transform="matrix(0,1,-1,0,0,0)"
sodipodi:open="true" />
<path
style="opacity:1;fill:#0000ff;fill-opacity:1;stroke:#0073a5;stroke-width:6.29300022;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 22.680842,59.920282 c -0.200475,-0.117838 -0.275843,-0.396506 -0.163747,-0.605473 0.06847,-0.127647 6.23255,-6.134563 6.360539,-6.198365 0.392258,-0.195545 0.855076,0.251364 0.642267,0.620185 -0.07284,0.126224 -6.189266,6.102887 -6.331952,6.187254 -0.132981,0.07863 -0.370069,0.07695 -0.507107,-0.0036 z"
id="path4607"
inkscape:connector-curvature="0" />
<path
style="opacity:1;fill:#0000ff;fill-opacity:0;stroke:#074cff;stroke-width:7.17656517;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4493-7-4"
sodipodi:type="arc"
sodipodi:cx="44.282707"
sodipodi:cy="-36.47887"
sodipodi:rx="13.25736"
sodipodi:ry="11.251647"
sodipodi:start="0.72672196"
sodipodi:end="3.961412"
d="m 54.190681,-29.003013 a 13.25736,11.251647 0 0 1 -12.98397,3.468739 13.25736,11.251647 0 0 1 -9.741185,-8.069302 13.25736,11.251647 0 0 1 3.770978,-11.100502"
transform="matrix(0,1,-1,0,0,0)"
sodipodi:open="true" />
<path
style="opacity:1;fill:#0000ff;fill-opacity:1;stroke:#0073a5;stroke-width:6.29300022;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 46.325822,37.304891 c -0.20047,-0.117838 -0.27584,-0.396506 -0.16374,-0.605473 0.0685,-0.127647 6.23255,-6.134563 6.36054,-6.198365 0.39225,-0.195545 0.85507,0.251364 0.64226,0.620185 -0.0728,0.126224 -6.18926,6.102887 -6.33195,6.187254 -0.13298,0.07863 -0.37007,0.07695 -0.50711,-0.0036 z"
id="path4607-6"
inkscape:connector-curvature="0" />
<path
style="opacity:1;fill:#0000ff;fill-opacity:1;stroke:#072307;stroke-width:1.54277837;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 44.168454,39.229883 c -0.908001,-0.908 -0.998269,-1.121269 -0.998269,-2.358524 l 0,-1.360256 3.644687,-3.676019 c 2.004578,-2.021811 4.036843,-3.86211 4.516146,-4.089554 1.797212,-0.852833 4.139833,0.240871 4.729175,2.207919 0.546714,1.824768 -0.06479,2.791622 -4.280797,6.768377 l -3.717275,3.506326 -1.447699,0 c -1.338832,0 -1.52277,-0.07507 -2.445968,-0.998269 z"
id="path4641"
inkscape:connector-curvature="0" />
<path
style="opacity:1;fill:#0000ff;fill-opacity:1;stroke:#072307;stroke-width:1.54277837;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 20.603275,61.975372 c -0.906523,-0.830766 -0.960461,-0.967625 -0.960461,-2.437026 l 0,-1.556829 2.158212,-2.169482 2.158212,-2.169482 1.096936,1.490081 c 1.272296,1.728292 1.911517,2.230819 3.322829,2.612259 l 1.022297,0.2763 -2.484833,2.417188 -2.484833,2.417188 -1.433949,0 c -1.274197,0 -1.540952,-0.09806 -2.39441,-0.880197 z"
id="path4643"
inkscape:connector-curvature="0" />
<path
style="opacity:1;fill:#009b00;fill-opacity:0;stroke:#000400;stroke-width:2.00664043;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 10.299719,60.107011 C 8.7818295,59.359085 8.0163043,57.552175 8.4830143,55.818948 8.691309,55.045399 9.4267017,54.113872 11.504032,51.992202 l 2.745704,-2.804311 -1.094962,-2.229983 c -1.512547,-3.080432 -1.911487,-4.761001 -2.055327,-8.658229 -0.141024,-3.820923 0.340236,-6.49121 1.717225,-9.528096 2.468534,-5.444235 7.787018,-9.78382 13.190103,-10.762386 l 0.964237,-0.174635 0,1.30537 c 0,0.934592 0.111761,1.348256 0.393469,1.456358 0.216408,0.08304 1.660663,-0.402951 3.209455,-1.079989 2.570923,-1.12385 2.877928,-1.202243 3.527759,-0.900802 l 0.711774,0.330174 -1.028519,0.482742 c -0.565685,0.265508 -1.925259,0.881981 -3.021274,1.36994 -1.140664,0.507837 -1.992756,1.044155 -1.992756,1.254268 0,0.377834 3.400167,2.490615 4.008227,2.490615 0.187191,0 0.938003,-0.35239 1.668468,-0.783088 0.730467,-0.430699 1.38199,-0.72922 1.447828,-0.663381 0.06584,0.06584 -0.286556,0.562864 -0.783102,1.1045 l -0.902808,0.984793 -3.812107,0 c -3.602908,0 -3.893283,0.03804 -5.291284,0.693193 -2.980957,1.396978 -5.595059,4.662833 -6.472579,8.086332 -0.514087,2.005628 -0.519114,5.202002 -0.01125,7.151835 0.458319,1.759603 1.714121,4.226974 2.552014,5.014133 l 0.583751,0.548403 0.138307,-3.161621 c 0.149803,-3.424412 0.62962,-5.305959 2.024061,-7.937124 2.054198,-3.876056 5.876382,-6.920658 9.679501,-7.710313 2.048813,-0.425402 5.751411,-0.18275 7.497873,0.491376 0.769386,0.29698 1.449193,0.489656 1.510683,0.428168 0.198859,-0.198859 -0.707613,-2.184063 -1.735394,-3.800566 l -1.001479,-1.575141 8.374705,-8.567639 c 4.606086,-4.712202 8.746389,-8.7973535 9.20067,-9.0781151 0.496011,-0.3065523 1.276071,-0.5100917 1.9527,-0.5095145 2.950451,0.00252 4.709645,2.968509 3.232489,5.4499616 -0.362073,0.608237 -4.657726,5.097196 -9.545901,9.975464 -4.888175,4.878268 -8.887592,8.95862 -8.887592,9.067448 0,0.108828 0.376053,0.536873 0.835672,0.951211 l 0.835672,0.75334 -1.735626,1.756502 c -1.707776,1.728318 -1.735626,1.778587 -1.735626,3.13273 l 0,1.376225 -1.172432,-1.080711 c -1.554467,-1.432858 -2.992553,-2.058305 -4.741552,-2.062183 -5.402156,-0.01198 -9.152604,6.850502 -7.199588,13.173631 0.312121,1.010533 1.019698,2.358358 1.799908,3.42855 1.072307,1.470851 1.285604,1.947765 1.285604,2.874502 0,1.31474 -0.501458,2.392304 -1.381687,2.969054 -0.590896,0.38717 -0.740137,0.382943 -2.079418,-0.05889 -1.712495,-0.564958 -2.147781,-0.92696 -3.663638,-3.046846 -0.63237,-0.884351 -1.245053,-1.549019 -1.361518,-1.477038 -0.116466,0.07198 -0.35226,-0.187982 -0.523987,-0.577691 l -0.312231,-0.708564 -4.245685,4.294683 c -2.335127,2.362076 -4.623047,4.473754 -5.084268,4.692618 -1.076697,0.510927 -2.334922,0.49751 -3.418585,-0.03646 z"
id="path6116"
inkscape:connector-curvature="0" />
<path
style="fill:#072307;fill-opacity:1;fill-rule:evenodd;stroke:#074cff;stroke-width:4.97419834;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 43.772633,24.429864 59.263921,8.7587602"
id="path4333-3"
inkscape:connector-curvature="0" />
</g>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
style="opacity:1">
<g
id="g4358"
transform="matrix(0.58483815,0,0,0.51339436,70.144089,12.290628)">
<path
sodipodi:nodetypes="ccccccccccccccccc"
inkscape:connector-curvature="0"
id="rect4417"
d="m -72.590791,-22.878017 0,17.4659094 c 0,0 0,1.310757 0,8.59375 l 17.343749,-8.59375 0,-1.90625 0,-15.5596594 z m 17.343749,22.55965938 -17.343749,8.56250002 0,7.0312496 17.343749,-8.5937496 z m 0,12.09374962 -14.562499,7.21875 5.937499,3.90625 8.625,-5.71875 z"
style="color:#000000;display:inline;overflow:visible;visibility:visible;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-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
</g>
</g>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="Layer 3" />
</svg>

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -0,0 +1,299 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TaskPanel</class>
<widget class="QWidget" name="TaskPanel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>352</width>
<height>525</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>400</height>
</size>
</property>
<property name="windowTitle">
<string>Surface</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QToolBox" name="toolBox">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="Geometry">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>334</width>
<height>387</height>
</rect>
</property>
<attribute name="icon">
<iconset resource="../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/FreeCAD-default/scalable/accessories-calculator.svg</normaloff>:/icons/FreeCAD-default/scalable/accessories-calculator.svg</iconset>
</attribute>
<attribute name="label">
<string>Base Geometry</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0" colspan="3">
<widget class="QListWidget" name="baseList">
<property name="toolTip">
<string>Drag to reorder, then update.</string>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragDrop</enum>
</property>
<property name="defaultDropAction">
<enum>Qt::MoveAction</enum>
</property>
<property name="sortingEnabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="addBase">
<property name="toolTip">
<string>Add item selected in window.</string>
</property>
<property name="text">
<string>add</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="deleteBase">
<property name="toolTip">
<string>Remove Item selected in list, then update.</string>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="reorderBase">
<property name="toolTip">
<string>Update the path with the removed and reordered items.</string>
</property>
<property name="text">
<string>Update</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="3">
<widget class="QLabel" name="label">
<property name="text">
<string>All objects will be profiled using the same depth and speed settings</string>
</property>
<property name="textFormat">
<enum>Qt::AutoText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="Depths">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>334</width>
<height>387</height>
</rect>
</property>
<attribute name="icon">
<iconset resource="../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/FreeCAD-default/scalable/Part_Measure_Clear_All.svg</normaloff>:/icons/FreeCAD-default/scalable/Part_Measure_Clear_All.svg</iconset>
</attribute>
<attribute name="label">
<string>Depths</string>
</attribute>
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="Gui::InputField" name="startDepth">
<property name="unit" stdset="0">
<string notr="true">mm</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Start Depth</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="Gui::InputField" name="finalDepth">
<property name="unit" stdset="0">
<string notr="true">mm</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Final Depth</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="Gui::InputField" name="finishDepth">
<property name="unit" stdset="0">
<string notr="true">mm</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Finish Depth</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QDoubleSpinBox" name="stepDown">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Step Down</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="Heights">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>334</width>
<height>387</height>
</rect>
</property>
<attribute name="icon">
<iconset resource="../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/FreeCAD-default/scalable/document-open.svg</normaloff>:/icons/FreeCAD-default/scalable/document-open.svg</iconset>
</attribute>
<attribute name="label">
<string>Heights</string>
</attribute>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="Gui::InputField" name="safeHeight">
<property name="unit" stdset="0">
<string notr="true">mm</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Safe Height</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="Gui::InputField" name="clearanceHeight">
<property name="unit" stdset="0">
<string notr="true">mm</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Clearance Height</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_3">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>334</width>
<height>387</height>
</rect>
</property>
<attribute name="icon">
<iconset resource="Resources/Path.qrc">
<normaloff>:/icons/Path-Hamburger.svg</normaloff>:/icons/Path-Hamburger.svg</iconset>
</attribute>
<attribute name="label">
<string>Operation</string>
</attribute>
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Algorithm</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="algorithmSelect">
<item>
<property name="text">
<string>OCL Dropcutter</string>
</property>
</item>
<item>
<property name="text">
<string>OCL Waterline</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Gui::InputField</class>
<extends>QLineEdit</extends>
<header>Gui/InputField.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../../Gui/Icons/resource.qrc"/>
<include location="Resources/Path.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -24,7 +24,7 @@
import FreeCAD,Path
from PySide import QtCore,QtGui
from PathScripts import PathUtils,PathSelection,PathProject
from PathScripts import PathUtils
FreeCADGui = None
if FreeCAD.GuiUp:
@ -43,25 +43,25 @@ except AttributeError:
class ObjectDrilling:
def __init__(self,obj):
obj.addProperty("App::PropertyLinkSubList","Base","Path",translate("Parent Object(s)","The base geometry of this toolpath"))
obj.addProperty("App::PropertyVectorList","locations","Path","The drilling locations")
obj.addProperty("App::PropertyLinkSubList","Base","Path",translate("PathProject","The base geometry of this toolpath"))
obj.addProperty("App::PropertyBool","Active","Path",translate("PathProject","Make False, to prevent operation from generating code"))
obj.addProperty("App::PropertyString","Comment","Path",translate("PathProject","An optional comment for this profile"))
obj.addProperty("App::PropertyLength", "PeckDepth", "Depth", translate("PathProject","Incremental Drill depth before retracting to clear chips"))
obj.addProperty("App::PropertyLength", "StartDepth", "Depth", translate("PathProject","Starting Depth of Tool- first cut depth in Z"))
obj.addProperty("App::PropertyDistance", "ClearanceHeight", "Depth", translate("PathProject","The height needed to clear clamps and obstructions"))
obj.addProperty("App::PropertyDistance", "FinalDepth", "Depth", translate("PathProject","Final Depth of Tool- lowest value in Z"))
obj.addProperty("App::PropertyDistance", "SafeHeight", "Depth", translate("PathProject","Height to clear top of materil"))
obj.addProperty("App::PropertyDistance", "RetractHeight", "Depth", translate("Retract Height","The height where feed starts and height during retract tool when path is finished"))
#obj.addProperty("App::PropertyLength", "VertFeed", "Feed",translate("Vert Feed","Feed rate for vertical moves in Z"))
obj.addProperty("App::PropertyString","Comment","Path",translate("PathProject","An optional comment for this profile"))
obj.addProperty("App::PropertyBool","Active","Path",translate("Active","Make False, to prevent operation from generating code"))
obj.addProperty("App::PropertyDistance", "RetractHeight", "Depth", translate("PathProject","The height where feed starts and height during retract tool when path is finished"))
#Tool Properties
obj.addProperty("App::PropertyIntegerConstraint","ToolNumber","Tool",translate("PathProfile","The tool number in use"))
obj.ToolNumber = (0,0,1000,1)
obj.ToolNumber = (0,0,1000,1)
obj.setEditorMode('ToolNumber',1) #make this read only
obj.Proxy = self
def __getstate__(self):
@ -69,26 +69,24 @@ class ObjectDrilling:
def __setstate__(self,state):
return None
def execute(self,obj):
output = ""
toolLoad = PathUtils.getLastToolLoad(obj)
if toolLoad == None:
self.vertFeed = 100
self.horizFeed = 100
radius = 0.25
obj.ToolNumber= 0
obj.ToolNumber= 0
else:
self.vertFeed = toolLoad.VertFeed.Value
self.horizFeed = toolLoad.HorizFeed.Value
tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
radius = tool.Diameter/2
obj.ToolNumber= toolLoad.ToolNumber
obj.ToolNumber= toolLoad.ToolNumber
if obj.Base:
locations = []
for loc in obj.Base:
if "Face" in loc[1] or "Edge" in loc[1]:
if "Face" in loc[1] or "Edge" in loc[1]:
s = getattr(loc[0].Shape,loc[1])
else:
s = loc[0].Shape
@ -131,6 +129,26 @@ class ObjectDrilling:
def addDrillableLocation(self, obj, ss, sub=""):
baselist = obj.Base
item = (ss, sub)
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
obj.RetractHeight = bb.ZMax + 1.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
obj.RetractHeight = 6.0
if item in baselist:
FreeCAD.Console.PrintWarning("Drillable location already in the list"+ "\n")
else:
@ -151,10 +169,6 @@ class _ViewProviderDrill:
def getIcon(self): #optional
return ":/icons/Path-Drilling.svg"
# def attach(self): #optional
# # this is executed on object creation and object load from file
# pass
def onChanged(self,obj,prop): #optional
# this is executed when a property of the VIEW PROVIDER changes
pass
@ -188,8 +202,6 @@ class CommandPathDrilling:
return not FreeCAD.ActiveDocument is None
def Activated(self):
import Path, Part
# if everything is ok, execute and register the transaction in the undo/redo stack
FreeCAD.ActiveDocument.openTransaction(translate("Path_Drilling","Create Drilling"))
@ -221,14 +233,14 @@ class TaskPanel:
FreeCADGui.ActiveDocument.resetEdit()
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
FreeCADGui.Selection.removeObserver(self.s)
FreeCADGui.Selection.removeObserver(self.s)
def reject(self):
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
FreeCADGui.Selection.removeObserver(self.s)
FreeCADGui.Selection.removeObserver(self.s)
def getFields(self):
def getFields(self):
if self.obj:
if hasattr(self.obj,"StartDepth"):
self.obj.StartDepth = self.form.startDepth.text()
@ -248,7 +260,7 @@ class TaskPanel:
def open(self):
self.s =SelObserver()
# install the function mode resident
FreeCADGui.Selection.addObserver(self.s)
FreeCADGui.Selection.addObserver(self.s)
def addBase(self):
# check that the selection contains exactly what we want
@ -261,14 +273,15 @@ class TaskPanel:
if s.HasSubObjects:
for i in s.SubElementNames:
self.obj.Proxy.addDrillableLocation(self.obj, s.Object, i)
else:
else:
self.obj.Proxy.addDrillableLocation(self.obj, s.Object)
self.setupUi() #defaults may have changed. Reload.
self.form.baseList.clear()
for i in self.obj.Base:
for i in self.obj.Base:
self.form.baseList.addItem(i[0].Name + "." + i[1])
def deleteBase(self):
dlist = self.form.baseList.selectedItems()
for d in dlist:
@ -288,7 +301,7 @@ class TaskPanel:
objstring = i.text().partition(".")
obj = FreeCAD.ActiveDocument.getObject(objstring[0])
# sub = o.Shape.getElement(objstring[2])
if objstring[2] != "":
if objstring[2] != "":
FreeCADGui.Selection.addSelection(obj,objstring[2])
else:
FreeCADGui.Selection.addSelection(obj)
@ -321,29 +334,28 @@ class TaskPanel:
self.form.retractHeight.setText(str(self.obj.RetractHeight.Value))
for i in self.obj.Base:
for i in self.obj.Base:
self.form.baseList.addItem(i[0].Name + "." + i[1])
#Connect Signals and Slots
self.form.startDepth.editingFinished.connect(self.getFields) #This is newer syntax
#QtCore.QObject.connect(self.form.startDepth, QtCore.SIGNAL("editingFinished()"), self.getFields)
QtCore.QObject.connect(self.form.finalDepth, QtCore.SIGNAL("editingFinished()"), self.getFields)
QtCore.QObject.connect(self.form.safeHeight, QtCore.SIGNAL("editingFinished()"), self.getFields)
QtCore.QObject.connect(self.form.clearanceHeight, QtCore.SIGNAL("editingFinished()"), self.getFields)
self.form.finalDepth.editingFinished.connect(self.getFields)
self.form.safeHeight.editingFinished.connect(self.getFields)
self.form.clearanceHeight.editingFinished.connect(self.getFields)
QtCore.QObject.connect(self.form.addBase, QtCore.SIGNAL("clicked()"), self.addBase)
QtCore.QObject.connect(self.form.deleteBase, QtCore.SIGNAL("clicked()"), self.deleteBase)
QtCore.QObject.connect(self.form.reorderBase, QtCore.SIGNAL("clicked()"), self.reorderBase)
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)
class SelObserver:
def __init__(self):
import PathScripts.PathSelection as PST
import PathScripts.PathSelection as PST
PST.drillselect()
def __del__(self):
import PathScripts.PathSelection as PST
import PathScripts.PathSelection as PST
PST.clear()
def addSelection(self,doc,obj,sub,pnt): # Selection object
@ -351,7 +363,7 @@ class SelObserver:
FreeCADGui.updateGui()
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_Drilling',CommandPathDrilling())

View File

@ -22,10 +22,10 @@
#* *
#***************************************************************************
import FreeCAD,FreeCADGui,Path,PathGui,Draft
import FreeCAD,FreeCADGui,Path,Draft
from PySide import QtCore,QtGui
from PathScripts import PathUtils,PathProject
from PathScripts import PathUtils
"""Path Engrave object and FreeCAD command"""
@ -40,16 +40,19 @@ except AttributeError:
class ObjectPathEngrave:
def __init__(self,obj):
obj.addProperty("App::PropertyLinkSubList","Base","Path","The base geometry of this object")
obj.addProperty("App::PropertyBool","Active","Path",translate("Path","Make False, to prevent operation from generating code"))
obj.addProperty("App::PropertyString","Comment","Path",translate("Path","An optional comment for this profile"))
obj.addProperty("App::PropertyEnumeration", "Algorithm", "Algorithm",translate("Path", "The library or Algorithm used to generate the path"))
obj.Algorithm = ['OCC Native']
#Tool Properties
obj.addProperty("App::PropertyIntegerConstraint","ToolNumber","Tool",translate("Path","The tool number in use"))
obj.ToolNumber = (0,0,1000,1)
obj.ToolNumber = (0,0,1000,1)
obj.setEditorMode('ToolNumber',1) #make this read only
#Depth Properties
@ -58,7 +61,6 @@ class ObjectPathEngrave:
obj.addProperty("App::PropertyDistance", "StartDepth", "Depth", translate("Path","Starting Depth of Tool- first cut depth in Z"))
obj.addProperty("App::PropertyDistance", "FinalDepth", "Depth", translate("Path","Final Depth of Tool- lowest value in Z"))
obj.addProperty("App::PropertyInteger","StartVertex","Path","The vertex index to start the path from")
#Feed Properties
if FreeCAD.GuiUp:
_ViewProviderEngrave(obj.ViewObject)
@ -70,22 +72,22 @@ class ObjectPathEngrave:
def __setstate__(self,state):
return None
def execute(self,obj):
output = ""
toolLoad = PathUtils.getLastToolLoad(obj)
if toolLoad == None:
self.vertFeed = 100
self.horizFeed = 100
radius = 0.25
obj.ToolNumber= 0
self.radius = 0.25
obj.ToolNumber= 0
else:
self.vertFeed = toolLoad.VertFeed.Value
self.horizFeed = toolLoad.HorizFeed.Value
tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
radius = tool.Diameter/2
obj.ToolNumber= toolLoad.ToolNumber
self.radius = tool.Diameter/2
obj.ToolNumber= toolLoad.ToolNumber
if obj.Base:
for o in obj.Base:
@ -111,10 +113,10 @@ class ObjectPathEngrave:
for wire in wires:
offset = wire
# reorder the wire
offset = DraftGeomUtils.rebaseWire(offset,obj.StartVertex)
# we create the path from the offset shape
last = None
for edge in offset.Edges:
@ -153,6 +155,24 @@ class ObjectPathEngrave:
def addShapeString(self, obj, ss):
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, "")
if item in baselist:
FreeCAD.Console.PrintWarning("ShapeString already in the Engraving list"+ "\n")
@ -198,9 +218,9 @@ class CommandPathEngrave:
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
# if everything is ok, execute and register the transaction in the undo/redo stack
FreeCAD.ActiveDocument.openTransaction("Create Engrave Path")
@ -231,14 +251,14 @@ class TaskPanel:
FreeCADGui.ActiveDocument.resetEdit()
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
FreeCADGui.Selection.removeObserver(self.s)
FreeCADGui.Selection.removeObserver(self.s)
def reject(self):
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
FreeCADGui.Selection.removeObserver(self.s)
FreeCADGui.Selection.removeObserver(self.s)
def getFields(self):
def getFields(self):
if self.obj:
if hasattr(self.obj,"StartDepth"):
self.obj.StartDepth = self.form.startDepth.text()
@ -255,7 +275,7 @@ class TaskPanel:
def open(self):
self.s =SelObserver()
# install the function mode resident
FreeCADGui.Selection.addObserver(self.s)
FreeCADGui.Selection.addObserver(self.s)
def addBase(self):
# check that the selection contains exactly what we want
@ -271,7 +291,7 @@ class TaskPanel:
self.obj.Proxy.addShapeString(self.obj, s.Object)
self.form.baseList.clear()
for i in self.obj.Base:
for i in self.obj.Base:
self.form.baseList.addItem(i[0].Name)
def deleteBase(self):
@ -313,38 +333,35 @@ class TaskPanel:
self.form.safeHeight.setText(str(self.obj.SafeHeight.Value))
self.form.clearanceHeight.setText(str(self.obj.ClearanceHeight.Value))
for i in self.obj.Base:
for i in self.obj.Base:
self.form.baseList.addItem(i[0].Name)
#Connect Signals and Slots
self.form.startDepth.editingFinished.connect(self.getFields) #This is newer syntax
#QtCore.QObject.connect(self.form.startDepth, QtCore.SIGNAL("editingFinished()"), self.getFields)
QtCore.QObject.connect(self.form.finalDepth, QtCore.SIGNAL("editingFinished()"), self.getFields)
QtCore.QObject.connect(self.form.safeHeight, QtCore.SIGNAL("editingFinished()"), self.getFields)
QtCore.QObject.connect(self.form.clearanceHeight, QtCore.SIGNAL("editingFinished()"), self.getFields)
self.form.startDepth.editingFinished.connect(self.getFields)
self.form.finalDepth.editingFinished.connect(self.getFields)
self.form.safeHeight.editingFinished.connect(self.getFields)
self.form.clearanceHeight.editingFinished.connect(self.getFields)
QtCore.QObject.connect(self.form.addBase, QtCore.SIGNAL("clicked()"), self.addBase)
QtCore.QObject.connect(self.form.deleteBase, QtCore.SIGNAL("clicked()"), self.deleteBase)
QtCore.QObject.connect(self.form.reorderBase, QtCore.SIGNAL("clicked()"), self.reorderBase)
QtCore.QObject.connect(self.form.baseList, QtCore.SIGNAL("itemSelectionChanged()"), self.itemActivated)
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)
class SelObserver:
def __init__(self):
import PathScripts.PathSelection as PST
import PathScripts.PathSelection as PST
PST.engraveselect()
def __del__(self):
import PathScripts.PathSelection as PST
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:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_Engrave',CommandPathEngrave())

View File

@ -44,12 +44,12 @@ except AttributeError:
class ObjectPocket:
def __init__(self,obj):
obj.addProperty("App::PropertyLinkSubList","Base","Path",translate("PathProject","The base geometry of this object"))
obj.addProperty("App::PropertyBool","Active","Path",translate("PathProject","Make False, to prevent operation from generating code"))
obj.addProperty("App::PropertyString","Comment","Path",translate("PathProject","An optional comment for this profile"))
obj.addProperty("App::PropertyEnumeration", "Algorithm", "Algorithm",translate("PathProject", "The library to use to generate the path"))
obj.Algorithm = ['OCC Native','libarea']
@ -113,19 +113,35 @@ class ObjectPocket:
return None
def addpocketbase(self, obj, ss, sub=""):
#sublist = []
#sublist.append(sub)
baselist = obj.Base
if baselist == None:
baselist = []
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
print "this base is: " + str(baselist)
self.execute(obj)
print "this base is: " + str(baselist)
self.execute(obj)
def getStock(self,obj):
"retrieves a stock object from hosting project if any"
@ -140,16 +156,14 @@ class ObjectPocket:
return None
def buildpathlibarea(self, obj, a):
import PathScripts.PathUtils as PathUtils
import PathScripts.PathAreaUtils as PathAreaUtils
from PathScripts.PathUtils import depth_params
import area
FreeCAD.Console.PrintMessage(translate("PathPocket","Generating toolpath with libarea offsets.\n"))
depthparams = depth_params (obj.ClearanceHeight.Value, obj.SafeHeight.Value, obj.StartDepth.Value, obj.StepDown, obj.FinishDepth.Value, obj.FinalDepth.Value)
horizfeed = self.horizFeed
extraoffset = obj.MaterialAllowance.Value
stepover = obj.StepOver
use_zig_zag = obj.UseZigZag
@ -159,7 +173,7 @@ class ObjectPocket:
zig_unidirectional = obj.ZigUnidirectional
start_point = None
cut_mode = obj.CutMode
PathAreaUtils.flush_nc()
PathAreaUtils.output('mem')
PathAreaUtils.feedrate_hv(self.horizFeed, self.vertFeed)
@ -214,7 +228,7 @@ class ObjectPocket:
retstr += str("%.4f" % self.horizFeed)
else:
retstr += str("%.4f" % self.vertFeed)
if (x != None) or (y != None) or (z != None):
if (x != None):
retstr += " X" + str("%.4f" % x)
@ -235,7 +249,7 @@ class ObjectPocket:
if (math.sqrt((cx - sx)**2 + (cy - sy)**2) - math.sqrt((cx - ex)**2 + (cy - ey)**2)) >= eps:
print "ERROR: Illegal arc: Stand and end radii not equal"
return ""
#Set [C]CW and feed
retstr = ""
if ccw:
@ -243,17 +257,17 @@ class ObjectPocket:
else:
retstr += "G02 F"
retstr += str(self.horizFeed)
#End location
retstr += " X" + str("%.4f" % ex) + " Y" + str("%.4f" % ey)
#Helix if requested
if ez != None:
retstr += " Z" + str("%.4f" % ez)
#Append center offsets
retstr += " I" + str("%.4f" % (cx - sx)) + " J" + str("%.4f" % (cy - sy))
return retstr + "\n"
def helicalPlunge(plungePos, rampangle, destZ, startZ):
@ -270,14 +284,14 @@ class ObjectPocket:
helixX = plungePos.x + tool.Diameter/2. * plungeR
helixY = plungePos.y;
helixCirc = math.pi * tool.Diameter * plungeR
dzPerRev = math.sin(rampangle/180. * math.pi) * helixCirc
#Go to the start of the helix position
helixCmds += rapid(helixX, helixY)
helixCmds += rapid(z=startZ)
#Helix as required to get to the requested depth
lastZ = startZ
curZ = max(startZ-dzPerRev, destZ)
@ -286,14 +300,14 @@ class ObjectPocket:
done = (curZ == destZ)
#NOTE: FreeCAD doesn't render this, but at least LinuxCNC considers it valid
#helixCmds += arc(plungePos.x, plungePos.y, helixX, helixY, helixX, helixY, ez = curZ, ccw=True)
#Use two half-helixes; FreeCAD renders that correctly,
#and it fits with the other code breaking up 360-degree arcs
helixCmds += arc(plungePos.x, plungePos.y, helixX, helixY, helixX - tool.Diameter * plungeR, helixY, ez = (curZ + lastZ)/2., ccw=True)
helixCmds += arc(plungePos.x, plungePos.y, helixX - tool.Diameter * plungeR, helixY, helixX, helixY, ez = curZ, ccw=True)
lastZ = curZ
curZ = max(curZ - dzPerRev, destZ)
return helixCmds
def rampPlunge(edge, rampangle, destZ, startZ):
@ -310,8 +324,8 @@ class ObjectPocket:
return None
if(not tool):
raise Error("Ramp plunging requires a tool!")
sPoint = edge.Vertexes[0].Point
ePoint = edge.Vertexes[1].Point
#Evidently edges can get flipped- pick the right one in this case
@ -320,21 +334,21 @@ class ObjectPocket:
#print "FLIP"
ePoint = edge.Vertexes[-1].Point
#print "Start: " + str(sPoint) + " End: " + str(ePoint) + " Zhigh: " + prnt(startZ) + " ZLow: " + prnt(destZ)
rampDist = edge.Length
rampDZ = math.sin(rampangle/180. * math.pi) * rampDist
rampCmds += rapid(sPoint.x, sPoint.y)
rampCmds += rapid(z=startZ)
#Ramp down to the requested depth
#FIXME: This might be an arc, so handle that as well
lastZ = startZ
curZ = max(startZ-rampDZ, destZ)
done = False
while not done:
done = (curZ == destZ)
#If it's an arc, handle it!
if isinstance(edge.Curve,Part.Circle):
raise Error("rampPlunge: Screw it, not handling an arc.")
@ -343,12 +357,9 @@ class ObjectPocket:
rampCmds += feed(ePoint.x, ePoint.y, curZ)
rampCmds += feed(sPoint.x, sPoint.y)
lastZ = curZ
curZ = max(curZ - rampDZ, destZ)
return rampCmds
return rampCmds
output = ""
offsets = []
@ -360,12 +371,12 @@ class ObjectPocket:
offsets.extend(result)
nextradius += self.radius
result = DraftGeomUtils.pocket2d(shape,nextradius)
# first move will be rapid, subsequent will be at feed rate
first = True
startPoint = None
fastZPos = max(obj.StartDepth.Value + 2, obj.ClearanceHeight.Value)
# revert the list so we start with the outer wires
if obj.StartAt != 'Edge':
offsets.reverse()
@ -378,7 +389,7 @@ class ObjectPocket:
#Fraction of tool radius our plunge helix is to be
plungeR = obj.HelixSize
#(minimum) Fraction of tool DIAMETER to go back and forth while ramp-plunging
#FIXME: The ramp plunging should maybe even be limited to this distance; I don't know what's best
rampD = obj.RampSize
@ -386,8 +397,8 @@ class ObjectPocket:
#Total offset from the desired pocket edge is tool radius plus the plunge helix radius
#Any point on these curves could be the center of a plunge
helixBounds = DraftGeomUtils.pocket2d(shape, self.radius * (1 + plungeR))
#Try to find a location to nicely plunge, starting with a helix, then ramp
#Can't do it without knowledge of a tool
plungePos = None
@ -400,7 +411,7 @@ class ObjectPocket:
#Since we're going to start machining either the inner-most
#edge or the outer (depending on StartAt setting), try to
#plunge near that location
if helixBounds and obj.UseEntry:
#Edge is easy- pick a point on helixBounds and go with it
if obj.StartAt == 'Edge':
@ -408,7 +419,7 @@ class ObjectPocket:
#Center is harder- use a point from the first offset, check if it works
else:
plungePos = offsets[0].Edges[0].Vertexes[0].Point
#If it turns out this is invalid for some reason, nuke plungePos
[perp,idx] = DraftGeomUtils.findPerpendicular(plungePos, shape.Edges)
if not perp or perp.Length < self.radius * (1 + plungeR):
@ -416,8 +427,7 @@ class ObjectPocket:
#FIXME: Really need to do a point-in-polygon operation to make sure this is within helixBounds
#Or some math to prove that it has to be (doubt that's true)
#Maybe reverse helixBounds and pick off that?
#If we didn't find a place to helix, how about a ramp?
if not plungePos and obj.UseEntry:
#Check first edge of our offsets
@ -429,7 +439,6 @@ class ObjectPocket:
else:
print "Neither edge works: " + str(offsets[0].Edges[0]) + ", " + str(offsets[0].Edges[-1])
#FIXME: There's got to be a smarter way to find a place to ramp
#For helix-ing/ramping, know where we were last time
#FIXME: Can probably get this from the "machine"?
@ -509,13 +518,13 @@ class ObjectPocket:
self.horizFeed = toolLoad.HorizFeed.Value
tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
self.radius = tool.Diameter/2
obj.ToolNumber= toolLoad.ToolNumber
obj.ToolNumber= toolLoad.ToolNumber
if obj.Base:
for b in obj.Base:
print "object base: " + str(b)
import Part, PathScripts.PathKurveUtils, DraftGeomUtils
import Part, PathScripts.PathKurveUtils
if "Face" in b[1]:
print "inside"
shape = getattr(b[0].Shape,b[1])
@ -528,7 +537,6 @@ class ObjectPocket:
wire = Part.Wire(edges)
shape = None
# output = ""
if obj.Algorithm == "OCC Native":
if shape == None:
@ -540,7 +548,7 @@ class ObjectPocket:
except:
FreeCAD.Console.PrintError(translate("PathKurve","libarea needs to be installed for this command to work.\n"))
return
a = area.Area()
if shape == None:
c = PathScripts.PathKurveUtils.makeAreaCurve(wire.Edges, 'CW')
@ -564,8 +572,7 @@ class ObjectPocket:
##This puts out some interesting information from libarea
print a.text()
########
a.Reorder()
output += self.buildpathlibarea(obj, a)
@ -587,7 +594,7 @@ class _CommandSetPocketStartPoint:
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def setpoint(self,point,o):
obj=FreeCADGui.Selection.getSelection()[0]
obj.StartPoint.x = point.x
@ -636,7 +643,7 @@ class CommandPathPocket:
return not FreeCAD.ActiveDocument is None
def Activated(self):
# check that the selection contains exactly what we want
# selection = FreeCADGui.Selection.getSelectionEx()
# if len(selection) != 1:
@ -672,18 +679,18 @@ class CommandPathPocket:
zbottom = 0.0
ztop = 10.0
# if everything is ok, execute and register the transaction in the undo/redo stack
FreeCAD.ActiveDocument.openTransaction(translate("PathPocket","Create Pocket"))
FreeCADGui.addModule("PathScripts.PathPocket")
FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Pocket")')
FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Pocket")')
FreeCADGui.doCommand('PathScripts.PathPocket.ObjectPocket(obj)')
FreeCADGui.doCommand('obj.Active = True')
FreeCADGui.doCommand('PathScripts.PathPocket.ViewProviderPocket(obj.ViewObject)')
FreeCADGui.doCommand('from PathScripts import PathUtils')
FreeCADGui.doCommand('obj.StepOver = 1.0')
@ -698,7 +705,7 @@ class CommandPathPocket:
FreeCADGui.doCommand('obj.HelixSize = 0.75')
FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)')
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
FreeCADGui.doCommand('obj.ViewObject.startEditing()')
@ -716,14 +723,14 @@ class TaskPanel:
FreeCADGui.ActiveDocument.resetEdit()
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
FreeCADGui.Selection.removeObserver(self.s)
FreeCADGui.Selection.removeObserver(self.s)
def reject(self):
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
FreeCADGui.Selection.removeObserver(self.s)
FreeCADGui.Selection.removeObserver(self.s)
def getFields(self):
def getFields(self):
if self.obj:
if hasattr(self.obj,"StartDepth"):
self.obj.StartDepth = self.form.startDepth.text()
@ -748,7 +755,7 @@ class TaskPanel:
def open(self):
self.s =SelObserver()
# install the function mode resident
FreeCADGui.Selection.addObserver(self.s)
FreeCADGui.Selection.addObserver(self.s)
def addBase(self):
# check that the selection contains exactly what we want
@ -761,13 +768,14 @@ class TaskPanel:
if s.HasSubObjects:
for i in s.SubElementNames:
self.obj.Proxy.addpocketbase(self.obj, s.Object, i)
else:
else:
self.obj.Proxy.addpocketbase(self.obj, s.Object)
self.setupUi() #defaults may have changed. Reload.
self.form.baseList.clear()
for i in self.obj.Base:
for i in self.obj.Base:
self.form.baseList.addItem(i[0].Name + "." + i[1])
def deleteBase(self):
dlist = self.form.baseList.selectedItems()
newlist = []
@ -787,7 +795,7 @@ class TaskPanel:
objstring = i.text().partition(".")
obj = FreeCAD.ActiveDocument.getObject(objstring[0])
# sub = o.Shape.getElement(objstring[2])
if objstring[2] != "":
if objstring[2] != "":
FreeCADGui.Selection.addSelection(obj,objstring[2])
else:
FreeCADGui.Selection.addSelection(obj)
@ -829,7 +837,7 @@ class TaskPanel:
if index >= 0:
self.form.algorithmSelect.setCurrentIndex(index)
for i in self.obj.Base:
for i in self.obj.Base:
self.form.baseList.addItem(i[0].Name + "." + i[1])
#Connect Signals and Slots
@ -840,35 +848,35 @@ class TaskPanel:
self.form.reorderBase.clicked.connect(self.reorderBase)
#Depths
self.form.startDepth.editingFinished.connect(self.getFields)
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.algorithmSelect.currentIndexChanged.connect(self.getFields)
self.form.cutMode.currentIndexChanged.connect(self.getFields)
self.form.useStartPoint.clicked.connect(self.getFields)
self.form.extraOffset.editingFinished.connect(self.getFields)
class SelObserver:
def __init__(self):
import PathScripts.PathSelection as PST
import PathScripts.PathSelection as PST
PST.pocketselect()
def __del__(self):
import PathScripts.PathSelection as PST
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:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_Pocket',CommandPathPocket())
FreeCADGui.addCommand('Set_PocketStartPoint',_CommandSetPocketStartPoint())

View File

@ -59,10 +59,10 @@ class ObjectProfile:
obj.addProperty("App::PropertyString","Comment","Path",translate("Path","An optional comment for this profile"))
obj.addProperty("App::PropertyEnumeration", "Algorithm", "Algorithm",translate("Path", "The library or algorithm used to generate the path"))
obj.Algorithm = ['OCC Native','libareal']
obj.Algorithm = ['OCC Native','libarea']
obj.addProperty("App::PropertyIntegerConstraint","ToolNumber","Tool",translate("Path","The tool number in use"))
obj.ToolNumber = (0,0,1000,1)
obj.ToolNumber = (0,0,1000,1)
obj.setEditorMode('ToolNumber',1) #make this read only
#Depth Properties
@ -72,7 +72,7 @@ class ObjectProfile:
obj.StepDown = (1,0.01,1000,0.5)
obj.addProperty("App::PropertyDistance", "StartDepth", "Depth", translate("Path","Starting Depth of Tool- first cut depth in Z"))
obj.addProperty("App::PropertyDistance", "FinalDepth", "Depth", translate("Path","Final Depth of Tool- lowest value in Z"))
#Start Point Properties
obj.addProperty("App::PropertyVector","StartPoint","Start Point",translate("Path_Profile","The start point of this path"))
obj.addProperty("App::PropertyBool","UseStartPoint","Start Point",translate("Path_Profile","make True, if specifying a Start Point"))
@ -121,6 +121,24 @@ class ObjectProfile:
def addprofilebase(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")
@ -164,7 +182,7 @@ class ObjectProfile:
output = ""
if obj.StartPoint and obj.UseStartPoint:
startpoint = obj.StartPoint
startpoint = obj.StartPoint
else:
startpoint = None
@ -198,7 +216,7 @@ print "y - " + str(point.y)
extend_at_end = 0.0
lead_in_line_len=0.0
lead_out_line_len= 0.0
'''
Right here, I need to know the Holding Tags group from the tree that refers to this profile operation and build up the tags for PathKurve Utils.
@ -212,7 +230,7 @@ print "y - " + str(point.y)
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, \
@ -241,17 +259,17 @@ print "y - " + str(point.y)
self.vertFeed = 100
self.horizFeed = 100
self.radius = 0.25
obj.ToolNumber= 0
obj.ToolNumber= 0
else:
self.vertFeed = toolLoad.VertFeed.Value
self.horizFeed = toolLoad.HorizFeed.Value
tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
self.radius = tool.Diameter/2
obj.ToolNumber= toolLoad.ToolNumber
obj.ToolNumber= toolLoad.ToolNumber
if obj.Base:
for b in obj.Base:
# we only consider the outer wire if this is a Face
#shape = getattr(obj.Base[0][0].Shape,obj.Base[0][1])
shape = getattr(b[0].Shape,b[1])
@ -259,7 +277,7 @@ print "y - " + str(point.y)
if shape.ShapeType in ["Edge"]:
edges = [getattr(obj.Base[0].Shape,sub) for sub in obj.Base[1]]
wire = Part.Wire(edges)
if not wire.Edges[0].isSame(shape):
wire.Edges.reverse()
@ -268,10 +286,10 @@ print "y - " + str(point.y)
edgelist = wire.Edges
edgelist = Part.__sortEdges__(edgelist)
if obj.Algorithm == "OCC Native":
output += self._buildPathOCC(obj, wire)
else:
try:
import area
@ -325,7 +343,7 @@ class _CommandAddTag:
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def setpoint(self,point,o):
obj=FreeCADGui.Selection.getSelection()[0]
obj.StartPoint.x = point.x
@ -334,7 +352,7 @@ class _CommandAddTag:
h = obj.heights
l = obj.lengths
a = obj.angles
x = point.x
y = point.y
z = float(0.0)
@ -360,7 +378,7 @@ class _CommandSetStartPoint:
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def setpoint(self,point,o):
obj=FreeCADGui.Selection.getSelection()[0]
obj.StartPoint.x = point.x
@ -377,7 +395,7 @@ class _CommandSetEndPoint:
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def setpoint(self,point,o):
obj=FreeCADGui.Selection.getSelection()[0]
obj.EndPoint.x = point.x
@ -396,7 +414,7 @@ class CommandPathProfile:
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
#import Path
#from PathScripts import PathProject, PathUtils, PathKurveUtils
@ -416,7 +434,7 @@ class CommandPathProfile:
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.Side = "Left"')
FreeCADGui.doCommand('obj.OffsetExtra = 0.0')
@ -441,14 +459,14 @@ class TaskPanel:
FreeCADGui.ActiveDocument.resetEdit()
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
FreeCADGui.Selection.removeObserver(self.s)
FreeCADGui.Selection.removeObserver(self.s)
def reject(self):
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
FreeCADGui.Selection.removeObserver(self.s)
FreeCADGui.Selection.removeObserver(self.s)
def getFields(self):
def getFields(self):
if self.obj:
if hasattr(self.obj,"StartDepth"):
self.obj.StartDepth = self.form.startDepth.text()
@ -483,7 +501,7 @@ class TaskPanel:
def open(self):
self.s =SelObserver()
# install the function mode resident
FreeCADGui.Selection.addObserver(self.s)
FreeCADGui.Selection.addObserver(self.s)
def addBase(self):
# check that the selection contains exactly what we want
@ -496,13 +514,13 @@ class TaskPanel:
if s.HasSubObjects:
for i in s.SubElementNames:
self.obj.Proxy.addprofilebase(self.obj, s.Object, i)
else:
else:
self.obj.Proxy.addprofilebase(self.obj, s.Object)
self.setupUi() #defaults may have changed. Reload.
self.form.baseList.clear()
for i in self.obj.Base:
for i in self.obj.Base:
self.form.baseList.addItem(i[0].Name + "." + i[1])
def deleteBase(self):
dlist = self.form.baseList.selectedItems()
newlist = []
@ -522,7 +540,7 @@ class TaskPanel:
objstring = i.text().partition(".")
obj = FreeCAD.ActiveDocument.getObject(objstring[0])
# sub = o.Shape.getElement(objstring[2])
if objstring[2] != "":
if objstring[2] != "":
FreeCADGui.Selection.addSelection(obj,objstring[2])
else:
FreeCADGui.Selection.addSelection(obj)
@ -557,7 +575,7 @@ class TaskPanel:
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 == None) or (remove != i):
@ -655,7 +673,7 @@ class TaskPanel:
self.form.direction.setCurrentIndex(index)
for i in self.obj.Base:
for i in self.obj.Base:
self.form.baseList.addItem(i[0].Name + "." + i[1])
for i in range(len(self.obj.locs)):
@ -677,14 +695,14 @@ class TaskPanel:
self.form.reorderBase.clicked.connect(self.reorderBase)
#Depths
self.form.startDepth.editingFinished.connect(self.getFields)
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.algorithmSelect.currentIndexChanged.connect(self.getFields)
self.form.cutSide.currentIndexChanged.connect(self.getFields)
@ -695,7 +713,7 @@ class TaskPanel:
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)
@ -704,11 +722,11 @@ class TaskPanel:
class SelObserver:
def __init__(self):
import PathScripts.PathSelection as PST
import PathScripts.PathSelection as PST
PST.profileselect()
def __del__(self):
import PathScripts.PathSelection as PST
import PathScripts.PathSelection as PST
PST.clear()
def addSelection(self,doc,obj,sub,pnt): # Selection object
@ -716,7 +734,7 @@ class SelObserver:
FreeCADGui.updateGui()
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_Profile',CommandPathProfile())
FreeCADGui.addCommand('Add_Tag',_CommandAddTag())

View File

@ -35,10 +35,7 @@ def equals(p1,p2):
v = Vector(p2.X,p2.Y,p2.Z)
vector = (u.sub(v))
isNull = (round(vector.x,p)==0 and round(vector.y,p)==0 and round(vector.z,p)==0)
return isNull
return isNull
def segments(poly):
''' A sequence of (x,y) numeric coordinates pairs '''
@ -67,6 +64,11 @@ class EGate:
def allow(self,doc,obj,sub):
return (sub[0:4] == 'Edge')
class MESHGate:
def allow(self,doc,obj,sub):
print obj.TypeId[0:4] == 'Mesh'
return (obj.TypeId[0:4] == 'Mesh')
class ENGRAVEGate:
def allow(self,doc,obj,sub):
return (obj.Name[0:11] == 'ShapeString')
@ -79,15 +81,15 @@ class DRILLGate:
obj = obj.Shape
except:
return False
if obj.ShapeType == 'Vertex':
if obj.ShapeType == 'Vertex':
drillable = True
elif obj.ShapeType == 'Edge':
elif obj.ShapeType == 'Edge':
if isinstance(obj.Curve, Part.Circle):
drillable = True
elif obj.ShapeType == 'Face':
drillable = True
elif obj.ShapeType == 'Face':
if isinstance(obj.Edges[0].Curve, Part.Circle):
drillable = True
elif obj.ShapeType == 'Wire':
drillable = True
elif obj.ShapeType == 'Wire':
if isinstance(obj.Edges[0].Curve, Part.Circle):
drillable = True
elif obj.ShapeType == 'Solid':
@ -111,7 +113,7 @@ class PROFILEGate:
return False
if obj.ShapeType == 'Edge':
if obj.ShapeType == 'Edge':
profileable = True
elif obj.ShapeType == 'Face':
@ -124,12 +126,12 @@ class PROFILEGate:
if sub[0:4] == 'Edge':
profileable = True
elif obj.ShapeType == 'Wire':
elif obj.ShapeType == 'Wire':
profileable = True
if sub[0:6] == 'Vertex':
print "might be fun to try to derive the loop by hovering near a vertex"
return profileable
class POCKETGate:
@ -143,7 +145,7 @@ class POCKETGate:
return False
if obj.ShapeType == 'Edge':
if obj.ShapeType == 'Edge':
pocketable = False
elif obj.ShapeType == 'Face':
@ -156,12 +158,12 @@ class POCKETGate:
# if sub[0:4] == 'Edge':
# pocketable = True
# elif obj.ShapeType == 'Wire':
# elif obj.ShapeType == 'Wire':
# pocketable = True
# if sub[0:6] == 'Vertex':
# print "might be fun to try to derive the loop by hovering near a vertex"
return pocketable
@ -183,19 +185,20 @@ def drillselect():
def engraveselect():
FreeCADGui.Selection.addSelectionGate(ENGRAVEGate())
FreeCAD.Console.PrintWarning("Engrave Select Mode\n")
FreeCAD.Console.PrintWarning("Engraving Select Mode\n")
def profileselect():
FreeCADGui.Selection.addSelectionGate(PROFILEGate())
FreeCAD.Console.PrintWarning("Profile Select Mode\n")
FreeCAD.Console.PrintWarning("Profiling Select Mode\n")
def pocketselect():
FreeCADGui.Selection.addSelectionGate(POCKETGate())
FreeCAD.Console.PrintWarning("Pocket Select Mode\n")
FreeCAD.Console.PrintWarning("Pocketing Select Mode\n")
def surfaceselect():
FreeCADGui.Selection.addSelectionGate(MESHGate())
FreeCAD.Console.PrintWarning("Surfacing Select Mode\n")
def clear():
FreeCADGui.Selection.removeSelectionGate()
FreeCAD.Console.PrintWarning("Free Select\n")

View File

@ -23,11 +23,10 @@
#***************************************************************************
import FreeCAD,Path
from FreeCAD import Vector
from PathScripts import PathUtils,PathSelection,PathProject
from PathScripts import PathUtils
if FreeCAD.GuiUp:
import FreeCADGui, PathGui
import FreeCADGui
from PySide import QtCore, QtGui
from DraftTools import translate
from pivy import coin
@ -52,12 +51,12 @@ except AttributeError:
class ObjectSurface:
def __init__(self,obj):
obj.addProperty("App::PropertyLinkSub","Base","Path",translate("Parent Object(s)","The base geometry of this toolpath"))
obj.addProperty("App::PropertyLinkSubList","Base","Path",translate("Parent Object(s)","The base geometry of this toolpath"))
obj.addProperty("App::PropertyBool","Active","Path",translate("Active","Make False, to prevent operation from generating code"))
obj.addProperty("App::PropertyString","Comment","Path",translate("PathProject","An optional comment for this profile"))
obj.addProperty("App::PropertyEnumeration", "Algorithm", "Algorithm",translate("PathProject", "The library to use to generate the path"))
obj.Algorithm = ['OCL Dropcutter', 'OCL Waterline']
@ -69,22 +68,48 @@ class ObjectSurface:
#Surface Properties
obj.addProperty("App::PropertyFloatConstraint", "SampleInterval", "Surface", translate("PathSurface","The Sample Interval. Small values cause long wait"))
obj.SampleInterval = (0,0,1,0)
#Depth Properties
obj.addProperty("App::PropertyFloat", "ClearanceHeight", "Depth", translate("PathProject","The height needed to clear clamps and obstructions"))
obj.addProperty("App::PropertyFloat", "SafeHeight", "Depth", translate("PathProject","Rapid Safety Height between locations."))
obj.addProperty("App::PropertyDistance", "ClearanceHeight", "Depth", translate("PathProject","The height needed to clear clamps and obstructions"))
obj.addProperty("App::PropertyDistance", "SafeHeight", "Depth", translate("PathProject","Rapid Safety Height between locations."))
obj.addProperty("App::PropertyFloatConstraint", "StepDown", "Depth", translate("PathProject","Incremental Step Down of Tool"))
obj.StepDown = (0.0, 0.01, 100.0, 0.5)
obj.addProperty("App::PropertyFloat", "StartDepth", "Depth", translate("PathProject","Starting Depth of Tool- first cut depth in Z"))
obj.addProperty("App::PropertyFloat", "FinalDepth", "Depth", translate("PathProject","Final Depth of Tool- lowest value in Z"))
obj.addProperty("App::PropertyFloat", "FinishDepth", "Depth", translate("PathProject","Maximum material removed on final pass."))
obj.addProperty("App::PropertyDistance", "StartDepth", "Depth", translate("PathProject","Starting Depth of Tool- first cut depth in Z"))
obj.addProperty("App::PropertyDistance", "FinalDepth", "Depth", translate("PathProject","Final Depth of Tool- lowest value in Z"))
obj.addProperty("App::PropertyDistance", "FinishDepth", "Depth", translate("PathProject","Maximum material removed on final pass."))
#Feed Properties
obj.addProperty("App::PropertySpeed", "VertFeed", "Feed",translate("Path","Feed rate for vertical moves in Z"))
obj.addProperty("App::PropertySpeed", "HorizFeed", "Feed",translate("Path","Feed rate for horizontal moves"))
obj.Proxy = self
def addsurfacebase(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
@ -93,7 +118,6 @@ class ObjectSurface:
def _waterline(self,obj, s, bb):
import ocl
# from PathScripts.PathUtils import fmt
from PathScripts.PathUtils import depth_params, fmt
import time
@ -104,7 +128,7 @@ class ObjectSurface:
for loop in loops:
p = loop[0]
loopstring = "(loop begin)" +"\n"
loopstring += "G0 Z" + str(obj.SafeHeight) +"\n"
loopstring += "G0 Z" + str(obj.SafeHeight.Value) +"\n"
loopstring += "G0 X" + str(fmt(p.x)) + " Y" + str(fmt(p.y)) +"\n"
loopstring += "G1 Z" + str(fmt(p.z)) +"\n"
for p in loop[1:]:
@ -117,54 +141,21 @@ class ObjectSurface:
nloop = nloop+1
waterlinestring += loopstring
waterlinestring += "(waterline end)" +"\n"
return waterlinestring
# nloop = 0
# for lop in loops:
# n = 0
# N = len(lop)
# first_point=ocl.Point(-1,-1,5)
# previous=ocl.Point(-1,-1,5)
# for p in lop:
# if n==0: # don't draw anything on the first iteration
# previous=p
# first_point = p
# elif n== (N-1): # the last point
# # and a line from p to the first point
# p1=(p.x,p.y,p.z)
# p2=(first_point.x,first_point.y,first_point.z)
# output += "G1 X" + str(p2[0]) + " Y" + str (p2[1]) + " Z" +str(p2[2]) +"\n"
# else:
# p1=(previous.x,previous.y,previous.z)
# p2=(p.x,p.y,p.z)
# output += "G1 X" + str(p2[0]) + " Y" + str (p2[1]) + " Z" +str(p2[2]) +"\n"
# #print "line from: " + str (p1) + "To: " + str (p2)
# #print "line X: " + str (p1.x) +" Y: " + str(p1.y) + "Z: " + str(p1.z) + " To X: " + str (p2.x) +" Y: " + str(p2.y) + "Z: " + str(p2.z)
# previous=p
# n=n+1
# print " loop ",nloop, " with ", len(lop), " points"
# nloop = nloop+1
# return output
depthparams = depth_params (obj.ClearanceHeight, obj.SafeHeight, obj.StartDepth, obj.StepDown, obj.FinishDepth, obj.FinalDepth)
depthparams = depth_params (obj.ClearanceHeight.Value, obj.SafeHeight.Value, obj.StartDepth.Value, obj.StepDown, obj.FinishDepth.Value, obj.FinalDepth.Value)
# stlfile = "../../stl/gnu_tux_mod.stl"
# surface = STLSurfaceSource(stlfile)
surface = s
t_before = time.time()
t_before = time.time()
zheights= depthparams.get_depths()
wl = ocl.Waterline()
wl = ocl.Waterline()
#wl = ocl.AdaptiveWaterline() # this is slower, ca 60 seconds on i7 CPU
wl.setSTL(surface)
diam = 0.5
length= 10
length= 10.0
cutter = ocl.BallCutter( diam , length ) # any ocl MillingCutter class should work here
wl.setCutter(cutter)
wl.setSampling(obj.SampleInterval) # this should be smaller than the smallest details in the STL file
@ -194,36 +185,35 @@ class ObjectSurface:
cutter = ocl.CylCutter(self.radius*2, 5)
pdc = ocl.PathDropCutter() # create a pdc
pdc.setSTL(s)
pdc.setCutter(cutter)
pdc.minimumZ = 0.25
pdc.setCutter(cutter)
pdc.minimumZ = 0.25
pdc.setSampling(obj.SampleInterval)
# some parameters for this "zigzig" pattern
# some parameters for this "zigzig" pattern
xmin=bb.XMin - cutter.getDiameter()
xmax=bb.XMax + cutter.getDiameter()
ymin=bb.YMin - cutter.getDiameter()
ymax=bb.YMax + cutter.getDiameter()
zmax=bb.ZMax + cutter.getDiameter()
Ny=int(bb.YLength/cutter.getDiameter()) # number of lines in the y-direction
dy = float(ymax-ymin)/Ny # the y step-over
path = ocl.Path() # create an empty path object
# add Line objects to the path in this loop
for n in xrange(0,Ny):
y = ymin+n*dy
p1 = ocl.Point(xmin,y,0) # start-point of line
p2 = ocl.Point(xmax,y,0) # end-point of line
if (n % 2 == 0): #even
if (n % 2 == 0): #even
l = ocl.Line(p1,p2) # line-object
else: #odd
l = ocl.Line(p2,p1) # line-object
path.append( l ) # add the line to the path
pdc.setPath( path )
# run drop-cutter on the path
t_before = time.time()
pdc.run()
@ -231,70 +221,66 @@ class ObjectSurface:
print "calculation took ", t_after-t_before," s"
#retrieve the points
clp = pdc.getCLPoints()
clp = pdc.getCLPoints()
print "points received: " + str(len(clp))
#generate the path commands
output = ""
output += "G0 Z" + str(obj.ClearanceHeight) + "\n"
output += "G0 Z" + str(obj.ClearanceHeight.Value) + "\n"
output += "G0 X" + str(clp[0].x) +" Y" + str(clp[0].y) + "\n"
output += "G1 Z" + str(clp[0].z) + " F" + str(obj.VertFeed.Value) + "\n"
output += "G1 Z" + str(clp[0].z) + " F" + str(self.vertFeed) + "\n"
for c in clp:
output += "G1 X" + str(c.x) +" Y" + str(c.y) +" Z" + str(c.z)+ "\n"
return output
def execute(self,obj):
import Part
import Mesh
import MeshPart
FreeCAD.Console.PrintWarning(translate("PathSurface","Hold on. This might take a minute.\n"))
output = ""
if obj.Algorithm in ['OCL Dropcutter', 'OCL Waterline']:
try:
import ocl
except:
FreeCAD.Console.PrintError(translate("PathSurface","This operation requires OpenCamLib to be installed.\n"))
return
# tie the toolnumber to the PathLoadTool object ToolNumber
if len(obj.InList)>0: #check to see if obj is in the Project group yet
project = obj.InList[0]
tl = int(PathUtils.changeTool(obj,project))
obj.ToolNumber= tl
tool = PathUtils.getTool(obj,obj.ToolNumber)
if tool:
self.radius = tool.Diameter/2
else:
# temporary value,in case we don't have any tools defined already
toolLoad = PathUtils.getLastToolLoad(obj)
if toolLoad == None:
self.vertFeed = 100
self.horizFeed = 100
self.radius = 0.25
mesh = obj.Base[0]
if mesh.TypeId.startswith('Mesh'):
mesh = mesh.Mesh
bb = mesh.BoundBox
obj.ToolNumber= 0
else:
bb = mesh.Shape.BoundBox
mesh = MeshPart.meshFromShape(mesh.Shape,MaxLength=2)
self.vertFeed = toolLoad.VertFeed.Value
self.horizFeed = toolLoad.HorizFeed.Value
tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
self.radius = tool.Diameter/2
obj.ToolNumber= toolLoad.ToolNumber
s= ocl.STLSurf()
for f in mesh.Facets:
p = f.Points[0];q=f.Points[1];r=f.Points[2]
t= ocl.Triangle(ocl.Point(p[0],p[1],p[2]),ocl.Point(q[0],q[1],q[2]),ocl.Point(r[0],r[1],r[2]))
s.addTriangle(t)
if obj.Algorithm == 'OCL Dropcutter':
output = self._dropcutter(obj, s, bb)
elif obj.Algorithm == 'OCL Waterline':
output = self._waterline(obj, s, bb)
if obj.Base:
for b in obj.Base:
if obj.Algorithm in ['OCL Dropcutter', 'OCL Waterline']:
try:
import ocl
except:
FreeCAD.Console.PrintError(translate("PathSurface","This operation requires OpenCamLib to be installed.\n"))
return
mesh = b[0]
if mesh.TypeId.startswith('Mesh'):
mesh = mesh.Mesh
bb = mesh.BoundBox
else:
bb = mesh.Shape.BoundBox
mesh = MeshPart.meshFromShape(mesh.Shape,MaxLength=2)
s= ocl.STLSurf()
for f in mesh.Facets:
p = f.Points[0];q=f.Points[1];r=f.Points[2]
t= ocl.Triangle(ocl.Point(p[0],p[1],p[2]),ocl.Point(q[0],q[1],q[2]),ocl.Point(r[0],r[1],r[2]))
s.addTriangle(t)
if obj.Algorithm == 'OCL Dropcutter':
output = self._dropcutter(obj, s, bb)
elif obj.Algorithm == 'OCL Waterline':
output = self._waterline(obj, s, bb)
path = Path.Path(output)
obj.Path = path
@ -315,10 +301,6 @@ class ViewProviderSurface:
def getIcon(self): #optional
return ":/icons/Path-Surfacing.svg"
# def attach(self): #optional
# # this is executed on object creation and object load from file
# pass
def onChanged(self,obj,prop): #optional
# this is executed when a property of the VIEW PROVIDER changes
pass
@ -327,9 +309,13 @@ class ViewProviderSurface:
# this is executed when a property of the APP OBJECT changes
pass
def setEdit(self,vobj,mode): #optional
# this is executed when the object is double-clicked in the tree
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
@ -351,48 +337,51 @@ class CommandPathSurfacing:
def Activated(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
for s in selection[0].SubObjects:
if s.ShapeType != "Edge":
if (s.ShapeType != "Face") or (len(selection[0].SubObjects) != 1):
FreeCAD.Console.PrintError(translate("PathSurface","Please select only edges or a single face\n"))
return
# 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
# for s in selection[0].SubObjects:
# if s.ShapeType != "Edge":
# if (s.ShapeType != "Face") or (len(selection[0].SubObjects) != 1):
# FreeCAD.Console.PrintError(translate("PathSurface","Please select only edges or a single face\n"))
# return
sel = selection[0].Object
#get type of object
if sel.TypeId.startswith('Mesh'):
#it is a mesh already
print 'was already mesh'
ztop = sel.Mesh.BoundBox.ZMax
zbottom = sel.Mesh.BoundBox.ZMin
# sel = selection[0].Object
# #get type of object
# if sel.TypeId.startswith('Mesh'):
# #it is a mesh already
# print 'was already mesh'
# ztop = sel.Mesh.BoundBox.ZMax
# zbottom = sel.Mesh.BoundBox.ZMin
#mesh = sel
elif sel.TypeId.startswith('Part') and \
(sel.Shape.BoundBox.XLength > 0) and \
(sel.Shape.BoundBox.YLength > 0) and \
(sel.Shape.BoundBox.ZLength > 0):
ztop = sel.Shape.BoundBox.ZMax
zbottom = sel.Shape.BoundBox.ZMin
print 'this is a solid Part object'
else:
FreeCAD.Console.PrintError(translate("PathSurface","Cannot work with this object\n"))
return
# #mesh = sel
# elif sel.TypeId.startswith('Part') and \
# (sel.Shape.BoundBox.XLength > 0) and \
# (sel.Shape.BoundBox.YLength > 0) and \
# (sel.Shape.BoundBox.ZLength > 0):
# ztop = sel.Shape.BoundBox.ZMax
# zbottom = sel.Shape.BoundBox.ZMin
# print 'this is a solid Part object'
# else:
# FreeCAD.Console.PrintError(translate("PathSurface","Cannot work with this object\n"))
# return
# if everything is ok, execute and register the transaction in the undo/redo stack
ztop = 10
zbottom = 0
FreeCAD.ActiveDocument.openTransaction(translate("Path_Surfacing","Create Surface"))
FreeCADGui.addModule("PathScripts.PathSurface")
FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Surface")')
FreeCADGui.doCommand('PathScripts.PathSurface.ObjectSurface(obj)')
FreeCADGui.doCommand('obj.Active = True')
FreeCADGui.doCommand('PathScripts.PathSurface.ViewProviderSurface(obj.ViewObject)')
FreeCADGui.doCommand('obj.Base = (FreeCAD.ActiveDocument.'+selection[0].ObjectName+',[])')
FreeCADGui.doCommand('from PathScripts import PathUtils')
FreeCADGui.doCommand('obj.ClearanceHeight = ' + str(ztop + 2))
FreeCADGui.doCommand('obj.StartDepth = ' + str(ztop))
@ -405,9 +394,153 @@ class CommandPathSurfacing:
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
FreeCADGui.doCommand('obj.ViewObject.startEditing()')
if FreeCAD.GuiUp:
class TaskPanel:
def __init__(self):
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/SurfaceEdit.ui")
#self.form = FreeCADGui.PySideUic.loadUi(":/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,"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,"Algorithm"):
self.obj.Algorithm = str(self.form.algorithmSelect.currentText())
self.obj.Proxy.execute(self.obj)
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'
#mesh = sel
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.addsurfacebase(self.obj, sel)
self.setupUi() #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):
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))
for i in self.obj.Base:
self.form.baseList.addItem(i[0].Name)
#Connect Signals and Slots
self.form.startDepth.editingFinished.connect(self.getFields)
self.form.finalDepth.editingFinished.connect(self.getFields)
self.form.safeHeight.editingFinished.connect(self.getFields)
self.form.clearanceHeight.editingFinished.connect(self.getFields)
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)
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_Surfacing',CommandPathSurfacing())