Change parent but keep position.

Post here for help on using FreeCAD's graphical user interface (GUI).
Forum rules
and Helpful information
IMPORTANT: Please click here and read this first, before asking for help

Also, be nice to others! Read the FreeCAD code of conduct!
Post Reply
koirat
Posts: 66
Joined: Tue Oct 05, 2021 5:24 pm

Change parent but keep position.

Post by koirat »

How can I change parent of a body or a part but keep global location during change.
openBrain
Veteran
Posts: 9034
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: Change parent but keep position.

Post by openBrain »

What is parent ?
koirat
Posts: 66
Joined: Tue Oct 05, 2021 5:24 pm

Re: Change parent but keep position.

Post by koirat »

It is a parent element of a body in hierarchy.
When I drag body on top of a part, the part becomes parent of a body.
openBrain
Veteran
Posts: 9034
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: Change parent but keep position.

Post by openBrain »

So it's an Std_Part object.
AFAIK you have to use Python console.
Let's say that you have an object 'OBJECT' and you want to drag it into a container 'PART' :

Code: Select all

## Run the 2 below lines before mowing object
pl_orig = App.ActiveDocument.OBJECT.getGlobalPlacement()
pl_part = App.ActiveDocument.PART.getGlobalPlacement()
## Now drag OBJECT into Part before running following lines
App.ActiveDocument.OBJECT.Placement = pl_part.inverse().multiply(pl_orig)
koirat
Posts: 66
Joined: Tue Oct 05, 2021 5:24 pm

Re: Change parent but keep position.

Post by koirat »

openBrain wrote: Wed Oct 13, 2021 3:20 pm So it's an Std_Part object.
AFAIK you have to use Python console.
Let's say that you have an object 'OBJECT' and you want to drag it into a container 'PART' :

Code: Select all

## Run the 2 below lines before mowing object
pl_orig = App.ActiveDocument.OBJECT.getGlobalPlacement()
pl_part = App.ActiveDocument.PART.getGlobalPlacement()
## Now drag OBJECT into Part before running following lines
App.ActiveDocument.OBJECT.Placement = pl_part.inverse().multiply(pl_orig)
Thank you. This is quite convoluted but at least I have learned how to use python console.

Also I have made this one liner one can use when the body is in global space and you just dragged it into new parent.
(tested only few times so far)

Code: Select all

App.ActiveDocument.BODY.Placement=App.ActiveDocument.PART.getGlobalPlacement().inverse() * App.ActiveDocument.BODY.Placement
openBrain
Veteran
Posts: 9034
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: Change parent but keep position.

Post by openBrain »

koirat wrote: Wed Oct 13, 2021 11:15 pm Also I have made this one liner one can use when the body is in global space and you just dragged it into new parent.
(tested only few times so far)

Code: Select all

App.ActiveDocument.BODY.Placement=App.ActiveDocument.PART.getGlobalPlacement().inverse() * App.ActiveDocument.BODY.Placement
Be careful to run this line only once, and indeed in the only simple case that you mention :)
plbarrio
Posts: 1
Joined: Thu Jun 08, 2023 12:41 pm

Re: Change parent but keep position.

Post by plbarrio »

I was looking for this featura and ended creating my own macro use it like in blender. Last node will the the future parent

Code: Select all

__Title__    = "Reparent"
__Author__   = "PedroBarrio"
__Version__  = "00.01"
__Date__     = "2023.6.7"
debug = False
'''Usage:
This macro Changes parent maintaning Global coordinates.
Last Object Selected should be the parent.

If the shape is a BaseFeature inside a body, the base feature's placement in the body is adjusted.
'''
def printObjectInfo(obj):
    print(f'ObjectName is {obj.Name}')
    print(f'ObjectLabel is {obj.Label}')
    print(f'Placement is {obj.Placement}')
    print(f'GlobalPlacement is {obj.getGlobalPlacement()}')

    for par in obj.InList:
        print(f'Parent is {par.Name} with Label {par.Label}')
        '''
        for prop in par.PropertiesList:
            print(f'   {prop} = {getattr(par,prop)}')
            if getattr(par,prop) == obj:
                print( "Changed property '"+prop+"' of object "+par.Label+" from "+obj.Label+" to ")
'''        
## Objetos seleccionados
selt = Gui.Selection.getSelection()

## Comprobaciones
if len(selt) < 2:
    print('Select More than 1 objects, the last one should be the new parent')
    shift = App.Vector(0, 0, 0)  # bail and do nothing  
else:
    ## Target es el último elemento
    tar = selt[-1]   
    print('\n Target Object')
    printObjectInfo(tar)

    ## Comprobamos que el destino sea de tipo part
    if (tar.isDerivedFrom("App::Part") == False):
        print('Target object is not of type Part')
    else:
        App.ActiveDocument.openTransaction('Undo Reparent Mantain Coordinates ')
        for obj in selt:
            if (obj  != tar):
                print('\n Moving Object')
                printObjectInfo(obj)
                ## Cambiar localizacion
                obj.Placement= tar.getGlobalPlacement().inverse().multiply( obj.getGlobalPlacement() ) 

                ## Cambiar de padre
                ## Quitar del padre original
                for par in obj.InList:
                    if (par.isDerivedFrom("App::Part")):
                        par.removeObject(obj)
                ## Poner en el padre nuevo
                tar.addObject(obj)

        App.ActiveDocument.commitTransaction()
        App.ActiveDocument.recompute()
  
Post Reply