This repository has been archived on 2025-05-08. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
Fractals/flowsnake.py
2019-04-08 17:24:02 +02:00

124 lines
3.8 KiB
Python

from typing import List
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from vector import *
FS_VECTOR = Vector(1, 0) + Vector(1, -60) + Vector(1, -180) + Vector(1, -120) + Vector(2, 0) + Vector(1, 60)
class Line:
def __init__(self, vector: Vector, variant: bool):
self.vector = vector
self.variant = variant
def flowsnake(self) -> list:
out = []
d = self.vector.distance / FS_VECTOR.distance
a = (self.vector.angle - FS_VECTOR.angle) % 360
if self.variant:
out.append(Line(Vector(d, a), True))
a -= 60
out.append(Line(Vector(d, a), False))
a -= 120
out.append(Line(Vector(d, a), False))
a += 60
out.append(Line(Vector(d, a), self.variant))
a += 120
out.append(Line(Vector(d, a), True))
out.append(Line(Vector(d, a), True))
a += 60
out.append(Line(Vector(d, a), False))
else:
a += 60
out.append(Line(Vector(d, a), True))
a -= 60
out.append(Line(Vector(d, a), False))
out.append(Line(Vector(d, a), False))
a -= 120
out.append(Line(Vector(d, a), self.variant))
a -= 60
out.append(Line(Vector(d, a), True))
a += 120
out.append(Line(Vector(d, a), True))
a += 60
out.append(Line(Vector(d, a), False))
return out
class FlowSnake(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Flow Snake - Iteration 0")
self.setFixedSize(600, 600)
self.iterations = [[Line(Vector(480, FS_VECTOR.angle + 90), True)]]
self.current_iteration = 0
self.points = []
self.prepare_drawing()
self.show()
def keyPressEvent(self, e: QKeyEvent):
if e.key() == Qt.Key_Q:
self.close()
elif e.key() == Qt.Key_Right:
if self.current_iteration < 7:
self.current_iteration += 1
if len(self.iterations) <= self.current_iteration:
self.iterations.append(self.flowsnake(self.iterations[-1]))
self.prepare_drawing()
self.setWindowTitle(f"Flow Snake - Iteration {self.current_iteration}")
self.repaint()
elif e.key() == Qt.Key_Left:
if self.current_iteration > 0:
self.current_iteration -= 1
self.setWindowTitle(f"Flow Snake - Iteration {self.current_iteration}")
self.repaint()
@staticmethod
def flowsnake(fs: List[Line]) -> List[Line]:
out = []
for line in fs:
out += line.flowsnake()
return out
def prepare_drawing(self):
lines = self.iterations[self.current_iteration]
p = Point(0, 0)
minx, miny = maxx, maxy = p
points = [p]
for line in lines:
p += line.vector.to_point()
minx = min(p.x, minx)
miny = min(p.y, miny)
maxx = max(p.x, maxx)
maxy = max(p.y, maxy)
points.append(p)
midpoint = Point((maxx + minx) / 2, (maxy + miny) / 2)
midpoint = Point(self.width() / 2, self.height() / 2) - midpoint
self.points.append([p + midpoint for p in points])
def paintEvent(self, e: QPaintEvent):
qp = QPainter(self)
qp.setPen(Qt.white)
qp.setBrush(Qt.white)
qp.drawRect(self.rect())
qp.setPen(QPen(Qt.black, 1))
points = self.points[self.current_iteration]
for p1, p2 in zip(points[:-1], points[1:]):
qp.drawLine(*p1, *p2)
if __name__ == '__main__':
app = QApplication([])
flowsnake = FlowSnake()
app.exec_()