Orientate plane perpendicular to line - C# VS Plugin - [Solved]

I have issues plane orientation. I am constructing a plane perpendicular to a line object at the start point of the line. This works well for perpendicularity as well as the direction and length of the normal vector.

The issues is that the plane XAxis and YAxis components are randomly rotated as per my image.
I am trying to orientate rectangle3d to the start point of the line. Extruding it along the line and capping it. All works fine apart from the plane orientation.

Considering the normal vector, how can I ensure that all plane XAxis are pointing right and all YAxis are pointing up. The ZAxis (normal) remains as is

This is the code i’m using. Any help or advise will be appreciated.

public Line CreateBeamAxis()
        {
            Line line = new Line(this.StartPoint, this.EndPoint);
            return line;
        }

        private Plane GetBeamPlane()
        {
            var axis = CreateBeamAxis();
            Plane plane = new Plane(this.StartPoint, axis.Direction);
            return plane;
        }

I also tried and alternative method. Same result.

private Plane GetBeamPlane1()
        {
            var axis = CreateBeamAxis();
            axis.TryGetPlane(out Plane plane);
            return plane;
        }

Not 100% sure why this happens but my guess is that it happens in plain Rhino too. Maybe as a workaround you can instead make a plane that has its orientation right and move it’s centerpoint to your line end and rotate the plane around the Y axis according to the line orientation

Thanks. Will try this approach and see what happens.

I took a different approach. Found this link of Dale Fugier

The method works well, but I am not sure how to deal with returning a struct from various loops.
The PerpendicularFrameAt and ClosestPoint both return bool values, so have to return from two levels.

Any help restructuring this method is welcome.

PS: My C# knowledge not there yet, but learning fast.

SampleCsOrientPerpendicularToCurve.cs

private Plane SetBeamPlane()
        {
            var curve = CreateBeamAxis().ToNurbsCurve();
            if (curve.ClosestPoint(this.StartPoint, out double t))
            {
                if (curve.PerpendicularFrameAt(t, out Plane myplane))
                {
                    return myplane;
                }
            }
            return default(Plane);
        }

if your axes are only ever lines I personally would prefer right hand rule as on a line, the perpendicular frame really can only be achieved with a reference. In my PlugIn the reference is World Z Up but it could be any plane, maybe your class carries plane information?

private Plane SetBeamPlane(Plane reference)
        {
            var curve = CreateBeamAxis().ToNurbsCurve();
            if (curve.ClosestPoint(this.StartPoint, out double t)
            {
                return new Plane(curve.PointAtStart, Vector3d.CrossProduct(curve.TangentAtStart, reference.ZAxis), reference.ZAxis);
            }
        }
1 Like

@lando.schumpich :clap: :smiley: After reading up on the right hand rule, I am in agreement. I only do use Lines as beam axis and therefore more applicable. Also, all the information is read from an text based analysis file and the assumption is that the reference plane is WorldXY. So I also reference WorldXY.ZAxis for the CrossProduct operation.

It’s become clear to me that I need to brush up on my vector algebra and recap on vector processing. :shushing_face:

Last question. Considering your suggested method, in the unlikely event that the IF statement test false, I have to return a plane of some sort. At the moment not sure how to deal with it so I use “return default(Plane)”.
I don’t believe this is correct. What would you do?

I just read the first part of your question and understand your methods a bit better. When you know its only ever going to be lines you can do it like this and don’t need the if statment at all:

private Plane SetBeamPlane(Plane reference)
        {
            Line axis = CreateBeamAxis();
            return new Plane(axis.From, Vector3d.CrossProduct(axis.Direction, reference.ZAxis), reference.ZAxis);
        }

Excellent. Thanks.