def drawv(f, data, value, geometry):
    """
    y = drawv(f, data, value, geometry)

    Superpose points, rectangles and lines on an image.

    `drawv` creates the image `y` by a superposition of points,
    rectangles and lines of gray-level `value` on the image `f`. The
    parameters for each geometrical primitive are defined by each line
    in the `data` parameter. For points, they are represented by 2-D
    coordinates.  For lines, they are drawn with the same convention
    used by points, with a straight line connecting them in the order
    given by the data matrix. For rectangles and filled rectangles,
    data should be an array of 2 x 2D points.

    Parameters
    ----------
    f :        Gray-scale (uint8 or uint16) or binary image.
    data :     Vector of coordinates.
    value :    Gray value(s) for drawing.
                  If it's a single value, then it will be used for all objects,
                  otherwise, it should be an array of same length as `data`.
    geometry :  { 'point', 'line', 'rect', 'frect' (filled rectangles)}

    Returns
    -------
    y : Image of same type as `f`
    """
    """
        - Examples
            #
            #   example 1
            #
            f=to_uint8(zeros((3,5)))
            pcoords=to_uint16([[0,2,4],
                            [0,0,2]])
            pvalue=to_uint16([1,2,3])
            print drawv(f,pcoords,pvalue,'point')
            print drawv(f,pcoords,pvalue,'line')
            rectcoords=to_uint16([[0],
                               [0],
                               [3],
                               [2]])
            print drawv(f,rectcoords, to_uint16(5), 'rect')
            #
            #   example 2
            #
            f=readgray('blob3.tif')
            pc=blob(label(f),'centroid','data')
            lines=drawv(intersec(f,0),transpose(pc),to_uint8(1),'line')
            show(f,lines)
    """
    from numpy import array, newaxis, zeros, put, ravel, arange, floor, int32, zeros_like
    import itertools
    geometry = geometry.lower()
    if len(f.shape) == 1:
        f = f[(newaxis), :]
    value = array(value)
    if value.shape == ():
        value = itertools.repeat(value)
    else:
        assert len(data) == len(value
            ) or geometry == 'line', 'pymorph.drawv: Length of data does not match length of values'
        assert len(data) == len(value
            ) + 1 or geometry != 'line', 'pymorph.drawv: Length of data does not match length of values -1 (for line option)'
    res = zeros_like(f)
    if geometry == 'point':
        for (y, x), val in zip(data, value):
            res[y, x] = val
    elif geometry == 'line':
        for val, (x0, y0), (x1, y1) in itertools.izip(value, data[:-1],
            data[1:]):
            steep = abs(y1 - y0) > abs(x1 - x0)
            if steep:
                y0, x0 = x0, y0
                y1, x1 = x1, y1
            if x0 > x1:
                x0, x1 = x1, x0
                y0, y1 = y1, y0
            deltax = x1 - x0
            deltay = abs(y1 - y0)
            error = deltax // 2
            y = y0
            ystep = 1 if y0 < y1 else -1
            for x in range(x0, x1 + 1):
                if steep:
                    res[y, x] = val
                else:
                    res[x, y] = val
                error -= deltay
                if error < 0:
                    y += ystep
                    error += deltax
    elif geometry in ('frect', 'rect'):
        for (y0, x0, y1, x1), val in zip(data, value):
            assert y1 >= y0, 'pymorph.drawv: bad arguments'
            assert x1 >= x0, 'pymorph.drawv: bad arguments'
            if geometry == 'rect':
                res[y0:y1 + 1, (x0)] = val
                res[y0:y1 + 1, (x1)] = val
                res[(y0), x0:x1 + 1] = val
                res[(y1), x0:x1 + 1] = val
            else:
                res[y0:y1 + 1, x0:x1 + 1] = val
    else:
        assert False, "pymorph.drawv: geometry should be 'point', 'line', 'rect', or 'frect'."
    return res
