Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/plot/disk.py
4034 views
1
"""
2
Disks
3
"""
4
#*****************************************************************************
5
# Copyright (C) 2006 Alex Clemesha <[email protected]>,
6
# William Stein <[email protected]>,
7
# 2008 Mike Hansen <[email protected]>,
8
#
9
# Distributed under the terms of the GNU General Public License (GPL)
10
#
11
# This code is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
# General Public License for more details.
15
#
16
# The full text of the GPL is available at:
17
#
18
# http://www.gnu.org/licenses/
19
#*****************************************************************************
20
from sage.plot.primitive import GraphicPrimitive
21
from sage.misc.decorators import options, rename_keyword
22
from sage.plot.colors import to_mpl_color
23
from math import sin, cos, pi
24
25
class Disk(GraphicPrimitive):
26
"""
27
Primitive class for the ``Disk`` graphics type. See ``disk?`` for
28
information about actually plotting a disk (the Sage term for a sector
29
or wedge of a circle).
30
31
INPUT:
32
33
- ``point`` - coordinates of center of disk
34
35
- ``r`` - radius of disk
36
37
- ``angle`` - beginning and ending angles of disk (i.e.
38
angle extent of sector/wedge)
39
40
- ``options`` - dict of valid plot options to pass to constructor
41
42
EXAMPLES:
43
44
Note this should normally be used indirectly via ``disk``::
45
46
sage: from sage.plot.disk import Disk
47
sage: D = Disk((1,2), 2, (pi/2,pi), {'zorder':3})
48
sage: D
49
Disk defined by (1.0,2.0) with r=2.0 spanning (1.57079632679, 3.14159265359) radians
50
sage: D.options()['zorder']
51
3
52
sage: D.x
53
1.0
54
55
TESTS:
56
57
We test creating a disk::
58
59
sage: disk((2,3), 2, (0,pi/2))
60
"""
61
def __init__(self, point, r, angle, options):
62
"""
63
Initializes base class ``Disk``.
64
65
EXAMPLES::
66
67
sage: D = disk((2,3), 1, (pi/2, pi), fill=False, color='red', thickness=1, alpha=.5)
68
sage: D[0].x
69
2.0
70
sage: D[0].r
71
1.0
72
sage: D[0].rad1
73
1.5707963267948966
74
sage: D[0].options()['rgbcolor']
75
'red'
76
sage: D[0].options()['alpha']
77
0.500000000000000
78
sage: print loads(dumps(D))
79
Graphics object consisting of 1 graphics primitive
80
"""
81
self.x = float(point[0])
82
self.y = float(point[1])
83
self.r = float(r)
84
self.rad1 = float(angle[0])
85
self.rad2 = float(angle[1])
86
GraphicPrimitive.__init__(self, options)
87
88
def get_minmax_data(self):
89
"""
90
Returns a dictionary with the bounding box data.
91
92
EXAMPLES::
93
94
sage: D = disk((5,4), 1, (pi/2, pi))
95
sage: d = D.get_minmax_data()
96
sage: d['xmin']
97
4.0
98
sage: d['ymin']
99
3.0
100
sage: d['xmax']
101
6.0
102
sage: d['ymax']
103
5.0
104
105
"""
106
from sage.plot.plot import minmax_data
107
return minmax_data([self.x - self.r, self.x + self.r],
108
[self.y - self.r, self.y + self.r],
109
dict=True)
110
111
def _allowed_options(self):
112
"""
113
Return the allowed options for the ``Disk`` class.
114
115
EXAMPLES::
116
117
sage: p = disk((3, 3), 1, (0, pi/2))
118
sage: p[0]._allowed_options()['alpha']
119
'How transparent the figure is.'
120
sage: p[0]._allowed_options()['zorder']
121
'The layer level in which to draw'
122
"""
123
return {'alpha':'How transparent the figure is.',
124
'fill':'Whether or not to fill the disk.',
125
'legend_label':'The label for this item in the legend.',
126
'thickness':'How thick the border of the disk is.',
127
'rgbcolor':'The color as an RGB tuple.',
128
'hue':'The color given as a hue.',
129
'zorder':'The layer level in which to draw'}
130
131
def _repr_(self):
132
"""
133
String representation of ``Disk`` primitive.
134
135
EXAMPLES::
136
137
sage: P = disk((3, 3), 1, (0, pi/2))
138
sage: p = P[0]; p
139
Disk defined by (3.0,3.0) with r=1.0 spanning (0.0, 1.57079632679) radians
140
"""
141
return "Disk defined by (%s,%s) with r=%s spanning (%s, %s) radians"%(self.x,
142
self.y, self.r, self.rad1, self.rad2)
143
144
def _render_on_subplot(self, subplot):
145
"""
146
TESTS::
147
148
sage: D = disk((2,-1), 2, (0, pi), color='black', thickness=3, fill=False); D
149
"""
150
import matplotlib.patches as patches
151
options = self.options()
152
deg1 = self.rad1*(180./pi) #convert radians to degrees
153
deg2 = self.rad2*(180./pi)
154
z = int(options.pop('zorder', 0))
155
p = patches.Wedge((float(self.x), float(self.y)), float(self.r), float(deg1),
156
float(deg2), zorder=z)
157
p.set_linewidth(float(options['thickness']))
158
p.set_fill(options['fill'])
159
p.set_alpha(options['alpha'])
160
c = to_mpl_color(options['rgbcolor'])
161
p.set_edgecolor(c)
162
p.set_facecolor(c)
163
p.set_label(options['legend_label'])
164
subplot.add_patch(p)
165
166
def plot3d(self, z=0, **kwds):
167
"""
168
Plots a 2D disk (actually a 52-gon) in 3D,
169
with default height zero.
170
171
INPUT:
172
173
174
- ``z`` - optional 3D height above `xy`-plane.
175
176
AUTHORS:
177
178
- Karl-Dieter Crisman (05-09)
179
180
EXAMPLES::
181
182
sage: disk((0,0), 1, (0, pi/2)).plot3d()
183
sage: disk((0,0), 1, (0, pi/2)).plot3d(z=2)
184
sage: disk((0,0), 1, (pi/2, 0), fill=False).plot3d(3)
185
186
These examples show that the appropriate options are passed::
187
188
sage: D = disk((2,3), 1, (pi/4,pi/3), hue=.8, alpha=.3, fill=True)
189
sage: d = D[0]
190
sage: d.plot3d(z=2).texture.opacity
191
0.300000000000000
192
193
::
194
195
sage: D = disk((2,3), 1, (pi/4,pi/3), hue=.8, alpha=.3, fill=False)
196
sage: d = D[0]
197
sage: dd = d.plot3d(z=2)
198
sage: dd.jmol_repr(dd.testing_render_params())[0][-1]
199
'color $line_4 translucent 0.7 [204,0,255]'
200
"""
201
options = dict(self.options())
202
fill = options['fill']
203
del options['fill']
204
if 'zorder' in options:
205
del options['zorder']
206
n = 50
207
x, y, r, rad1, rad2 = self.x, self.y, self.r, self.rad1, self.rad2
208
dt = float((rad2-rad1)/n)
209
xdata = [x]
210
ydata = [y]
211
xdata.extend([x+r*cos(t*dt+rad1) for t in range(n+1)])
212
ydata.extend([y+r*sin(t*dt+rad1) for t in range(n+1)])
213
xdata.append(x)
214
ydata.append(y)
215
if fill:
216
from polygon import Polygon
217
return Polygon(xdata, ydata, options).plot3d(z)
218
else:
219
from line import Line
220
return Line(xdata, ydata, options).plot3d().translate((0,0,z))
221
222
@rename_keyword(color='rgbcolor')
223
@options(alpha=1, fill=True, rgbcolor=(0,0,1), thickness=0, legend_label=None,
224
aspect_ratio=1.0)
225
def disk(point, radius, angle, **options):
226
r"""
227
A disk (that is, a sector or wedge of a circle) with center
228
at a point = `(x,y)` (or `(x,y,z)` and parallel to the
229
`xy`-plane) with radius = `r` spanning (in radians)
230
angle=`(rad1, rad2)`.
231
232
Type ``disk.options`` to see all options.
233
234
EXAMPLES:
235
236
Make some dangerous disks::
237
238
sage: bl = disk((0.0,0.0), 1, (pi, 3*pi/2), color='yellow')
239
sage: tr = disk((0.0,0.0), 1, (0, pi/2), color='yellow')
240
sage: tl = disk((0.0,0.0), 1, (pi/2, pi), color='black')
241
sage: br = disk((0.0,0.0), 1, (3*pi/2, 2*pi), color='black')
242
sage: P = tl+tr+bl+br
243
sage: P.show(xmin=-2,xmax=2,ymin=-2,ymax=2)
244
245
The default aspect ratio is 1.0::
246
247
sage: disk((0.0,0.0), 1, (pi, 3*pi/2)).aspect_ratio()
248
1.0
249
250
Another example of a disk::
251
252
sage: bl = disk((0.0,0.0), 1, (pi, 3*pi/2), rgbcolor=(1,1,0))
253
sage: bl.show(figsize=[5,5])
254
255
Note that since ``thickness`` defaults to zero, it is best to change
256
that option when using ``fill=False``::
257
258
sage: disk((2,3), 1, (pi/4,pi/3), hue=.8, alpha=.3, fill=False, thickness=2)
259
260
The previous two examples also illustrate using ``hue`` and ``rgbcolor``
261
as ways of specifying the color of the graphic.
262
263
We can also use this command to plot three-dimensional disks parallel
264
to the `xy`-plane::
265
266
sage: d = disk((1,1,3), 1, (pi,3*pi/2), rgbcolor=(1,0,0))
267
sage: d
268
sage: type(d)
269
<type 'sage.plot.plot3d.index_face_set.IndexFaceSet'>
270
271
Extra options will get passed on to ``show()``, as long as they are valid::
272
273
sage: disk((0, 0), 5, (0, pi/2), xmin=0, xmax=5, ymin=0, ymax=5, figsize=(2,2), rgbcolor=(1, 0, 1))
274
sage: disk((0, 0), 5, (0, pi/2), rgbcolor=(1, 0, 1)).show(xmin=0, xmax=5, ymin=0, ymax=5, figsize=(2,2)) # These are equivalent
275
276
TESTS:
277
278
We cannot currently plot disks in more than three dimensions::
279
280
sage: d = disk((1,1,1,1), 1, (0,pi))
281
Traceback (most recent call last):
282
...
283
ValueError: The center point of a plotted disk should have two or three coordinates.
284
"""
285
from sage.plot.all import Graphics
286
g = Graphics()
287
g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
288
g.add_primitive(Disk(point, radius, angle, options))
289
if options['legend_label']:
290
g.legend(True)
291
if len(point)==2:
292
return g
293
elif len(point)==3:
294
return g[0].plot3d(z=point[2])
295
else:
296
raise ValueError, 'The center point of a plotted disk should have two or three coordinates.'
297
298