annotate arrow drawn slightly off

I've been trying to track down a problem in the arrows where the arrow seems to be off by a little bit. I've narrowed down the problem to a small example:

import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
fig=plt.figure()
ax = fig.add_subplot(111, xlim=(.98,1.02), ylim=(.98,1.02),aspect='equal')
from matplotlib.patheffects import Stroke

ax.annotate('', (1,1),
             (0,0),
             arrowprops=dict(arrowstyle="-|>",
                             fc="w", ec="k",lw=30,
                             path_effects=[Stroke(joinstyle='miter')]),)
ax.plot([0,1],[1,1])
ax.plot([1,1],[0,1])
ax.plot([0,1.02],[0,1.02])

fig.savefig('test.png')

I've used a miter join above because it illustrates the problem better. Notice that the arrowhead tip is just below the line, but should be right on the line. Any clue about what the problem is?

Thanks,

Jason

···

--
Jason Grout

Thanks for tracking down this.
It turned out to be a silly error while adjusting the line end-point.
I’m attaching the patch. Please test the patch if you can.
I’ll commit the change sometime tomorrow.

Regards,

-JJ

arrow.patch (2.34 KB)

···

On Tue, Nov 9, 2010 at 9:15 PM, Jason Grout <jason-sage@…2130…> wrote:

I’ve been trying to track down a problem in the arrows where the arrow

seems to be off by a little bit. I’ve narrowed down the problem to a

small example:

import matplotlib.patches as mpatches

import matplotlib.pyplot as plt

fig=plt.figure()

ax = fig.add_subplot(111, xlim=(.98,1.02), ylim=(.98,1.02),aspect=‘equal’)

from matplotlib.patheffects import Stroke

ax.annotate(’’, (1,1),

         (0,0),

         arrowprops=dict(arrowstyle="-|>",

                         fc="w", ec="k",lw=30,

                         path_effects=[Stroke(joinstyle='miter')]),)

ax.plot([0,1],[1,1])

ax.plot([1,1],[0,1])

ax.plot([0,1.02],[0,1.02])

fig.savefig(‘test.png’)

I’ve used a miter join above because it illustrates the problem better.

Notice that the arrowhead tip is just below the line, but should be

right on the line. Any clue about what the problem is?

Thanks,

Jason

Jason Grout


The Next 800 Companies to Lead America’s Growth: New Video Whitepaper

David G. Thomson, author of the best-selling book "Blueprint to a

Billion" shares his insights and actions to help propel your

business during the next growth cycle. Listen Now!

http://p.sf.net/sfu/SAP-dev2dev


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Jae-Joon,

I just tested out the patch, and while it did seem to fix the problem for me on the test script, I am not 100% certain that it is properly lined up (maybe an off-by-one-pixel error?). Anyway, I tried zooming in to see which kind of error it was and I got a very weird image. I am not certain exactly what triggers it, but I think if the rubber-banding does not incorporate the entire arrow-head, then the distortion appears. I was also able to reproduce the distortion without the patch (although I think it was easier to cause with the patch).

Ben Root

weird_arrow.png

···

On Tue, Nov 9, 2010 at 7:24 AM, Jae-Joon Lee <lee.j.joon@…1003…7…> wrote:

Thanks for tracking down this.
It turned out to be a silly error while adjusting the line end-point.
I’m attaching the patch. Please test the patch if you can.
I’ll commit the change sometime tomorrow.

Regards,

-JJ

On Tue, Nov 9, 2010 at 9:15 PM, Jason Grout <jason-sage@…2130…> wrote:

I’ve been trying to track down a problem in the arrows where the arrow

seems to be off by a little bit. I’ve narrowed down the problem to a

small example:

import matplotlib.patches as mpatches

import matplotlib.pyplot as plt

fig=plt.figure()

ax = fig.add_subplot(111, xlim=(.98,1.02), ylim=(.98,1.02),aspect=‘equal’)

from matplotlib.patheffects import Stroke

ax.annotate(’’, (1,1),

         (0,0),

         arrowprops=dict(arrowstyle="-|>",

                         fc="w", ec="k",lw=30,

                         path_effects=[Stroke(joinstyle='miter')]),)

ax.plot([0,1],[1,1])

ax.plot([1,1],[0,1])

ax.plot([0,1.02],[0,1.02])

