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)])