Skip to content

Commit

Permalink
path simplification for paths with gaps
Browse files Browse the repository at this point in the history
svn path=/trunk/matplotlib/; revision=6174
  • Loading branch information
efiring committed Oct 9, 2008
1 parent 4cf4bfe commit 1c521fa
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 51 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
2008-10-08 Add path simplification support to paths with gaps. - EF

2008-10-05 Fix problem with AFM files that don't specify the font's
full name or family name. - JKS

Expand Down
2 changes: 1 addition & 1 deletion examples/pylab_examples/clippedline.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def __init__(self, ax, *args, **kwargs):

def set_data(self, *args, **kwargs):
Line2D.set_data(self, *args, **kwargs)
if self._invalid:
if self._invalid:
self.recache()
self.xorig = np.array(self._x)
self.yorig = np.array(self._y)
Expand Down
5 changes: 2 additions & 3 deletions lib/matplotlib/path.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,8 @@ def __init__(self, vertices, codes=None):
assert vertices.ndim == 2
assert vertices.shape[1] == 2

self.should_simplify = (codes is None and
np.all(np.isfinite(vertices)) and
len(vertices) >= 128)
self.should_simplify = (len(vertices) >= 128 and
(codes is None or np.all(codes <= Path.LINETO)))
self.codes = codes
self.vertices = vertices

Expand Down
129 changes: 82 additions & 47 deletions src/agg_py_path_iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ class SimplifyPath
double width = 0.0, double height = 0.0) :
m_source(&source), m_quantize(quantize), m_simplify(simplify),
m_width(width + 1.0), m_height(height + 1.0), m_queue_read(0), m_queue_write(0),
m_moveto(true), m_lastx(0.0), m_lasty(0.0), m_clipped(false),
m_moveto(true), m_after_moveto(false),
m_lastx(0.0), m_lasty(0.0), m_clipped(false),
m_do_clipping(width > 0.0 && height > 0.0),
m_origdx(0.0), m_origdy(0.0),
m_origdNorm2(0.0), m_dnorm2Max(0.0), m_dnorm2Min(0.0),
Expand Down Expand Up @@ -205,6 +206,7 @@ class SimplifyPath
*y = front.y;
#if DEBUG_SIMPLIFY
printf((cmd == agg::path_cmd_move_to) ? "|" : "-");
printf(" 1 %f %f\n", *x, *y);
#endif
return cmd;
}
Expand Down Expand Up @@ -239,18 +241,40 @@ class SimplifyPath

//if we are starting a new path segment, move to the first point
// + init
if (m_moveto)

#if DEBUG_SIMPLIFY
printf("x, y, code: %f, %f, %d\n", *x, *y, cmd);
#endif
if (m_moveto || cmd == agg::path_cmd_move_to)
{
// m_moveto check is not generally needed because
// m_source generates an initial moveto; but it
// is retained for safety in case circumstances
// arise where this is not true.
if (m_origdNorm2 && !m_after_moveto)
{
// m_origdNorm2 is nonzero only if we have a vector;
// the m_after_moveto check ensures we push this
// vector to the queue only once.
_push(x,y);
}
m_after_moveto = true;
m_lastx = *x;
m_lasty = *y;
m_moveto = false;
m_origdNorm2 = 0.0;
#if DEBUG_SIMPLIFY
m_pushed++;
printf("|");
#endif
return agg::path_cmd_move_to;
// A moveto resulting from a nan yields a missing
// line segment, hence a break in the line, just
// like clipping, so we treat it the same way.
m_clipped = true;
if (m_queue_read < m_queue_write)
{
// If we did a push, empty the queue now.
break;
}
continue;
}
m_after_moveto = false;

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

//set all the variables to reflect this new orig vecor
//set all the variables to reflect this new orig vector
m_dnorm2Max = m_origdNorm2;
m_dnorm2Min = 0.0;
m_haveMin = false;
Expand Down Expand Up @@ -376,54 +400,16 @@ class SimplifyPath
#endif
continue;
}