fig.savefig(‘test.png’)

I’ve used a miter join above because it illustrates the problem better.

Notice that the arrowhead tip is just below the line, but should be

right on the line. Any clue about what the problem is?

Thanks,

Jason

Jason Grout


The Next 800 Companies to Lead America’s Growth: New Video Whitepaper

David G. Thomson, author of the best-selling book "Blueprint to a

Billion" shares his insights and actions to help propel your

business during the next growth cycle. Listen Now!

http://p.sf.net/sfu/SAP-dev2dev


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users


The Next 800 Companies to Lead America’s Growth: New Video Whitepaper

David G. Thomson, author of the best-selling book "Blueprint to a

Billion" shares his insights and actions to help propel your

business during the next growth cycle. Listen Now!

http://p.sf.net/sfu/SAP-dev2dev


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users

If it looks like an off-by-one pixel error, make sure you are doing:

import matplotlib
matplotlib.rcParams['path.snap'] = False

to turn off the pixel-snapping that happens with horizontal and vertical lines in png images, or make sure you are seeing the off-by-one in a vector graphic format like pdf. For me, saving a pdf with the slanted line a linewidth of .01 showed that the arrow is right on it now.

I did notice one thing that did seem a little off, though. I see that the tip of the arrow just barely projects over the corner of the box. The arrow is supposed to go to (1,1), and the linewidth is 30, so I'm thinking that the miter join should project a long ways over the box (because the centers of the lines are at (1,1), and the line width is very large). If I change the path_effects argument to:

path_effects=[Stroke(joinstyle='miter'),Stroke(linewidth=1,foreground='w',joinstyle='miter')]

so that I see more clearly where the actual line center is, it appears that the line center is far off of (1,1). I guess at this point, I'm confused about how the arrow is supposed to be representing the segment between (0,0) and (1,1). Is the tip of the arrow (after the miter join) supposed to hit (1,1), or is the center of the line supposed to hit (1,1)? Or maybe the tip of the joinstyle='round' arrow (the default) is supposed to hit (1,1)?

I noticed this bug when I was trying to figure out a way to have the actual drawn arrow end at a specific point (maybe using miter join, so that we had a sharp arrow) for Sage. It would be nice if there was some sort of option that would do the math to shorten the arrow by the necessary amount. Of course, if that's not an option, I could do that math myself in Sage's "arrow" wrapper command.

Thanks,

Jason

···

On 11/9/10 9:21 AM, Benjamin Root wrote:

I just tested out the patch, and while it did seem to fix the problem for me
on the test script, I am not 100% certain that it is properly lined up
(maybe an off-by-one-pixel error?). Anyway, I tried zooming in to see which
kind of error it was and I got a very weird image. I am not certain exactly
what triggers it, but I think if the rubber-banding does not incorporate the
entire arrow-head, then the distortion appears. I was also able to
reproduce the distortion without the patch (although I think it was easier
to cause with the patch).

Thanks for tracking down this.
It turned out to be a silly error while adjusting the line end-point.
I'm attaching the patch. Please test the patch if you can.
I'll commit the change sometime tomorrow.

Thanks. I can reproduce the problem.

aa = ax.annotate('', (1,1),
                 (-10,-10),
                 arrowprops=dict(arrowstyle="-|>",
                                 fc="w", ec="k",lw=30,
                                 path_effects=[Stroke(joinstyle='miter')])
                 )

The erroneous behavior happens when one tries to draw a path that
connects points far outside of the canvas (point 10,10 in above
example). And this is a AGG-specific issue. The erroneous behavior
goes away if we clip the path.

aa.arrow_patch.set_clip_box(ax.figure.bbox)

I try to reproduce the problem with simple plot command, but couldn't.
Maybe this happens only for rendering bezier splines?
Michael, any idea?

One thing I may do to prevent it is to set the clip_path of the arrow
to the figure.bbox by default.
I'll think about it.

Regards,

-JJ

···

On Wed, Nov 10, 2010 at 12:21 AM, Benjamin Root <ben.root@...1304...> wrote:

On Tue, Nov 9, 2010 at 7:24 AM, Jae-Joon Lee <lee.j.joon@...287...> wrote:

Regards,

-JJ

On Tue, Nov 9, 2010 at 9:15 PM, Jason Grout <jason-sage@...2130...> >> wrote:

