Plane orientation

I have question about plane orientation.

Assuming I have multiple polylines that are planar and winding in the same orientation.
I would like to compute normal vector of such polyline.

If I use Plane Fit method plane normal is sometimes flipped.
If I take the Mesh.FromClosedPolyline method to get mesh and then extract one mesh normal I get good orientation:

Is there any mathematical method how to compute polygon normal for polyline coordinates?


Question.gh (5.7 KB)

//Fit polyline points to plane results in incorrect plane orientation
Plane plane0;
Plane.FitPlaneToPoints(polyline, out plane0);


//Mesh from closed polyline takes into account polyline orientation and results in good result
Mesh mesh = Mesh.CreateFromClosedPolyline(polyline);

//output
A = polyline.CenterPoint();
B = plane0.ZAxis * 100;
C = mesh.FaceNormals[0] * 100;

Hi Petras, here’s one approach: Making consecutive vertex-vertex-center planes,
and subsequently getting the dominant Z-axis direction of the generated planes, which should work with both convex and concave polygons (I think, but haven’t tested):


PolylineOrientation_Deleuran.gh (12.1 KB)

1 Like

Thank you Anders it is what I needed:)

1 Like

Could not figure out most common element in C#, so this is a version without common search.

Just wondering how and why it works when most common is getting the good direction, on one hand it is not connected with winding direction but on other hand it is a valid result:

Do you think something similar can be measured in 3D when polyline is planar without orienting planar curve to 2D? It is probably somehow the way how normals in polygonal meshes are computed .

Or maybe more simple question how you would know the most common vector when polyline is planar but rotated in 3D?

  private void RunScript(Polyline polyline, object y, ref object A)
  {

    int a = (polyline.IsClosed) ? 1 : 0;
    int n = polyline.Count - a;

    Plane[] planes = new Plane[n];
    Point3d center = polyline.CenterPoint();
    Plane plane = new Plane();
    Plane.FitPlaneToPoints(polyline, out plane);
    plane.Origin = center;

    int ne = 0;
    int po = 0;
    for(int i = 0; i < n;i++){
      planes[i] = new Plane(polyline[i], polyline[i + 1], center);

      if(planes[i].ZAxis.Z < 0)
        ne++;
      else
        po++;
    }

    if( po < ne && (plane.ZAxis.Z > 0) )
      plane.Flip();

    A = plane;

Found the other answer by averaging cross products:

public static Vector3d AverageNormal(this Polyline p)
{

    int len = p.Count - 1;
    Vector3d vector3d = new Vector3d();


    for (int i = 0; i < len; i++)
    {
        int num = ((i - 1) + len) % len;
        int item1 = ((i + 1) + len) % len;
        Point3d point3d = p[num];
        Point3d point3d1 = p[item1];
        Point3d item2 = p[i];
        vector3d = vector3d + Vector3d.CrossProduct(new Vector3d(item2 - point3d), new Vector3d(point3d1 - item2));
    }

    if (vector3d.X == 0 & vector3d.Y == 0 & vector3d.Z == 0)
        vector3d.Unitize();

    return vector3d;
}
2 Likes

Thank you pointing me to this topic @AndersDeleuran!
The most common method seems to work great except for concave polylines.
@Petras_Vestartas, your last method works with concave ones as well!
Thank you both.

2 Likes