Files
sphere-grid/grid/ui/pattern.py

185 lines
5.9 KiB
Python

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))