From: <md...@us...> - 2008-08-11 12:48:59
|
Revision: 6018 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6018&view=rev Author: mdboom Date: 2008-08-11 12:48:50 +0000 (Mon, 11 Aug 2008) Log Message: ----------- Does simplify paths when NaN/inf is present. Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/path.py trunk/matplotlib/src/_backend_agg.cpp trunk/matplotlib/src/_path.cpp trunk/matplotlib/src/agg_py_path_iterator.h Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-08-11 07:09:16 UTC (rev 6017) +++ trunk/matplotlib/CHANGELOG 2008-08-11 12:48:50 UTC (rev 6018) @@ -1,3 +1,9 @@ +2008-08-11 Fix more bugs in NaN/inf handling. In particular, path simplification + (which does not handle NaNs or infs) will be turned off automatically + when infs or NaNs are present. Also masked arrays are now converted + to arrays with NaNs for consistent handling of masks and NaNs + - MGD and EF + ================================================================= 2008-08-03 Released 0.98.3 at svn r5947 Modified: trunk/matplotlib/lib/matplotlib/path.py =================================================================== --- trunk/matplotlib/lib/matplotlib/path.py 2008-08-11 07:09:16 UTC (rev 6017) +++ trunk/matplotlib/lib/matplotlib/path.py 2008-08-11 12:48:50 UTC (rev 6018) @@ -56,6 +56,11 @@ :class:`Path` objects, as an optimization, do not store a *codes* at all, but have a default one provided for them by :meth:`iter_segments`. + + Note also that the vertices and codes arrays should be treated as + immutable -- there are a number of optimizations and assumptions + made up front in the constructor that will not change when the + data changes. """ # Path codes @@ -84,46 +89,29 @@ dimension. If *codes* is None, *vertices* will be treated as a series of - line segments. If *vertices* contains masked values, the - resulting path will be compressed, with ``MOVETO`` codes - inserted in the correct places to jump over the masked - regions. + line segments. + + If *vertices* contains masked values, they will be converted + to NaNs which are then handled correctly by the Agg + PathIterator and other consumers of path data, such as + :meth:`iter_segments`. """ if ma.isMaskedArray(vertices): - is_mask = True - mask = ma.getmask(vertices) + vertices = vertices.astype(np.float_).filled(np.nan) else: - is_mask = False vertices = np.asarray(vertices, np.float_) - mask = ma.nomask if codes is not None: codes = np.asarray(codes, self.code_type) assert codes.ndim == 1 assert len(codes) == len(vertices) - # The path being passed in may have masked values. However, - # the backends (and any affine transformations in matplotlib - # itself), are not expected to deal with masked arrays, so we - # must remove them from the array (using compressed), and add - # MOVETO commands to the codes array accordingly. - if is_mask: - if mask is not ma.nomask: - mask1d = np.logical_or.reduce(mask, axis=1) - gmask1d = np.invert(mask1d) - if codes is None: - codes = np.empty((len(vertices)), self.code_type) - codes.fill(self.LINETO) - codes[0] = self.MOVETO - vertices = vertices[gmask1d].filled() # ndarray - codes[np.roll(mask1d, 1)] = self.MOVETO - codes = codes[gmask1d] # np.compress is much slower - else: - vertices = np.asarray(vertices, np.float_) - 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.codes = codes self.vertices = vertices Modified: trunk/matplotlib/src/_backend_agg.cpp =================================================================== --- trunk/matplotlib/src/_backend_agg.cpp 2008-08-11 07:09:16 UTC (rev 6017) +++ trunk/matplotlib/src/_backend_agg.cpp 2008-08-11 12:48:50 UTC (rev 6018) @@ -387,7 +387,7 @@ double x0, y0, x1, y1; unsigned code; - if (path.total_vertices() > 15) + if (!path.should_simplify() || path.total_vertices() > 15) return false; code = path.vertex(&x0, &y0); @@ -420,11 +420,6 @@ return true; } -template<class Path> -bool should_simplify(Path& path) { - return !path.has_curves() && path.total_vertices() >= 128; -} - Py::Object RendererAgg::copy_from_bbox(const Py::Tuple& args) { //copy region in bbox to buffer and return swig/agg buffer object @@ -938,7 +933,7 @@ trans *= agg::trans_affine_scaling(1.0, -1.0); trans *= agg::trans_affine_translation(0.0, (double)height); bool snap = should_snap(path, trans); - bool simplify = should_simplify(path) && !face.first; + bool simplify = path.should_simplify() && !face.first; transformed_path_t tpath(path, trans); simplify_t simplified(tpath, snap, simplify, width, height); @@ -1236,6 +1231,10 @@ inline unsigned total_vertices() { return 5; } + + inline bool should_simplify() { + return false; + } }; public: Modified: trunk/matplotlib/src/_path.cpp =================================================================== --- trunk/matplotlib/src/_path.cpp 2008-08-11 07:09:16 UTC (rev 6017) +++ trunk/matplotlib/src/_path.cpp 2008-08-11 12:48:50 UTC (rev 6018) @@ -1120,7 +1120,7 @@ double width = Py::Float(args[2]); double height = Py::Float(args[3]); - bool simplify = !path.has_curves() && width != 0.0 && height != 0.0; + bool simplify = path.should_simplify() && width != 0.0 && height != 0.0; transformed_path_t tpath(path, trans); simplify_t simplified(tpath, false, simplify, width, height); Modified: trunk/matplotlib/src/agg_py_path_iterator.h =================================================================== --- trunk/matplotlib/src/agg_py_path_iterator.h 2008-08-11 07:09:16 UTC (rev 6017) +++ trunk/matplotlib/src/agg_py_path_iterator.h 2008-08-11 12:48:50 UTC (rev 6018) @@ -15,6 +15,7 @@ PyArrayObject* m_codes; size_t m_iterator; size_t m_total_vertices; + bool m_should_simplify; public: PathIterator(const Py::Object& path_obj) : @@ -22,6 +23,7 @@ { Py::Object vertices_obj = path_obj.getAttr("vertices"); Py::Object codes_obj = path_obj.getAttr("codes"); + Py::Object should_simplify_obj = path_obj.getAttr("should_simplify"); m_vertices = (PyArrayObject*)PyArray_FromObject (vertices_obj.ptr(), PyArray_DOUBLE, 2, 2); @@ -38,6 +40,7 @@ throw Py::ValueError("Invalid codes array."); } + m_should_simplify = bool(Py::Int(should_simplify_obj)); m_total_vertices = m_vertices->dimensions[0]; } @@ -100,9 +103,9 @@ return m_total_vertices; } - inline bool has_curves() + inline bool should_simplify() { - return m_codes; + return m_should_simplify; } }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |