# Place object according the normal

• On 21/03/2018 at 02:20, xxxxxxxx wrote:

Yes, the Z axis is now perpendicular.
Let's call that the up axis and the other 2 (x, and y) the ground axis.

So, the up axis is now correct and next the ground axis should be aligned with the ground axis of object A.

For below example this means:
Object A Y axis is aligned to Object B Z axis (perpendicular)
Object A Z axis is aligned to Object B -Y axis
Object A X axis is aligned to Object B X axis

• On 21/03/2018 at 03:45, xxxxxxxx wrote:

But what happens in the case where object axis is not perpendicular to the polygon selection (which will happens pretty much everytime even for a simple object like torus or sphere) as shown for example in this picture.

Z can't remain perpendicular to the polygon selection and get his -Y axis aligned to the Z axis and X axis aligned to the X axis.

Maybe there is a mode on the Modeling Axis tab you want to mimic?
Remember that you could get this axis by using GetModelingAxis

• On 21/03/2018 at 05:44, xxxxxxxx wrote:

For the first version of the plugin is the assumption that the selection is one plane (flat).
So, either the x, y or  size is 0.

GetModelingAxis gives me the same information as GetMp().
What is the difference?

Is it possible to perpendicular align to another axis than the z axis?

• On 21/03/2018 at 06:16, xxxxxxxx wrote:

Again what I am trying to do:
Put an object perpendicular to each side of a cube and aligned with that side.

• On 22/03/2018 at 06:30, xxxxxxxx wrote:

Hi Pim,

I think you don't understand the problem, you are still missing a constraint here.
In the following picture, you can see 4 different results which are matching your rules while the initial cube is the same with same rotation for each one.

Moreover, if you only want to deal with cube. You can hardcode all rotations and then multiply by the matrix of the cube and offset with the cube size.
But it will only work for cube and not other geometry.
So your final goal is to work only with cube or any kind of object?

Originally posted by xxxxxxxx

GetModelingAxis gives me the same information as GetMp().
What is the difference?

GeModelingAxis actually return a matrix of the current Handle in the viewport (so if you select a polygon in polygon mode GetModelingAxis will return you the matrix of this selection)
While GetMp returns you a vector which represents the center of an object according to its bounding box, in its local space.

• On 22/03/2018 at 11:03, xxxxxxxx wrote:

Hi MaximeA,

Thanks for your patience.
I guess we do not understand each other.

I agree that the rotation is dependend on the axis.
Indeed for a cube I can hardcode that, but what for other objects?

My rules:
- (polygon) selection is done using object A
- selection is a flat rectangular surface
- object to be placed (object B) is placed at the middle of the selection (GetMp())
- object to be placed (object B) is placed perpendicular on the selection.
- object to be placed (object B) is scaled acoording to the selection.
- object to be placed (object B) is aligned with object A

The intent is to place an object where the selection is defined.

Perhaps you have another method to do this?

What do you mean with "missing a constraint"?
Which constraint?

-Pim

• On 22/03/2018 at 15:29, xxxxxxxx wrote:

Hi Pim!

I'm new to python, but I've played with matrices and vectors for sometime in Xpresso. I think that you need at least 2 axes aligned with the polygon to call id properly aligned. If only Z is aligned to the normal of the polygon than the result should not be stable (imagine the object spining 360 degrees around the normal). Try to align another axis of the object to one of the edges of the polygon. This should act as an up vector. The problem you are facing is somewhat similar to the align to spline tag. Whenever the driving spline rotates onto itself, the object flips, although it is always oriented along the tangent of the spline. That's why the rails spline or an up vector is for. I hope to have made myself clear.

• On 23/03/2018 at 06:47, xxxxxxxx wrote:

Hi Ilirbeqiri, Thanks for coming to my rescue! Welcome at Plugin Cafe ! :)

Regarding your question Pim,
As I understand you want to create a kind of polygnome plugin, which as you can see also get this limitation about rotation, (the user define and rotate the object).
So your last step is not possible, to be determined mathematically (at least easily), but here is how to do your first steps, but the last step is still not possible... According to what Ilirbeqiri said.

``````import c4d

def main() :
if not op:
return

saveDocMode = doc.GetMode()
saveDocAction = doc.GetAction()

doc.SetMode(c4d.Mpolygons)
doc.SetAction(c4d.ID_MODELING_LIVESELECTION)

toolBc = doc.GetActiveToolData()
saveToolBc = toolBc.GetClone(c4d.COPYFLAGS_PRIVATE_CONTAINER_COPY_IDENTICAL)