I've been trying to track down a problem in the arrows where the arrow
seems to be off by a little bit. I've narrowed down the problem to a
small example:

import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
fig=plt.figure()
ax = fig.add_subplot(111, xlim=(.98,1.02),
ylim=(.98,1.02),aspect='equal')
from matplotlib.patheffects import Stroke

ax.annotate('', (1,1),
(0,0),
arrowprops=dict(arrowstyle="-|>",
fc="w", ec="k",lw=30,
path_effects=[Stroke(joinstyle='miter')]),)
ax.plot([0,1],[1,1])
ax.plot([1,1],[0,1])
ax.plot([0,1.02],[0,1.02])

fig.savefig('test.png')

I've used a miter join above because it illustrates the problem better.
Notice that the arrowhead tip is just below the line, but should be
right on the line. Any clue about what the problem is?

Thanks,

Jason

--
Jason Grout

------------------------------------------------------------------------------
The Next 800 Companies to Lead America's Growth: New Video Whitepaper
David G. Thomson, author of the best-selling book "Blueprint to a
Billion" shares his insights and actions to help propel your
business during the next growth cycle. Listen Now!
http://p.sf.net/sfu/SAP-dev2dev
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

------------------------------------------------------------------------------
The Next 800 Companies to Lead America's Growth: New Video Whitepaper
David G. Thomson, author of the best-selling book "Blueprint to a
Billion" shares his insights and actions to help propel your
business during the next growth cycle. Listen Now!
http://p.sf.net/sfu/SAP-dev2dev
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Jae-Joon,

I just tested out the patch, and while it did seem to fix the problem for me
on the test script, I am not 100% certain that it is properly lined up
(maybe an off-by-one-pixel error?). Anyway, I tried zooming in to see which
kind of error it was and I got a very weird image. I am not certain exactly
what triggers it, but I think if the rubber-banding does not incorporate the
entire arrow-head, then the distortion appears. I was also able to
reproduce the distortion without the patch (although I think it was easier
to cause with the patch).

Ben Root

The tip of the arrow is meant to hit (1,1), which is done by the
underlying arrow class adjusting the end point of the path during the
drawing time. This only happens for arrowstyle "->" and etc.
However, there was an incorrect arithmetic which I think is fixed now.
The patch is attached (it also fixes dpi-related issues).
I'm not sure it would be better if this could be optionally turned
off. Any suggestion?
Let me know of any (persisting or other) issues.

FYI, path is shortened by small amount by default. This is controlled
by *shrink* parameter (shrinkA and shrinkB shortens the line begin and
the line end respectively.)

