def _generate_normals(polygons):
if isinstance(polygons, np.ndarray):<EOL><INDENT>n = polygons.shape[-<NUM_LIT:2>]<EOL>i1, i2, i3 = <NUM_LIT:0>, n//<NUM_LIT:3>, <NUM_LIT:2>*n//<NUM_LIT:3><EOL>v1 = polygons[..., i1, :] - polygons[..., i2, :]<EOL>v2 = polygons[..., i2, :] - polygons[..., i3, :]<EOL><DEDENT>else:<EOL><INDENT>v1 = np.empty((len(polygons), <NUM_LIT:3>))<EOL>v2 = np.empty((len(polygons), <NUM_LIT:3>))<EOL>for poly_i, ps in enumerate(polygons):<EOL><INDENT>n = len(ps)<EOL>i1, i2, i3 = <NUM_LIT:0>, n//<NUM_LIT:3>, <NUM_LIT:2>*n//<NUM_LIT:3><EOL>v1[poly_i, :] = ps[i1, :] - ps[i2, :]<EOL>v2[poly_i, :] = ps[i2, :] - ps[i3, :]<EOL><DEDENT><DEDENT>return np.cross(v1, v2)<EOL>
Takes a list of polygons and return an array of their normals.
Normals point towards the viewer for a face with its vertices in
counterclockwise order, following the right hand rule.
Uses three points equally spaced around the polygon.
This normal of course might not make sense for polygons with more than
three points not lying in a plane, but it's a plausible and fast
approximation.
Args:
    polygons (list): list of (M_i, 3) array_like, or (..., M, 3) array_like
        A sequence of polygons to compute normals for, which can have
        varying numbers of vertices. If the polygons all have the same
        number of vertices and array is passed, then the operation will
        be vectorized.
Returns:
    normals: (..., 3) array_like
        A normal vector estimated for the polygon.