6
This module contains a class implementing a LCD symbol.
10
__author__ = 'Florian Krause <florian@expyriment.org>, \
11
Oliver Lindemann <oliver@expyriment.org>'
13
__revision__ = '55a4e7e'
14
__date__ = 'Wed Mar 26 14:33:37 2014 +0100'
24
from expyriment.stimuli._visual import Visual
25
from expyriment.stimuli.extras._polygondot import PolygonDot
28
class LcdSymbol(Visual):
29
"""A LCD symbol class.
31
IDs for points and line ::
41
'0','1','2','3','4','5','6','7','8','9'
42
'A','C','E','F','U','H','L','P','h'
46
_shapes = {"0":(0, 1, 2, 4, 5, 6),
52
"6":(0, 1, 3, 4, 5, 6),
54
"8":(0, 1, 2 , 3 , 4 , 5 , 6),
55
"9":(0, 1 , 2 , 3 , 5, 6),
56
"A":(0, 1, 2, 3, 4, 5),
67
_lines = ((0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 5), (4, 5))
69
def __init__(self, shape, position=None, size=None, colour=None,
70
inactive_colour=None, background_colour=None,
71
line_width=None, gap=None, simple_lines=None):
72
"""Create a LCD symbol.
78
position : (int, int), optional
79
position to show the symbol
81
size of the LCD symbol
82
colour : (int, int, int), optional
84
inactive_colour : (int, int, int), optional
85
colour of inactive lines
86
background_colour : (int, int, int), optional
87
line_width : int, optional
91
simple_lines : bool, optional
96
Visual.__init__(self, position)
97
if shape in self._shapes:
98
self._shape = self._shapes[shape]
102
self._width = size[0]
103
self._height = size[1]
105
size = defaults.lcdsymbol_size
108
size = expyriment._active_exp.screen.surface.get_size()
110
raise RuntimeError("Could not get size of screen!")
111
self._width = size[0]
112
self._height = size[1]
114
colour = defaults.lcdsymbol_colour
115
if colour is not None:
116
self._colour = colour
118
self._colour = expyriment._active_exp.foreground_colour
119
if inactive_colour is not None:
120
self._inactive_colour = inactive_colour
122
self._inactive_colour = \
123
defaults.lcdsymbol_inactive_colour
124
if background_colour is not None:
125
self._background_colour = background_colour
127
self._background_colour = \
128
defaults.lcdsymbol_background_colour
129
if line_width is not None:
130
self._line_width = line_width
132
self._line_width = defaults.lcdsymbol_line_width
136
self._gap = defaults.lcdsymbol_gap
137
if simple_lines is not None:
138
self._simple_lines = simple_lines
140
self._simple_lines = defaults.lcdsymbol_simple_lines
142
x = int(self.line_width / 2.0) + 1
143
self._points = (PolygonDot(radius=0, position=(x, x)),
144
PolygonDot(radius=0, position=(self._width - x, x)), \
146
position=(x, math.floor(self._height / 2))), \
148
position=(self._width - x,
149
math.floor(self._height / 2))), \
150
PolygonDot(radius=0, position=(x, self._height - x)), \
152
position=(self._width - x, self._height - x)))
153
expyriment.stimuli._stimulus.Stimulus._id_counter -= 6
155
_getter_exception_message = "Cannot set {0} if surface exists!"
159
"""Getter for shape."""
164
def shape(self, value):
165
"""Setter for shape."""
168
raise AttributeError(
169
LcdSymbol._getter_exception_message.format("shape"))
171
if value in self.shapes:
172
self._shape = self.shapes[value]
178
"""Getter for size."""
180
return (self._width, self._height)
183
def size(self, value):
184
"""Setter for size."""
187
raise AttributeError(
188
LcdSymbol._getter_exception_message.format("shape"))
190
self._width = value[0]
191
self._height = value[1]
192
self._points = (PolygonDot(radius=0, position=(0, 0)),
193
PolygonDot(radius=0, position=(self._width, 0)),
195
position=(0, math.floor(self._height / 2))),
196
PolygonDot(radius=0, position=(self._width,
197
math.floor(self._height / 2))),
198
PolygonDot(radius=0, position=(0, self._height)),
199
PolygonDot(radius=0, position=(self._width, self._height)))
200
expyriment.stimuli._stimulus.Stimulus._id_counter -= 6
204
"""Getter for colour."""
209
def colour(self, value):
210
"""Setter for colour."""
213
raise AttributeError(
214
LcdSymbol._getter_exception_message.format("colour"))
219
def inactive_colour(self):
220
"""Getter for inactive_colour."""
222
return self._inactive_colour
224
@inactive_colour.setter
225
def inactive_colour(self, value):
226
"""Setter for inactive_colour."""
229
raise AttributeError(
230
LcdSymbol._getter_exception_message.format(
233
self._inactive_colour = value
236
def background_colour(self):
237
"""Getter for background_colour."""
239
return self._background_colour
241
@background_colour.setter
242
def background_colour(self, value):
243
"""Setter for background_colour."""
246
raise AttributeError(
247
LcdSymbol._getter_exception_message.format(
248
"background_colour"))
250
self._background_colour = value
253
def line_width(self):
254
"""Getter for line_width."""
256
return self._line_width
259
def line_width(self, value):
260
"""Setter for line_width."""
263
raise AttributeError(
264
LcdSymbol._getter_exception_message.format("line_width"))
266
self._line_width = value
270
"""Getter for gap."""
275
def gap(self, value):
276
"""Setter for gap."""
279
raise AttributeError(
280
LcdSymbol._getter_exception_message.format("gap"))
285
def simple_lines(self):
286
"""Getter for simple_lines."""
288
return self._simple_lines
291
def simple_lines(self, value):
292
"""Setter for simple_lines."""
295
raise AttributeError(
296
LcdSymbol._getter_exception_message.format(
299
self._simple_lines = value
303
"""Getter for points."""
307
def _create_surface(self):
308
"""Create the surface of the stimulus."""
310
surface = pygame.surface.Surface((self._width, self._height),
311
pygame.SRCALPHA).convert_alpha()
312
if self.background_colour is not None:
313
surface.fill(self.background_colour)
314
if self.inactive_colour is not None:
316
for x in self._shapes["8"]:
318
for p in self.get_line_polygon(x):
319
moved_poly.append((p[0], p[1]))
320
pygame.draw.polygon(surface, self.inactive_colour,
322
if len(self._shape) > 0:
323
for x in self._shape:
325
for p in self.get_line_polygon(x):
326
moved_poly.append((p[0], p[1]))
327
pygame.draw.polygon(surface, self.colour, moved_poly, 0)
330
def get_line_points(self, idx):
331
"""Return point tuple including start and end point of a line.
340
points : ((int, int), (int,int))
341
point tuple including start and end point of a line
345
if idx == 0 or idx == 3 or idx == 6 : # horizontal line
346
p1 = copy.copy(self.points[self._lines[idx][0]])
347
p2 = copy.copy(self.points[self._lines[idx][1]])
348
p1.position[0] = p1.position[0] + self.gap
349
p2.position[0] = p2.position[0] - self.gap
350
return (p1.position, p2.position)
351
elif idx == 1 or idx == 2 or idx == 4 or idx == 5: # vertical line
352
p1 = copy.copy(self.points[self._lines[idx][0]])
353
p2 = copy.copy(self.points[self._lines[idx][1]])
354
p1.position[1] = p1.position[1] + self.gap
355
p2.position[1] = p2.position[1] - self.gap
356
return (p1.position, p2.position)
360
def get_line_polygon(self, idx):
361
"""Return point list describing the line as polygon.
366
index of the line (int)
370
point : list of tuple
373
if idx == 0 or idx == 3 or idx == 6 : # horizontal line
374
return self._line_to_polygon(self.points[self._lines[idx][0]], \
375
self.points[self._lines[idx][1]], True)
376
elif idx == 1 or idx == 2 or idx == 4 or idx == 5: # vertical line
377
return self._line_to_polygon(self.points[self._lines[idx][0]], \
378
self.points[self._lines[idx][1]], False)
382
def _line_to_polygon(self, start, end, horizontal):
383
"""Convert a line defined by start and end points to a polygon.
396
w2 = math.floor((self.line_width - 1) / 2)
400
poly.append(copy.copy(start.position))
401
p = PolygonDot(radius=0, position=(0, 0))
402
expyriment.stimuli._stimulus.Stimulus._id_counter -= 1
404
p.position[0] = start.position[0] + self.gap
405
p.position[1] = start.position[1] - w2
406
poly.append(copy.copy(p.position))
407
p.position[0] = end.position[0] - self.gap
408
poly.append(copy.copy(p.position))
409
poly.append(copy.copy(end.position))
410
p.position[0] = end.position[0] - self.gap
411
p.position[1] = end.position[1] + w2
412
poly.append(copy.copy(p.position))
413
p.position[0] = start.position[0] + self.gap
414
poly.append(copy.copy(p.position))
416
p.position[0] = start.position[0] + w2
417
p.position[1] = start.position[1] + self.gap
418
poly.append(copy.copy(p.position))
419
p.position[1] = end.position[1] - self.gap
420
poly.append(copy.copy(p.position))
421
poly.append(copy.copy(end.position))
422
p.position[0] = end.position[0] - w2
423
p.position[1] = end.position[1] - self.gap
424
poly.append(copy.copy(p.position))
425
p.position[1] = start.position[1] + self.gap
426
poly.append(copy.copy(p.position))
428
if self.simple_lines:
435
if __name__ == "__main__":
436
from expyriment import control
437
control.set_develop_mode(True)
438
defaults.event_logging = 0
439
exp = control.initialize()
440
lcdsymbol = LcdSymbol("A", size=(100, 100))