Code cleanup and additional work on panels
This commit is contained in:
committed by
Yorik van Havre
parent
670ae854f3
commit
704cc23ab7
@@ -57,6 +57,8 @@ SET(PathScripts_SRCS
|
||||
PathScripts/PathInspect.py
|
||||
PathScripts/PathSimpleCopy.py
|
||||
PathScripts/PathEngrave.py
|
||||
PathScripts/PathSurface.py
|
||||
|
||||
)
|
||||
|
||||
SET(PathScripts_NC_SRCS
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
644
src/Mod/Path/Gui/Resources/icons/Path-Surfacing.svg
Normal file
644
src/Mod/Path/Gui/Resources/icons/Path-Surfacing.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 26 KiB |
299
src/Mod/Path/Gui/SurfaceEdit.ui
Normal file
299
src/Mod/Path/Gui/SurfaceEdit.ui
Normal 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>
|
||||
@@ -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())
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user