Mathematical Challenge: Mapping a Local Frame to Global Axes

I’m trying to create a C# script that aligns a beam from its local axis to the global axis based on specific criteria. The beam to be aligned always has a rectangular cross-section, where the base (the shorter side) and the height (the longer side) are clearly defined. The alignment should be such that:

  • The base is always parallel to the global Y-axis.
  • The height is always parallel to the global Z-axis.
  • The part’s main axis is aligned with the global X-axis.

My current script works in some cases; however, when the beam is rotated significantly, it only partially aligns with the global axes, resulting in a slight rotation error. I considered implementing quaternions, but I’m not sure if that’s necessary.

How can I ensure that, regardless of the beam initial orientation, it always aligns perfectly with the global axes following these criteria?

For parts with moderate rotations, my script aligns them correctly:

cases of more significant rotations, it fails to achieve proper alignment:

 private void RunScript(Brep brep, Curve axis, ref object A)
  {
    Point3d p0 = axis.PointAtStart;
    Point3d p1 = axis.PointAtEnd;
    Vector3d xLocal = p1 - p0;

    Vector3d globalZ = Vector3d.ZAxis;
    Vector3d zLocal = globalZ - (globalZ * xLocal) * xLocal;

    Vector3d yLocal = Vector3d.CrossProduct(zLocal, xLocal);
    yLocal.Unitize();

    BoundingBox bbox = brep.GetBoundingBox(true);
    double sizeY = bbox.Max.Y - bbox.Min.Y;
    double sizeZ = bbox.Max.Z - bbox.Min.Z;

    Plane localPlane = new Plane(p0, xLocal, yLocal);

    Transform toWorldXY = Transform.PlaneToPlane(localPlane, Plane.WorldXY);
    Brep finalBrep = brep.DuplicateBrep();
    finalBrep.Transform(toWorldXY);

    BoundingBox finalBBox = finalBrep.GetBoundingBox(true);


    A = finalBrep;
  }

My knowledge about C# is very low. The question however is interesting me.
So I thought to give it a try and do this in regular components.
The idea:

  • deconstruct the brep you have
  • use three of the vertices to create a new plane.
    I did this manually, but I think you can use a sort list to get the plane you need of the brep.
  • Use orient to place a copy on the Plane XY.

Next thought: Would AI know how to do this?
So I asked LeChat from Mistral to translate my solution to C#. It came up with this:

private void RunScript(Brep brep, ref object A)
{
    // Deconstruct the Brep to get its vertices
    Point3d[] vertices = brep.Vertices.ToArray();

    // Choose three vertices to define a plane
    // For simplicity, we'll use the first three vertices
    // You can implement a more sophisticated selection if needed
    Point3d p0 = vertices[0];
    Point3d p1 = vertices[1];
    Point3d p2 = vertices[2];

    // Create a plane using the three points
    Plane localPlane = new Plane(p0, p1, p2);

    // Create a transformation to align the local plane with the world XY plane
    Transform toWorldXY = Transform.PlaneToPlane(localPlane, Plane.WorldXY);

    // Duplicate the Brep and apply the transformation
    Brep finalBrep = brep.DuplicateBrep();
    finalBrep.Transform(toWorldXY);

    // Assign the transformed Brep to the output
    A = finalBrep;
}

No idea if it is usefull, but could be a start to search further.

what are you trying to achieve with this line of code?

you only use one Vector as Referenz (“local”) xLocal.
so the rotation around xLocal is not defined.

even if I do not understand, what you re trying to do with 2 nested Dot-products. …
looks like your script aligns xLocal to Wold-X-Axis.
And does not have any information to align the rotation around this pair of axis.

are all Breps you re trying to align boxes ?
maybe post a .gh file with internalized geometry as well.

kind regards - tom

Thank you for your response.

However, I’d like to solve this issue without extracting the Brep’s vertices or edges. I’m aiming for a mathematical solution.

While it would be possible to resolve this by obtaining the cross-section and then using its edges to define a local plane, my goal is to define the plane using only the tangent (i.e., the beam’s axis).

The problem I’m facing is that the vector rejection calculation fails when the rotation is along the tangent.

As far as I know, defining a second reference axis is typically required, but my intuition tells me it should be possible to define it using only the tangent.

Hi,

This line of code is intended to compute the rejection vector.

First, I calculate the dot product to project onto the tangent (which represents the local X axis), and then subtract this projection to remove the influence along the tangent direction.

The result is a vector that is, in most cases, perpendicular to the tangent.

Of course, if the beam is rotated around its own axis, the rejection vector no longer behaves as expected.

// without any testing this should be the same as broken down into 2 lines:
double k = globalZ * xLocal; // * dot product
Vector3d zLocal = globalZ - k * xLocal; // * multiplication

is this what you intended ? I don t see the logic behind this

Thank you for your response, but it’s not what I need.

Imagine a beam defined by its length, base, and height, positioned arbitrarily. I need to align this beam with the global axes according to specific criteria: the longer side of its cross-section (the height) should align with the global Z-axis, and the shorter side (the base) should align with the global Y-axis. The concept is simple, yet the challenge is: how do I align the beam to the global axes regardless of its position or rotation, using only the beam’s own axis? The images I attached clearly illustrate the problem with the current code.

Also, I don’t want to use the beam’s vertices or edges because that would be an easy solution—if I extracted the cross-section and then defined its edges to create a local plane, it would defeat the purpose of the challenge.

It could be that this challenge is comparable to searching for the perpetual motion machine. It would be nice if you could find it, but it goes beyond the laws of nature as we know them.

Every position of an object in space is determined by either:

  • 3 points of the object that are not on the same line.
  • 2 vectors of the object that are not parallel.
  • 1 plane + basepoint

However, you want to achieve this with 1 vector and its starting point. The result will always be that the object can have any rotational state (360 degrees). In any case, a second property is needed to solve this.

Correct me if I am wrong, regards Eef

2 Likes

it is exactly what you have programmed. Just separated into 2 lines of code.

As @Eef_Weenink wrote - you will need more “properties” / input to define the rotation around the point (p0) and axis (xLoca).
The calculation of yLocal does not make sense in my eyes / brain.
Same as I wrote in my initial post.

Your “mathematical Challenge” does not use the inputs needed to solve it.

Add a second output to your script and output localPlane - so you will see that something is wrong.

these are my 2 cents - hope they help - kind regards -tom

Thank you all for your responses. I’ve found a mathematical solution that allows me to align the piece with the global axis using only the tangent, regardless of the object’s position or rotation.

… then please share it.
would love to see the code.

me too :slight_smile:

What I see in the video, I explain like this:

  • the direction of the green object is coming from the object turned (that is why it flipped around at a certain moment.
  • the Z and Y direction are probably adopted from the global XYZ point.

So I would love to see the code so we see how the Z and Y are set.