Source code for shapevolve.gene

"""A Gene class that defines the properties of a single shape on an image."""

from random import random, randint


[docs]class Gene: """A Gene class that defines the properties of a single shape on an image.""" def __init__(self, max_radius, min_radius, height, width, num_colors, radius=None, center=None, color=None, alpha=None): """Constructs a gene and its initial properties. :param max_radius: The maximum possible radius the gene can have. :param min_radius: The minimum possible radius the gene can have. :param height: The height of the image that the gene is drawing on. :param width: The width of the image that the gene is drawing on. :param num_colors: The number of colours the gene can have. :param radius: The current radius of the gene. :param center: The coordinates of the center of the gene's shape. :param color: The current color of the gene, as an index of an external color palette list. :param alpha: The current opacity of the gene, between 0 and 1. :type max_radius: int :type min_radius: int :type height: int :type width: int :type num_colors: int :type radius: int :type center: Tuple[int, int] :type color: int :type alpha: float """ self.max_radius = max_radius self.min_radius = min_radius self.height = height self.width = width self.num_colors = num_colors if radius is None: self.completely_randomize(initialization=True) # Randomize values at initialization. else: self.radius = radius self.center = center self.color = color self.alpha = alpha self.history = [radius, center, color, alpha]
[docs] def revert(self): """Reverts the gene's properties to before it was last modified.""" self.radius = self.history[0] self.center = self.history[1] self.color = self.history[2] self.alpha = self.history[3]
[docs] def completely_randomize(self, initialization=False): """Completely randomizes the properties of the gene. :param initialization: Whether this is being called from the constructor. :type initialization: bool """ self.randomize_radius() self.randomize_center() self.randomize_color() self.randomize_alpha() if initialization: self.history = [self.radius, self.center, self.color, self.alpha]
[docs] def mutate(self): """Mutates the gene randomly.""" # backup self.history = [self.radius, self.center, self.color, self.alpha] # Chances of altering the radius or alpha radius_alter = random() < 0.293 alpha_alter = random() < 0.293 # Whether an alteration still needs to be made no_alter = not (radius_alter or alpha_alter) # Mutate. if radius_alter: self.randomize_radius() if alpha_alter: self.randomize_alpha() if no_alter: self.completely_randomize()
[docs] def randomize_radius(self): """Randomizes the radius.""" self.radius = randint(self.min_radius, self.max_radius)
[docs] def randomize_center(self): """Randomizes the center of the shape.""" # The center can be a little bit outside the width and height of the image. self.center = (randint(0 - round(self.radius / 5), self.width + round(self.radius / 5)), randint(0 - round(self.radius / 5), self.height + round(self.radius / 5)))
[docs] def randomize_color(self): """Randomizes the color of the shape.""" self.color = randint(0, self.num_colors - 2) # The num_colors is off by one because of ColorThief.
[docs] def randomize_alpha(self): """Randomizes the opacity of the shape.""" self.alpha = random() * 0.45 + 0.05 # between 0.05 and 0.5
[docs] def get_scaled_version(self, ratio, fill_gaps): """Creates a scaled version of the gene, according to some ratio (original dimension / scaled dimension) :param ratio: (original dimension) / (scaled dimension) :param fill_gaps: Whether the radii should be slightly expanded so gaps don't form between shapes. :return: The scaled gene. :rtype: Gene """ radius_padding = 1 if fill_gaps else 0 new_radius = round((self.radius + radius_padding) / ratio) new_center = (round(self.center[0] / ratio), round(self.center[1] / ratio)) new_height = round(self.height / ratio) new_width = round(self.width / ratio) new_max_radius = round(self.max_radius / ratio) new_min_radius = round(self.min_radius / ratio) return Gene(new_max_radius, new_min_radius, new_height, new_width, self.num_colors, new_radius, new_center, self.color, self.alpha)
[docs] def clone(self): """Clones itself.""" return Gene(self.max_radius, self.min_radius, self.height, self.width, self.num_colors, self.radius, self.center, self.color, self.alpha)