1
2
3
4
5
6
7
8
9
10
11
12 """
13 Stimuli on spheres, including texture maps.
14
15 """
16
17 import math, types
18
19 import logging
20
21 import VisionEgg.Core
22 import VisionEgg.Textures
23 import VisionEgg.Text
24 import VisionEgg.Gratings
25 import VisionEgg.ThreeDeeMath
26 import VisionEgg.ParameterTypes as ve_types
27
28 import numpy
29 import numpy.oldnumeric as Numeric
30 import Image
31
32 import VisionEgg.GL as gl
33
34 __version__ = VisionEgg.release_name
35
37 """Spherical grid of iso-azimuth and iso-elevation lines.
38
39 Parameters
40 ==========
41 anti_aliasing -- (Boolean)
42 Default: True
43 center_azimuth -- (Real)
44 Default: 0.0
45 center_elevation -- (Real)
46 Default: 0.0
47 major_line_color -- (AnyOf(Sequence3 of Real or Sequence4 of Real))
48 Default: (0.0, 0.0, 0.0)
49 major_line_width -- (Real)
50 Default: 2.0
51 minor_line_color -- (AnyOf(Sequence3 of Real or Sequence4 of Real))
52 Default: (0.0, 0.0, 1.0)
53 minor_line_width -- (Real)
54 Default: 1.0
55 my_viewport -- (Instance of <class 'VisionEgg.Core.Viewport'>)
56 Default: (determined at runtime)
57 on -- (Boolean)
58 Default: True
59 text_offset -- (Sequence2 of Real)
60 Default: (3, -2)
61
62 Constant Parameters
63 ===================
64 az_major_spacing -- (Real)
65 Default: 30.0
66 az_minor_spacing -- (Real)
67 Default: 10.0
68 el_major_spacing -- (Real)
69 Default: 30.0
70 el_minor_spacing -- (Real)
71 Default: 10.0
72 font_size -- (UnsignedInteger)
73 Default: 24
74 num_samples_per_circle -- (UnsignedInteger)
75 Default: 100
76 radius -- (Real)
77 Default: 1.0
78 text_anchor -- (String)
79 Default: lowerleft
80 text_color -- (AnyOf(Sequence3 of Real or Sequence4 of Real))
81 Default: (0.0, 0.0, 0.0)
82 use_text -- (Boolean)
83 Default: True
84 """
85
86 parameters_and_defaults = {
87 'on':(True,
88 ve_types.Boolean),
89 'center_azimuth':(0.0,
90 ve_types.Real),
91 'center_elevation':(0.0,
92 ve_types.Real),
93 'minor_line_width':(1.0,
94 ve_types.Real),
95 'major_line_width':(2.0,
96 ve_types.Real),
97 'minor_line_color':((0.0,0.0,1.0),
98 ve_types.AnyOf(ve_types.Sequence3(ve_types.Real),
99 ve_types.Sequence4(ve_types.Real))),
100 'major_line_color':((0.0,0.0,0.0),
101 ve_types.AnyOf(ve_types.Sequence3(ve_types.Real),
102 ve_types.Sequence4(ve_types.Real))),
103 'my_viewport':(None,
104 ve_types.Instance(VisionEgg.Core.Viewport)),
105 'text_offset':((3,-2),
106 ve_types.Sequence2(ve_types.Real)),
107 'anti_aliasing' : ( True,
108 ve_types.Boolean ),
109 }
110
111 constant_parameters_and_defaults = {
112 'use_text':(True,
113 ve_types.Boolean),
114 'radius':(1.0,
115 ve_types.Real),
116 'az_minor_spacing':(10.0,
117 ve_types.Real),
118 'az_major_spacing':(30.0,
119 ve_types.Real),
120 'el_minor_spacing':(10.0,
121 ve_types.Real),
122 'el_major_spacing':(30.0,
123 ve_types.Real),
124 'num_samples_per_circle':(100,
125 ve_types.UnsignedInteger),
126 'font_size':(24,
127 ve_types.UnsignedInteger),
128 'text_color':((0.0,0.0,0.0),
129 ve_types.AnyOf(ve_types.Sequence3(ve_types.Real),
130 ve_types.Sequence4(ve_types.Real))),
131 'text_anchor':('lowerleft',
132 ve_types.String),
133 }
134
135 __slots__ = (
136 'cached_minor_lines_display_list',
137 'cached_major_lines_display_list',
138 'text_viewport',
139 'text_viewport_orig',
140 '_gave_alpha_warning',
141 'labels',
142 'labels_xyz',
143 )
144
146 VisionEgg.Core.Stimulus.__init__(self,**kw)
147 self.cached_minor_lines_display_list = gl.glGenLists(1)
148 self.cached_major_lines_display_list = gl.glGenLists(1)
149 self.__rebuild_display_lists()
150 self.text_viewport = None
151 self._gave_alpha_warning = False
152
154 def get_xyz(theta,phi,radius):
155
156
157 y = radius * math.cos( theta )
158 w = radius * math.sin( theta )
159 x = w * math.cos( phi )
160 z = w * math.sin( phi )
161 return x,y,z
162 def draw_half_great_circle(az):
163 for i in range(cp.num_samples_per_circle/2):
164
165 theta_start = i/float(cp.num_samples_per_circle)*2*math.pi
166 theta_stop = (i+1)/float(cp.num_samples_per_circle)*2*math.pi
167 phi_start = phi_stop = (az-90.0)/180.0*math.pi
168 x_start,y_start,z_start = get_xyz(theta_start,phi_start,cp.radius)
169 x_stop,y_stop,z_stop = get_xyz(theta_stop,phi_stop,cp.radius)
170 gl.glVertex3f(x_start, y_start, z_start)
171 gl.glVertex3f(x_stop, y_stop, z_stop)
172 def draw_iso_elevation_circle(el):
173
174 theta_start = theta_stop = -(el-90) / 180.0 * math.pi
175 for i in range(cp.num_samples_per_circle):
176 phi_start = i/float(cp.num_samples_per_circle)*2*math.pi
177 phi_stop = (i+1)/float(cp.num_samples_per_circle)*2*math.pi
178 x_start,y_start,z_start = get_xyz(theta_start,phi_start,cp.radius)
179 x_stop,y_stop,z_stop = get_xyz(theta_stop,phi_stop,cp.radius)
180 gl.glVertex3f(x_start, y_start, z_start)
181 gl.glVertex3f(x_stop, y_stop, z_stop)
182
183 cp = self.constant_parameters
184
185 azs_major = numpy.concatenate((
186 numpy.arange(0.0,180.0,cp.az_major_spacing),
187 -numpy.arange(0.0,180.0,cp.az_major_spacing)[1:]))
188 azs_minor = numpy.concatenate((
189 numpy.arange(0.0,180.0,cp.az_minor_spacing),
190 -numpy.arange(0.0,180.0,cp.az_minor_spacing)[1:]))
191 els_major = numpy.concatenate((
192 numpy.arange(0.0,90.0,cp.el_major_spacing),
193 -numpy.arange(0.0,90.0,cp.el_major_spacing)[1:]))
194 els_minor = numpy.concatenate((
195 numpy.arange(0.0,90.0,cp.el_minor_spacing),
196 -numpy.arange(0.0,90.0,cp.el_minor_spacing)[1:]))
197
198 gl.glNewList(self.cached_minor_lines_display_list,gl.GL_COMPILE)
199 gl.glBegin(gl.GL_LINES)
200
201 for az in azs_minor:
202 if az in azs_major:
203 continue
204 draw_half_great_circle(az)
205 for el in els_minor:
206 if el in els_major:
207 continue
208 draw_iso_elevation_circle(el)
209 gl.glEnd()
210 gl.glEndList()
211
212 gl.glNewList(self.cached_major_lines_display_list,gl.GL_COMPILE)
213 gl.glBegin(gl.GL_LINES)
214 for az in azs_major:
215 draw_half_great_circle(az)
216 for el in els_major:
217 draw_iso_elevation_circle(el)
218 gl.glEnd()
219 gl.glEndList()
220
221 if cp.use_text:
222 self.labels = []
223 self.labels_xyz = []
224 els_major = list(els_major)+[90.0]
225 for el in els_major:
226 for az in azs_major:
227 theta = -(el-90) / 180.0 * math.pi
228 phi = (az-90.0)/180.0*math.pi
229 x,y,z = get_xyz(theta,phi,cp.radius)
230 self.labels_xyz.append((x,y,z))
231 self.labels.append(
232 VisionEgg.Text.Text( text = '%.0f, %.0f'%(az,el),
233 font_size = cp.font_size,
234 color = cp.text_color,
235 anchor = cp.text_anchor,
236 )
237 )
238 if (el == -90) or (el == 90):
239 self.labels[-1].parameters.text = 'x, %.0f'%(el,)
240 break
241
242 self.labels_xyz = Numeric.array(self.labels_xyz)
243
245 p = self.parameters
246 cp = self.constant_parameters
247 if p.on:
248
249 gl.glDisable( gl.GL_DEPTH_TEST )
250 gl.glDisable( gl.GL_TEXTURE_2D )
251 gl.glMatrixMode(gl.GL_MODELVIEW)
252 gl.glPushMatrix()
253 gl.glRotatef(p.center_azimuth,0.0,-1.0,0.0)
254 gl.glRotatef(p.center_elevation,1.0,0.0,0.0)
255
256 if p.anti_aliasing:
257 if len(p.minor_line_color) == 4 and not self._gave_alpha_warning:
258 if p.minor_line_color[3] != 1.0:
259 logger = logging.getLogger('VisionEgg.SphereMap')
260 logger.warning("The parameter anti_aliasing is "
261 "set to true in the AzElGrid "
262 "stimulus class, but the color "
263 "parameter specifies an alpha "
264 "value other than 1.0. To "
265 "acheive the best anti-aliasing, "
266 "ensure that the alpha value for "
267 "the color parameter is 1.0.")
268 self._gave_alpha_warning = 1
269 if len(p.major_line_color) == 4 and not self._gave_alpha_warning:
270 if p.major_line_color[3] != 1.0:
271 logger = logging.getLogger('VisionEgg.SphereMap')
272 logger.warning("The parameter anti_aliasing is "
273 "set to true in the AzElGrid "
274 "stimulus class, but the color "
275 "parameter specifies an alpha "
276 "value other than 1.0. To "
277 "acheive the best anti-aliasing, "
278 "ensure that the alpha value for "
279 "the color parameter is 1.0.")
280 self._gave_alpha_warning = 1
281 gl.glEnable( gl.GL_LINE_SMOOTH )
282
283 gl.glEnable( gl.GL_BLEND )
284 gl.glBlendFunc( gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA )
285 else:
286 gl.glDisable( gl.GL_BLEND )
287
288 if len(p.minor_line_color)==3:
289 gl.glColor3f(*p.minor_line_color)
290 elif len(p.minor_line_color)==4:
291 gl.glColor4f(*p.minor_line_color)
292 gl.glLineWidth(p.minor_line_width)
293 gl.glCallList(self.cached_minor_lines_display_list)
294
295 if len(p.major_line_color)==3:
296 gl.glColor3f(*p.major_line_color)
297 elif len(p.major_line_color)==4:
298 gl.glColor4f(*p.major_line_color)
299 gl.glLineWidth(p.major_line_width)
300 gl.glCallList(self.cached_major_lines_display_list)
301
302 if p.anti_aliasing:
303 gl.glDisable( gl.GL_LINE_SMOOTH )
304
305 if cp.use_text:
306 my_view = p.my_viewport
307 if (my_view is None) or (not my_view._is_drawing):
308 raise ValueError('use_text is True, but my_viewport not (properly) assigned')
309
310 if self.text_viewport is None or self.text_viewport_orig != my_view:
311
312 vp = my_view.parameters
313 self.text_viewport = VisionEgg.Core.Viewport(screen=vp.screen,
314 position=vp.position,
315 size=vp.size,
316 anchor=vp.anchor,
317 )
318 lowerleft = VisionEgg._get_lowerleft(vp.position,vp.anchor,vp.size)
319 self.text_viewport.parameters.projection.stateless_translate(