diff --git a/main.py b/main.py index 42ae358..323f95f 100644 --- a/main.py +++ b/main.py @@ -5,25 +5,39 @@ class Plot: def __init__(self): self.fig, self.ax = plt.subplots() + # Obsługa kliknięć myszą 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) + self.cid_key = self.fig.canvas.mpl_connect('key_press_event', self.on_key_press) # Obsługa klawiatury + # Ustawienia wykresu plt.xlim(0, 800) plt.ylim(0, 600) plt.grid() - self.line = [] - self.controlPoints = [] - self.curvePoints = [] - self.isDrawing = False - self.inputMode = 0 - self.n = 15 + 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}") def onclick(self, event): + # Tryb rysowania linii if self.inputMode == 0: self.isDrawing = True - if self.inputMode == 1 and len(self.controlPoints) < self.n: + # Tryb dodawania punktów kontrolnych + elif self.inputMode == 1 and len(self.controlPoints) < 15: self.controlPoints.append((event.xdata, event.ydata)) + # Automatyczna generacja segmentów krzywej Béziera po dodaniu nowych punktów + if len(self.controlPoints) >= 4: + self.generate_bezier_segments() self.drawPlot() def on_mouse_move(self, event): @@ -32,28 +46,48 @@ class Plot: self.drawPlot() def on_release(self, event): + # Zakończ rysowanie linii if self.inputMode == 0: self.isDrawing = False - self.inputMode = 1 + + 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) def drawPlot(self): self.ax.clear() - self.ax.plot(*zip(*self.line), color='red', label='linia') + # 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 if len(self.controlPoints) > 0: self.ax.scatter(*zip(*self.controlPoints), color='black', label='Punkty kontrolne') - if len(self.controlPoints) >= self.n: - t_values = np.linspace(0, 1, num=100) - bezier_points = np.array([self.de_casteljau(t) for t in t_values]) - self.ax.plot(bezier_points[:, 0], bezier_points[:, 1], color='blue', label='Krzywa Béziera') - + + # 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') + self.ax.legend() self.ax.set_xlim(0, 800) self.ax.set_ylim(0, 600) self.ax.grid() plt.draw() - def de_casteljau(self, t): - points = np.array(self.controlPoints) + def de_casteljau(self, points, t): + """Oblicza punkt na krzywej Béziera za pomocą algorytmu de Casteljau dla danego t.""" + points = np.array(points) n = len(points) for r in range(1, n): for i in range(n - r): @@ -66,4 +100,3 @@ class Plot: if __name__ == "__main__": plot = Plot() plot.run() -