def is_collapse_legal(mesh, u, v, allow_boundary=False):
    """Verify if the requested collapse is legal for a triangle mesh.

    Parameters
    ----------
    mesh : :class:`compas.datastructures.Mesh`
        The mesh.
    u : str
        The vertex to collapse towards.
    v : str
        The vertex to collapse.
    allow_boundary : bool, optional
        If True, collapse is allowed even if `u` and/or `v` is on the boundary.

    Returns
    -------
    bool
        True if the collapse is legal.
        False otherwise.

    """
    u_on = mesh.is_vertex_on_boundary(u)
    v_on = mesh.is_vertex_on_boundary(v)

    if v_on and not u_on:
        return False

    # collapsing of boundary vertices is currently not supported
    # change this to `and` to support collapsing to or from the boundary
    if not allow_boundary:
        if u_on or v_on:
            return False

    fkey_uv = mesh.halfedge[u][v]
    fkey_vu = mesh.halfedge[v][u]

    # check for contained faces
    for nbr in mesh.halfedge[u]:
        if nbr in mesh.halfedge[v]:
            fkey_nbr_v = mesh.halfedge[nbr][v]
            fkey_u_nbr = mesh.halfedge[u][nbr]

            if fkey_nbr_v is None and fkey_u_nbr is None:
                return False

            # in a trimesh
            # u and v should have one neighbor in common
            # and uv-nbr or vu-nbr
            # should define a face
            # check if UV > NBR is a face
            if mesh.halfedge[v][nbr] == fkey_uv and mesh.halfedge[nbr][u] != fkey_uv:
                return False
            # check if VU > NBR is a face
            if mesh.halfedge[u][nbr] == fkey_vu and mesh.halfedge[nbr][v] != fkey_vu:
                return False

    for nbr in mesh.halfedge[v]:
        if nbr in mesh.halfedge[u]:
            # check if UV > NBR is a face
            if mesh.halfedge[v][nbr] == fkey_uv and mesh.halfedge[nbr][u] != fkey_uv:
                return False
            # check if V > U > NBR is a face
            if mesh.halfedge[u][nbr] == fkey_vu and mesh.halfedge[nbr][v] != fkey_vu:
                return False

    return True