ThreadProfile
ThreadProfile copied to clipboard
how to script generating a helix and shapebinder ... ??
Working on figuring out how to script the thread profile workbench. Thanks for any help or tips.
Here's the current state of my test macro.
file: vtp_test.FCMacro
# -*- coding: utf-8 -*-
import FreeCAD as App
import FreeCADGui as Gui
import sys
import Part
import ThreadProfileCmd
minor_diameter = 30
thread_pitch = 2.0
thread_count = 3
try:
vtp_test = App.getDocument("vtp_test1")
except NameError:
vtp_test = App.newDocument("vtp_test1")
vtp_body = vtp_test.getObject('vtp_body')
if (id(vtp_body) == id(None)):
vtp_body = vtp_test.addObject('PartDesign::Body','vtp_body')
else:
vtp_body.removeObjectsFromDocument()
# make vthreadprofile
vtp = ThreadProfileCmd.ThreadProfileCreateObjectCommandClass().makeThreadProfile('VThreadProfile')
vtp_body.addObject(vtp)
vtp.InternalOrExternal = 'External'
vtp.MinorDiameter = minor_diameter
vtp.Pitch = thread_pitch
vtp.ThreadCount = thread_count
vtp_body.recompute()
# make helix and associates shapebinder
ThreadProfileCmd.ThreadProfileMakeHelixCommandClass();
# ... ??
# sweep shapebinder along thread profile
# ... ??
Gui.ActiveDocument.ActiveView.viewIsometric()
Gui.ActiveDocument.ActiveView.fitAll()
I got a bit further ... new macro code below. Being new to FreeCAD I realize I'm starting with the assumption that I can script the creation and modification of objects without interacting with the GUI -- I suspect now that is an incorrect assumption.
In order to create a VThreadProfile
correctly embedded in the body I needed to make the new body active after creating it using this gui command in the macro and before creating the VThreadProfile
Gui.ActiveDocument.ActiveView.setActiveObject('pdbody', vtp_body)
Without doing this the VThreadProfile
object appeared to be in the body in the tree view bit when manually adding a helix using the gui only a Helix was made -- not a Helix and ShapeBinder.
The VThreadProfile
can then be made correctly in the script.
NOTE: this may be a bug elsewhere. I've also been debugging by comparing the XML Content of objects generated manually to the objects I'm creating with the script. The output to the Python console for a VThreadProfile
object is truncated -- presumably because it's large. Should I step into the regular FreeCAD bug reporting/tracking process for this issue?
To make the Helix and ShapeBinder I tried to follow the pattern I used making the VThreadProfile
by directly accessing classes like ThreadProfileMakeHelixCommandClass()
but wasn't able to get it to work.
The updated macro code below instead works by scripting through GUI commands
It's almost all working but I'm left with the Task dialog still open.
# -*- coding: utf-8 -*-
import FreeCAD as App
import FreeCADGui as Gui
import sys
import Part
import ThreadProfileCmd
minor_diameter = 30
thread_pitch = 2.0
thread_count = 3
try:
vtp_test = App.getDocument("vtp_test1")
except NameError:
vtp_test = App.newDocument("vtp_test1")
vtp_body = vtp_test.getObject('vtp_body')
if (id(vtp_body) == id(None)):
vtp_body = vtp_test.addObject('PartDesign::Body','vtp_body')
else:
vtp_body.removeObjectsFromDocument()
vtp_test.recompute()
names = [o.Name for o in vtp_test.RootObjects if o.Name != 'vtp_body']
[vtp_test.removeObject(o.Name) for o in vtp_test.RootObjects if o.Name != 'vtp_body']
Gui.ActiveDocument.ActiveView.setActiveObject('pdbody', vtp_body)
# make vthreadprofile
vtp = ThreadProfileCmd.ThreadProfileCreateObjectCommandClass().makeThreadProfile('VThreadProfile')
# vtp_body.addObject(vtp)
vtp.InternalOrExternal = 'External'
vtp.MinorDiameter = minor_diameter
vtp.Pitch = thread_pitch
vtp.ThreadCount = thread_count
vtp_body.recompute()
# make helix and associated shapebinder
Gui.Selection.clearSelection()
Gui.Selection.addSelection('vtp_test1','VThreadProfile')
Gui.runCommand('ThreadProfileMakeHelix',0)
# select VThreadProfile and ShapeBinder and sweep shapebinder along thread profile
Gui.Selection.clearSelection()
Gui.Selection.addSelection('vtp_test1','VThreadProfile')
Gui.Selection.addSelection('vtp_test1','vtp_body','ShapeBinder.')
Gui.runCommand('ThreadProfileDoSweep',0)
vtp_test.recompute()
vtp_test.resetEdit()
Gui.activateWorkbench('ThreadProfileWorkbench')
vtp_test1.getObject('AdditivePipe').Visibility = True
# make the result nicely visible
Gui.ActiveDocument.ActiveView.viewIsometric()
Gui.ActiveDocument.ActiveView.fitAll()
Hmmm ... noticed this error without a line number generated in the Report panel before running ThreadProfileDoSweep
which is commented out in the macro code below
15:30:54 <Exception> ObjectIdentifier.cpp(1512): Document object 'VThreadProfile' not found in 'VThreadProfile.Placement.Rotation.Axis.z'
in property binding 'Placement'
import FreeCAD as App
import FreeCADGui as Gui
import sys
import Part
import ThreadProfileCmd
minor_diameter = 30
thread_pitch = 2.0
thread_count = 3
try:
vtp_test = App.getDocument("vtp_test1")
except NameError:
vtp_test = App.newDocument("vtp_test1")
vtp_body = vtp_test.getObject('vtp_body')
if (id(vtp_body) == id(None)):
vtp_body = vtp_test.addObject('PartDesign::Body','vtp_body')
else:
vtp_body.removeObjectsFromDocument()
vtp_test.recompute()
names = [o.Name for o in vtp_test.RootObjects if o.Name != 'vtp_body']
[vtp_test.removeObject(o.Name) for o in vtp_test.RootObjects if o.Name != 'vtp_body']
Gui.ActiveDocument.ActiveView.setActiveObject('pdbody', vtp_body)
# make vthreadprofile
vtp = ThreadProfileCmd.ThreadProfileCreateObjectCommandClass().makeThreadProfile('VThreadProfile')
# vtp_body.addObject(vtp)
vtp.InternalOrExternal = 'External'
vtp.MinorDiameter = minor_diameter
vtp.Pitch = thread_pitch
vtp.ThreadCount = thread_count
vtp_body.recompute()
# make helix and associated shapebinder
Gui.Selection.clearSelection()
Gui.Selection.addSelection('vtp_test1','VThreadProfile')
Gui.runCommand('ThreadProfileMakeHelix',0)
# select VThreadProfile and ShapeBinder and sweep shapebinder along thread profile
#Gui.Selection.clearSelection()
#Gui.Selection.addSelection('vtp_test1','VThreadProfile')
#Gui.Selection.addSelection('vtp_test1','vtp_body','ShapeBinder.')
# Gui.runCommand('ThreadProfileDoSweep',1)
# vtp_test.recompute()
# vtp_test.resetEdit()
# Gui.activateWorkbench('ThreadProfileWorkbench')
# vtp_test.getObject('AdditivePipe').Visibility = True
# make the result nicely visible
Gui.ActiveDocument.ActiveView.viewIsometric()
Gui.ActiveDocument.ActiveView.fitAll()
fyI version info: ThreadProfile: 1.68
FreeCAD: OS: macOS 10.16 Word size of OS: 64-bit Word size of FreeCAD: 64-bit Version: 0.19.24267 (Git) Build type: Release Branch: releases/FreeCAD-0-19 Hash: b2ca86d8d72b636011a73394bf9bcdedb3b109b7 Python version: 3.8.8 Qt version: 5.12.9 Coin version: 4.0.0 OCC version: 7.4.0 Locale: C/Default (C)
Perhaps solved ...
Updated to ThreadProfile 1.6.9 and FreeCAD .19.1
As long as I delete the document vtp_test1
before running the macro it all seems to work.
If I run it without deleting vtp_test1
first it works but this error with no line number is generated in the Report panel:
17:33:08 <Exception> ObjectIdentifier.cpp(1512): Document object 'VThreadProfile' not found in 'VThreadProfile.Placement.Rotation.Axis.z'
in property binding 'Placement'
The code at the beginning is intended to empty out the document vtp_test1
* every time the macro is run to make iterative development easier.
I also suspect there might also be a simpler method to switch the Combo View from the Task tab back to the Model tabb at the end.
# -*- coding: utf-8 -*-
import FreeCAD as App
import FreeCADGui as Gui
import sys
import Part
import ThreadProfileCmd
from PySide import QtGui
minor_diameter = 30
thread_pitch = 2.0
thread_count = 3
try:
vtp_test = App.getDocument("vtp_test1")
except NameError:
vtp_test = App.newDocument("vtp_test1")
vtp_body = vtp_test.getObject('vtp_body')
if (id(vtp_body) == id(None)):
vtp_body = vtp_test.addObject('PartDesign::Body','vtp_body')
else:
vtp_body.removeObjectsFromDocument()
vtp_test.recompute()
[vtp_test.removeObject(o.Name) for o in vtp_test.RootObjects if o.Name != 'vtp_body']
Gui.ActiveDocument.ActiveView.setActiveObject('pdbody', vtp_body)
# make vthreadprofile
vtp = ThreadProfileCmd.ThreadProfileCreateObjectCommandClass().makeThreadProfile('VThreadProfile')
# vtp_body.addObject(vtp)
vtp.InternalOrExternal = 'External'
vtp.MinorDiameter = minor_diameter
vtp.Pitch = thread_pitch
vtp.ThreadCount = thread_count
vtp_body.recompute()
# make helix and associated shapebinder
Gui.Selection.clearSelection()
Gui.Selection.addSelection('vtp_test1','VThreadProfile')
Gui.runCommand('ThreadProfileMakeHelix')
# select VThreadProfile and ShapeBinder and sweep shapebinder along thread profile
Gui.Selection.clearSelection()
Gui.Selection.addSelection('vtp_test1','VThreadProfile')
Gui.Selection.addSelection('vtp_test1','vtp_body','ShapeBinder.')
Gui.runCommand('ThreadProfileDoSweep',1)
Gui.activeDocument().resetEdit()
# switch from Task to Model in Combo View
mw = FreeCADGui.getMainWindow()
dws = mw.findChildren(QtGui.QDockWidget)
comboView = next(filter(lambda qw: qw.windowTitle() == 'Combo View', dws), None)
comboView.findChild(QtGui.QTabWidget).setCurrentIndex(0)
# make the result nicely visible
Gui.ActiveDocument.ActiveView.viewIsometric()
Gui.ActiveDocument.ActiveView.fitAll()