Revision: 7341
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7341&view=rev
Author:   efiring
Date:     2009-08-04 07:01:43 +0000 (Tue, 04 Aug 2009)

Log Message:
-----------
contourf uses complex paths instead of simple paths with cuts

Modified Paths:
--------------
    trunk/matplotlib/CHANGELOG
    trunk/matplotlib/lib/matplotlib/contour.py
    trunk/matplotlib/src/cntr.c

Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG  2009-08-04 06:52:24 UTC (rev 7340)
+++ trunk/matplotlib/CHANGELOG  2009-08-04 07:01:43 UTC (rev 7341)
@@ -1,3 +1,6 @@
+2009-08-03 Add PathCollection; modify contourf to use complex
+           paths instead of simple paths with cuts. - EF
+
 2009-08-03 Fixed boilerplate.py so it doesn't break the ReST docs. - JKS
 
 ======================================================================

Modified: trunk/matplotlib/lib/matplotlib/contour.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/contour.py  2009-08-04 06:52:24 UTC (rev 
7340)
+++ trunk/matplotlib/lib/matplotlib/contour.py  2009-08-04 07:01:43 UTC (rev 
7341)
@@ -8,7 +8,7 @@
 import numpy as np
 from numpy import ma
 import matplotlib._cntr as _cntr
-import matplotlib.path as path
+import matplotlib.path as mpath
 import matplotlib.ticker as ticker
 import matplotlib.cm as cm
 import matplotlib.colors as colors
@@ -499,7 +499,7 @@
                     if inline:
                         for n in new:
                             # Add path if not empty or single point
-                            if len(n)>1: additions.append( path.Path(n) )
+                            if len(n)>1: additions.append( mpath.Path(n) )
                 else: # If not adding label, keep old path
                     additions.append(linepath)
 
@@ -579,6 +579,8 @@
             self.collections = cbook.silent_list('collections.PolyCollection')
         else:
             self.collections = cbook.silent_list('collections.LineCollection')
+        self.segs = []
+        self.kinds = []
         # label lists must be initialized here
         self.labelTexts = []
         self.labelCValues = []
@@ -601,13 +603,21 @@
             for level, level_upper in zip(lowers, uppers):
                 nlist = C.trace(level, level_upper, points = 0,
                         nchunk = self.nchunk)
-                col = collections.PolyCollection(nlist,
+                nseg = len(nlist)//2
+                segs = nlist[:nseg]
+                kinds = nlist[nseg:]
+
+
+                paths = self._make_paths(segs, kinds)
+
+                col = collections.PathCollection(paths,
                                      antialiaseds = (self.antialiased,),
                                      edgecolors= 'none',
                                      alpha=self.alpha)
                 self.ax.add_collection(col)
                 self.collections.append(col)
-
+                self.segs.append(segs)
+                self.kinds.append(kinds)
         else:
             tlinewidths = self._process_linewidths()
             self.tlinewidths = tlinewidths
@@ -615,7 +625,10 @@
             C = _cntr.Cntr(x, y, z.filled(), _mask)
             for level, width, lstyle in zip(self.levels, tlinewidths, 
tlinestyles):
                 nlist = C.trace(level, points = 0)
-                col = collections.LineCollection(nlist,
+                nseg = len(nlist)//2
+                segs = nlist[:nseg]
+                kinds = nlist[nseg:]
+                col = collections.LineCollection(segs,
                                      linewidths = width,
                                      linestyle = lstyle,
                                      alpha=self.alpha)
@@ -623,6 +636,8 @@
                 col.set_label('_nolegend_')
                 self.ax.add_collection(col, False)
                 self.collections.append(col)
+                self.segs.append(segs)
+                self.kinds.append(kinds)
         self.changed() # set the colors
         x0 = ma.minimum(x)
         x1 = ma.maximum(x)
@@ -631,6 +646,17 @@
         self.ax.update_datalim([(x0,y0), (x1,y1)])
         self.ax.autoscale_view()
 
+    @staticmethod
+    def _make_paths(segs, kinds):
+        paths = []
+        for seg, kind in zip(segs, kinds):
+            codes = np.zeros(kind.shape, dtype=mpath.Path.code_type)
+            codes.fill(mpath.Path.LINETO)
+            codes[0] = mpath.Path.MOVETO
+            codes[kinds >= _cntr._slitkind] = mpath.Path.MOVETO
+            paths.append(mpath.Path(seg, codes))
+        return paths
+
     def changed(self):
         tcolors = [ (tuple(rgba),) for rgba in
                                 self.to_rgba(self.cvalues, alpha=self.alpha)]

Modified: trunk/matplotlib/src/cntr.c
===================================================================
--- trunk/matplotlib/src/cntr.c 2009-08-04 06:52:24 UTC (rev 7340)
+++ trunk/matplotlib/src/cntr.c 2009-08-04 07:01:43 UTC (rev 7341)
@@ -199,6 +199,7 @@
     /* making the actual marks requires a bunch of other stuff */
     const double *x, *y, *z;    /* mesh coordinates and function values */
     double *xcp, *ycp;          /* output contour points */
+    short *kcp;                 /* kind of contour point */
 };
 
 void print_Csite(Csite *Csite)
@@ -268,6 +269,9 @@
 #define START_MARK(left) \
   ((left)>0?((left)>1?J1_START:I1_START):((left)<-1?J0_START:I0_START))
 
+enum {kind_zone, kind_edge1, kind_edge2,
+        kind_slit_up, kind_slit_down, kind_start_slit=16} point_kinds;
+
 /* ------------------------------------------------------------------------ */
 
 /* these actually mark points */
@@ -317,6 +321,7 @@
     double zlevel = pass2 ? site->zlevel[level] : 0.0;
     double *xcp = pass2 ? site->xcp : 0;
     double *ycp = pass2 ? site->ycp : 0;
+    short *kcp = pass2 ? site->kcp : 0;
 
     int z0, z1, z2, z3;
     int keep_left = 0;          /* flag to try to minimize curvature in 
saddles */
@@ -338,6 +343,7 @@
             double zcp = (zlevel - z[p0]) / (z[p1] - z[p0]);
             xcp[n] = zcp * (x[p1] - x[p0]) + x[p0];
             ycp[n] = zcp * (y[p1] - y[p0]) + y[p0];
+            kcp[n] = kind_zone;
         }
         if (!done && !jedge)
         {
@@ -487,7 +493,15 @@
     site->edge = edge;
     site->n = n;
     site->left = left;
-    return done > 4 ? slit_cutter (site, done - 5, pass2) : done;
+    if (done <= 4)
+    {
+        return done;
+    }
+    if (pass2 && n > 0)
+    {
+        kcp[n-1] += kind_start_slit;
+    }
+    return slit_cutter (site, done - 5, pass2);
 }
 
 /* edge_walker assumes that the current edge is being drawn CCW
@@ -513,11 +527,13 @@
     long left0 = site->left0;
     int level0 = site->level0 == 2;
     int marked;
+    int n_kind = 0;
 
     const double *x = pass2 ? site->x : 0;
     const double *y = pass2 ? site->y : 0;
     double *xcp = pass2 ? site->xcp : 0;
     double *ycp = pass2 ? site->ycp : 0;
+    short *kcp = pass2 ? site->kcp : 0;
 
     int z0, z1, heads_up = 0;
 
@@ -528,6 +544,7 @@
         z0 = data[p0] & Z_VALUE;
         z1 = data[p1] & Z_VALUE;
         marked = 0;
+        n_kind = 0;
         if (z0 == 1)
         {
             /* mark current boundary point */
@@ -535,6 +552,8 @@
             {
                 xcp[n] = x[p0];
                 ycp[n] = y[p0];
+                kcp[n] = kind_edge1;
+                n_kind = n;
             }
             marked = 1;
         }
@@ -549,6 +568,8 @@
                 zcp = (zcp - site->z[p0]) / (site->z[p1] - site->z[p0]);
                 xcp[n] = zcp * (x[p1] - x[p0]) + x[p0];
                 ycp[n] = zcp * (y[p1] - y[p0]) + y[p0];
+                kcp[n] = kind_edge2;
+                n_kind = n;
             }
             marked = 1;
         }
@@ -562,7 +583,10 @@
                 site->n = n + marked;
                 /* if the curve is closing on a hole, need to make a downslit 
*/
                 if (fwd < 0 && !(data[edge] & (jedge ? J_BNDY : I_BNDY)))
+                {
+                    if (n_kind) kcp[n_kind] += kind_start_slit;
                     return slit_cutter (site, 0, pass2);
+                }
                 return 3;
             }
             else if (pass2)
@@ -572,6 +596,7 @@
                     site->edge = edge;
                     site->left = left;
                     site->n = n + marked;
+                    if (n_kind) kcp[n_kind] += kind_start_slit;
                     return slit_cutter (site, heads_up, pass2);
                 }
             }
@@ -649,6 +674,7 @@
     const double *y = pass2 ? site->y : 0;
     double *xcp = pass2 ? site->xcp : 0;
     double *ycp = pass2 ? site->ycp : 0;
+    short *kcp = pass2 ? site->kcp : 0;
 
     if (up)
     {
@@ -677,6 +703,7 @@
             }
             xcp[n] = x[p1];
             ycp[n] = y[p1];
+            kcp[n] = kind_slit_up;
             n++;
             p1 += imax;
         }
@@ -733,6 +760,7 @@
             {
                 xcp[n] = x[p0];
                 ycp[n] = y[p0];
+                kcp[n] = kind_slit_down;
                 n++;
             }
             else
@@ -1230,6 +1258,7 @@
     site->triangle = NULL;
     site->xcp = NULL;
     site->ycp = NULL;
+    site->kcp = NULL;
     site->x = NULL;
     site->y = NULL;
     site->z = NULL;
@@ -1279,6 +1308,7 @@
     site->z = z;
     site->xcp = NULL;
     site->ycp = NULL;
+    site->kcp = NULL;
     return 0;
 }
 
@@ -1291,11 +1321,12 @@
     site = NULL;
 }
 
-/* Build a list of lists of points, where each point is an (x,y)
+/* Build a list of lists of points, where each point is an (x,y,k)
    tuple.
 */
 static PyObject *
-build_cntr_list_p(long *np, double *xp, double *yp, int nparts, long ntotal)
+build_cntr_list_p(long *np, double *xp, double *yp, short *kp,
+                                    int nparts, long ntotal)
 {
     PyObject *point, *contourList, *all_contours;
     int start = 0, end = 0;
@@ -1310,7 +1341,7 @@
         contourList = PyList_New(np[i]);
         for (k = 0, j = start; j < end; j++, k++)
         {
-            point = Py_BuildValue("(dd)", xp[j], yp[j]);
+            point = Py_BuildValue("(ddh)", xp[j], yp[j], kp[j]);
             if (PyList_SetItem(contourList, k, point)) goto error;
         }
         if (PyList_SetItem(all_contours, i, contourList)) goto error;
@@ -1323,73 +1354,43 @@
 }
 
 
-#if 0
-/* the following function is not used, so it produces a warning
- * commented it out NN - 070630 */
-
-/* Build a list of tuples (X, Y), where X and Y are 1-D arrays. */
+/* Build a list of XY 2-D arrays, shape (N,2), to which a list of K arrays
+        is concatenated concatenated. */
 static PyObject *
-build_cntr_list_v(long *np, double *xp, double *yp, int nparts, long ntotal)
+build_cntr_list_v2(long *np, double *xp, double *yp, short *kp,
+                                            int nparts, long ntotal)
 {
-    PyObject *point, *all_contours;
-    PyArrayObject *xv, *yv;
-    npy_intp dims[1];
-    int i;
-    long j, k;
-
-    all_contours = PyList_New(nparts);
-
-    k = 0;
-    for (i = 0; i < nparts; i++)
-    {
-        dims[0] = np[i];
-        xv = (PyArrayObject *) PyArray_SimpleNew(1, dims, PyArray_DOUBLE);
-        yv = (PyArrayObject *) PyArray_SimpleNew(1, dims, PyArray_DOUBLE);
-        if (xv == NULL || yv == NULL)  goto error;
-        for (j = 0; j < dims[0]; j++)
-        {
-            ((double *)xv->data)[j] = xp[k];
-            ((double *)yv->data)[j] = yp[k];
-            k++;
-        }
-        point = Py_BuildValue("(NN)", xv, yv);
-        /* "O" increments ref count; "N" does not. */
-        if (PyList_SetItem(all_contours, i, point)) goto error;
-    }
-    return all_contours;
-
-    error:
-    Py_XDECREF(all_contours);
-    return NULL;
-}
-#endif
-
-/* Build a list of XY 2-D arrays, shape (N,2) */
-static PyObject *
-build_cntr_list_v2(long *np, double *xp, double *yp, int nparts, long ntotal)
-{
     PyObject *all_contours;
     PyArrayObject *xyv;
+    PyArrayObject *kv;
     npy_intp dims[2];
+    npy_intp kdims[1];
     int i;
     long j, k;
 
-    all_contours = PyList_New(nparts);
+    all_contours = PyList_New(nparts*2);
 
     k = 0;
     for (i = 0; i < nparts; i++)
     {
         dims[0] = np[i];
         dims[1] = 2;
+        kdims[0] = np[i];
         xyv = (PyArrayObject *) PyArray_SimpleNew(2, dims, PyArray_DOUBLE);
         if (xyv == NULL)  goto error;
+        kv = (PyArrayObject *) PyArray_SimpleNew(1, kdims, PyArray_SHORT);
+        if (kv == NULL) goto error;
+
         for (j = 0; j < dims[0]; j++)
         {
             ((double *)xyv->data)[2*j] = xp[k];
             ((double *)xyv->data)[2*j+1] = yp[k];
+            ((short *)kv->data)[j] = kp[k];
             k++;
         }
         if (PyList_SetItem(all_contours, i, (PyObject *)xyv)) goto error;
+        if (PyList_SetItem(all_contours, nparts+i,
+                                (PyObject *)kv)) goto error;
     }
     return all_contours;
 
@@ -1413,6 +1414,7 @@
     PyObject *c_list = NULL;
     double *xp0;
     double *yp0;
+    short *kp0;
     long *nseg0;
     int iseg;
 
@@ -1451,12 +1453,14 @@
     }
     xp0 = (double *) PyMem_Malloc(ntotal * sizeof(double));
     yp0 = (double *) PyMem_Malloc(ntotal * sizeof(double));
+    kp0 = (short *) PyMem_Malloc(ntotal * sizeof(short));
     nseg0 = (long *) PyMem_Malloc(nparts * sizeof(long));
-    if (xp0 == NULL || yp0 == NULL || nseg0 == NULL) goto error;
+    if (xp0 == NULL || yp0 == NULL || kp0 == NULL || nseg0 == NULL) goto error;
 
     /* second pass */
     site->xcp = xp0;
     site->ycp = yp0;
+    site->kcp = kp0;
     iseg = 0;
     for (;;iseg++)
     {
@@ -1475,6 +1479,7 @@
             nseg0[iseg] = n;
             site->xcp += n;
             site->ycp += n;
+            site->kcp += n;
             ntotal2 += n;
             nparts2++;
         }
@@ -1487,21 +1492,31 @@
     }
 
 
-    if (points)
+    if (points)  /* It is False when called; we don't need the point version */
     {
-        c_list = build_cntr_list_p(nseg0, xp0, yp0, nparts, ntotal);
+        c_list = build_cntr_list_p(nseg0, xp0, yp0, kp0, nparts, ntotal);
     }
     else
     {
-        c_list = build_cntr_list_v2(nseg0, xp0, yp0, nparts, ntotal);
+        c_list = build_cntr_list_v2(nseg0, xp0, yp0, kp0, nparts, ntotal);
     }
-    PyMem_Free(xp0); PyMem_Free(yp0); PyMem_Free(nseg0);
-    site->xcp = NULL; site->ycp = NULL;
+    PyMem_Free(xp0);
+    PyMem_Free(yp0);
+    PyMem_Free(kp0);
+    PyMem_Free(nseg0);
+    site->xcp = NULL;
+    site->ycp = NULL;
+    site->kcp = NULL;
     return c_list;
 
     error:
-    PyMem_Free(xp0); PyMem_Free(yp0); PyMem_Free(nseg0);
-    site->xcp = NULL; site->ycp = NULL;
+    PyMem_Free(xp0);
+    PyMem_Free(yp0);
+    PyMem_Free(kp0);
+    PyMem_Free(nseg0);
+    site->xcp = NULL;
+    site->ycp = NULL;
+    site->kcp = NULL;
     Py_XDECREF(c_list);
     return NULL;
 }
@@ -1603,16 +1618,14 @@
     }
 
     xpa = (PyArrayObject *) PyArray_ContiguousFromObject(xarg,
-                                                        PyArray_DOUBLE, 2, 2);
+                                                      PyArray_DOUBLE, 2, 2);
     ypa = (PyArrayObject *) PyArray_ContiguousFromObject(yarg,
-                                                        PyArray_DOUBLE,
-                                                        2, 2);
-    zpa = (PyArrayObject *) PyArray_ContiguousFromObject(zarg, PyArray_DOUBLE,
-                                                        2, 2);
+                                                      PyArray_DOUBLE, 2, 2);
+    zpa = (PyArrayObject *) PyArray_ContiguousFromObject(zarg,
+                                                      PyArray_DOUBLE, 2, 2);
     if (marg)
         mpa = (PyArrayObject *) PyArray_ContiguousFromObject(marg,
-                                                            PyArray_SBYTE,
-                                                            2, 2);
+                                                      PyArray_SBYTE, 2, 2);
     else
         mpa = NULL;
 
@@ -1751,7 +1764,8 @@
 
     if (m == NULL)
       return;
-
+    PyModule_AddIntConstant(m, "_slitkind", (long)kind_slit_up );
+    /* We can add all the point_kinds values later if we need them. */
     import_array();
     Py_INCREF(&CntrType);
     PyModule_AddObject(m, "Cntr", (PyObject *)&CntrType);


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to