import math from typing import List, Tuple from PySide6.QtCore import Qt from PySide6.QtGui import QBrush, QPainter from PySide6.QtWidgets import QGraphicsItemGroup from PySide6.QtWidgets import ( QStyleOptionGraphicsItem, QWidget, ) from grid.ui.items import ( HPSphereGraphicsItem, ArcGraphicsItem, LineGraphicsItem, random_sphere_factory, ) class Pattern(QGraphicsItemGroup): PATTERN_WIDTH = 0 SPACE_BETWEEN_SPHERE = 60 def __init__(self, top_left_corner_x: int, top_left_corner_y: int) -> None: super().__init__() self.top_left_corner_x = top_left_corner_x self.top_left_corner_y = top_left_corner_y # center coordinates of the pattern self.center_x = top_left_corner_x + int(self.PATTERN_WIDTH / 2) self.center_y = top_left_corner_y + int(self.PATTERN_WIDTH / 2) def paint( self, painter: QPainter, option: QStyleOptionGraphicsItem, widget: QWidget | None = ..., ): super().paint(painter, option, widget) brush = QBrush(Qt.GlobalColor.gray) painter.setBrush(brush) painter.drawRect( self.top_left_corner_x, self.top_left_corner_y, self.PATTERN_WIDTH, self.PATTERN_WIDTH, ) @staticmethod def generate_circle_points( center_x: int, center_y: int, radius: int, n_points: int ) -> List[Tuple[int, int]]: """generate coordinates of points on a circle equally spaced Args: self.center_x (int): center x coordinate self.center_y (int): center y coordinate radius (int): circle radius n_points (int): number of points on the circle to generate Returns: List[Tuple[int, int]]: list of points coordinates, (x,y) """ points = [] angle_step = 2 * math.pi / n_points for i in range(n_points): theta = i * angle_step x = int(center_x + radius * math.cos(theta)) y = int(center_y + radius * math.sin(theta)) points.append((x, y)) return points class LargeUltimaPattern(Pattern): """Common pattern on the sphere grid""" PATTERN_WIDTH = 350 def __init__(self, top_left_corner_x: int, top_left_corner_y: int) -> None: super().__init__(top_left_corner_x, top_left_corner_y) # center line_start_x = self.center_x line_start_y = self.center_y line_end_x = self.center_x line_end_y = int(self.center_y + self.SPACE_BETWEEN_SPHERE) self.addToGroup( LineGraphicsItem(line_start_x, line_start_y, line_end_x, line_end_y, self) ) line_start_x = self.center_x line_start_y = top_left_corner_y + self.SPACE_BETWEEN_SPHERE line_end_x = self.center_x line_end_y = line_start_y + self.SPACE_BETWEEN_SPHERE self.addToGroup( LineGraphicsItem(line_start_x, line_start_y, line_end_x, line_end_y, self) ) self.addToGroup(HPSphereGraphicsItem(self.center_x, self.center_y)) # first cercle sphere_on_circle = 4 for i in range(sphere_on_circle): self.addToGroup( ArcGraphicsItem( x_pos=self.center_x, y_pos=self.center_y, width=self.SPACE_BETWEEN_SPHERE * 2, angle_start=(i * 360 / sphere_on_circle) % 360, #angle_end=((i + 1) * 360 / sphere_on_circle) % 360, angle_end=(360 / sphere_on_circle ), parent=self, ) ) points = self.generate_circle_points( self.center_x, self.center_y, self.SPACE_BETWEEN_SPHERE, sphere_on_circle ) for x, y in points: self.addToGroup(random_sphere_factory(x, y)) # second cercle sphere_on_circle = 8 points = self.generate_circle_points( self.center_x, self.center_y, self.SPACE_BETWEEN_SPHERE * 2, sphere_on_circle, ) for i in range(sphere_on_circle): self.addToGroup( ArcGraphicsItem( x_pos=self.center_x, y_pos=self.center_y, width=self.SPACE_BETWEEN_SPHERE * 4, angle_start=int(i * 360 / sphere_on_circle) % 360, angle_end=int((i + 1) * 360 / sphere_on_circle) % 360, parent=self, ) ) for x, y in points: self.addToGroup(random_sphere_factory(x, y)) # self.addToGroup( # ArcGraphicsItem( # self.center_x, self.center_y, self.SPACE_BETWEEN_SPHERE * 2, 0, 90, self # ) # ) class SmallZPattern(Pattern): """Small pattern used in the sphere grid""" PATTERN_WIDTH = 200 def __init__(self, top_left_corner_x: int, top_left_corner_y: int) -> None: super().__init__(top_left_corner_x, top_left_corner_y) sphere_on_circle = 6 for i in range(sphere_on_circle): if i == 2 or i == 3: continue else: self.addToGroup( ArcGraphicsItem( x_pos=self.center_x, y_pos=self.center_y, width=self.SPACE_BETWEEN_SPHERE * 2, angle_start=(i * 360 / sphere_on_circle) % 360, angle_end=int((i + 1) * 360 / sphere_on_circle) % 360, parent=self, ) ) points = self.generate_circle_points( self.center_x, self.center_y, self.SPACE_BETWEEN_SPHERE, sphere_on_circle ) # Remove left and right sphere del points[0] del points[2] for x, y in points: self.addToGroup(random_sphere_factory(x, y))