Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how to script generating a helix and shapebinder ... ?? #27

Open
stepheneb opened this issue Mar 18, 2021 · 4 comments
Open

how to script generating a helix and shapebinder ... ?? #27

stepheneb opened this issue Mar 18, 2021 · 4 comments

Comments

@stepheneb
Copy link

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()

@stepheneb
Copy link
Author

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.

image

# -*- 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()


@stepheneb
Copy link
Author

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()

@stepheneb
Copy link
Author

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)

@stepheneb
Copy link
Author

stepheneb commented Mar 18, 2021

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.

image

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()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant