'Perform the 3D projection for this object.'

def do_3d_projection(self, renderer):

    if (self._A is not None):
        self.update_scalarmappable()
        self._facecolors3d = self._facecolors
    (txs, tys, tzs) = proj3d.proj_transform_vec(self._vec, renderer.M)
    xyzlist = [(txs[si:ei], tys[si:ei], tzs[si:ei]) for (si, ei) in self._segis]
    cface = self._facecolors3d
    cedge = self._edgecolors3d
    if (len(cface) != len(xyzlist)):
        cface = cface.repeat(len(xyzlist), axis=0)
    if (len(cedge) != len(xyzlist)):
        if (len(cedge) == 0):
            cedge = cface
        else:
            cedge = cedge.repeat(len(xyzlist), axis=0)
    if self._zsort:
        z_segments_2d = sorted(((self._zsortfunc(zs), list(zip(xs, ys)), fc, ec, idx) for (idx, ((xs, ys, zs), fc, ec)) in enumerate(zip(xyzlist, cface, cedge))), key=(lambda x: x[0]), reverse=True)
    else:
        raise ValueError(u'whoops')
    segments_2d = [s for (z, s, fc, ec, idx) in z_segments_2d]
    if (self._codes3d is not None):
        codes = [self._codes3d[idx] for (z, s, fc, ec, idx) in z_segments_2d]
        PolyCollection.set_verts_and_codes(self, segments_2d, codes)
    else:
        PolyCollection.set_verts(self, segments_2d, self._closed)
    self._facecolors2d = [fc for (z, s, fc, ec, idx) in z_segments_2d]
    if (len(self._edgecolors3d) == len(cface)):
        self._edgecolors2d = [ec for (z, s, fc, ec, idx) in z_segments_2d]
    else:
        self._edgecolors2d = self._edgecolors3d
    if (self._sort_zpos is not None):
        zvec = np.array([[0], [0], [self._sort_zpos], [1]])
        ztrans = proj3d.proj_transform_vec(zvec, renderer.M)
        return ztrans[2][0]
    elif (tzs.size > 0):
        return np.min(tzs)
    else:
        return np.nan
