Selecting a part from hierarchy of assemblies

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
xbit
Posts: 140
Joined: Mon Sep 21, 2020 10:48 am

Re: Selecting a part from hierarchy of assemblies

Post by xbit »

Before asking, i always search the API, or at least try to search the API, because i cannot always find stuff.
Can you send me a link of a good reference to learn?
Perhaps i am browsing the wrong resources.

Anyway i get a strange error from your snippet (i also added Part.Compound(ssh))

Code: Select all

ssh = sh.SubShapes.copy()
scaling_matrix = App.Matrix(x_scale,0,0,0,  0,y_scale,0,0,  0,0,z_scale,0,  0,0,0,1)
scaling_center = ssh[0].BoundBox.Center
global_matrix = App.Matrix()
global_matrix.transform(scaling_center, scaling_matrix
ssh[0].transformGeometry(global_matrix)
newPart = Part.Compound(ssh)
newPart.exportStep(STEP_FilenameAndPath)
The error is:

Code: Select all

    ssh[0].transformGeometry(global_matrix)
    ^
SyntaxError: invalid syntax
Thank you very much for your help!
openBrain
Veteran
Posts: 9041
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: Selecting a part from hierarchy of assemblies

Post by openBrain »

xbit wrote: Mon Jan 18, 2021 2:45 pm Before asking, i always search the API, or at least try to search the API, because i cannot always find stuff.
Can you send me a link of a good reference to learn?
Perhaps i am browsing the wrong resources.
I have no link. :)
To work with TopoShape, I search the TopoShape API. To work with transformation matrices, I search the Matrix API. Etc...
Anyway i get a strange error from your snippet (i also added Part.Compound(ssh))
Not really strange. The closing parenthesis is missing on the line above the one with the error.
I edited my previous post to fix but hey, kind of things you should be able to find by yourself. ;)
xbit
Posts: 140
Joined: Mon Sep 21, 2020 10:48 am

Re: Selecting a part from hierarchy of assemblies

Post by xbit »

Sorry for my shortsight.

Anyway, the script still does not function.
The resulting file is the same as the original with no changes to the subShape
openBrain
Veteran
Posts: 9041
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: Selecting a part from hierarchy of assemblies

Post by openBrain »

xbit wrote: Mon Jan 18, 2021 3:57 pm Sorry for my shortsight.

Anyway, the script still does not function.
The resulting file is the same as the original with no changes to the subShape
Indeed

Code: Select all

ssh[0].transformGeometry(global_matrix)
shall be replaced by

Code: Select all

ssh[0] = ssh[0].transformGeometry(global_matrix)
or

Code: Select all

ssh[0].transformShape(global_matrix)
Any of both is right.
xbit
Posts: 140
Joined: Mon Sep 21, 2020 10:48 am

Re: Selecting a part from hierarchy of assemblies

Post by xbit »

Thank you very much my friend!
You're the man.
xbit
Posts: 140
Joined: Mon Sep 21, 2020 10:48 am

Re: Selecting a part from hierarchy of assemblies

Post by xbit »

If i also want to perform translation and rotation to the selected part, what would you suggest, in terms of API?

Could you guide me on where to look?

I don't know what function to use for translation - nor do know where to look exactly.

As for rotation, i tried the .rotate() function i have already used, to no effect.
This is my code:

Code: Select all

x_axis = 0
y_axis = 0
z_axis = 0

#NOTE: The elements of sys.argv are strings, you need to convert them to 
#integers before comparing with integers.

#the second argument is the axis to rotate (1-3 for axis x,y,z)
axis_Select = int(sys.argv[2])
#the third argument is the angle, for the axis we specified in the second arg
angle = int(sys.argv[3])

if axis_Select == 1:
	x_axis = 1
elif axis_Select == 2:
	y_axis = 1
elif axis_Select == 3:
	z_axis = 1


ssh = sh.SubShapes.copy()

ssh[0] = ssh[0].rotate(FreeCAD.Vector(0,0,0), FreeCAD.Vector(x_axis, y_axis, z_axis), angle)

newPart = Part.Compound(ssh)
newPart.exportStep(STEP_FilenameAndPath)
openBrain
Veteran
Posts: 9041
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: Selecting a part from hierarchy of assemblies

Post by openBrain »

xbit wrote: Tue Jan 19, 2021 10:33 pm If i also want to perform translation and rotation to the selected part, what would you suggest, in terms of API?

Could you guide me on where to look?

I don't know what function to use for translation - nor do know where to look exactly.
You can add functions to your matrix (not tested) :

Code: Select all

