From: John H. <jdh...@ac...> - 2005-02-18 20:41:55
|
>>>>> "Chris" == Chris Barker <Chr...@no...> writes: Chris> Hi all, Is there a way to get the size of a text object? I Chris> can't seem to find a method that does that. The Chris> functionality must be in there somewhere, or having Chris> different reference points wouldn't work. The size of a text object is tricky. Do you mean the width and height in points? Or in data coords? The x,y location of text is in one coordinate system (axes, figure or data), but the width and height are not. To convert between coordinate systems (eg points or display versus data) the way mpl does it is to one transform coord system to display and use the other coordinate system to inverse transform. This would enable you to get, for example, a text bounding box in data coords, but could be screwed up by a figure resize. If you tell me more precisely what you are trying to achieve, I might be able to help you or think about design changes to accommodate it. FYI, this is an issue that crops up a lot and is vexing. What one would like to be able to do is use a layout engine and say, place object one above and to the right of object 2 with a pad of 2 points. The text instance can give you its bounding box in display if you pass it the backend renderer -- this is required because the width and height can be backend dependent. I suppose you are using OO agg based on your previous posts. One problem with the current design that is that the agg canvas doesn't generate it's renderer until draw time (with caching), but you need access to the renderer before draw time for layout that depends on text. If we move this logic to a get_renderer method, you can use it at draw time. I'll attach a replacement backend_agg.FigureCanvasAgg class to support this below from matplotlib.figure import Figure from matplotlib.backends.backend_agg import FigureCanvasAgg fig = Figure() canvas = FigureCanvasAgg(fig) renderer = canvas.get_renderer() ax = fig.add_subplot(111) ax.plot([1,2,3]) t = ax.text(1,2,'hi mom') bbox = t.get_window_extent(renderer) print 'display', bbox.get_bounds() #l,b,w,h # get the axes data coords bbox of this display bounding box from matplotlib.transforms import inverse_transform_bbox axbox = inverse_transform_bbox(ax.transData, bbox) print 'data coords', axbox.get_bounds() fig.savefig('test') In backend_agg.py FigureCanvasAgg, replace the draw method with the following 2 methods def draw(self): """ Draw the figure using the renderer """ if __debug__: verbose.report('FigureCanvasAgg.draw', 'debug-annoying') renderer = self.get_renderer() self.figure.draw(renderer) def get_renderer(self): l,b,w,h = self.figure.bbox.get_bounds() key = w, h, self.figure.dpi.get() try: self._lastKey, self.renderer except AttributeError: need_new_renderer = True else: need_new_renderer = (self._lastKey != key) if need_new_renderer: self.renderer = RendererAgg(w, h, self.figure.dpi) self._lastKey = key return self.renderer Hope this gets you started -- if you provide more details we maybe able to improve from here. JDG |