# How to calculate ngon face normal correctly?

Hi,

How mesh faces normals are normally calculated?

I want to get ngon face normal.

I used method below. But I see it does work only for one polyline, but not on full mesh.
To get a plane origin I sum up all boundary vertices and divided by number of them.
Then for normal vector I thought I could do the same by summing up all vertex normals and dividing by number of them.
But this does not produce normal perpendicular planar ngon face.

Before I was using this method:

``````    public static Plane[] GetNgonPlanes(this Mesh mesh)
{
Plane[] p = new Plane[mesh.Ngons.Count];
uint[][] b = mesh.GetNGonsBoundaries(); //extension method

for (int i = 0; i < mesh.Ngons.Count; i++)
{
Vector3f temp = new Vector3f();
for (int j = 0; j < b[i].Length; j++)
temp += mesh.Normals[(int)b[i][j]];

if (b[i].Length > 0)
temp /= b[i].Length;

p[i] = new Plane(mesh.Ngons.GetNgonCenter(i), temp); //Extension method
}

return p;
}
``````

Ok it has to be cross product:

``````    public static Vector3d GetNGonNormal(this Mesh mesh, uint[] boundaryVertices)
{
//PolyFace item = this[index];
Vector3d vector3d = new Vector3d();
int count = checked(boundaryVertices.Length - 1);
for (int i = 0; i <= count; i++)
{
int num = (int)boundaryVertices[(checked(checked(i - 1) + boundaryVertices.Length)) %  boundaryVertices.Length];
int item1 = (int)boundaryVertices[(checked(checked(i + 1) + boundaryVertices.Length)) % boundaryVertices.Length];
Point3d point3d = mesh.Vertices[num];
Point3d point3d1 = mesh.Vertices[item1];
Point3d item2 = mesh.Vertices[(int)boundaryVertices[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;
}``````

Rhino will calculate mesh face normals for, by way of `MeshFaceNormalList.ComputeFaceNormals`, which basically does something like this:

``````public static Vector3d CalculateMeshFaceNormal(Mesh mesh, int faceIndex)
{
var n = Vector3d.Unset;
if (null != mesh && faceIndex >= 0 && faceIndex < mesh.Faces.Count)
{
var face = mesh.Faces[faceIndex];
var a = mesh.Vertices[face.C] - mesh.Vertices[face.A];
var b = mesh.Vertices[face.D] - mesh.Vertices[face.B];
n = Vector3d.CrossProduct(a, b);
n.Unitize();
}
return n;
}
``````

Since Rhino’s ngons are planar, if face normals have already been calculated then just get the normal of one of the ngon’s faces.

– Dale

Oh that is more straight forward thank you:)

Would it work also for triangles polylines if this would look like this?

``````    public static Vector3d CalculateMeshFaceNormal(this Polyline p)
{
var n = Vector3d.Unset;
if (null != p && p.Count-1 > 3)
{
var a = p[1] - p[0];
var b = p[2] - p[1];
n = Vector3d.CrossProduct(a, b);
n.Unitize();
}
return n;
}``````

Here is a more generalized approach:

``````public static Vector3d CalculatePolygonNormal(Polyline polyline)
{
var n = Vector3d.Unset;
if (null != polyline && polyline.IsValid && polyline.IsClosed)
{
Plane plane;
var rc = Plane.FitPlaneToPoints(polyline, out plane);
if (rc == PlaneFitResult.Success)
n = plane.Normal;
}
return n;
}
``````

– Dale

Does Plane.FitPlaneToPoints take into account direction of polyline? For clockwise pointing in one direction and for anticlockwise pointing into opposite?

It seems that it follow, but it when I rotate polyline in 3d plane z axis is flipping from time to time. While cross product seems to be stable.

This is probably better than my previous example…

``````public static Vector3d GetPolylineCurveNormal(PolylineCurve curve, double tolerance)
{
var n = Vector3d.Unset;
if (null != curve && curve.IsValid && curve.IsClosed)
{
if (tolerance < RhinoMath.ZeroTolerance)
tolerance = RhinoMath.ZeroTolerance;
Plane plane;
if (curve.TryGetPlane(out plane, tolerance))
n = plane.Normal;
}
return n;
}
``````

– D