def interpolateNormals(coords, elems, atNodes=False, treshold=None):
    """Interpolate normals in all points of elems.

    coords is a (ncoords,3) array of nodal coordinates.
    elems is an (nel,nplex) array of element connectivity.
    
    The default return value is an (nel,nplex,3) array with the averaged
    unit normals in all points of all elements.
    If atNodes == True, a more compact array with the unique averages
    at the nodes is returned.
    """
    n = geomtools.polygonNormals(coords[elems])
    n = nodalSum(n, elems, return_all=not atNodes, direction_treshold=treshold)
    return normalize(n)
def drawPolygons(x, e, mode, color=None, alpha=1.0, normals=None, objtype=-1):
    """Draw a collection of polygon elements.

    This function is like drawPolygons, but the vertices of the polygons
    are specified by:
    coords (npts,3) : the coordinates of the points
    elems (nels,nplex): the connectivity of nels polygons of plexitude nplex

    color is either None or an RGB color array with shape (3,), (nels,3) or
    (nels,nplex,3).

    objtype sets the OpenGL drawing mode. The default (-1) will select the
    appropriate value depending on the plexitude of the elements:
    1: point, 2: line, 3: triangle, 4: quad, >4: polygon.
    The value can be set to GL.GL_LINE_LOOP to draw the element's circumference
    independent from the drawing mode.
    """
    pf.debug("drawPolygons")
    if e is None:
        nelems = x.shape[0]
    else:
        nelems = e.shape[0]
    n = None
    if mode.startswith("smooth") and objtype == -1:
        if normals is None:
            pf.debug("Computing normals")
            if mode == "smooth_avg" and e is not None:
                n = interpolateNormals(x, e, treshold=pf.cfg["render/avgnormaltreshold"])
                mode = "smooth"
            else:
                if e is None:
                    n = geomtools.polygonNormals(x)
                else:
                    n = geomtools.polygonNormals(x[e])
                pf.debug("NORMALS:%s" % str(n.shape))
        else:
            try:
                n = asarray(normals)
                if not (n.ndim in [2, 3] and n.shape[0] == nelems and n.shape[-1] == 3):
                    raise
            except:
                raise ValueError, """Invalid normals specified"""

    # Sanitize data before calling library function
    x = x.astype(float32)
    if e is not None:
        e = e.astype(int32)
    if n is not None:
        n = n.astype(float32)
    if color is not None:
        color = color.astype(float32)
        pf.debug("COLORS:%s" % str(color.shape))
        if color.shape[-1] != 3 or (color.ndim > 1 and color.shape[0] != nelems):
            pf.debug("INCOMPATIBLE COLOR SHAPE: %s, while nelems=%s" % (str(color.shape), nelems))
            color = None

    # Call library function
    if e is None:
        drawgl.draw_polygons(x, n, color, alpha, objtype)
    else:
        drawgl.draw_polygon_elems(x, e, n, color, alpha, objtype)