# Finding Mesh Cell Normals

I need to find a normal pointing outside for every face / cell of a closed Mesh Region.

How can I do this?

Here's what I have now - mesh + mesh cells centers and I'm stuck and puzzled. There's VertexNormals, but there's no "CellNormals" or whatever else.

(* import OBJ *)
input = Import["torus.obj"];

(* Faces & Points *)
coords = MeshCoordinates[input]; (* вершины *)
cells = MeshCells[input, 2]; (* грани *)

(* Boundary Mesh Region *)
torus = BoundaryMeshRegion[coords, cells,
MeshCellStyle -> Opacity[0.3]];

(* Cell Centers *)
meshprimitives = MeshPrimitives[torus, 2];
cellcenters =
Table[RegionCentroid[meshprimitives[[i]]], {i,
meshprimitives // Length}];
ссPoints = ListPointPlot3D[cellcenters, PlotStyle -> Red];

(* Graph *)
Show[torus, ссPoints]


Here's what I need:

NB! The normals need to be pointed outside.

• @UlrichNeumann I would, if I could ) Jun 24, 2022 at 13:41
• Starting examplary with a Sphere[] ??? Jun 24, 2022 at 13:49
• @UlrichNeumann I could draw a vector ))) Jun 24, 2022 at 13:51
• There's RegionMeshMeshCellNormals. See mathematica.stackexchange.com/questions/130226/… etc. from searching the site for MeshCellNormals. Jun 24, 2022 at 14:41

Here is an approach using the undocumented RegionMeshMeshCellNormals function mentioned previously in this answer, from which the vector plotting code I show below is also inspired.

First let's get a coarsely-discretized torus:

input =
DiscretizeRegion[
ParametricRegion[
{Cos[t] (3 + Cos[u]), Sin[t] (3 + Cos[u]), Sin[u]},
{{t, 0, 2 Pi}, {u, 0, 2 Pi}}
],
MaxCellMeasure -> 1000
]


Then let's use the undocumented fucntion to calculate the direction of the normals to each face:

normals = RegionMeshMeshCellNormals[input, 2]

(* Out:
{{0.999555, 0.00942983, 0.0282893}, {-0.652107, 0.577115, -0.491625}, ... ,
{-0.847775, 0.493059, -0.195371}, {0.846814, -0.513404, 0.139001}}
*)


... and plot them on the surface, as arrows:

Show[
input,
Graphics3D[{
{Darker[rc = RandomColor[]], FaceForm[rc], #} & /@
{#1, Arrow[{Mean@#1[[1]], Mean@#1[[1]] + Normalize@#2}]} &,
{MeshPrimitives[input, 2], normals}
]
}]
]


• Ah, I forgot that one. Very nice. Jun 24, 2022 at 14:27
• Excellent, thank you! Jun 24, 2022 at 14:31

The conventional way to get face normals is to use Newell's method (which I have also used in previous answers):

newellNormals[pts_?MatrixQ] := Module[{tp = Transpose[pts]}, Normalize[MapThread[Dot,
{RotateLeft[ListConvolve[{{-1, 1}}, tp, {-1, -1}]],
RotateRight[ListConvolve[{{1, 1}}, tp, {-1, -1}]]}]]]


This assumes that all the polygons in your mesh are consistently oriented: if a polygon in your mesh is oriented anticlockwise from where it is being viewed, then the resulting normal will point in that direction. (Both FindMeshDefects[] and to a lesser extent FaceForm[] are useful for diagnostics like this.)

Since the OP does not give a usable example, I'll use one of the built-in meshes:

herbie = ExampleData[{"Geometry3D", "UtahVWBug"}, "MeshRegion"];
polys = MeshPrimitives[herbie, 2];
nrms = newellNormals @@@ polys;