zadanie1Analiza/main.py

103 lines
4.1 KiB
Python
Raw Normal View History

2024-10-23 21:31:03 +02:00
import matplotlib.pyplot as plt
import numpy as np
class Plot:
def __init__(self):
self.fig, self.ax = plt.subplots()
2024-10-26 18:56:21 +02:00
# Obsługa kliknięć myszą
2024-10-23 21:31:03 +02:00
self.cid_click = self.fig.canvas.mpl_connect('button_press_event', self.onclick)
self.cid_motion = self.fig.canvas.mpl_connect('motion_notify_event', self.on_mouse_move)
self.cid_release = self.fig.canvas.mpl_connect('button_release_event', self.on_release)
2024-10-26 18:56:21 +02:00
self.cid_key = self.fig.canvas.mpl_connect('key_press_event', self.on_key_press) # Obsługa klawiatury
2024-10-23 21:31:03 +02:00
2024-10-26 18:56:21 +02:00
# Ustawienia wykresu
2024-10-23 21:31:03 +02:00
plt.xlim(0, 800)
plt.ylim(0, 600)
plt.grid()
2024-10-26 18:56:21 +02:00
self.line = [] # Linia rysowana przez użytkownika
self.controlPoints = [] # Punkty kontrolne krzywej Béziera
self.approximation_points = [] # Punkty aproksymacji krzywej
self.isDrawing = False # Flaga rysowania
self.inputMode = 0 # Tryb wejścia: 0 - rysowanie linii, 1 - dodawanie punktów kontrolnych
def on_key_press(self, event):
"""Przełączanie trybu rysowania i dodawania punktów kontrolnych przy użyciu klawisza 'm'."""
if event.key == 'm':
self.inputMode = (self.inputMode + 1) % 2
mode = "Rysowanie linii" if self.inputMode == 0 else "Dodawanie punktów kontrolnych"
print(f"Tryb zmieniony na: {mode}")
2024-10-23 21:31:03 +02:00
def onclick(self, event):
2024-10-26 18:56:21 +02:00
# Tryb rysowania linii
2024-10-23 21:31:03 +02:00
if self.inputMode == 0:
self.isDrawing = True
2024-10-26 18:56:21 +02:00
# Tryb dodawania punktów kontrolnych
elif self.inputMode == 1 and len(self.controlPoints) < 15:
2024-10-23 21:31:03 +02:00
self.controlPoints.append((event.xdata, event.ydata))
2024-10-26 18:56:21 +02:00
# Automatyczna generacja segmentów krzywej Béziera po dodaniu nowych punktów
if len(self.controlPoints) >= 4:
self.generate_bezier_segments()
2024-10-23 21:31:03 +02:00
self.drawPlot()
def on_mouse_move(self, event):
if self.isDrawing:
self.line.append((event.xdata, event.ydata))
self.drawPlot()
def on_release(self, event):
2024-10-26 18:56:21 +02:00
# Zakończ rysowanie linii
2024-10-23 21:31:03 +02:00
if self.inputMode == 0:
self.isDrawing = False
2024-10-26 18:56:21 +02:00
def generate_bezier_segments(self):
"""Tworzy segmenty krzywej Béziera na podstawie punktów kontrolnych."""
self.approximation_points = []
# Dzielenie punktów kontrolnych na segmenty długości 4 (dla krzywej Béziera stopnia 3)
for i in range(0, len(self.controlPoints) - 3, 3):
segment = self.controlPoints[i:i + 4]
t_values = np.linspace(0, 1, num=100)
bezier_points = np.array([self.de_casteljau(segment, t) for t in t_values])
self.approximation_points.append(bezier_points)
2024-10-23 21:31:03 +02:00
def drawPlot(self):
self.ax.clear()
2024-10-26 18:56:21 +02:00
# Rysowanie linii narysowanej przez użytkownika
if len(self.line) > 1:
self.ax.plot(*zip(*self.line), color='red', label='Linia narysowana')
# Rysowanie punktów kontrolnych
2024-10-23 21:31:03 +02:00
if len(self.controlPoints) > 0:
self.ax.scatter(*zip(*self.controlPoints), color='black', label='Punkty kontrolne')
2024-10-26 18:56:21 +02:00
# Rysowanie segmentów krzywej Béziera (dodanie etykiety tylko raz)
first_segment = True
for segment in self.approximation_points:
if first_segment:
self.ax.plot(segment[:, 0], segment[:, 1], color='blue', label='Krzywa Béziera')
first_segment = False
else:
self.ax.plot(segment[:, 0], segment[:, 1], color='blue')
2024-10-23 21:31:03 +02:00
self.ax.legend()
self.ax.set_xlim(0, 800)
self.ax.set_ylim(0, 600)
self.ax.grid()
plt.draw()
2024-10-26 18:56:21 +02:00
def de_casteljau(self, points, t):
"""Oblicza punkt na krzywej Béziera za pomocą algorytmu de Casteljau dla danego t."""
points = np.array(points)
2024-10-23 21:31:03 +02:00
n = len(points)
for r in range(1, n):
for i in range(n - r):
points[i] = (1 - t) * points[i] + t * points[i + 1]
return points[0]
def run(self):
plt.show()
if __name__ == "__main__":
plot = Plot()
plot.run()