toolBc[c4d.MDATA_AXIS_MODE] = c4d.MDATA_AXIS_MODE_SELECTED
toolBc[c4d.MDATA_AXIS_ROT] = c4d.MDATA_AXIS_ROT_NORMALS
toolBc[c4d.MDATA_AXIS_BOUNDS_X] = 0.0
toolBc[c4d.MDATA_AXIS_BOUNDS_Y] = 0.0
toolBc[c4d.MDATA_AXIS_BOUNDS_Z] = 0.0

mSelection = op.GetModelingAxis(doc)

cyl = doc.SearchObject("Cylinder")
if not cyl:
return
cyl.SetMg(mSelection)

saveToolBc.CopyTo(toolBc, c4d.COPYFLAGS_PRIVATE_CONTAINER_COPY_IDENTICAL)
doc.SetMode(saveDocMode)
doc.SetAction(saveDocAction)

c4d.EventAdd()

if __name__=='__main__':
main()
``````

Scaling according to polygon size is a bit more challenging, and there is no quick way(at least to know how much you should scale your object to match the polygon area) for doing it.
But I guess by computing the bounding box of the selected polygons will work then scaling your object to match this bounding box will work.
If you need some help about that I may spend some more time next week but I can't promise anything.

About GetMp() I'm really confused why you use it since it returns the position of the object axis. Not the one from the selection.

Hope it's help anyway.

Cheers,
Maxime

• On 23/03/2018 at 12:20, xxxxxxxx wrote:

Originally posted by xxxxxxxx

Hi Pim!

I'm new to python, but I've played with matrices and vectors for sometime in Xpresso. I think that you need at least 2 axes aligned with the polygon to call id properly aligned. If only Z is aligned to the normal of the polygon than the result should not be stable (imagine the object spining 360 degrees around the normal). Try to align another axis of the object to one of the edges of the polygon. This should act as an up vector. The problem you are facing is somewhat similar to the align to spline tag. Whenever the driving spline rotates onto itself, the object flips, although it is always oriented along the tangent of the spline. That's why the rails spline or an up vector is for. I hope to have made myself clear.

Yes,I agree, using an up-vector would do the trick.
But how youdo that?
So, how to align another axis of the object to one of the edges of the polygon?

-pim

• On 23/03/2018 at 12:37, xxxxxxxx wrote:

Hi MaximeA,

Thanks, that code works!
Hopefully, scaling should not be an issue when using GetMp().

But, I would like to see how you would handle that.
So, if you have the time please do.

About the code: briljant, something I would never have figured out myself.
Is it true that you get the global matrix of the selection and use that to set object B?

Note: I split the selection and then GetMp() gives me the size of of that split object.

-Pim

• On 23/03/2018 at 15:14, xxxxxxxx wrote:

Hi Pim!

I see that Maxime's code has worked for you! I'm glad for you! I learned something new also!

As I mentioned in my previous post, I'm not experienced in Python, but to prove my point I've built a demo scene using Xpresso. The setup is as follows: There's one polygon object and a null that will be aligned to its normal. The polygon's normal and center are easily attained using the Polygon node. I made use of a Vector2Matrix node to convert the normal vector to a rotation Matrix and feed it's result to a Matrix2HPB node. This yields three rotation values, which you can combine in a Reals2Vector node. The edge I chose for the Up vector is the one between points 0 and 1. A simple vector subtraction returns the direction vector, which is later normalized and fed to a Vector2Matrix node and decmposed into three rotation values. Now comes the combination of the rotation values of the normal and edge into the Reals2Vector node and then the rotation is combined into a Generate Matrix node with the center of the polygon as the offset. I'm sending a link of the scene file for inspection. https://goo.gl/uKxwJv The poin is that whatever transformation you do to the polygon (assuming it stays planar) the Null will always stay in the center of it and aligned to the normal and one of the edges. I'm not sure how it all translates into Python, but I presume a coder  with you experience can easily do that. Actually I'm curious to see you come up with something!

Respects
Ilir

Edited

Here's an even simpler version with the same result https://goo.gl/tVkZer. The setup is as follows: First get the normal of the polygon (first matrix axis) and it's center (matrix offset) using the Polygon node. Then get the difference of the vectors for the positions of the point 0 and 1, normalize the result (this is the second matrix axis). The third matrix axis can be calculated with the Cross Product of the first and the second axes vectors. Feed the offset and the three direction axes to a Vector2Matrix node and the matrix goes to the Global Matrix port of the Null object. Now whatever transformation is applied to the Polygon object, the null should stay rock solid on the center and aligned to the normal and the first edge.

• On 26/03/2018 at 04:24, xxxxxxxx wrote:

Great, thank you.
I will transform it to python and let you know.

-Pim