Attached is a patch that I want to commit to the trunk.
It introduces new attribute "_check_contains" (any name suggestion?)
for Annotation class.

          * True : the annotation will only be drawn when self.xy is
inside the axes.
          * False : the annotation will always be drawn regardless of
its position.
          * None : the self.xy will be checked only if *xycoords* is "data"

The default value is None, i.e., position is only checked if the
xycoords is "data".

I'll commit this soon if others don't object.
Regards,

-JJ


On Fri, May 15, 2009 at 3:44 AM, Ben Coppin <cop...@gmail.com> wrote:
> Thanks! As far as I can tell, this works perfectly.
>
> I agree that this should probably be the default behaviour.
>
> Ben
>
> On Thu, May 14, 2009 at 8:03 PM, Jae-Joon Lee <lee.j.j...@gmail.com> wrote:
>> On Thu, May 14, 2009 at 4:36 AM, Ben Coppin <cop...@gmail.com> wrote:
>>> Hi,
>>>
>>> I've added annotations to a graph I am producing using matplotlib. The
>>> annotations work fine, but when you zoom and pan, the annotations move off
>>> the edge of the chart and are still visible while they're in the main TK
>>> window. Does anyone know of a way to make the annotations disappear when
>>> they move off the edge of the chart?
>>
>> Currently, there is no support for this. However, a monkey patching
>> can be a quick solution for now.
>>
>>
>> from matplotlib.text import Annotation
>>
>> def draw(self, renderer):
>>    x, y = self.xy
>>    x, y = self._get_xy(x, y, self.xycoords)
>>    if not self.axes.bbox.contains(x, y):
>>        return
>>
>>    self.draw_real(renderer)
>>
>> Annotation.draw_real = Annotation.draw
>> Annotation.draw = draw
>>
>> ann = annotate("test", (0.5, 0.5), xytext=(0.6, 0.6),
>>               arrowprops=dict(arrowstyle="->"))
>>
>>
>> I think this should be the default behavior (with optionally turned
>> off). If other developers don't object, i'll try to push this feature
>> into the svn.
>>
>> Regards,
>>
>> -JJ
>>
>>
>>>
>>> Thanks,
>>>
>>> Ben
>>>
>>> ------------------------------------------------------------------------------
>>> The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your
>>> production scanning environment may not be a perfect world - but thanks to
>>> Kodak, there's a perfect scanner to get the job done! With the NEW KODAK
>>> i700
>>> Series Scanner you'll get full speed at 300 dpi even with all image
>>> processing features enabled. http://p.sf.net/sfu/kodak-com
>>> _______________________________________________
>>> Matplotlib-users mailing list
>>> Matplotlib-users@lists.sourceforge.net
>>> https://lists.sourceforge.net/lists/listinfo/matplotlib-users
>>>
>>>
>>
>
Index: lib/matplotlib/text.py
===================================================================
--- lib/matplotlib/text.py	(revision 7100)
+++ lib/matplotlib/text.py	(working copy)
@@ -1407,6 +1407,8 @@
         else:
             self.arrow_patch = None
 
+        # if True, draw annotation only if self.xy is inside the axes
+        self._check_contains = None
 
     __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd
 
@@ -1524,15 +1526,39 @@
             trans = self.axes.transAxes
             return trans.transform_point((x, y))
 
+    def set_check_contains(self, b):
+        """
+        set *check_contains* attribute.
 
+          * True : the annotation will only be drawn when self.xy is inside the axes.
+          * False : the annotation will always be drawn regardless of its position.
+          * None : the self.xy will be checked only if *xycoords* is "data"
+        """
+        self._check_contains = b
+
+    def get_check_contains(self):
+        " retrun *check_contains* attribute. "
+        return self._check_contains
+        
+
     def update_positions(self, renderer):
 
+        xy_pixel = self._get_position_xy(renderer)
+        self._update_position_xytext(renderer, xy_pixel)
+
+
+    def _get_position_xy(self, renderer):
+        x, y = self.xy
+        return self._get_xy(x, y, self.xycoords)
+
+
+    def _update_position_xytext(self, renderer, xy_pixel):
+
         x, y = self.xytext
         self._x, self._y = self._get_xy(x, y, self.textcoords)
 
 
-        x, y = self.xy
-        x, y = self._get_xy(x, y, self.xycoords)
+        x, y = xy_pixel
 
         ox0, oy0 = self._x, self._y
         ox1, oy1 = x, y
@@ -1608,6 +1634,23 @@
 
                 self.arrow.set_clip_box(self.get_clip_box())
 
+
+    class _SimpleEvent:
+        def __init__(self, xy):
+            self.x, self.y = xy
+
+    def _check_xy(self, renderer, xy_pixel):
+        "given the xy coordinate, check if the annotation need to be drawn"
+
+        b = self.get_check_contains()
+        if b or (b is None and self.xycoords == "data"):
+            # check if self.xy is inside the axes.
+            if not self.axes.contains(Annotation._SimpleEvent(xy_pixel))[0]:
+                return False
+
+        return True
+
+
     def draw(self, renderer):
         """
         Draw the :class:`Annotation` object to the given *renderer*.
@@ -1617,7 +1660,13 @@
             self._renderer = renderer
         if not self.get_visible(): return
 
-        self.update_positions(renderer)
+        xy_pixel = self._get_position_xy(renderer)
+
+        if not self._check_xy(renderer, xy_pixel):
+            return
+
+        self._update_position_xytext(renderer, xy_pixel)
+
         self.update_bbox_position_size(renderer)
 
         if self.arrow is not None:
------------------------------------------------------------------------------
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables 
unlimited royalty-free distribution of the report engine 
for externally facing server and web deployment. 
http://p.sf.net/sfu/businessobjects
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Reply via email to