[Solved] getGlobalPlacement(), how do I setGlobalPlacement()
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Be nice to others! Respect the FreeCAD code of conduct!
[Solved] getGlobalPlacement(), how do I setGlobalPlacement()
I'm trying to position an object to a selected vertex; In my macro I select the object and then select a stand alone vertex that I created in Sketcher. The vertex can be seen in the 3D because it's normal geo. I'm not in Sketch-edit.
The best way I can think of is to use getGlobalPlacement() of the vertex and then make my object use that as a placement. I have some code that is 50 lines long and very hard to understand, layers of this and that for adjusted placements, offsets, Part containers; is there some simple way to perform this:
x = myVertex.getGlobalPlacement()
myObject.Placement= setGlobalPlacement(x)
Of coarse there is no command setGlobalPlacement(). It just seems like such a simple concept since we can get a global Placement.
Thanks for any ideas.
The best way I can think of is to use getGlobalPlacement() of the vertex and then make my object use that as a placement. I have some code that is 50 lines long and very hard to understand, layers of this and that for adjusted placements, offsets, Part containers; is there some simple way to perform this:
x = myVertex.getGlobalPlacement()
myObject.Placement= setGlobalPlacement(x)
Of coarse there is no command setGlobalPlacement(). It just seems like such a simple concept since we can get a global Placement.
Thanks for any ideas.
Last edited by freedman on Mon Nov 29, 2021 7:44 pm, edited 1 time in total.
Re: getGlobalPlacement(), how do I setGlobalPlacement()
Placement is composed by two element,
it is almost easy to see using:
You get info about placement and rotation
using:
you will obtain:
Simply use:
Hope it helps
Regards
Carlo D.
- "Placement"
- Rotation
it is almost easy to see using:
Code: Select all
print(obj.Placement)
Code: Select all
Placement [Pos=(0,0,0), Yaw-Pitch-Roll=(0,0,0)]
using:
Code: Select all
print(dir(obj.Placement))
Code: Select all
['Base', 'Matrix', 'Rotation', '__abs__', '__add__', '__and__', '__bool__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__xor__', 'copy', 'inverse', 'isIdentity', 'move', 'multVec', 'multiply', 'pow', 'rotate', 'sclerp', 'slerp', 'toMatrix', 'translate']
- Base for the "Translation" part
- Rotation for the rotation
Code: Select all
DOC = FreeCAD.ActiveDocument
pl1 = obj.Placement
pos1 = pl1.Base
rot1 = pl1.Rotation
pos2 = Vector() # your new placement
obj.Placement = FreeCAD.Placement (pos2, rot1)
DOC.recompute()
Regards
Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.
Blog: https://okkmkblog.wordpress.com/
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.
Blog: https://okkmkblog.wordpress.com/
Re: getGlobalPlacement(), how do I setGlobalPlacement()
Global placement is the cummulative placement of the object itself and all its parent Containers. There cannot be a setglobal() as it would be undefined how to distribute the placement between object and parents.
Re: getGlobalPlacement(), how do I setGlobalPlacement()
I have to disagree with @ickby. To me your request makes sense, as I understand it as "set object placement so it maps to a vertex, both potentially being in different CS".
This is just a few calculus. Lets consider :
* obj : the object to move
* sk : the object owning the target vertex (called 'sk' because you said its a sketch, but can virtually be anything)
* id : the id of the target vertex in 'sk' shape ('id' is basically 'name-1', for example "Vertex3" has id = 2)
As you're targeting a vertex, there's no way to define a particular rotation for the object so I'll leave it unchanged
And it's done
This is just a few calculus. Lets consider :
* obj : the object to move
* sk : the object owning the target vertex (called 'sk' because you said its a sketch, but can virtually be anything)
* id : the id of the target vertex in 'sk' shape ('id' is basically 'name-1', for example "Vertex3" has id = 2)
As you're targeting a vertex, there's no way to define a particular rotation for the object so I'll leave it unchanged
Code: Select all
skOffset = sk.getGlobalPlacement().multiply(sk.Placement.inverse()) # get sk root in GCS
targetPos = skOffset.multVec(sk.Shape.Vertexes[id].Point) # get target point coordinates in GCS
objOffset = obj.getGlobalPlacement().multiply(obj.Placement.inverse()) # get obj root in GCS
obj.Placement.Base = objOffset.inverse().multVec(targetPos) # move obj origin to sk.id
Re: getGlobalPlacement(), how do I setGlobalPlacement()
openBrain, Thank you very much, I could not put that together. It took me about 10 minutes to get this working since I already had the sketch, index-1, object. You made my day.
And you were correct about object rotation, let it be.
Here I added the code for when I pick the vertex, Stored_obj is the object I selected prior.
And you were correct about object rotation, let it be.
Here I added the code for when I pick the vertex, Stored_obj is the object I selected prior.
Code: Select all
if self.sk.TypeId == "Sketcher::SketchObject":
self.sel = Gui.Selection.getSelectionEx()
for so in self.sel:
for sub in so.SubElementNames:
if "Vertex" in sub:
self.current_index = eval(sub.lstrip('Vertex'))
skOffset = self.sk.getGlobalPlacement().multiply(self.sk.Placement.inverse()) # get sk root in GCS
targetPos = skOffset.multVec(self.sk.Shape.Vertexes[self.current_index-1].Point) # get target point coordinates in GCS
objOffset = self.stored_obj.getGlobalPlacement().multiply(self.stored_obj.Placement.inverse()) # get obj root in GCS
self.stored_obj.Placement.Base = objOffset.inverse().multVec(targetPos) # move obj origin to sk.id
Re: getGlobalPlacement(), how do I setGlobalPlacement()
If vertex is currently selected, you can get a direct reference to it (as well as the sketch) with something like :
Code: Select all
self.sel = Gui.Selection.getSelectionEx()
for so in self.sel:
if so.Object.isDerivedFrom("Sketcher::SketchObject"):
for sub in so.SubObjects:
if isinstance(sub, Part.Vertex):
self.sk = so.Object # !!!!!!!! At this time you seem to already have 'self.sk' so you can skip this, but I wrote it just in case
skOffset = self.sk.getGlobalPlacement().multiply(self.sk.Placement.inverse()) # get sk root in GCS
targetPos = skOffset.multVec(sub.Point) # get target point coordinates in GCS
objOffset = self.stored_obj.getGlobalPlacement().multiply(self.stored_obj.Placement.inverse()) # get obj root in GCS
self.stored_obj.Placement.Base = objOffset.inverse().multVec(targetPos) # move obj origin to sk.id
break
pass #endif
break
pass #endif
Re: [Solved] getGlobalPlacement(), how do I setGlobalPlacement()
I don't know about the forum/FreeCAD structure, should this be turned into a method, formalized and tested. Options could be added for adoption of Rotations. Ultimately working towards being added to the API.
def setGlobalPlacement(motile_object, destination_object, Option)
Options:
0) no change to rotation
1) use motile object rotation (if possible)
2) use motile object parent rotation
3) use destination rotation
4) use destination parent rotation (if possible)
Not really sure what I can do but I will probably end up close to this by the time I'm done.
def setGlobalPlacement(motile_object, destination_object, Option)
Options:
0) no change to rotation
1) use motile object rotation (if possible)
2) use motile object parent rotation
3) use destination rotation
4) use destination parent rotation (if possible)
Not really sure what I can do but I will probably end up close to this by the time I'm done.
Re: [Solved] getGlobalPlacement(), how do I setGlobalPlacement()
It depends on what you are talking about.
Usually if you deal with Part objects you usually have only the methods exposed by OCCT, internally FreeCAD will store Placement as a quaternion.
Said so Placement in FreeCAD needs more Documentation, or to be more clear more Documentation taylored for newbies, or from people that come here from other CAD, as it deals with something that is managed by the "core libraries".
It is a complex arguments, and the question is solved in different ways by Assembly??? workbenches, as it is somewhat a matter of tastes.
I've not a very deep math background and for me dealing with vectors maths is a "bad beast", so sadly I could not give useful advice.
Having some "helper methods" is a great improvement, expecially for "complex things" but so many options maybe are confusing.
Plus "if possible" seems to open a whole range of risks, of doing something that has "no sense".
There will be a reason why pos and rot have been a property for each of them.
You could ever do some "matrix manipulation" that from what i know is translated into the internal representation, when dealing with complex and subsequent rotations an translations, i have done some helpers methods that apply transformation in sequence to the Matrix, with predictable results.
But I think my code will be not useful, I have opened a "snippets thread", maybe i will publish some method here.
Sorry if my post is not clear. (probably due to the difficult concepts and my bad English)
Regards
Carlo D.
Usually if you deal with Part objects you usually have only the methods exposed by OCCT, internally FreeCAD will store Placement as a quaternion.
Said so Placement in FreeCAD needs more Documentation, or to be more clear more Documentation taylored for newbies, or from people that come here from other CAD, as it deals with something that is managed by the "core libraries".
It is a complex arguments, and the question is solved in different ways by Assembly??? workbenches, as it is somewhat a matter of tastes.
I've not a very deep math background and for me dealing with vectors maths is a "bad beast", so sadly I could not give useful advice.
Having some "helper methods" is a great improvement, expecially for "complex things" but so many options maybe are confusing.
Plus "if possible" seems to open a whole range of risks, of doing something that has "no sense".
There will be a reason why pos and rot have been a property for each of them.
You could ever do some "matrix manipulation" that from what i know is translated into the internal representation, when dealing with complex and subsequent rotations an translations, i have done some helpers methods that apply transformation in sequence to the Matrix, with predictable results.
But I think my code will be not useful, I have opened a "snippets thread", maybe i will publish some method here.
Sorry if my post is not clear. (probably due to the difficult concepts and my bad English)
Regards
Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.
Blog: https://okkmkblog.wordpress.com/
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.
Blog: https://okkmkblog.wordpress.com/
Re: [Solved] getGlobalPlacement(), how do I setGlobalPlacement()
I'm not sure adding to API is a good idea as there can be many many different needs that API method can't cover.
But maybe if you think this can be useful to others, adding this to Code snippets can be fine.
Re: [Solved] getGlobalPlacement(), how do I setGlobalPlacement()
I'm having another problem. When I rotate the whole group of objects (using Part container rotations) the stored object does not stay Normal to the sketch. I had this which takes the sketch (self.sel) and assigns it's rotation to the stored object.
And thought that I could instead use this:
But, Rotation doesn't have an attribute "inverse". So, what do I need to look at to Null all of the parent rotations?
Thanks all
Code: Select all
self.stored_obj.Placement.Rotation = self.sel.getGlobalPlacement().Rotation
Code: Select all
self.stored_obj.Placement.Rotation = self.sel.getGlobalPlacement().Rotation.multiply(self.sel.Placement.Rotation.inverse())
But, Rotation doesn't have an attribute "inverse". So, what do I need to look at to Null all of the parent rotations?
Thanks all
Last edited by freedman on Fri Dec 17, 2021 6:43 am, edited 1 time in total.