Welcome to the Onshape forum! Ask questions and join in the discussions about everything Onshape.

First time visiting? Here are some places to start:

  1. Looking for a certain topic? Check out the categories filter or use Search (upper right).
  2. Need support? Ask a question to our Community Support category.
  3. Please submit support tickets for bugs but you can request improvements in the Product Feedback category.
  4. Be respectful, on topic and if you see a problem, Flag it.

If you would like to contact our Community Manager personally, feel free to send a private message or an email.

Rotate plane by degrees about an axis

mark_stouffermark_stouffer Member Posts: 9
edited June 2017 in FeatureScript
I am trying to create a series of similar bodies in different different orientations. They are like fingers on a hand.

I am able to create each finger currently, but am having some difficulty orienting them. I pass in a plane to the function that creates each finger, but then I have to rotate several features on each finger.

The passed-in plane parameter needs to be slightly rotated on the x axis. Then when I construct the finger I have to rotate several planes to construct the additional fingers. Right now I am rotating the additional fingers with respect to the original base plane. For the additional features I should be rotating the feature planes with respect to the x-rotated passed-in plane parameter.

I can use opTransform to rotate each finger after it's construction, but is seems to me like it would be more appropriate to construct the bodies on the appropriate plane first, to simplify further construction process.

Is there a method or function that accepts a plane, a degree * number, and a rotationAxis to move the plane or return a new rotated plane?

Thanks for any help or suggestions of a better way to perform such a construction.


  • mahirmahir Member, Developers Posts: 882 ✭✭✭✭
    You can create a rotated plane using existing plane vectors (x-axis & normal) as a base and then create rotated vectors by multiplying with a transform created with rotationAround().
  • mark_stouffermark_stouffer Member Posts: 9
    I have the rotationAround transform already. What is the function that performs the transform? Is it one of the transform(), or opTransform()? I thought opTransform() only operated on bodies. 
  • mark_stouffermark_stouffer Member Posts: 9
    I use: 
    var pipRotation = rotationAround(axisLine, rotateDegrees * degree);
    ... and then it looks like I can parse some values out of pipRotation["linear"] but I thought there might already be a function for rotating a plane along an axis without having to parse the contents of a transform.
  • mahirmahir Member, Developers Posts: 882 ✭✭✭✭
    edited June 2017
    You don't have to parse anything. The output of rotationAround is a transformation matrix. This is just a 3x3 matrix that you multiply with a base point or vector to transform it (translate, rotate, or scale). In your case, 

    newNormal = pipRotation*oldPlane.normal
    newOrigin = pipRotation*oldPlane.origin
    newX = pipRotation*oldPlane.x


  • mark_stouffermark_stouffer Member Posts: 9
    Wow, that is just about 100 times simpler than what I was trying to do. Thanks!
  • mark_stouffermark_stouffer Member Posts: 9
    edited June 2017
    It looks like I have to use:
    var dipNormal = pipRotation.linear * oldPlane.normal;

  • mahirmahir Member, Developers Posts: 882 ✭✭✭✭
    edited June 2017
    I would use the whole transform, not just the linear component. When you use rotationAround, it generates the required transform to rotate around a specific axis. This transform is really just a combination of a rotation about the origin and a translation. If you separate out the linear portion of the transform, the result will no longer be a rotation about the desired axis. It will probably be around a parallel axis that goes through the origin. 
  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 963
    Mark is correct in that when transforming the plane normal, you want just the linear component.  However, there's an easier way: you can just multiply transforms and planes directly (operator * is overloaded for these in surfaceGeometry.fs).  So you can do:
    var newPlane = pipRotation * oldPlane;

    Ilya Baran \ Director, Architecture and FeatureScript \ Onshape Inc
  • mahirmahir Member, Developers Posts: 882 ✭✭✭✭
    @ilya_baran, that's handy. I understand why the .linear component can be used for the normal and x, since they're just direction vectors centered on the origin, but would it yield an incorrect result to use the whole transform? Does applying a translation to a direction vector end up changing its direction?

    Also, in the overloaded operator, the normal is transformed by inverse(tranpose(transform.linear)). What does using the inverse of the transpose do?
  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 963
    Not using linear would not work because of a units mismatch I believe (this is why units are great IMO).  Without units, it would give the wrong result because the normal is a direction vector rather than a point (e.g., the easiest case to see is that if you translate a plane, you leave the normal be).

    The inverse transpose is the correct way to transform a normal if your transform does not preserve right angles: when you apply a transform to a plane, you're actually transforming the basis vectors.  If you transform the normal the same way, the result may not be orthogonal to the transformed basis. A more mathematical explanation is here: https://computergraphics.stackexchange.com/questions/1502/why-is-the-transposed-inverse-of-the-model-view-matrix-used-to-transform-the-nor
    Ilya Baran \ Director, Architecture and FeatureScript \ Onshape Inc
  • mahirmahir Member, Developers Posts: 882 ✭✭✭✭
    Thanks for the math lesson:)
  • mark_stouffermark_stouffer Member Posts: 9
    edited June 2017
    One of the things that threw me off for a while was that you must do Rotation * Plane. Whereas Plane * Rotation fails. This does not conform to the commutative property of the multiplication operator, which I think coders could reasonably expect. I don't think I've ever seen it disregarded before.
  • mahirmahir Member, Developers Posts: 882 ✭✭✭✭
    edited June 2017
    The issue is you're not really performing a multiplication. As a coder, you can appreciate overloading functions. The multiplication operator has been overloaded to perform what amounts to a matrix multiplication, which is not a commutative operation. 
  • mark_stouffermark_stouffer Member Posts: 9
    I see. I guess adding a Plane * Rotation overload would be misleading.
  • Jake_RosenfeldJake_Rosenfeld Moderator, Onshape Employees, Developers Posts: 1,470
    Hi Mark,

    To give a little more detail: Matrix multiplication is not commutative, and the origin and normal of the plane being transformed are column vectors.

    If you were to want to apply a more complicated transformation to the plane than one rotation, you could do something like:
    (transform1) * (transform2) * (plane)
    Which is not the same transformation as:
    (transform2) * (transform1) * (plane)

    (^ as a note here in case you are interested, these multiplications are associative, just not commutative)

    because of the way matrix multiplication operates
    (plane) * (transform)
    or more specifically
    (origin) * (transform) and
    (normal) * (transform)
    are not valid matrix multiplications (the dimensions of the matrices don't line up)

    Jake Rosenfeld - Modeling Team
Sign In or Register to comment.