Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7d809b1

Browse files
committed
Make curves and NaNs play nice together
svn path=/branches/v0_98_5_maint/; revision=6827
1 parent 6f77123 commit 7d809b1

4 files changed

Lines changed: 90 additions & 14 deletions

File tree

CHANGELOG

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
2009-01-26 Make curves and NaNs play nice together - MGD
2+
13
2009-01-19 Fix bug in quiver argument handling. - EF
24

35
2009-01-19 Fix bug in backend_gtk: don't delete nonexistent toolbar. - EF

lib/matplotlib/patches.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,7 @@ def draw(self, renderer):
298298
tpath = transform.transform_path_non_affine(path)
299299
affine = transform.get_affine()
300300

301-
if not np.isnan(tpath.vertices).any():
302-
renderer.draw_path(gc, tpath, affine, rgbFace)
301+
renderer.draw_path(gc, tpath, affine, rgbFace)
303302

304303
#renderer.close_group('patch')
305304

lib/matplotlib/path.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,8 @@ def iter_segments(self, simplify=None):
214214
if not isfinite(curr_vertices).all():
215215
was_nan = True
216216
elif was_nan:
217-
yield curr_vertices[-2:], MOVETO
217+
yield curr_vertices[:2], MOVETO
218+
yield curr_vertices, code
218219
was_nan = False
219220
else:
220221
yield curr_vertices, code

src/agg_py_path_iterator.h

Lines changed: 85 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ class PathIterator
1515
PyArrayObject* m_codes;
1616
size_t m_iterator;
1717
size_t m_total_vertices;
18+
size_t m_ok;
1819
bool m_should_simplify;
20+
static const unsigned char num_extra_points_map[16];
21+
static const unsigned code_map[];
1922

2023
public:
2124
PathIterator(const Py::Object& path_obj) :
@@ -41,6 +44,7 @@ class PathIterator
4144
throw Py::ValueError("Invalid codes array.");
4245
if (PyArray_DIM(m_codes, 0) != PyArray_DIM(m_vertices, 0))
4346
throw Py::ValueError("Codes array is wrong length");
47+
m_ok = 0;
4448
}
4549

4650
m_should_simplify = should_simplify_obj.isTrue();
@@ -53,8 +57,6 @@ class PathIterator
5357
Py_XDECREF(m_codes);
5458
}
5559

56-
static const unsigned code_map[];
57-
5860
private:
5961
inline void vertex(const unsigned idx, double* x, double* y)
6062
{
@@ -82,20 +84,86 @@ class PathIterator
8284
if (m_iterator >= m_total_vertices) return agg::path_cmd_stop;
8385
unsigned code = vertex_with_code(m_iterator++, x, y);
8486

85-
if (MPL_notisfinite64(*x) || MPL_notisfinite64(*y))
86-
{
87-
do
87+
if (!m_codes) {
88+
// This is the fast path for when we know we have no curves
89+
if (MPL_notisfinite64(*x) || MPL_notisfinite64(*y))
8890
{
89-
if (m_iterator < m_total_vertices)
91+
do
92+
{
93+
if (m_iterator < m_total_vertices)
94+
{
95+
vertex(m_iterator++, x, y);
96+
}
97+
else
98+
{
99+
return agg::path_cmd_stop;
100+
}
101+
} while (MPL_notisfinite64(*x) || MPL_notisfinite64(*y));
102+
return agg::path_cmd_move_to;
103+
}
104+
}
105+
else
106+
{
107+
// This is the slow method for when there might be curves.
108+
109+
/* If m_ok is 0, we look ahead to see if the next curve
110+
segment has any NaNs. If it does, we skip the whole
111+
thing and return a move_to to the first point of the
112+
next curve segment. This move_to may include NaNs,
113+
which is ok, since in that case, it will always be
114+
followed by another non-NaN move_to before any other
115+
curves are actually drawn. If the current curve
116+
segment doesn't have NaNs, we set the m_ok counter to
117+
the number of points in the curve segment, which will
118+
skip this check for the next N points.
119+
*/
120+
if (m_ok == 0) {
121+
if (code == agg::path_cmd_stop ||
122+
code == (agg::path_cmd_end_poly | agg::path_flags_close))
90123
{
91-
vertex(m_iterator++, x, y);
124+
return code;
92125
}
93-
else
126+
127+
size_t num_extra_points = num_extra_points_map[code & 0xF];
128+
bool has_nan = (MPL_notisfinite64(*x) || MPL_notisfinite64(*y));
129+
for (size_t i = 0; !has_nan && i < num_extra_points; ++i)
130+
{
131+
double x0, y0;
132+
vertex(m_iterator + i, &x0, &y0);
133+
has_nan = (MPL_notisfinite64(x0) || MPL_notisfinite64(y0));
134+
}
135+
136+
if (has_nan)
137+
{
138+
m_iterator += num_extra_points;
139+
if (m_iterator < m_total_vertices)
140+
{
141+
code = vertex_with_code(m_iterator, x, y);
142+
if (code == agg::path_cmd_stop ||
143+
code == (agg::path_cmd_end_poly | agg::path_flags_close))
144+
{
145+
return code;
146+
}
147+
else
148+
{
149+
return agg::path_cmd_move_to;
150+
}
151+
}
152+
else
153+
{
154+
return agg::path_cmd_stop;
155+
}
156+
}
157+
else /* !has_nan */
94158
{
95-
return agg::path_cmd_stop;
159+
m_ok = num_extra_points;
160+
return code;
96161
}
97-
} while (MPL_notisfinite64(*x) || MPL_notisfinite64(*y));
98-
return agg::path_cmd_move_to;
162+
}
163+
else /* m_ok != 0 */
164+
{
165+
m_ok--;
166+
}
99167
}
100168

101169
return code;
@@ -127,6 +195,12 @@ const unsigned PathIterator::code_map[] =
127195
agg::path_cmd_end_poly | agg::path_flags_close
128196
};
129197

198+
const unsigned char PathIterator::num_extra_points_map[] =
199+
{0, 0, 0, 1,
200+
2, 0, 0, 0,
201+
0, 0, 0, 0,
202+
0, 0, 0, 0};
203+
130204
#define DEBUG_SIMPLIFY 0
131205

132206
template<class VertexSource>

0 commit comments

Comments
 (0)