Skip to content

Commit dc8eab4

Browse files
committed
[2890979] Close paths correctly in PolyCollection
svn path=/trunk/matplotlib/; revision=7921
1 parent 3c21a25 commit dc8eab4

File tree

8 files changed

+99
-34
lines changed

8 files changed

+99
-34
lines changed

lib/matplotlib/collections.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -574,14 +574,19 @@ def set_verts(self, verts, closed=True):
574574
if closed:
575575
self._paths = []
576576
for xy in verts:
577-
if np.ma.isMaskedArray(xy):
578-
if len(xy) and (xy[0] != xy[-1]).any():
579-
xy = np.ma.concatenate([xy, [xy[0]]])
577+
if len(xy):
578+
if np.ma.isMaskedArray(xy):
579+
xy = np.ma.concatenate([xy, np.zeros((1,2))])
580+
else:
581+
xy = np.asarray(xy)
582+
xy = np.concatenate([xy, np.zeros((1,2))])
583+
codes = np.empty(xy.shape[0], dtype=mpath.Path.code_type)
584+
codes[:] = mpath.Path.LINETO
585+
codes[0] = mpath.Path.MOVETO
586+
codes[-1] = mpath.Path.CLOSEPOLY
587+
self._paths.append(mpath.Path(xy, codes))
580588
else:
581-
xy = np.asarray(xy)
582-
if len(xy) and (xy[0] != xy[-1]).any():
583-
xy = np.concatenate([xy, [xy[0]]])
584-
self._paths.append(mpath.Path(xy))
589+
self._paths.append(mpath.Path(xy))
585590
else:
586591
self._paths = [mpath.Path(xy) for xy in verts]
587592

Binary file not shown.
Binary file not shown.
Loading
Lines changed: 50 additions & 0 deletions
Loading

lib/matplotlib/tests/test_axes.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,23 @@ def test_imshow_clip():
407407
ax.imshow(r, clip_path=clip_path)
408408
fig.savefig('imshow_clip')
409409

410+
@image_comparison(baseline_images=['polycollection_joinstyle'])
411+
def test_polycollection_joinstyle():
412+
# Bug #2890979 reported by Matthew West
413+
414+
from matplotlib import collections as mcoll
415+
416+
fig = plt.figure()
417+
ax = fig.add_subplot(111)
418+
verts = np.array([[1,1], [1,2], [2,2], [2,1]])
419+
c = mcoll.PolyCollection([verts], linewidths = 40)
420+
ax.add_collection(c)
421+
ax.set_xbound(0, 3)
422+
ax.set_ybound(0, 3)
423+
ax.set_xticks([])
424+
ax.set_yticks([])
425+
426+
fig.savefig('polycollection_joinstyle')
410427

411428
if __name__=='__main__':
412429
import nose

src/_backend_agg.cpp

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,7 @@ Py::Object BufferRegion::to_string_argb(const Py::Tuple &args) {
147147
}
148148

149149
GCAgg::GCAgg(const Py::Object &gc, double dpi) :
150-
dpi(dpi), isaa(true), linewidth(1.0), alpha(1.0),
151-
dashOffset(0.0)
150+
dpi(dpi), isaa(true), dashOffset(0.0)
152151
{
153152
_VERBOSE("GCAgg::GCAgg");
154153
linewidth = points_to_pixels ( gc.getAttr("_linewidth") ) ;
@@ -164,13 +163,6 @@ GCAgg::GCAgg(const Py::Object &gc, double dpi) :
164163
_set_hatch_path(gc);
165164
}
166165

167-
GCAgg::GCAgg(double dpi) :
168-
dpi(dpi), isaa(true), linewidth(1.0), alpha(1.0),
169-
dashOffset(0.0)
170-
{
171-
172-
}
173-
174166
void
175167
GCAgg::_set_antialiased(const Py::Object& gc) {
176168
_VERBOSE("GCAgg::antialiased");
@@ -219,11 +211,11 @@ GCAgg::_set_joinstyle(const Py::Object& gc) {
219211

220212
std::string joinstyle = Py::String( gc.getAttr("_joinstyle") );
221213

222-
if (joinstyle=="miter")
223-
join = agg::miter_join_revert;
224-
else if (joinstyle=="round")
214+
if (joinstyle == "miter")
215+
join = agg::miter_join_revert;
216+
else if (joinstyle == "round")
225217
join = agg::round_join;
226-
else if(joinstyle=="bevel")
218+
else if (joinstyle == "bevel")
227219
join = agg::bevel_join;
228220
else
229221
throw Py::ValueError(Printf("GC _joinstyle attribute must be one of butt, round, projecting; found %s", joinstyle.c_str()).str());
@@ -532,7 +524,7 @@ RendererAgg::draw_markers(const Py::Tuple& args) {
532524
if (args.size() == 6)
533525
face_obj = args[5];
534526

535-
GCAgg gc = GCAgg(gc_obj, dpi);
527+
GCAgg gc(gc_obj, dpi);
536528

537529
// Deal with the difference in y-axis direction
538530
marker_trans *= agg::trans_affine_scaling(1.0, -1.0);
@@ -775,7 +767,7 @@ RendererAgg::draw_text_image(const Py::Tuple& args) {
775767

776768
double angle = Py::Float( args[3] );
777769

778-
GCAgg gc = GCAgg(args[4], dpi);
770+
GCAgg gc(args[4], dpi);
779771

780772
theRasterizer.reset_clipping();
781773
rendererBase.reset_clipping(true);
@@ -1081,7 +1073,8 @@ RendererAgg::draw_path(const Py::Tuple& args) {
10811073
template<class PathGenerator, int check_snap, int has_curves>
10821074
Py::Object
10831075
RendererAgg::_draw_path_collection_generic
1084-
(agg::trans_affine master_transform,
1076+
(GCAgg& gc,
1077+
agg::trans_affine master_transform,
10851078
const Py::Object& cliprect,
10861079
const Py::Object& clippath,
10871080
const agg::trans_affine& clippath_trans,
@@ -1101,8 +1094,6 @@ RendererAgg::_draw_path_collection_generic
11011094
typedef agg::conv_curve<quantized_t> quantized_curve_t;
11021095
typedef agg::conv_curve<clipped_t> curve_t;
11031096

1104-
GCAgg gc(dpi);
1105-
11061097
PyArrayObject* offsets = NULL;
11071098
PyArrayObject* facecolors = NULL;
11081099
PyArrayObject* edgecolors = NULL;
@@ -1312,7 +1303,8 @@ RendererAgg::draw_path_collection(const Py::Tuple& args) {
13121303

13131304
try {
13141305
_draw_path_collection_generic<PathListGenerator, 0, 1>
1315-
(master_transform,
1306+
(gc,
1307+
master_transform,
13161308
gc.cliprect,
13171309
gc.clippath,
13181310
gc.clippath_trans,
@@ -1449,7 +1441,8 @@ RendererAgg::draw_quad_mesh(const Py::Tuple& args) {
14491441
try {
14501442
try {
14511443
_draw_path_collection_generic<QuadMeshGenerator, 0, 0>
1452-
(master_transform,
1444+
(gc,
1445+
master_transform,
14531446
gc.cliprect,
14541447
gc.clippath,
14551448
gc.clippath_trans,

src/_backend_agg.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ class BufferRegion : public Py::PythonExtension<BufferRegion> {
104104
class GCAgg {
105105
public:
106106
GCAgg(const Py::Object& gc, double dpi);
107-
GCAgg(double dpi);
108107

109108
double dpi;
110109
bool isaa;
@@ -224,15 +223,16 @@ class RendererAgg: public Py::PythonExtension<RendererAgg> {
224223
bool render_clippath(const Py::Object& clippath, const agg::trans_affine& clippath_trans);
225224
template<class PathIteratorType>
226225
void _draw_path(PathIteratorType& path, bool has_clippath,
227-
const facepair_t& face, const GCAgg& gc);
226+
const facepair_t& face, const GCAgg& gc);
228227
template<class PathGenerator, int check_snap, int has_curves>
229228
Py::Object
230229
_draw_path_collection_generic
231-
(agg::trans_affine master_transform,
232-
const Py::Object& cliprect,
233-
const Py::Object& clippath,
230+
(GCAgg& gc,
231+
agg::trans_affine master_transform,
232+
const Py::Object& cliprect,
233+
const Py::Object& clippath,
234234
const agg::trans_affine& clippath_trans,
235-
const PathGenerator& path_generator,
235+
const PathGenerator& path_generator,
236236
const Py::SeqBase<Py::Object>& transforms_obj,
237237
const Py::Object& offsets_obj,
238238
const agg::trans_affine& offset_trans,
@@ -262,7 +262,7 @@ class _backend_agg_module : public Py::ExtensionModule<_backend_agg_module>
262262
BufferRegion::init_type();
263263

264264
add_keyword_method("RendererAgg", &_backend_agg_module::new_renderer,
265-
"RendererAgg(width, height, dpi)");
265+
"RendererAgg(width, height, dpi)");
266266
initialize( "The agg rendering backend" );
267267
}
268268

0 commit comments

Comments
 (0)