Scripted objects with attachment: Difference between revisions

From FreeCAD Documentation
(Add scripted objects with attachment page)
 
(Second argument of obj.addExtension() is deprecated)
 
(13 intermediate revisions by 8 users not shown)
Line 1: Line 1:
<languages/>
=Introduction=
{{TOCright}}
The purpose of this page is to show a minimal example of [[Part Attachment]] feature using [[Scripted objects]] in Python.
<translate>


==Introduction== <!--T:1-->

<!--T:2-->
The purpose of this page is to show a minimal example of [[Part_EditAttachment|Part EditAttachment]] feature using [[Scripted objects]] in Python.

<!--T:3-->
See [[#Full_and_Complete_Minimal_Example|full and complete minimal example]] below.
See [[#Full_and_Complete_Minimal_Example|full and complete minimal example]] below.


<!--T:4-->
The following '''GIF''' demonstrates attaching our custom box to a cylinder, and automatically updating it's position when the cylinder's position changes.
The following GIF demonstrates attaching our custom box to a cylinder, and automatically updating it's position when the cylinder's position changes.


</translate>
[[File:Box-attached-to-cylinder-demo.gif]]
[[File:Box-attached-to-cylinder-demo.gif]]
<translate>


<!--T:5-->
'''NOTE:''' The box is our custom scripted object, and the cylinder is a regular FreeCAD object generated from the Part workbench.
'''NOTE:''' The box is our custom scripted object, and the cylinder is a regular FreeCAD object generated from the Part workbench.


=Making Scripted Objects Attachable=
==Making Scripted Objects Attachable== <!--T:6-->


==Add Attach Extension==
===Add Attach Extension=== <!--T:7-->


<!--T:8-->
First, we need to add the <code>Part::AttachExtensionPython</code> extension to our <code>Part::FeaturePython</code> oject in the constructor, or <code>__init__</code> method, of our custom scripted object.
First, we need to add the <code>Part::AttachExtensionPython</code> extension to our <code>Part::FeaturePython</code> oject in the constructor, or <code>__init__</code> method, of our custom scripted object.
</translate>

<syntaxhighlight lang="python" line='line'>
<syntaxhighlight lang="python" line='line'>
class Box():
class Box():
Line 28: Line 40:


# Needed to make this object "attachable"
# Needed to make this object "attachable"
obj.addExtension('Part::AttachExtensionPython', obj)
obj.addExtension('Part::AttachExtensionPython')
</syntaxhighlight>
</syntaxhighlight>
<translate>

<!--T:9-->
Without adding this code, we'll see the following warning dialog when attaching our custom scripted object to another object.
Without adding this code, we'll see the following warning dialog when attaching our custom scripted object to another object.


</translate>
[[File:Part-attachment-warning-dialog.png]]
[[File:Part-attachment-warning-dialog.png]]
<translate>


==Update Position Based on Attached Object==
===Update Position Based on Attached Object=== <!--T:10-->

<!--T:11-->
Then, in the `execute` method of our custom scripted object, we need to call the `positionBySupport` on our `Part::FeaturePython` object.
Then, in the `execute` method of our custom scripted object, we need to call the `positionBySupport` on our `Part::FeaturePython` object.
</translate>

<syntaxhighlight lang="python" line='line'>
<syntaxhighlight lang="python" line='line'>
class Box:
class Box:
Line 49: Line 66:
obj.Shape = Part.makeBox(...)
obj.Shape = Part.makeBox(...)
</syntaxhighlight>
</syntaxhighlight>
<translate>

<!--T:12-->
Without calling <code>positionBySupport</code>, our custom scripted object won't update it's position when the position of the attached-to object changes.
Without calling <code>positionBySupport</code>, our custom scripted object won't update it's position when the position of the attached-to object changes.


=Full and Complete Minimal Example=
==Full and Complete Minimal Example== <!--T:13-->
</translate>
<syntaxhighlight lang="python" line='line'>
<syntaxhighlight lang="python" line='line'>
import FreeCAD as App
import FreeCAD as App
Line 85: Line 104:
# Needed to make this object "attachable",
# Needed to make this object "attachable",
# or able to attach parameterically to other objects
# or able to attach parameterically to other objects
obj.addExtension('Part::AttachExtensionPython', obj)
obj.addExtension('Part::AttachExtensionPython')


def execute(self, obj):
def execute(self, obj):
Line 103: Line 122:
Create a Box.
Create a Box.
"""
"""

obj = document.addObject('Part::FeaturePython', obj_name)
obj = document.addObject('Part::FeaturePython', obj_name)
Box(obj)
Box(obj)
Line 117: Line 135:
document.recompute()
document.recompute()
</syntaxhighlight>
</syntaxhighlight>
<translate>


=References=
==References== <!--T:14-->

* [[Part Attachment]]
<!--T:15-->
* [[Part_EditAttachment|Part EditAttachment]]
* [https://forum.freecadweb.org/viewtopic.php?f=22&t=24794 FreeCAD Forum - Parametric attachment of scripted object]
* [https://forum.freecadweb.org/viewtopic.php?f=22&t=24794 FreeCAD Forum - Parametric attachment of scripted object]
* [https://forum.freecadweb.org/viewtopic.php?f=10&t=18978&start=10 FreeCAD Forum - Port attachment to be an extension]
* [https://forum.freecadweb.org/viewtopic.php?f=10&t=18978&start=10 FreeCAD Forum - Port attachment to be an extension]
* [https://github.com/gbroques/freecad-part-attachment-python-example GitHub - freecad-part-attachment-python-example]
* [https://github.com/gbroques/freecad-part-attachment-python-example GitHub - freecad-part-attachment-python-example]


=Tested With the Following FreeCAD Version=
==Tested With the Following FreeCAD Version== <!--T:16-->
Tested with the following FreeCAD version information:


<!--T:17-->
Tested with the following FreeCAD version information:
</translate>
<pre>
<pre>
OS: Ubuntu 18.04.3 LTS
OS: Ubuntu 18.04.3 LTS
Line 141: Line 164:
Locale: English/UnitedStates (en_US)
Locale: English/UnitedStates (en_US)
</pre>
</pre>
<translate>

<!--T:18-->
Note: For FreeCAD 0.19 this tutorial needs a minor update:
* The second argument of the`addExtension` method got deprecated.
* For details see https://forum.freecadweb.org/viewtopic.php?f=10&t=54370

</translate>
{{Powerdocnavi{{#translation:}}}}
[[Category:Developer Documentation{{#translation:}}]]
[[Category:Python Code{{#translation:}}]]
{{clear}}

Latest revision as of 22:17, 19 March 2024

Introduction

The purpose of this page is to show a minimal example of Part EditAttachment feature using Scripted objects in Python.

See full and complete minimal example below.

The following GIF demonstrates attaching our custom box to a cylinder, and automatically updating it's position when the cylinder's position changes.

NOTE: The box is our custom scripted object, and the cylinder is a regular FreeCAD object generated from the Part workbench.

Making Scripted Objects Attachable

Add Attach Extension

First, we need to add the Part::AttachExtensionPython extension to our Part::FeaturePython oject in the constructor, or __init__ method, of our custom scripted object.

class Box():
    """Custom Scripted Box Object"""

    def __init__(self, obj):
        self.Type = 'Box'

        obj.Proxy = self
        
        ... custom properties

        # Needed to make this object "attachable"
        obj.addExtension('Part::AttachExtensionPython')

Without adding this code, we'll see the following warning dialog when attaching our custom scripted object to another object.

Update Position Based on Attached Object

Then, in the `execute` method of our custom scripted object, we need to call the `positionBySupport` on our `Part::FeaturePython` object.

class Box:
    
    ...

    def execute(self, obj):
        obj.positionBySupport()
        
        # Assign a Shape to obj
        obj.Shape = Part.makeBox(...)

Without calling positionBySupport, our custom scripted object won't update it's position when the position of the attached-to object changes.

Full and Complete Minimal Example

import FreeCAD as App
import Part


class Box():
    """
    Simple Custom Box Object
    See Also:
        https://wiki.freecadweb.org/FeaturePython_Objects
    """

    def __init__(self, obj):
        """
        Constructor
        Arguments
        ---------
        - obj: an existing document object or an object created with FreeCAD.Document.addObject('Part::FeaturePython', '{name}').
        """

        self.Type = 'Box'

        obj.Proxy = self
        obj.addProperty('App::PropertyLength', 'Length',
                        'Dimensions', 'Box length').Length = 10.0
        obj.addProperty('App::PropertyLength', 'Width',
                        'Dimensions', 'Box width').Width = 10.0
        obj.addProperty('App::PropertyLength', 'Height',
                        'Dimensions', 'Box height').Height = 10.0

        # Needed to make this object "attachable",
        # or able to attach parameterically to other objects
        obj.addExtension('Part::AttachExtensionPython')

    def execute(self, obj):
        """
        Called on document recompute
        """
        # Needed to update position when attached-to object changes position.
        # Reposition object based on Support, MapMode and MapPathParameter properties.
        # Returns True if attachment calculation was successful, False if object is not attached and Placement wasn't updated,
        obj.positionBySupport()

        obj.Shape = Part.makeBox(obj.Length, obj.Width, obj.Height)


def create_box(obj_name, document):
    """
    Create a Box.
    """
    obj = document.addObject('Part::FeaturePython', obj_name)
    Box(obj)
    obj.ViewObject.Proxy = 0  # Mandatory unless ViewProvider is coded
    return obj


document = App.ActiveDocument
if document is None:
    document = App.newDocument('Part Attachment Example')

box = create_box('CustomBox', document)
document.recompute()

References

Tested With the Following FreeCAD Version

Tested with the following FreeCAD version information:

OS: Ubuntu 18.04.3 LTS
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.18.16146 (Git) AppImage
Build type: Release
Branch: (HEAD detached at 0.18.4)
Hash: 980bf9060e28555fecd9e3462f68ca74007b70f8
Python version: 3.6.7
Qt version: 5.6.2
Coin version: 4.0.0a
OCC version: 7.3.0
Locale: English/UnitedStates (en_US)

Note: For FreeCAD 0.19 this tutorial needs a minor update: