From: <md...@us...> - 2009-08-31 20:10:45
|
Revision: 7621 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7621&view=rev Author: mdboom Date: 2009-08-31 20:10:35 +0000 (Mon, 31 Aug 2009) Log Message: ----------- Add "draw_gouraud_triangles" (note the 's') backend method. Add initial support in Pdf backend (working in xpdf and evince, but not in acroread, strangely). Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backend_bases.py trunk/matplotlib/lib/matplotlib/backends/backend_agg.py trunk/matplotlib/lib/matplotlib/backends/backend_mixed.py trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py trunk/matplotlib/lib/matplotlib/collections.py trunk/matplotlib/src/_backend_agg.cpp trunk/matplotlib/src/_backend_agg.h Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2009-08-31 19:50:13 UTC (rev 7620) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2009-08-31 20:10:35 UTC (rev 7621) @@ -170,10 +170,31 @@ """ Draw a Gouraud-shaded triangle. - EXPERIMENTAL + *points* is a 3x2 array of (x, y) points for the triangle. + + *colors* is a 3x4 array of RGBA colors for each point of the + triangle. + + *transform* is an affine transform to apply to the points. """ raise NotImplementedError + def draw_gouraud_triangles(self, gc, triangles_array, colors_array, + transform): + """ + Draws a series of Gouraud triangles. + + *points* is a Nx3x2 array of (x, y) points for the trianglex. + + *colors* is a Nx3x4 array of RGBA colors for each point of the + triangles. + + *transform* is an affine transform to apply to the points. + """ + transform = transform.frozen() + for tri, col in zip(triangles_array, colors_array): + self.draw_gouraud_triangle(gc, tri, col, transform) + def _iter_collection_raw_paths(self, master_transform, paths, all_transforms): """ @@ -410,7 +431,7 @@ def start_rasterizing(self): """ - Used in MixedModeRenderer. Switch to the raster renderer. + Used in MixedModeRenderer. Switch to the raster renderer. """ pass @@ -425,7 +446,7 @@ def start_filter(self): """ Used in AggRenderer. Switch to a temporary renderer for image - filtering effects. + filtering effects. """ pass Modified: trunk/matplotlib/lib/matplotlib/backends/backend_agg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_agg.py 2009-08-31 19:50:13 UTC (rev 7620) +++ trunk/matplotlib/lib/matplotlib/backends/backend_agg.py 2009-08-31 20:10:35 UTC (rev 7621) @@ -80,6 +80,7 @@ self.draw_path_collection = self._renderer.draw_path_collection self.draw_quad_mesh = self._renderer.draw_quad_mesh self.draw_gouraud_triangle = self._renderer.draw_gouraud_triangle + self.draw_gouraud_triangles = self._renderer.draw_gouraud_triangles self.draw_image = self._renderer.draw_image self.copy_from_bbox = self._renderer.copy_from_bbox self.tostring_rgba_minimized = self._renderer.tostring_rgba_minimized Modified: trunk/matplotlib/lib/matplotlib/backends/backend_mixed.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_mixed.py 2009-08-31 19:50:13 UTC (rev 7620) +++ trunk/matplotlib/lib/matplotlib/backends/backend_mixed.py 2009-08-31 20:10:35 UTC (rev 7621) @@ -58,7 +58,8 @@ finalize flipy get_canvas_width_height get_image_magnification get_texmanager get_text_width_height_descent new_gc open_group option_image_nocomposite points_to_pixels strip_math - start_filter stop_filter + start_filter stop_filter draw_gouraud_triangle + draw_gouraud_triangles """.split() def _set_current_renderer(self, renderer): self._renderer = renderer Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2009-08-31 19:50:13 UTC (rev 7620) +++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2009-08-31 20:10:35 UTC (rev 7621) @@ -17,6 +17,7 @@ from cStringIO import StringIO from datetime import datetime from math import ceil, cos, floor, pi, sin +import struct try: set except NameError: @@ -268,7 +269,7 @@ gsave='q', grestore='Q', textpos='Td', selectfont='Tf', textmatrix='Tm', show='Tj', showkern='TJ', - setlinewidth='w', clip='W') + setlinewidth='w', clip='W', shading='sh') Op = Bunch(**dict([(name, Operator(value)) for name, value in _pdfops.items()])) @@ -377,6 +378,7 @@ self.fontObject = self.reserveObject('fonts') self.alphaStateObject = self.reserveObject('extended graphics states') self.hatchObject = self.reserveObject('tiling patterns') + self.gouraudObject = self.reserveObject('Gouraud triangles') self.XObjectObject = self.reserveObject('external objects') self.resourceObject = self.reserveObject('resources') @@ -403,6 +405,7 @@ self.nextAlphaState = 1 self.hatchPatterns = {} self.nextHatch = 1 + self.gouraudTriangles = [] self.images = {} self.nextImage = 1 @@ -421,6 +424,7 @@ 'XObject': self.XObjectObject, 'ExtGState': self.alphaStateObject, 'Pattern': self.hatchObject, + 'Shading': self.gouraudObject, 'ProcSet': procsets } self.writeObject(self.resourceObject, resources) @@ -452,6 +456,7 @@ dict([(val[0], val[1]) for val in self.alphaStates.values()])) self.writeHatches() + self.writeGouraudTriangles() xobjects = dict(self.images.values()) for tup in self.markers.values(): xobjects[tup[0]] = tup[1] @@ -1050,6 +1055,44 @@ self.endStream() self.writeObject(self.hatchObject, hatchDict) + def addGouraudTriangles(self, points, colors): + name = Name('GT%d' % len(self.gouraudTriangles)) + self.gouraudTriangles.append((name, points, colors)) + return name + + def writeGouraudTriangles(self): + gouraudDict = dict() + for name, points, colors in self.gouraudTriangles: + ob = self.reserveObject('Gouraud triangle') + gouraudDict[name] = ob + shape = points.shape + flat_points = points.reshape((shape[0] * shape[1], 2)) + points_min = npy.min(flat_points, axis=0) - (1 << 8) + points_max = npy.max(flat_points, axis=0) + (1 << 8) + factor = float(0xffffffff) / (points_max - points_min) + adjpoints = npy.array((points - points_min) * factor, dtype=npy.uint32) + adjcolors = npy.array(colors * 255.0, dtype=npy.uint8) + + self.beginStream( + ob.id, None, + { 'ShadingType': 4, + 'BitsPerCoordinate': 32, + 'BitsPerComponent': 8, + 'BitsPerFlag': 8, + 'ColorSpace': Name('DeviceRGB'), + 'AntiAlias': 1, + 'Decode': [points_min[0], points_max[0], + points_min[1], points_max[1], + 0, 1, 0, 1, 0, 1] + }) + + for tpoints, tcolors in zip(adjpoints, adjcolors): + for p, c in zip(tpoints, tcolors): + values = [int(x) for x in [0] + list(p) + list(c[:3])] + self.write(struct.pack('>BLLBBB', *values)) + self.endStream() + self.writeObject(self.gouraudObject, gouraudDict) + def imageObject(self, image): """Return name of an image XObject representing the given image.""" @@ -1326,6 +1369,18 @@ lastx, lasty = x, y output(Op.grestore) + def draw_gouraud_triangle(self, gc, points, colors, trans): + self.draw_gouraud_triangles(gc, points.reshape((1, 3, 2)), + colors.reshape((1, 3, 4)), trans) + + def draw_gouraud_triangles(self, gc, points, colors, trans): + shape = points.shape + points = points.reshape((shape[0] * shape[1], 2)) + tpoints = trans.transform(points) + tpoints = tpoints.reshape(shape) + name = self.file.addGouraudTriangles(tpoints, colors) + self.file.output(name, Op.shading) + def _setup_textpos(self, x, y, descent, angle, oldx=0, oldy=0, olddescent=0, oldangle=0): if angle == oldangle == 0: self.file.output(x - oldx, (y + descent) - (oldy + olddescent), Op.textpos) Modified: trunk/matplotlib/lib/matplotlib/collections.py =================================================================== --- trunk/matplotlib/lib/matplotlib/collections.py 2009-08-31 19:50:13 UTC (rev 7620) +++ trunk/matplotlib/lib/matplotlib/collections.py 2009-08-31 20:10:35 UTC (rev 7621) @@ -1217,8 +1217,7 @@ triangles, colors = self.convert_mesh_to_triangles( self._meshWidth, self._meshHeight, coordinates) check = {} - for tri, col in zip(triangles, colors): - renderer.draw_gouraud_triangle(gc, tri, col, transform.frozen()) + renderer.draw_gouraud_triangles(gc, triangles, colors, transform.frozen()) else: renderer.draw_quad_mesh( gc, transform.frozen(), self._meshWidth, self._meshHeight, Modified: trunk/matplotlib/src/_backend_agg.cpp =================================================================== --- trunk/matplotlib/src/_backend_agg.cpp 2009-08-31 19:50:13 UTC (rev 7620) +++ trunk/matplotlib/src/_backend_agg.cpp 2009-08-31 20:10:35 UTC (rev 7621) @@ -1455,21 +1455,14 @@ return Py::Object(); } -Py::Object -RendererAgg::draw_gouraud_triangle(const Py::Tuple& args) { - _VERBOSE("RendererAgg::draw_quad_mesh"); - args.verify_length(4); +void +RendererAgg::_draw_gouraud_triangle(const GCAgg& gc, + const double* points, const double* colors, agg::trans_affine trans) { typedef agg::rgba8 color_t; typedef agg::span_gouraud_rgba<color_t> span_gen_t; typedef agg::span_allocator<color_t> span_alloc_t; - //segments, trans, clipbox, colors, linewidths, antialiaseds - GCAgg gc(args[0], dpi); - Py::Object points_obj = args[1]; - Py::Object colors_obj = args[2]; - agg::trans_affine trans = py_to_agg_transformation_matrix(args[3].ptr()); - theRasterizer.reset_clipping(); rendererBase.reset_clipping(true); set_clipbox(gc.cliprect, theRasterizer); @@ -1477,6 +1470,43 @@ trans *= agg::trans_affine_scaling(1.0, -1.0); trans *= agg::trans_affine_translation(0.0, (double)height); + double tpoints[6]; + + for (int i = 0; i < 6; i += 2) { + tpoints[i] = points[i]; + tpoints[i+1] = points[i+1]; + trans.transform(&tpoints[i], &tpoints[i+1]); + } + + span_alloc_t span_alloc; + span_gen_t span_gen; + + span_gen.colors( + agg::rgba(colors[0], colors[1], colors[2], colors[3]), + agg::rgba(colors[4], colors[5], colors[6], colors[7]), + agg::rgba(colors[8], colors[9], colors[10], colors[11])); + span_gen.triangle( + tpoints[0], tpoints[1], + tpoints[2], tpoints[3], + tpoints[4], tpoints[5], + 0.5); + + theRasterizer.add_path(span_gen); + agg::render_scanlines_aa( + theRasterizer, slineP8, rendererBase, span_alloc, span_gen); +} + +Py::Object +RendererAgg::draw_gouraud_triangle(const Py::Tuple& args) { + _VERBOSE("RendererAgg::draw_gouraud_triangle"); + args.verify_length(4); + + //segments, trans, clipbox, colors, linewidths, antialiaseds + GCAgg gc(args[0], dpi); + Py::Object points_obj = args[1]; + Py::Object colors_obj = args[2]; + agg::trans_affine trans = py_to_agg_transformation_matrix(args[3].ptr()); + PyArrayObject* points = (PyArrayObject*)PyArray_ContiguousFromAny (points_obj.ptr(), PyArray_DOUBLE, 2, 2); if (!points || @@ -1490,32 +1520,57 @@ throw Py::ValueError("colors must be a 3x4 numpy array"); try { - double* opoints = (double*)PyArray_DATA(points); - double* c = (double*)PyArray_DATA(colors); - double tpoints[6]; + _draw_gouraud_triangle( + gc, (double*)PyArray_DATA(points), (double*)PyArray_DATA(colors), trans); + } catch (...) { + Py_DECREF(points); + Py_DECREF(colors); - for (int i = 0; i < 6; i += 2) { - tpoints[i] = opoints[i]; - tpoints[i+1] = opoints[i+1]; - trans.transform(&tpoints[i], &tpoints[i+1]); - } + throw; + } - span_alloc_t span_alloc; - span_gen_t span_gen; + Py_DECREF(points); + Py_DECREF(colors); - span_gen.colors( - agg::rgba(c[0], c[1], c[2], c[3]), - agg::rgba(c[4], c[5], c[6], c[7]), - agg::rgba(c[8], c[9], c[10], c[11])); - span_gen.triangle( - tpoints[0], tpoints[1], - tpoints[2], tpoints[3], - tpoints[4], tpoints[5], - 0.5); + return Py::Object(); +} - theRasterizer.add_path(span_gen); - agg::render_scanlines_aa( - theRasterizer, slineP8, rendererBase, span_alloc, span_gen); +Py::Object +RendererAgg::draw_gouraud_triangles(const Py::Tuple& args) { + _VERBOSE("RendererAgg::draw_gouraud_triangles"); + args.verify_length(4); + + typedef agg::rgba8 color_t; + typedef agg::span_gouraud_rgba<color_t> span_gen_t; + typedef agg::span_allocator<color_t> span_alloc_t; + + //segments, trans, clipbox, colors, linewidths, antialiaseds + GCAgg gc(args[0], dpi); + Py::Object points_obj = args[1]; + Py::Object colors_obj = args[2]; + agg::trans_affine trans = py_to_agg_transformation_matrix(args[3].ptr()); + + PyArrayObject* points = (PyArrayObject*)PyArray_ContiguousFromAny + (points_obj.ptr(), PyArray_DOUBLE, 3, 3); + if (!points || + PyArray_DIM(points, 1) != 3 || PyArray_DIM(points, 2) != 2) + throw Py::ValueError("points must be a Nx3x2 numpy array"); + + PyArrayObject* colors = (PyArrayObject*)PyArray_ContiguousFromAny + (colors_obj.ptr(), PyArray_DOUBLE, 3, 3); + if (!colors || + PyArray_DIM(colors, 1) != 3 || PyArray_DIM(colors, 2) != 4) + throw Py::ValueError("colors must be a Nx3x4 numpy array"); + + if (PyArray_DIM(points, 0) != PyArray_DIM(colors, 0)) { + throw Py::ValueError("points and colors arrays must be the same length"); + } + + try { + for (int i = 0; i < PyArray_DIM(points, 0); ++i) { + _draw_gouraud_triangle( + gc, (double*)PyArray_GETPTR1(points, i), (double*)PyArray_GETPTR1(colors, i), trans); + } } catch (...) { Py_DECREF(points); Py_DECREF(colors); @@ -1870,6 +1925,8 @@ "draw_quad_mesh(gc, master_transform, meshWidth, meshHeight, coordinates, offsets, offsetTrans, facecolors, antialiaseds, showedges)\n"); add_varargs_method("draw_gouraud_triangle", &RendererAgg::draw_gouraud_triangle, "draw_gouraud_triangle(gc, points, colors, master_transform)\n"); + add_varargs_method("draw_gouraud_triangles", &RendererAgg::draw_gouraud_triangles, + "draw_gouraud_triangles(gc, points, colors, master_transform)\n"); add_varargs_method("draw_markers", &RendererAgg::draw_markers, "draw_markers(gc, marker_path, marker_trans, path, rgbFace)\n"); add_varargs_method("draw_text_image", &RendererAgg::draw_text_image, Modified: trunk/matplotlib/src/_backend_agg.h =================================================================== --- trunk/matplotlib/src/_backend_agg.h 2009-08-31 19:50:13 UTC (rev 7620) +++ trunk/matplotlib/src/_backend_agg.h 2009-08-31 20:10:35 UTC (rev 7621) @@ -165,6 +165,7 @@ Py::Object draw_path_collection(const Py::Tuple & args); Py::Object draw_quad_mesh(const Py::Tuple& args); Py::Object draw_gouraud_triangle(const Py::Tuple& args); + Py::Object draw_gouraud_triangles(const Py::Tuple& args); Py::Object write_rgba(const Py::Tuple & args); Py::Object tostring_rgb(const Py::Tuple & args); @@ -241,6 +242,11 @@ const Py::SeqBase<Py::Object>& linestyles_obj, const Py::SeqBase<Py::Int>& antialiaseds); + void + _draw_gouraud_triangle( + const GCAgg& gc, + const double* points, const double* colors, agg::trans_affine trans); + private: void create_alpha_buffers(); }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |