Skip to content

Commit e82b391

Browse files
committed
fixed a line collection rounding bug in agg that caused strange bugs when path lengths were 0
svn path=/trunk/matplotlib/; revision=3387
1 parent 131f9dd commit e82b391

File tree

6 files changed

+86
-4
lines changed

6 files changed

+86
-4
lines changed

lib/matplotlib/axes.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2417,6 +2417,7 @@ def vlines(self, x, ymin, ymax, colors='k', linestyle='solid',
24172417

24182418
verts = [ ((thisx, thisymin), (thisx, thisymax))
24192419
for thisx, (thisymin, thisymax) in zip(x,Y)]
2420+
#print 'creating line collection'
24202421
coll = LineCollection(verts, colors=colors,
24212422
linestyle=linestyle, label=label)
24222423
self.add_collection(coll)

lib/matplotlib/collections.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,7 @@ def draw(self, renderer):
694694
offsets = zip(xs, ys)
695695

696696
self.update_scalarmappable()
697+
#print 'calling renderer draw line collection'
697698
renderer.draw_line_collection(
698699
segments, transform, self.clipbox,
699700
self._colors, self._lw, self._ls, self._aa, offsets,

lib/matplotlib/mpl-data/matplotlibrc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
# Agg Cairo GD GDK Paint PS PDF SVG Template
2929
backend : TkAgg
3030
numerix : numpy # numpy, Numeric or numarray
31-
units : True
3231
#interactive : False # see http://matplotlib.sourceforge.net/interactive.html
3332
#toolbar : toolbar2 # None | classic | toolbar2
3433
#timezone : UTC # a pytz timezone string, eg US/Central or Europe/Paris

matplotlibrc.template

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
# Agg Cairo GD GDK Paint PS PDF SVG Template
2929
backend : %(backend)s
3030
numerix : %(numerix)s # numpy, Numeric or numarray
31-
units : True
3231
#interactive : False # see http://matplotlib.sourceforge.net/interactive.html
3332
#toolbar : toolbar2 # None | classic | toolbar2
3433
#timezone : UTC # a pytz timezone string, eg US/Central or Europe/Paris

src/_backend_agg.cpp

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,53 @@ RendererAgg::draw_polygon(const Py::Tuple& args) {
579579

580580
}
581581

582+
583+
584+
SnapData
585+
SafeSnap::snap (const float& x, const float& y) {
586+
xsnap = (int)x + 0.5;
587+
ysnap = (int)y + 0.5;
588+
589+
590+
591+
if ( first || ( (xsnap!=lastxsnap) || (ysnap!=lastysnap) ) ) {
592+
lastxsnap = xsnap;
593+
lastysnap = ysnap;
594+
lastx = x;
595+
lasty = y;
596+
first = false;
597+
return SnapData(true, xsnap, ysnap);
598+
}
599+
600+
// ok both are equal and we need to do an offset
601+
if ( (x==lastx) && (y==lasty) ) {
602+
// no choice but to return equal coords; set newpoint = false
603+
lastxsnap = xsnap;
604+
lastysnap = ysnap;
605+
lastx = x;
606+
lasty = y;
607+
return SnapData(false, xsnap, ysnap);
608+
}
609+
610+
// ok the real points are not identical but the rounded ones, so do
611+
// a one pixel offset
612+
if (x>lastx) xsnap += 1.;
613+
else if (x<lastx) xsnap -= 1.;
614+
615+
if (y>lasty) ysnap += 1.;
616+
else if (y<lasty) ysnap -= 1.;
617+
618+
lastxsnap = xsnap;
619+
lastysnap = ysnap;
620+
lastx = x;
621+
lasty = y;
622+
return SnapData(true, xsnap, ysnap);
623+
}
624+
625+
626+
627+
628+
582629
Py::Object
583630
RendererAgg::draw_line_collection(const Py::Tuple& args) {
584631

@@ -669,8 +716,14 @@ RendererAgg::draw_line_collection(const Py::Tuple& args) {
669716
xys = segments[i%Nsegments];
670717
size_t numtups = xys.length();
671718
if (numtups<2) continue;
719+
720+
672721
bool snapto=numtups==2;
673722
agg::path_storage path;
723+
724+
//std::cout << "trying snapto " << numtups << " " << snapto << std::endl;
725+
726+
SafeSnap snap;
674727

675728

676729
for (size_t j=0; j<numtups; j++) {
@@ -694,8 +747,17 @@ RendererAgg::draw_line_collection(const Py::Tuple& args) {
694747
}
695748

696749
if (snapto) { // snap to pixel for len(2) lines
697-
thisx = (int)thisx + 0.5;
698-
thisy = (int)thisy + 0.5;
750+
SnapData snapdata(snap.snap(thisx, thisy));
751+
// TODO: process newpoint
752+
//if (!snapdata.newpoint) {
753+
// std::cout << "newpoint warning " << thisx << " " << thisy << std::endl;
754+
//}
755+
//std::cout << "snapto" << thisx << " " << thisy << std::endl;
756+
thisx = snapdata.xsnap;
757+
thisy = snapdata.ysnap;
758+
759+
//thisx = (int)thisx + 0.5;
760+
//thisy = (int)thisy + 0.5;
699761
}
700762

701763
if (j==0) path.move_to(thisx, height-thisy);

src/_backend_agg.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,26 @@ typedef agg::amask_no_clip_gray8 alpha_mask_type;
5454
typedef agg::renderer_base<agg::pixfmt_gray8> renderer_base_alpha_mask_type;
5555
typedef agg::renderer_scanline_aa_solid<renderer_base_alpha_mask_type> renderer_alpha_mask_type;
5656

57+
struct SnapData {
58+
SnapData(const bool& newpoint, const float& xsnap, const float& ysnap) :
59+
newpoint(newpoint), xsnap(xsnap), ysnap(ysnap) {}
60+
bool newpoint;
61+
float xsnap, ysnap;
62+
};
63+
64+
class SafeSnap {
65+
// snap to pixel center, avoiding 0 path length rounding errors.
66+
public:
67+
SafeSnap() : first(true), xsnap(0.0), lastx(0.0), lastxsnap(0.0),
68+
ysnap(0.0), lasty(0.0), lastysnap(0.0) {}
69+
SnapData snap (const float& x, const float& y);
70+
71+
private:
72+
bool first;
73+
float xsnap, lastx, lastxsnap, ysnap, lasty, lastysnap;
74+
};
75+
76+
5777
// a helper class to pass agg::buffer objects around. agg::buffer is
5878
// a class in the swig wrapper
5979
class BufferRegion : public Py::PythonExtension<BufferRegion> {

0 commit comments

Comments
 (0)