def make(self, n_dots, dot_radius, gap=0): """Make the cloud by randomly putting dots on it. Parameters ---------- n_dots : int number of dots to put into the cloud dot_radius : int radius of the dots gap : int, optional gap between dots (default = 0) """ top_left = dot_radius - self._radius bottom_right = self._radius - dot_radius remix = 0 while(True): #remix-loop self._cloud = [] remix = remix + 1 reps = 0 while(True): #find a solution dot = Dot(radius=dot_radius) expyriment.stimuli._stimulus.Stimulus._id_counter -= 1 dot.position = (random.randint(top_left, bottom_right), random.randint(top_left, bottom_right)) reps = reps + 1 if dot.is_inside(self.area): if not self._is_overlapping_with_point(dot, gap): self._cloud.append(dot) reps = 0 if reps > 10000: break if len(self._cloud) >= n_dots: self.clear_surface() return True if remix > 10: message = "Dotcloud make: Cannot find a solution." print("Warning: ", message) if self._logging: expyriment._active_exp._event_file_log(message) return False
def create_area(self): """Create the area of the cloud (a dot object itself).""" self._area = Dot(radius=self._radius, position=(0, 0), colour=self._background_colour) expyriment.stimuli._stimulus.Stimulus._id_counter -= 1 self._area._set_surface(pygame.surface.Surface( (self.radius * 2, self.radius * 2), pygame.SRCALPHA).convert_alpha()) if self._background_colour is not None: pygame.draw.circle(self._area._get_surface(), self._background_colour, (self._radius, self._radius), self._radius)
class DotCloud(Visual): """A dot cloud class. This class creates dots arranged in a circular cloud. """ def __init__(self, radius=None, position=None, background_colour=None, dot_colour=None): """Create a dot cloud. Parameters ---------- radius : int, optional radius of the cloud position : (int, int), optional position of the stimulus background_colour : (int, int, int), optional colour of the background dot_colour : (int, int, int), optional colour of the dots """ Visual.__init__(self, position) self._cloud = [] if radius is not None: self._radius = radius else: radius = defaults.dotcloud_radius if radius is None: try: self._radius = min( expyriment._active_exp.screen.surface.get_size()) / 2 except: raise RuntimeError("Could not get size of screen!") if background_colour is not None: self._background_colour = background_colour else: self._background_colour = \ defaults.dotcloud_background_colour if dot_colour is None: dot_colour = defaults.dotcloud_dot_colour if dot_colour is not None: self._dot_colour = dot_colour else: self._dot_colour = expyriment._active_exp.foreground_colour self.create_area() _getter_exception_message = "Cannot set {0} if surface exists!" @property def radius(self): """Getter for radius.""" return self._radius @radius.setter def radius(self, value): """Setter for radius.""" if self.has_surface: raise AttributeError(DotCloud._getter_exception_message.format( "radius")) else: self._radius = value self.create_area() @property def background_colour(self): """Getter for background_colour.""" return self._background_colour @background_colour.setter def background_colour(self, value): """Setter for background_colour.""" if self.has_surface: raise AttributeError(DotCloud._getter_exception_message.format( "background_colour")) else: self._background_colour = value self.create_area() @property def dot_colour(self): """Getter for dot_colour.""" return self._dot_colour @dot_colour.setter def dot_colour(self, value): """Setter for dot_colour.""" if self.has_surface: raise AttributeError(DotCloud._getter_exception_message.format( "dot_colour")) else: self._dot_colour = value self.create_area() @property def area(self): """Getter for area.""" return self._area def _create_surface(self): """Create the surface of the stimulus.""" surface = self.area._get_surface() for dot in self._cloud: dot.rect = pygame.Rect((0, 0), dot.surface_size) surface_size = surface.get_size() dot.rect.center = [dot.position[0] + surface_size[0] / 2, dot.position[1] + surface_size[1] / 2] surface.blit(dot._get_surface(), dot.rect) return surface def create_area(self): """Create the area of the cloud (a dot object itself).""" self._area = Dot(radius=self._radius, position=(0, 0), colour=self._background_colour) expyriment.stimuli._stimulus.Stimulus._id_counter -= 1 self._area._set_surface(pygame.surface.Surface( (self.radius * 2, self.radius * 2), pygame.SRCALPHA).convert_alpha()) if self._background_colour is not None: pygame.draw.circle(self._area._get_surface(), self._background_colour, (self._radius, self._radius), self._radius) def _is_overlapping_with_point(self, dot, gap): """Return True if a dot in the cloud is overlapping with another dot. Parameters ---------- dot : stimuli.dot the other dot gap : int constant added to the distance Returns ------- out : bool True if a dot in the cloud is overlapping with another dot """ for elem in self._cloud: d = elem.distance(dot) if d <= (elem.radius + dot.radius + gap): return True return False def make(self, n_dots, dot_radius, gap=0): """Make the cloud by randomly putting dots on it. Parameters ---------- n_dots : int number of dots to put into the cloud dot_radius : int radius of the dots gap : int, optional gap between dots (default = 0) """ top_left = dot_radius - self._radius bottom_right = self._radius - dot_radius remix = 0 while(True): #remix-loop self._cloud = [] remix = remix + 1 reps = 0 while(True): #find a solution dot = Dot(radius=dot_radius) expyriment.stimuli._stimulus.Stimulus._id_counter -= 1 dot.position = (random.randint(top_left, bottom_right), random.randint(top_left, bottom_right)) reps = reps + 1 if dot.is_inside(self.area): if not self._is_overlapping_with_point(dot, gap): self._cloud.append(dot) reps = 0 if reps > 10000: break if len(self._cloud) >= n_dots: self.clear_surface() return True if remix > 10: message = "Dotcloud make: Cannot find a solution." print("Warning: ", message) if self._logging: expyriment._active_exp._event_file_log(message) return False def shuffel_dot_sequence(self, from_idx=0, to_idx= -1): """Shuffle the dots sequence. Parameters ---------- from_idx : int, optional index to start from (default = 0) to_idx : int, optional index to end on (default = -1) """ if (from_idx < 0): from_idx = 0 if to_idx < from_idx or to_idx >= len(self._cloud): to_idx = len(self._cloud) - 1 for x in range(from_idx, to_idx) : r = random.randint(from_idx, to_idx) self._cloud[r], self._cloud[x] = self._cloud[x], self._cloud[r]