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

Skip to content

Commit 1c521fa

Browse files
committed
path simplification for paths with gaps
svn path=/trunk/matplotlib/; revision=6174
1 parent 4cf4bfe commit 1c521fa

4 files changed

Lines changed: 87 additions & 51 deletions

File tree

CHANGELOG

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
2008-10-08 Add path simplification support to paths with gaps. - EF
2+
13
2008-10-05 Fix problem with AFM files that don't specify the font's
24
full name or family name. - JKS
35

examples/pylab_examples/clippedline.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def __init__(self, ax, *args, **kwargs):
1919

2020
def set_data(self, *args, **kwargs):
2121
Line2D.set_data(self, *args, **kwargs)
22-
if self._invalid:
22+
if self._invalid:
2323
self.recache()
2424
self.xorig = np.array(self._x)
2525
self.yorig = np.array(self._y)

lib/matplotlib/path.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,8 @@ def __init__(self, vertices, codes=None):
109109
assert vertices.ndim == 2
110110
assert vertices.shape[1] == 2
111111

112-
self.should_simplify = (codes is None and
113-
np.all(np.isfinite(vertices)) and
114-
len(vertices) >= 128)
112+
self.should_simplify = (len(vertices) >= 128 and
113+
(codes is None or np.all(codes <= Path.LINETO)))
115114
self.codes = codes
116115
self.vertices = vertices
117116

src/agg_py_path_iterator.h

Lines changed: 82 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@ class SimplifyPath
137137
double width = 0.0, double height = 0.0) :
138138
m_source(&source), m_quantize(quantize), m_simplify(simplify),
139139
m_width(width + 1.0), m_height(height + 1.0), m_queue_read(0), m_queue_write(0),
140-
m_moveto(true), m_lastx(0.0), m_lasty(0.0), m_clipped(false),
140+
m_moveto(true), m_after_moveto(false),
141+
m_lastx(0.0), m_lasty(0.0), m_clipped(false),
141142
m_do_clipping(width > 0.0 && height > 0.0),
142143
m_origdx(0.0), m_origdy(0.0),
143144
m_origdNorm2(0.0), m_dnorm2Max(0.0), m_dnorm2Min(0.0),
@@ -205,6 +206,7 @@ class SimplifyPath
205206
*y = front.y;
206207
#if DEBUG_SIMPLIFY
207208
printf((cmd == agg::path_cmd_move_to) ? "|" : "-");
209+
printf(" 1 %f %f\n", *x, *y);
208210
#endif
209211
return cmd;
210212
}
@@ -239,18 +241,40 @@ class SimplifyPath
239241

240242
//if we are starting a new path segment, move to the first point
241243
// + init
242-
if (m_moveto)
244+
245+
#if DEBUG_SIMPLIFY
246+
printf("x, y, code: %f, %f, %d\n", *x, *y, cmd);
247+
#endif
248+
if (m_moveto || cmd == agg::path_cmd_move_to)
243249
{
250+
// m_moveto check is not generally needed because
251+
// m_source generates an initial moveto; but it
252+
// is retained for safety in case circumstances
253+
// arise where this is not true.
254+
if (m_origdNorm2 && !m_after_moveto)
255+
{
256+
// m_origdNorm2 is nonzero only if we have a vector;
257+
// the m_after_moveto check ensures we push this
258+
// vector to the queue only once.
259+
_push(x,y);
260+
}
261+
m_after_moveto = true;
244262
m_lastx = *x;
245263
m_lasty = *y;
246264
m_moveto = false;
247265
m_origdNorm2 = 0.0;
248-
#if DEBUG_SIMPLIFY
249-
m_pushed++;
250-
printf("|");
251-
#endif
252-
return agg::path_cmd_move_to;
266+
// A moveto resulting from a nan yields a missing
267+
// line segment, hence a break in the line, just
268+
// like clipping, so we treat it the same way.
269+
m_clipped = true;
270+
if (m_queue_read < m_queue_write)
271+
{
272+
// If we did a push, empty the queue now.
273+
break;
274+
}
275+
continue;
253276
}
277+
m_after_moveto = false;
254278

255279
// Don't render line segments less than one pixel long
256280
if (fabs(*x - m_lastx) < 1.0 && fabs(*y - m_lasty) < 1.0)
@@ -295,7 +319,7 @@ class SimplifyPath
295319
m_origdy = *y - m_lasty;
296320
m_origdNorm2 = m_origdx*m_origdx + m_origdy*m_origdy;
297321

298-
//set all the variables to reflect this new orig vecor
322+
//set all the variables to reflect this new orig vector
299323
m_dnorm2Max = m_origdNorm2;
300324
m_dnorm2Min = 0.0;
301325
m_haveMin = false;
@@ -376,54 +400,16 @@ class SimplifyPath
376400
#endif
377401
continue;
378402
}
379-
380403
//if we get here, then this vector was not similar enough to the
381404
//line we are building, so we need to draw that line and start the
382405
//next one.
383406

384407
//if the line needs to extend in the opposite direction from the
385408
//direction we are drawing in, move back to we start drawing from
386409
//back there.
387-
if (m_haveMin)
388-
{
389-
m_queue[m_queue_write++].set(agg::path_cmd_line_to, m_minX, m_minY);
390-
}
391-
m_queue[m_queue_write++].set(agg::path_cmd_line_to, m_maxX, m_maxY);
392410

393-
//if we clipped some segments between this line and the next line
394-
//we are starting, we also need to move to the last point.
395-
if (m_clipped) {
396-
m_queue[m_queue_write++].set(agg::path_cmd_move_to, m_lastx, m_lasty);
397-
}
398-
else if (!m_lastMax)
399-
{
400-
//if the last line was not the longest line, then move back to
401-
//the end point of the last line in the sequence. Only do this
402-
//if not clipped, since in that case lastx,lasty is not part of
403-
//the line just drawn.
404-
405-
//Would be move_to if not for the artifacts
406-
m_queue[m_queue_write++].set(agg::path_cmd_line_to, m_lastx, m_lasty);
407-
}
411+
_push(x, y);
408412

409-
//now reset all the variables to get ready for the next line
410-
m_origdx = *x - m_lastx;
411-
m_origdy = *y - m_lasty;
412-
m_origdNorm2 = m_origdx*m_origdx + m_origdy*m_origdy;
413-
414-
m_dnorm2Max = m_origdNorm2;
415-
m_dnorm2Min = 0.0;
416-
m_haveMin = false;
417-
m_lastMax = true;
418-
m_lastx = m_maxX = *x;
419-
m_lasty = m_maxY = *y;
420-
m_lastWrittenX = m_minX = m_lastx;
421-
m_lastWrittenY = m_minY = m_lasty;
422-
423-
m_clipped = false;
424-
#if DEBUG_SIMPLIFY
425-
m_pushed += m_queue_write - m_queue_read;
426-
#endif
427413
break;
428414
}
429415

@@ -453,6 +439,8 @@ class SimplifyPath
453439
*y = front.y;
454440
#if DEBUG_SIMPLIFY
455441
printf((cmd == agg::path_cmd_move_to) ? "|" : "-");
442+
printf(" 3 %f %f\n", *x, *y);
443+
456444
#endif
457445
return cmd;
458446
}
@@ -489,6 +477,7 @@ class SimplifyPath
489477
item m_queue[6];
490478

491479
bool m_moveto;
480+
bool m_after_moveto;
492481
double m_lastx, m_lasty;
493482
bool m_clipped;
494483
bool m_do_clipping;
@@ -512,6 +501,52 @@ class SimplifyPath
512501
unsigned m_pushed;
513502
unsigned m_skipped;
514503
#endif
504+
505+
void _push(double* x, double* y)
506+
{
507+
if (m_haveMin)
508+
{
509+
m_queue[m_queue_write++].set(agg::path_cmd_line_to, m_minX, m_minY);
510+
}
511+
m_queue[m_queue_write++].set(agg::path_cmd_line_to, m_maxX, m_maxY);
512+
513+
//if we clipped some segments between this line and the next line
514+
//we are starting, we also need to move to the last point.
515+
if (m_clipped) {
516+
m_queue[m_queue_write++].set(agg::path_cmd_move_to, m_lastx, m_lasty);
517+
}
518+
else if (!m_lastMax)
519+
{
520+
//if the last line was not the longest line, then move back to
521+
//the end point of the last line in the sequence. Only do this
522+
//if not clipped, since in that case lastx,lasty is not part of
523+
//the line just drawn.
524+
525+
//Would be move_to if not for the artifacts
526+
m_queue[m_queue_write++].set(agg::path_cmd_line_to, m_lastx, m_lasty);
527+
}
528+
529+
//now reset all the variables to get ready for the next line
530+
m_origdx = *x - m_lastx;
531+
m_origdy = *y - m_lasty;
532+
m_origdNorm2 = m_origdx*m_origdx + m_origdy*m_origdy;
533+
534+
m_dnorm2Max = m_origdNorm2;
535+
m_dnorm2Min = 0.0;
536+
m_haveMin = false;
537+
m_lastMax = true;
538+
m_lastx = m_maxX = *x;
539+
m_lasty = m_maxY = *y;
540+
m_lastWrittenX = m_minX = m_lastx;
541+
m_lastWrittenY = m_minY = m_lasty;
542+
543+
m_clipped = false;
544+
#if DEBUG_SIMPLIFY
545+
m_pushed += m_queue_write - m_queue_read;
546+
#endif
547+
548+
}
549+
515550
};
516551

517552
#endif // __AGG_PY_PATH_ITERATOR_H__

0 commit comments

Comments
 (0)