//if we get here, then this vector was not similar enough to the
//line we are building, so we need to draw that line and start the
//next one.

//if the line needs to extend in the opposite direction from the
//direction we are drawing in, move back to we start drawing from
//back there.
if (m_haveMin)
{
m_queue[m_queue_write++].set(agg::path_cmd_line_to, m_minX, m_minY);
}
m_queue[m_queue_write++].set(agg::path_cmd_line_to, m_maxX, m_maxY);

//if we clipped some segments between this line and the next line
//we are starting, we also need to move to the last point.
if (m_clipped) {
m_queue[m_queue_write++].set(agg::path_cmd_move_to, m_lastx, m_lasty);
}
else if (!m_lastMax)
{
//if the last line was not the longest line, then move back to
//the end point of the last line in the sequence. Only do this
//if not clipped, since in that case lastx,lasty is not part of
//the line just drawn.

//Would be move_to if not for the artifacts
m_queue[m_queue_write++].set(agg::path_cmd_line_to, m_lastx, m_lasty);
}
_push(x, y);

//now reset all the variables to get ready for the next line
m_origdx = *x - m_lastx;
m_origdy = *y - m_lasty;
m_origdNorm2 = m_origdx*m_origdx + m_origdy*m_origdy;

m_dnorm2Max = m_origdNorm2;
m_dnorm2Min = 0.0;
m_haveMin = false;
m_lastMax = true;
m_lastx = m_maxX = *x;
m_lasty = m_maxY = *y;
m_lastWrittenX = m_minX = m_lastx;
m_lastWrittenY = m_minY = m_lasty;

m_clipped = false;
#if DEBUG_SIMPLIFY
m_pushed += m_queue_write - m_queue_read;
#endif
break;
}

Expand Down Expand Up @@ -453,6 +439,8 @@ class SimplifyPath
*y = front.y;
#if DEBUG_SIMPLIFY
printf((cmd == agg::path_cmd_move_to) ? "|" : "-");
printf(" 3 %f %f\n", *x, *y);

#endif
return cmd;
}
Expand Down Expand Up @@ -489,6 +477,7 @@ class SimplifyPath
item m_queue[6];

bool m_moveto;
bool m_after_moveto;
double m_lastx, m_lasty;
bool m_clipped;
bool m_do_clipping;
Expand All @@ -512,6 +501,52 @@ class SimplifyPath
unsigned m_pushed;
unsigned m_skipped;
#endif

void _push(double* x, double* y)
{
if (m_haveMin)
{
m_queue[m_queue_write++].set(agg::path_cmd_line_to, m_minX, m_minY);
}
m_queue[m_queue_write++].set(agg::path_cmd_line_to, m_maxX, m_maxY);

//if we clipped some segments between this line and the next line
//we are starting, we also need to move to the last point.
if (m_clipped) {
m_queue[m_queue_write++].set(agg::path_cmd_move_to, m_lastx, m_lasty);
}
else if (!m_lastMax)
{
//if the last line was not the longest line, then move back to
//the end point of the last line in the sequence. Only do this
//if not clipped, since in that case lastx,lasty is not part of
//the line just drawn.

//Would be move_to if not for the artifacts
m_queue[m_queue_write++].set(agg::path_cmd_line_to, m_lastx, m_lasty);
}

//now reset all the variables to get ready for the next line
m_origdx = *x - m_lastx;
m_origdy = *y - m_lasty;
m_origdNorm2 = m_origdx*m_origdx + m_origdy*m_origdy;

m_dnorm2Max = m_origdNorm2;
m_dnorm2Min = 0.0;
m_haveMin = false;
m_lastMax = true;
m_lastx = m_maxX = *x;
m_lasty = m_maxY = *y;
m_lastWrittenX = m_minX = m_lastx;
m_lastWrittenY = m_minY = m_lasty;

m_clipped = false;
#if DEBUG_SIMPLIFY
m_pushed += m_queue_write - m_queue_read;
#endif

}

};

#endif // __AGG_PY_PATH_ITERATOR_H__

0 comments on commit 1c521fa

Please sign in to comment.