aa = ax.annotate('', (1,1), (0,0),
                 arrowprops=dict(arrowstyle="-|>",
                                 fc="k", ec="k",lw=50,
                                 shrinkB=0,
                                 path_effects=[Stroke(joinstyle='miter')]
                                 )

Also, I noticed that the arrow head is not correctly filled when
path_effects are in use. This is now fixed.

Regards,

-JJ

arrow.patch (8.62 KB)

···

On Wed, Nov 10, 2010 at 1:01 AM, Jason Grout <jason-sage@...2130...> wrote:

Is the tip of the arrow (after the miter join) supposed to hit (1,1), or is
the center of the line supposed to hit (1,1)? Or maybe the tip of the
joinstyle='round' arrow (the default) is supposed to hit (1,1)?

Is the tip of the arrow (after the miter join) supposed to hit (1,1), or is
the center of the line supposed to hit (1,1)? Or maybe the tip of the
joinstyle='round' arrow (the default) is supposed to hit (1,1)?

The tip of the arrow is meant to hit (1,1), which is done by the
underlying arrow class adjusting the end point of the path during the
drawing time. This only happens for arrowstyle "->" and etc.
However, there was an incorrect arithmetic which I think is fixed now.
The patch is attached (it also fixes dpi-related issues).
I'm not sure it would be better if this could be optionally turned
off. Any suggestion?
Let me know of any (persisting or other) issues.

Wow. You're amazing. Thanks for all the work you put into this right away! When I set shrinkB to zero, that arrow is right on the money.

FYI, path is shortened by small amount by default. This is controlled
by *shrink* parameter (shrinkA and shrinkB shortens the line begin and
the line end respectively.)

Right. In Sage, we're using the shrinkA and shrinkB options quite a bit. For example, we use it in drawing vertex-and-edge graphs (so the arrows go to the edges of the vertex circles), and right now we use it by default to shrink by the linewidth (though I think I'm going to turn off Sage's default shrinking and just leave that up to the user).

This latest patch seems to take care of the problems I was seeing.

Thanks again!

Jason

···

On 11/9/10 8:44 PM, Jae-Joon Lee wrote:

On Wed, Nov 10, 2010 at 1:01 AM, Jason Grout > <jason-sage@...2130...> wrote:

--
Jason Grout

I just seem to break things…

I am not 100% sure if the tip is placed correctly, but it does appear much better than before. I now see a tiny bit of the red line southwest of the vertex. Before, the issue was that the arrow tip was northeast of the vertex. In addition, I found that I was still able to produce the distortion after zooming in sufficiently (it took a few extra zooms to make it happen).

I then did one more zoom, and then tried resizing the window, and I think I broke the Agg renderer. Two exceptions were raised. First, an overflow error occurred while rendering the path (complexity exceeded). Then, an “SystemError: error return without exception set” exception was raised from the same spot. I am wondering if zooming into the arrow distortion and/or resizing the figure window triggered the complexity issue, and then the error handling routines weren’t properly handling the raised exception. Here was my traceback:

Traceback (most recent call last):
File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/backends/backend_gtk.py”, line 394, in expose_event
self._render_figure(self._pixmap, w, h)
File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/backends/backend_gtkagg.py”, line 75, in _render_figure

FigureCanvasAgg.draw(self)

File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/backends/backend_agg.py”, line 394, in draw
self.figure.draw(self.renderer)
File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/artist.py”, line 55, in draw_wrapper

draw(artist, renderer, *args, **kwargs)

File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/figure.py”, line 874, in draw
func(*args)
File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/artist.py”, line 55, in draw_wrapper

draw(artist, renderer, *args, **kwargs)

File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/axes.py”, line 1954, in draw
a.draw(renderer)
File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/artist.py”, line 55, in draw_wrapper

draw(artist, renderer, *args, **kwargs)

File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/text.py”, line 1986, in draw
self.arrow_patch.draw(renderer)
File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/patches.py”, line 3930, in draw

path_effect.draw_path(renderer, gc, p, affine, None)

File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/patheffects.py”, line 121, in draw_path
renderer.draw_path(gc0, tpath, affine, None)

File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/backends/backend_agg.py”, line 117, in draw_path
self._renderer.draw_path(gc, path, transform, rgbFace)
OverflowError: Agg rendering complexity exceeded. Consider downsampling or decimating your data.

Traceback (most recent call last):
File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/backends/backend_gtk.py”, line 394, in expose_event
self._render_figure(self._pixmap, w, h)
File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/backends/backend_gtkagg.py”, line 75, in _render_figure

FigureCanvasAgg.draw(self)

File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/backends/backend_agg.py”, line 394, in draw
self.figure.draw(self.renderer)
File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/artist.py”, line 55, in draw_wrapper

draw(artist, renderer, *args, **kwargs)

File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/figure.py”, line 814, in draw
if self.frameon: self.patch.draw(renderer)
File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/artist.py”, line 55, in draw_wrapper

draw(artist, renderer, *args, **kwargs)

File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/patches.py”, line 411, in draw
renderer.draw_path(gc, tpath, affine, rgbFace)
File “/home/bvr/Programs/matplotlib/matplotlib/lib/matplotlib/backends/backend_agg.py”, line 117, in draw_path

self._renderer.draw_path(gc, path, transform, rgbFace)

SystemError: error return without exception set

···

On Tue, Nov 9, 2010 at 8:44 PM, Jae-Joon Lee <lee.j.joon@…287…> wrote:

On Wed, Nov 10, 2010 at 1:01 AM, Jason Grout > <jason-sage@…120…2130…> wrote:

Is the tip of the arrow (after the miter join) supposed to hit (1,1), or is

the center of the line supposed to hit (1,1)? Or maybe the tip of the

joinstyle=‘round’ arrow (the default) is supposed to hit (1,1)?

The tip of the arrow is meant to hit (1,1), which is done by the

underlying arrow class adjusting the end point of the path during the

drawing time. This only happens for arrowstyle “->” and etc.

However, there was an incorrect arithmetic which I think is fixed now.

The patch is attached (it also fixes dpi-related issues).

I’m not sure it would be better if this could be optionally turned

off. Any suggestion?

Let me know of any (persisting or other) issues.

FYI, path is shortened by small amount by default. This is controlled

by shrink parameter (shrinkA and shrinkB shortens the line begin and

the line end respectively.)

aa = ax.annotate(’’, (1,1), (0,0),

             arrowprops=dict(arrowstyle="-|>",

                             fc="k", ec="k",lw=50,

                             shrinkB=0,

                             path_effects=[Stroke(joinstyle='miter')]

                             )

Also, I noticed that the arrow head is not correctly filled when

path_effects are in use. This is now fixed.

Regards,

-JJ

        > Is the tip of the arrow (after the miter

join) supposed to hit (1,1), or is

        > the center of the line supposed to hit (1,1)?  Or maybe

the tip of the

        > joinstyle='round' arrow (the default) is supposed to

hit (1,1)?

        >
      The tip of the arrow is meant to hit (1,1), which is done by

the

      underlying arrow class adjusting the end point of the path

during the

      drawing time. This only happens for arrowstyle "->" and

etc.

      However, there was an incorrect arithmetic which I think is

fixed now.

      The patch is attached (it also fixes dpi-related issues).

      I'm not sure it would be better if this could be optionally

turned

      off. Any suggestion?

      Let me know of any (persisting or other) issues.



      FYI, path is shortened by small amount by default. This is

controlled

      by *shrink* parameter (shrinkA and shrinkB shortens the line

begin and

      the line end respectively.)





      aa = ax.annotate('', (1,1), (0,0),

                      arrowprops=dict(arrowstyle="-|>",

                                      fc="k", ec="k",lw=50,

                                      shrinkB=0,

path_effects=[Stroke(joinstyle=‘miter’)]

                                      )



      Also, I noticed that the arrow head is not correctly filled

when

      path_effects are in use. This is now fixed.



      Regards,



        -JJ
  I just seem to break things...



  I am not 100% sure if the tip is placed correctly, but it does

appear much better than before. I now see a tiny bit of the red
line southwest of the vertex. Before, the issue was that the
arrow tip was northeast of the vertex. In addition, I found that
I was still able to produce the distortion after zooming in
sufficiently (it took a few extra zooms to make it happen).

  I then did one more zoom, and then tried resizing the window, and

I think I broke the Agg renderer. Two exceptions were raised.
First, an overflow error occurred while rendering the path
(complexity exceeded). Then, an “SystemError: error return
without exception set” exception was raised from the same spot. I
am wondering if zooming into the arrow distortion and/or resizing
the figure window triggered the complexity issue, and then the
error handling routines weren’t properly handling the raised
exception. Here was my traceback:
The reason for the rendering complexity problem is that the arrow
extends way, way, way off the edge of the image such that the values
overflow (in pixel units) – Agg uses 24.8 fixed-point arithmetic
internally. The exception throwing itself in this case was broken
(since fixed). Once the exception is thrown, it will always need to
be thrown in subsequent calls into Agg, since there doesn’t seem to
be a clean way to recover from the exception. (There might be, but
it gets down into a much hairier patch to Agg than I’ve been able to
work through).

matplotlib currently supports clipping paths to the bounds of the

image which prevents these huge values from getting passed to the
Agg layer and blowing it up. Unfortunately, this algorithm only
works on un-filled paths. Arrows are implemented as filled shapes,
so this clipping functionality is turned off for them. The solution
seems to be to implement a more sophisticated algorithm that would
clip the path to the rectangle correctly. Certainly such algorithms
exist.

Mike
···

http://p.sf.net/sfu/SAP-dev2dev


Matplotlib-users@lists.sourceforge.nethttps://lists.sourceforge.net/lists/listinfo/matplotlib-users

   

Thanks for tracking down this.
It turned out to be a silly error while adjusting the line end-point.
I'm attaching the patch. Please test the patch if you can.
I'll commit the change sometime tomorrow.

Thanks. I can reproduce the problem.

aa = ax.annotate('', (1,1),
                  (-10,-10),
                  arrowprops=dict(arrowstyle="-|>",
                                  fc="w", ec="k",lw=30,
                                  path_effects=[Stroke(joinstyle='miter')])
                  )

The erroneous behavior happens when one tries to draw a path that
connects points far outside of the canvas (point 10,10 in above
example). And this is a AGG-specific issue. The erroneous behavior
goes away if we clip the path.

aa.arrow_patch.set_clip_box(ax.figure.bbox)
   

It's good to know this works. No need to implement a clipping function of our own, as I previously alluded to.

I try to reproduce the problem with simple plot command, but couldn't.
Maybe this happens only for rendering bezier splines?
Michael, any idea?
   

Matplotlib has its own clipping algorithm that works only on simple paths (paths without a codes array). Basic line plots fit into this category. The reason matplotlib does this rather than always relying on Agg is a) so it works in all backends, thereby saving considerable file size in vector files, and b) removing the line segments outside of the image bounds before they get stroked by Agg saves considerable time. However, this clipping algorithm is pretty simple and doesn't handle filled shapes or bezier curves, so it's turned off in those cases.

One thing I may do to prevent it is to set the clip_path of the arrow
to the figure.bbox by default.
I'll think about it.
   

It may make more sense to apply a global clipping rectangle of the figure to every operation (at least in the Agg backend) -- then we've fixed this once and for all.

Mike

···

On 11/09/2010 07:57 PM, Jae-Joon Lee wrote:

On Wed, Nov 10, 2010 at 12:21 AM, Benjamin Root<ben.root@...1304...> wrote:

On Tue, Nov 9, 2010 at 7:24 AM, Jae-Joon Lee<lee.j.joon@...287...> wrote:

Regards,

-JJ

Regards,

-JJ

On Tue, Nov 9, 2010 at 9:15 PM, Jason Grout<jason-sage@...2130...> >>> wrote:
       

I've been trying to track down a problem in the arrows where the arrow
seems to be off by a little bit. I've narrowed down the problem to a
small example:

import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
fig=plt.figure()
ax = fig.add_subplot(111, xlim=(.98,1.02),
ylim=(.98,1.02),aspect='equal')
from matplotlib.patheffects import Stroke

ax.annotate('', (1,1),
             (0,0),
             arrowprops=dict(arrowstyle="-|>",
                             fc="w", ec="k",lw=30,
                             path_effects=[Stroke(joinstyle='miter')]),)
ax.plot([0,1],[1,1])
ax.plot([1,1],[0,1])
ax.plot([0,1.02],[0,1.02])

fig.savefig('test.png')

I've used a miter join above because it illustrates the problem better.
  Notice that the arrowhead tip is just below the line, but should be
right on the line. Any clue about what the problem is?

Thanks,

Jason

--
Jason Grout

------------------------------------------------------------------------------
The Next 800 Companies to Lead America's Growth: New Video Whitepaper
David G. Thomson, author of the best-selling book "Blueprint to a
Billion" shares his insights and actions to help propel your
business during the next growth cycle. Listen Now!
http://p.sf.net/sfu/SAP-dev2dev
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users
         
------------------------------------------------------------------------------
The Next 800 Companies to Lead America's Growth: New Video Whitepaper
David G. Thomson, author of the best-selling book "Blueprint to a
Billion" shares his insights and actions to help propel your
business during the next growth cycle. Listen Now!
http://p.sf.net/sfu/SAP-dev2dev
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Jae-Joon,

I just tested out the patch, and while it did seem to fix the problem for me
on the test script, I am not 100% certain that it is properly lined up
(maybe an off-by-one-pixel error?). Anyway, I tried zooming in to see which
kind of error it was and I got a very weird image. I am not certain exactly
what triggers it, but I think if the rubber-banding does not incorporate the
entire arrow-head, then the distortion appears. I was also able to
reproduce the distortion without the patch (although I think it was easier
to cause with the patch).

Ben Root

------------------------------------------------------------------------------
The Next 800 Companies to Lead America's Growth: New Video Whitepaper
David G. Thomson, author of the best-selling book "Blueprint to a
Billion" shares his insights and actions to help propel your
business during the next growth cycle. Listen Now!
http://p.sf.net/sfu/SAP-dev2dev
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users
   
--
Michael Droettboom
Science Software Branch
Space Telescope Science Institute
Baltimore, Maryland, USA