From: <md...@us...> - 2007-12-10 14:50:59
|
Revision: 4679 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4679&view=rev Author: mdboom Date: 2007-12-10 06:50:40 -0800 (Mon, 10 Dec 2007) Log Message: ----------- Use an 8-spline approximation of an ellipse instead of a 4-spline one. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py trunk/matplotlib/lib/matplotlib/patches.py Added Paths: ----------- trunk/matplotlib/unit/ellipse_large.py Modified: trunk/matplotlib/lib/matplotlib/backends/backend_ps.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2007-12-09 00:48:27 UTC (rev 4678) +++ trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2007-12-10 14:50:40 UTC (rev 4679) @@ -1644,11 +1644,15 @@ } bind def""", """/unitcircle { newpath --1. 0. moveto --1.0 0.552284749831 -0.552284749831 1.0 0.0 1.0 curveto -0.552284749831 1.0 1.0 0.552284749831 1.0 0.0 curveto -1.0 -0.552284749831 0.552284749831 -1.0 0.0 -1.0 curveto --0.552284749831 -1.0 -1.0 -0.552284749831 -1.0 0.0 curveto +0. -1. moveto +0.2652031 -1.0 0.519579870785 -0.894633691588 0.707106781187 -0.707106781187 curveto +0.894633691588 -0.519579870785 1.0 -0.2652031 1.0 0.0 curveto +1.0 0.2652031 0.894633691588 0.519579870785 0.707106781187 0.707106781187 curveto +0.519579870785 0.894633691588 0.2652031 1.0 0.0 1.0 curveto +-0.2652031 1.0 -0.519579870785 0.894633691588 -0.707106781187 0.707106781187 curveto +-0.894633691588 0.519579870785 -1.0 0.2652031 -1.0 0.0 curveto +-1.0 -0.2652031 -0.894633691588 -0.519579870785 -0.707106781187 -0.707106781187 curveto +-0.519579870785 -0.894633691588 -0.2652031 -1.0 0.0 -1.0 curveto closepath } bind def""", Modified: trunk/matplotlib/lib/matplotlib/patches.py =================================================================== --- trunk/matplotlib/lib/matplotlib/patches.py 2007-12-09 00:48:27 UTC (rev 4678) +++ trunk/matplotlib/lib/matplotlib/patches.py 2007-12-10 14:50:40 UTC (rev 4679) @@ -201,7 +201,7 @@ if cbook.is_string_like(self._edgecolor) and self._edgecolor.lower()=='none': gc.set_linewidth(0) - else: + else: gc.set_foreground(self._edgecolor) gc.set_linewidth(self._linewidth) @@ -764,32 +764,46 @@ """ A scale-free ellipse """ - offset = 4.0 * (npy.sqrt(2) - 1) / 3.0 + MAGIC = 0.2652031 + SQRT2 = npy.sqrt(0.5) + MAGIC45 = npy.sqrt((MAGIC*MAGIC) / 2.0) - circle = npy.array([ - [-1.0, 0.0], + circle = npy.array( + [[0.0, -1.0], - [-1.0, offset], - [-offset, 1.0], - [0.0, 1.0], + [MAGIC, -1.0], + [SQRT2-MAGIC45, -SQRT2-MAGIC45], + [SQRT2, -SQRT2], - [offset, 1.0], - [1.0, offset], - [1.0, 0.0], + [SQRT2+MAGIC45, -SQRT2+MAGIC45], + [1.0, -MAGIC], + [1.0, 0.0], - [1.0, -offset], - [offset, -1.0], - [0.0, -1.0], + [1.0, MAGIC], + [SQRT2+MAGIC45, SQRT2-MAGIC45], + [SQRT2, SQRT2], - [-offset, -1.0], - [-1.0, -offset], - [-1.0, 0.0], + [SQRT2-MAGIC45, SQRT2+MAGIC45], + [MAGIC, 1.0], + [0.0, 1.0], - [-1.0, 0.0] - ], - npy.float_) + [-MAGIC, 1.0], + [-SQRT2+MAGIC45, SQRT2+MAGIC45], + [-SQRT2, SQRT2], - + [-SQRT2-MAGIC45, SQRT2-MAGIC45], + [-1.0, MAGIC], + [-1.0, 0.0], + + [-1.0, -MAGIC], + [-SQRT2-MAGIC45, -SQRT2+MAGIC45], + [-SQRT2, -SQRT2], + + [-SQRT2+MAGIC45, -SQRT2-MAGIC45], + [-MAGIC, -1.0], + [0.0, -1.0]], + npy.float_) + def __str__(self): return "Ellipse(%d,%d;%dx%d)"%(self.center[0],self.center[1],self.width,self.height) @@ -823,9 +837,9 @@ width, height = self.width, self.height xcenter = self.convert_xunits(xcenter) - width = self.convert_xunits(width) + width = self.convert_xunits(width) ycenter = self.convert_yunits(ycenter) - height = self.convert_xunits(height) + height = self.convert_xunits(height) @@ -871,8 +885,8 @@ mpl.verbose.report('patches.Ellipse renderer does not support path drawing; falling back on vertex approximation for nonlinear transformation') renderer.draw_polygon(gc, rgbFace, self.get_verts()) return - + x, y = self.center x = self.convert_xunits(x) y = self.convert_yunits(y) @@ -887,14 +901,14 @@ - + S = npy.array([ [w, 0, 0], [0, h, 0], [0, 0, 1]]) - + # rotate by theta R = npy.array([ [npy.cos(theta), -npy.sin(theta), 0], @@ -903,8 +917,8 @@ # transform unit circle into ellipse E = npy.dot(T, npy.dot(R, S)) - + # Apply the display affine sx, b, c, sy, tx, ty = self.get_transform().as_vec6_val() @@ -918,25 +932,19 @@ C = npy.ones((3, len(self.circle))) C[0:2,:] = self.circle.T - + ellipse = npy.dot(M, C).T[:,:2] path = agg.path_storage() path.move_to(*ellipse[0]) - verts = ellipse[1:4].flat - path.curve4(*verts) - verts = ellipse[4:7].flat - path.curve4(*verts) - verts = ellipse[7:10].flat - path.curve4(*verts) - verts = ellipse[10:13].flat - path.curve4(*verts) + for i in range(1, 25, 3): + path.curve4(*ellipse[i:i+3].flat) path.close_polygon() renderer.draw_path(gc, rgbFace, path) - + class Circle(Ellipse): """ A circle patch Added: trunk/matplotlib/unit/ellipse_large.py =================================================================== --- trunk/matplotlib/unit/ellipse_large.py (rev 0) +++ trunk/matplotlib/unit/ellipse_large.py 2007-12-10 14:50:40 UTC (rev 4679) @@ -0,0 +1,107 @@ + +# This example can be boiled down to a more simplistic example +# to show the problem, but bu including the upper and lower +# bound ellipses, it demonstrates how significant this error +# is to our plots. + +import math +from pylab import * +from matplotlib.patches import Ellipse + +# given a point x, y +x = 2692.440 +y = 6720.850 + +# get is the radius of a circle through this point +r = math.sqrt( x*x+y*y ) + +# show some comparative circles +delta = 6 + + +################################################## +def custom_ellipse( ax, x, y, major, minor, theta, numpoints = 750, **kwargs ): + xs = [] + ys = [] + incr = 2.0*math.pi / numpoints + incrTheta = 0.0 + while incrTheta <= (2.0*math.pi): + a = major * math.cos( incrTheta ) + b = minor * math.sin( incrTheta ) + l = math.sqrt( ( a**2 ) + ( b**2 ) ) + phi = math.atan2( b, a ) + incrTheta += incr + + xs.append( x + ( l * math.cos( theta + phi ) ) ) + ys.append( y + ( l * math.sin( theta + phi ) ) ) + # end while + + incrTheta = 2.0*math.pi + a = major * math.cos( incrTheta ) + b = minor * math.sin( incrTheta ) + l = sqrt( ( a**2 ) + ( b**2 ) ) + phi = math.atan2( b, a ) + xs.append( x + ( l * math.cos( theta + phi ) ) ) + ys.append( y + ( l * math.sin( theta + phi ) ) ) + + ellipseLine = ax.plot( xs, ys, **kwargs ) + + +################################################## +# make the axes +ax = subplot( 211, aspect='equal' ) +ax.set_aspect( 'equal', 'datalim' ) + +# make the lower-bound ellipse +diam = (r - delta) * 2.0 +lower_ellipse = Ellipse( (0.0, 0.0), diam, diam, 0.0, fill=False, edgecolor="darkgreen" ) +ax.add_patch( lower_ellipse ) + +# make the target ellipse +diam = r * 2.0 +target_ellipse = Ellipse( (0.0, 0.0), diam, diam, 0.0, fill=False, edgecolor="darkred" ) +ax.add_patch( target_ellipse ) + +# make the upper-bound ellipse +diam = (r + delta) * 2.0 +upper_ellipse = Ellipse( (0.0, 0.0), diam, diam, 0.0, fill=False, edgecolor="darkblue" ) +ax.add_patch( upper_ellipse ) + +# make the target +diam = delta * 2.0 +target = Ellipse( (x, y), diam, diam, 0.0, fill=False, edgecolor="#DD1208" ) +ax.add_patch( target ) + +# give it a big marker +ax.plot( [x], [y], marker='x', linestyle='None', mfc='red', mec='red', markersize=10 ) + +################################################## +# now lets do the same thing again using a custom ellipse function + +# make the axes +ax = subplot( 212, aspect='equal', sharex=ax, sharey=ax ) +ax.set_aspect( 'equal', 'datalim' ) + +# make the lower-bound ellipse +custom_ellipse( ax, 0.0, 0.0, r-delta, r-delta, 0.0, color="darkgreen" ) + +# make the target ellipse +custom_ellipse( ax, 0.0, 0.0, r, r, 0.0, color="darkred" ) + +# make the upper-bound ellipse +custom_ellipse( ax, 0.0, 0.0, r+delta, r+delta, 0.0, color="darkblue" ) + +# make the target +custom_ellipse( ax, x, y, delta, delta, 0.0, color="#BB1208" ) + +# give it a big marker +ax.plot( [x], [y], marker='x', linestyle='None', mfc='red', mec='red', markersize=10 ) + +################################################## +# lets zoom in to see the area of interest + +ax.set_xlim(2650, 2735) +ax.set_ylim(6705, 6735) +show() + +savefig("ellipse") This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |