diff options
| author | Andrew <saintruler@gmail.com> | 2021-04-10 00:41:01 +0400 |
|---|---|---|
| committer | Andrew <saintruler@gmail.com> | 2021-04-10 00:41:01 +0400 |
| commit | ffe4cbeb66522b83375cc92f3cd7cd254f88a5f4 (patch) | |
| tree | d172f23561f16aa1578b2e77b918b8811febf19f | |
| parent | 95d8ed3af9f069620896d65ad24f64770611ffb1 (diff) | |
Added ellipse main file
| -rw-r--r-- | ellipse/main.py | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/ellipse/main.py b/ellipse/main.py new file mode 100644 index 0000000..93af34e --- /dev/null +++ b/ellipse/main.py @@ -0,0 +1,286 @@ +from pygame.locals import * +import pygame +from pygame.math import Vector2 + +import math +from math import sin, cos, pi, sqrt +import time + + +def screen2local(x, y): + nx = x - WIDTH / 2 + ny = HEIGHT / 2 - y + return (nx, ny) + + +def local2screen(x, y): + nx = x + WIDTH / 2 + ny = HEIGHT / 2 - y + return (nx, ny) + + +class Ellipse: + def __init__(self, a, b): + self.a = a + self.b = b + + self.c = sqrt(self.a * self.a - self.b * self.b) + # self.f1 = local2screen(self.c, 0) + # self.f2 = local2screen(-self.c, 0) + self.f1 = (self.c, 0) + self.f2 = (-self.c, 0) + + def draw(self, deltatime, screen, cx, cy): + cnt = 0 + for i in range(0, int(2 * pi * 100) + 1): + cnt += 1 + t = i / 100 + t1 = t + 1 / 100 + + # Координаты в локальном пространстве + x = self.a * cos(t) + y = self.b * sin(t) + x1 = self.a * cos(t1) + y1 = self.b * sin(t1) + + start = local2screen(x, y) + end = local2screen(x1, y1) + + pygame.draw.line(screen, WHITE, start, end, 2) + + pygame.draw.circle(screen, WHITE, local2screen(*self.f1), 3) + pygame.draw.circle(screen, WHITE, local2screen(*self.f2), 3) + + +class NiceEllipse: + def __init__(self, a, b): + self.a = a + self.b = b + + self.time = 0 + self.timeout = 700 + self.i = 0 + self.lines = [] + + self.c = sqrt(self.a * self.a - self.b * self.b) + self.f1 = local2screen(self.c, 0) + self.f2 = local2screen(-self.c, 0) + + self.lastend = None + + def draw(self, deltatime, screen, cx, cy): + print(deltatime) + for start, end in self.lines: + pygame.draw.line(screen, WHITE, start, end, 2) + + pygame.draw.circle(screen, WHITE, self.f1, 3) + pygame.draw.circle(screen, WHITE, self.f2, 3) + + if self.lastend is not None: + pygame.draw.line(screen, RED, self.f1, self.lastend, 2) + pygame.draw.line(screen, GREEN, self.f2, self.lastend, 2) + + if self.i >= int(2 * pi * 100) + 1: + self.lastend = None + return + + if self.time > 0: + self.time -= deltatime + return + + self.time = self.timeout + + t = self.i / 100 + t1 = t + 1 / 100 + self.i += 1 + + # Координаты в локальном пространстве + x = self.a * cos(t) + y = self.b * sin(t) + x1 = self.a * cos(t1) + y1 = self.b * sin(t1) + + start = local2screen(x, y) + end = local2screen(x1, y1) + self.lastend = end + + self.lines.append((start, end)) + + pygame.draw.line(screen, WHITE, start, end, 2) + + +class ScreenRay: + def __init__(self, a: Vector2, b: Vector2, speed: float): + # self.a = a + # self.b = b + self.pos = a + self.dir = Vector2(b.x - a.x, b.y - a.y) + self.dir.normalize_ip() + self.speed = speed + + def update(self, deltatime): + n_pos = self.pos + self.dir * (deltatime * self.speed) + + scr = Vector2(*local2screen(*tuple(self.pos))) + scr_npos = Vector2(*local2screen(*tuple(n_pos))) + + if scr_npos.x < 0: + self.dir = Vector2(-self.dir.x, self.dir.y) + n_pos = Vector2(*screen2local(0, scr.y)) + elif scr_npos.x > WIDTH: + self.dir = Vector2(-self.dir.x, self.dir.y) + n_pos = Vector2(*screen2local(WIDTH, scr.y)) + elif scr_npos.y < 0: + self.dir = Vector2(self.dir.x, -self.dir.y) + n_pos = Vector2(*screen2local(scr.x, 0)) + elif scr_npos.y > HEIGHT: + self.dir = Vector2(self.dir.x, -self.dir.y) + n_pos = Vector2(*screen2local(scr.x, HEIGHT)) + + self.pos = n_pos + + +class EllipseRay: + def __init__(self, s: Vector2, e: Vector2, speed: float, el): + self.a = el.a + self.b = el.b + self.pos = e + self.dir = Vector2(e.x - s.x, e.y - s.y) + self.dir.normalize_ip() + self.speed = speed + + def eps(self, x, y): + a = self.a + b = self.b + tmp = (x * x) / (a * a) + (y * y) / (b * b) + e = 0.05 + return tmp < 1 + e and tmp > 1 - e + + def update(self, deltatime): + npos = self.pos + self.dir * (deltatime * self.speed) + + scr = Vector2(*local2screen(*tuple(self.pos))) + scr_npos = Vector2(*local2screen(*tuple(npos))) + + p0 = self.pos + + ######################## + # Отражение от эллипса # + ######################## + + if p0.y == 0: + if p0.x < 0: + self.dir.reflect_ip(Vector2(-1, 0)) + else: + self.dir.reflect_ip(Vector2(1, 0)) + else: + t = 1 + m = 1 + n = -(p0.x * self.b * self.b) / (p0.y * self.a * self.a) + p1 = Vector2(p0.x + m * t, p0.y + n * t) + + kas = Vector2(p1.x - p0.x, p1.y - p0.y) + kas.normalize_ip() + # angle = kas.angle_to(self.dir) + + kas_p = Vector2(1, -kas.x / kas.y) + kas_p.normalize_ip() + + if self.eps(npos.x, npos.y): + self.dir.reflect_ip(kas_p) + + ######################## + + self.pos = npos + + + def draw(self, screen): + loc = tuple(self.pos) + scr = local2screen(*loc) + pygame.draw.circle(screen, RED, scr, 3) + + + +class Ray1Ellipse: + def __init__(self, a, b): + self.a = a + self.b = b + + def draw(self, deltatime, screen, cx, cy): + cnt = 0 + for i in range(0, int(2 * pi * 100) + 1): + cnt += 1 + t = i / 100 + t1 = t + 1 / 100 + + # Координаты в локальном пространстве + x = self.a * cos(t) + y = self.b * sin(t) + x1 = self.a * cos(t1) + y1 = self.b * sin(t1) + + start = local2screen(x, y) + end = local2screen(x1, y1) + + pygame.draw.line(screen, WHITE, start, end, 2) + + c = sqrt(self.a * self.a - self.b * self.b) + f1 = local2screen(c, 0) + f2 = local2screen(-c, 0) + + pygame.draw.circle(screen, WHITE, f1, 3) + pygame.draw.circle(screen, WHITE, f2, 3) + + +pygame.init() + +WIDTH, HEIGHT = SIZE = 800, 600 + +screen = pygame.display.set_mode(SIZE) + +clock = pygame.time.Clock() +running = True + +BLACK = Color("black") +WHITE = Color("white") +GREEN = Color("green") +RED = Color("red") + +el = Ellipse(300, 200) + +rays = [] +nn = 10 +for i in range(1, nn + 1): + x0, y0 = el.f2 + xr = cos(2 * pi * i / nn) + x0 + yr = sin(2 * pi * i / nn) + y0 + r = EllipseRay(Vector2(x0, y0), Vector2(xr, yr), 70, el) + rays.append(r) + +# deltatime = pygame.time.get_ticks() + +while running: + screen.fill(BLACK) + + deltatime = clock.get_time() / 1000 + + for r in rays: + r.update(deltatime) + r.draw(screen) + el.draw(deltatime, screen, 0, 0) + + # ... + + pygame.display.flip() + + for event in pygame.event.get(): + if event.type == QUIT: + pygame.quit() + exit() + elif event.type == KEYDOWN: + if event.key == K_ESCAPE: + pygame.quit() + exit() + clock.tick(60) + # deltatime = pygame.time.get_ticks() - deltatime + # print(clock.get_fps()) |