def inCenter4(vs):
    vs = [Vec(v) for v in vs]
    n = len(vs)
    assert n == 4
    inwardNormals = [(vs[(i+1)%n]-vs[i]).perpDot().normalized() for i in xrange(n)]
    offsets = [inwardNormals[i].dot(vs[i]) for i in xrange(n)]
    if use_numpy:
        M = numpy.matrix([
            list(inwardNormals[0])+[1,0],
            list(inwardNormals[1])+[0,1],
            list(inwardNormals[2])+[1,0],
            list(inwardNormals[3])+[0,1],
        ])
        xyrr = numpy.linalg.solve(M,offsets)
    else:
        M = Mat([
            list(inwardNormals[0])+[1,0],
            list(inwardNormals[1])+[0,1],
            list(inwardNormals[2])+[1,0],
            list(inwardNormals[3])+[0,1],
        ])
        xyrr = M.inverse() * Vec(offsets)
    x,y,r,R = xyrr
    return Vec(x,y)
def inCenter(vs):
    if False:
        do('vs')
    vs = [Vec(v) for v in vs]
    n = len(vs)
    inwardNormals = [(vs[(i+1)%n]-vs[i]).perpDot().normalized() for i in xrange(n)]
    offsets = [inwardNormals[i].dot(vs[i]) for i in xrange(n)]

    # compute n-2 tri-side in-centers...
    centers = []
    radii = []
    for i in xrange(n-2):
        if use_numpy:
            M = numpy.matrix([
                list(inwardNormals[ 0 ])+[-1],
                list(inwardNormals[i+1])+[-1],
                list(inwardNormals[i+2])+[-1],
            ])
            o = numpy.matrix([
                [offsets[ 0 ]],
                [offsets[i+1]],
                [offsets[i+2]],
            ])
            #x,y,r = numpy.linalg.solve(M,o)
            x,y,r = [float(x) for x in numpy.linalg.solve(M,o)]
        else:
            M = Mat([
                list(inwardNormals[ 0 ])+[-1],
                list(inwardNormals[i+1])+[-1],
                list(inwardNormals[i+2])+[-1],
            ])
            o = Vec([
                offsets[ 0 ],
                offsets[i+1],
                offsets[i+2],
            ])
            x,y,r = M.inverse() * o
        if False:
            # FUDGE
            r = abs(r)
        centers.append(Vec(x,y))
        radii.append(r)
        if False:
            #do('x')
            #do('y')
            do('r')


    if n == 3:
        # single weight will be zero in this case... no point in doing the undefined arithmetic
        return centers[0]

    if n == 4:
        # Either way works, but neither way is robust when cocircular
        if False:
            weights = [
                1./(inwardNormals[3].dot(centers[0]) - offsets[3] - radii[0]),
                1./(inwardNormals[n-3].dot(centers[n-2-1])-offsets[n-3] - radii[n-2-1])
            ]
        else:
            weights = [
                inwardNormals[1].dot(centers[1])-offsets[1] - radii[1],
                inwardNormals[3].dot(centers[0])-offsets[3] - radii[0],
            ]
            # fudge-- this shouldn't be needed, if I get a more robust formula to begin with
            if weights[0] == 0. and weights[1] == 0.:
                weights = [1.,1.]

    if n == 5:
        # I fear this doesn't really work
        weights = [
            (inwardNormals[1].dot(centers[1])-offsets[1] - radii[1])*(inwardNormals[2].dot(centers[2])-offsets[2] - radii[2]),
            (inwardNormals[2].dot(centers[2])-offsets[2] - radii[2])*(inwardNormals[3].dot(centers[0])-offsets[3] - radii[0]),
            (inwardNormals[3].dot(centers[0])-offsets[3] - radii[0])*(inwardNormals[4].dot(centers[1])-offsets[4] - radii[1]),
        ]


    if False: # XXX GET RID
        # weights other than first and last are
        # 1 / (distance from last side not involving that circle) / (distance from first side not involving that circle)
        for i in xrange(n-4):
            weights.append(1./((inwardNormals[1+i].dot(centers[1+i]) - offsets[1+i] - radii[1+i])
                             * (inwardNormals[4+i].dot(centers[1+i]) - offsets[4+i] - radii[1+i]) ))

    weightsSum = sum(weights)
    if weightsSum == 0.:
        return centers[0] # hack
    if False:
        do('[float(weight) for weight in weights]')
        do('weightsSum')
        do('[float(weight/weightsSum) for weight in weights]')

    return sum([center*(weight/weightsSum) for center,weight in zip(centers,weights)])