scaling_matrix = App.Matrix(x_scale,0,0,0,  0,y_scale,0,0,  0,0,z_scale,0,  0,0,0,1)
scaling_center = ssh[0].BoundBox.Center
move_vector = App.Vector(10,10,10) # to be changed
rotx_angle = 45 # to be changed
roty_angle = 45 # to be changed
rotz_angle = 45 # to be changed
global_matrix = App.Matrix()
global_matrix.transform(scaling_center, scaling_matrix)
global_matrix.move(move_vector)
global_matrix.rotateX(rotx_angle*math.pi/180)
global_matrix.rotateY(roty_angle*math.pi/180)
global_matrix.rotateZ(rotz_angle*math.pi/180)
Need to 'import math'
Have a look at : https://wiki.freecadweb.org/Matrix_API
xbit
Posts: 140
Joined: Mon Sep 21, 2020 10:48 am

Re: Selecting a part from hierarchy of assemblies

Post by xbit »

Thank you openBrain.

Unfortunately, your snippet did not work.
And with my attempt, that makes it two different aproaches that did not work.


I tried many iterations with your code and none of them worked.

I researched all the function calls in the API and some things are unclear for me.

1. Why are you using a scaling_matrix, for rotation only operations?
2. Is this line necessary?
3. Why do you use global_matrix.move()?

I am having trouble understanding your rotation philosophy....
xbit
Posts: 140
Joined: Mon Sep 21, 2020 10:48 am

Re: Selecting a part from hierarchy of assemblies

Post by xbit »

I brushed up my knowledge on linear algebra and transformation matrices. (https://www.varsitytutors.com/hotmath/h ... -rotations)

We need the center of rotation.
So this line of code makes sense:

Code: Select all

scaling_center = ssh[0].BoundBox.Center
(of course we don't do scaling, but you get the point, i kept the naming convention, in order to compare with your code).

We obviously have the rotation values:

Code: Select all

rotx_angle = 45 # to be changed
roty_angle = 45 # to be changed
rotz_angle = 45 # to be changed
I do not understand the purpose of the move_vector code:

Code: Select all

move_vector = App.Vector(10,10,10)
global_matrix.move(move_vector)
In order to rotate around a given axis, isn't it valid if we get the rotation matrix (for the given deegrees) and then perforn a transform on the part matrix, with the transformation matrix, in regards to the center of axis?
openBrain
Veteran
Posts: 9041
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: Selecting a part from hierarchy of assemblies

Post by openBrain »

xbit wrote: Wed Jan 20, 2021 7:47 pm Unfortunately, your snippet did not work.
And with my attempt, that makes it two different aproaches that did not work.
Works good here. You may have to had some extra lines to manage the rotation center though. ;)
[/quote]
1. Why are you using a scaling_matrix, for rotation only operations?
[/quote]
Because you said you want also a rotation and a move. Not only a rotation
2. Is this line necessary?
See above
3. Why do you use global_matrix.move()?
Because you said you want a translation...


Here's a complete detailed snippet with comments

Code: Select all

import Part
import FreeCAD as App
import math

sh = Part.read(PATH_TO_STEP) # replace with correct path
ssh = sh.SubShapes.copy()
### Define the center point used for transformations
trans_center = ssh[0].BoundBox.Center # replace by what you want to get as center for transformations
### Define the scaling transformation matrix
scaling_matrix = App.Matrix(2,0,0,0,  0,2,0,0,  0,0,2,0,  0,0,0,1) # replace '2" by scaling factor
### Define the rotation transformation matrix
rotx = App.Matrix()
rotx.rotateX(45*math.pi/180) # replace '45' by rotation angle around x in degrees
roty = App.Matrix()
roty.rotateY(45*math.pi/180) # replace '45' by rotation angle around y in degrees
rotz = App.Matrix()
rotz.rotateZ(45*math.pi/180) # replace '45' by rotation angle around z in degrees
### Define the translation transformation vector
move_vector = App.Vector(10,10,10) # replace '10' by needed translation
### Compute the global matrix
global_matrix = App.Matrix() # initialize the global transformation matrix
global_matrix.transform(trans_center, scaling_matrix) # apply scaling first (so axis are still correct, before rotation)
global_matrix.transform(trans_center, rotx) # apply rotation then (so center is still correct, before move)
global_matrix.transform(trans_center, roty) # apply rotation then (so center is still correct, before move)
global_matrix.transform(trans_center, rotz) # apply rotation then (so center is still correct, before move)
global_matrix.move(move_vector)
### Apply the matrix to the subshape
ssh[0] = ssh[0].transformGeometry(global_matrix)

newPart = Part.Compound(ssh)
newPart.exportStep(STEP_FilenameAndPath)
Post Reply