def makeCircularString(x, y, radius, angle, text, fontName, fontSize, inside=0, G=None,textAnchor='start'): '''make a group with circular text in it''' if not G: G = Group() angle %= 360 pi180 = pi/180 phi = angle*pi180 width = stringWidth(text, fontName, fontSize) sig = inside and -1 or 1 hsig = sig*0.5 sig90 = sig*90 if textAnchor!='start': if textAnchor=='middle': phi += sig*(0.5*width)/radius elif textAnchor=='end': phi += sig*float(width)/radius elif textAnchor=='numeric': phi += sig*float(numericXShift(textAnchor,text,width,fontName,fontSize,None))/radius for letter in text: width = stringWidth(letter, fontName, fontSize) beta = float(width)/radius h = Group() h.add(String(0, 0, letter, fontName=fontName,fontSize=fontSize,textAnchor="start")) h.translate(x+cos(phi)*radius,y+sin(phi)*radius) #translate to radius and angle h.rotate((phi-hsig*beta)/pi180-sig90) # rotate as needed G.add(h) #add to main group phi -= sig*beta #increment return G
def getBounds(obj): if hasattr(obj, 'getBounds'): # this is the preferred "future" solution :-) return obj.getBounds() # else try all the primitive shapes elif isinstance(obj, shapes.Line): return (obj.x1, obj.y1, obj.x2, obj.y2) elif isinstance(obj, shapes.Rect): return (obj.x, obj.y, obj.x + obj.width, obj.y + obj.height) elif isinstance(obj, shapes.Circle): return (obj.cx - obj.r, obj.cy - obj.r, obj.cx + obj.r, obj.cy + obj.r) elif isinstance(obj, shapes.Ellipse): return (obj.cx - obj.rx, obj.cy - obj.ry, obj.cx + obj.rx, obj.cy + obj.ry) elif isinstance(obj, shapes.Polygon): return getPointsBounds(obj.points) elif isinstance(obj, shapes.PolyLine): return getPointsBounds(obj.points) elif isinstance(obj, shapes.Wedge): return getPointsBounds(obj.asPolygon().points) elif isinstance(obj, shapes.String): w = stringWidth(obj.text, obj.fontName, obj.fontSize) x = obj.x tA = obj.textAnchor if tA != 'start': if tA == 'middle': x -= 0.5 * w elif tA == 'end': x -= w elif tA == 'numeric': x -= shapes.numericXShift(tA, obj.text, w, obj.fontName, obj.fontSize, obj.encoding) return (x, obj.y - 0.2 * obj.fontSize, x + w, obj.y + obj.fontSize) elif isinstance(obj, shapes.Path): xs = [] ys = [] points = obj.points[:] while points: xs.append(points[0]) ys.append(points[1]) points = points[2:] return (min(xs), min(ys), max(xs), max(ys)) # then groups, which need transformation... elif isinstance(obj, shapes.Group): #iterate over each thing getting its rect if obj.contents: b = [] for elem in obj.contents: b.append(getBounds(elem)) (x1, y1, x2, y2) = getRectsBounds(b) trans = obj.transform corners = [[x1, y1], [x1, y2], [x2, y1], [x2, y2]] newCorners = [] for corner in corners: newCorners.append(shapes.transformPoint(trans, corner)) return getPointsBounds(newCorners) else: #empty group needs a sane default; this #will happen when interactively creating a group #nothing has been added to yet. The alternative is #to handle None as an allowed return value everywhere. return (0, 0, 0, 0) elif isinstance(obj, shapes.UserNode): return getBounds(obj.provideNode()) else: raise ValueError("Don't know how to get bounds of %s" % obj)