/
karik
/
tenth
Обзор
Документация
Войти
/
karik
/
tenth
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
10.py
275 строк
9 KB
karik
upload files
07 дек 2025, 14:13
07 дек 2025, 14:13
46a0594
Код
Авторство
О чём код?
import tkinter as tk # ===== ЛИНЕЙНАЯ ИНТЕРПОЛЯЦИЯ ===== def lerp(p0, p1, t): return ((1 - t) * p0[0] + t * p1[0], (1 - t) * p0[1] + t * p1[1]) # ===== АЛГОРИТМ ДЕ КАСТЕЛЬЖО ===== def de_casteljau(points, t): steps = [points] current = points while len(current) > 1: nxt = [] for i in range(len(current) - 1): nxt.append(lerp(current[i], current[i + 1], t)) steps.append(nxt) current = nxt return steps # ===== КРИВАЯ БЕЗЬЕ (любой степени) ===== def bezier_curve(points, samples): curve = [] for i in range(samples + 1): t = i / samples pts = points while len(pts) > 1: pts = [lerp(pts[j], pts[j + 1], t) for j in range(len(pts) - 1)] curve.append(pts[0]) return curve # ===== МЕТОД ЧАЙКИНА ===== def chaikin(points, iterations): for _ in range(iterations): new_points = [] for i in range(len(points) - 1): p0, p1 = points[i], points[i + 1] Q = (0.75 * p0[0] + 0.25 * p1[0], 0.75 * p0[1] + 0.25 * p1[1]) R = (0.25 * p0[0] + 0.75 * p1[0], 0.25 * p0[1] + 0.75 * p1[1]) new_points.extend([Q, R]) points = new_points return points # ===== РИСОВАНИЕ ===== def draw_poly(points, color="black"): for i in range(len(points) - 1): canvas.create_line(points[i][0], points[i][1], points[i + 1][0], points[i + 1][1], fill=color) def draw_point(p, color="red", text=None): x, y = p canvas.create_oval(x - 4, y - 4, x + 4, y + 4, fill=color, outline=color) if text: canvas.create_text(x + 10, y, text=text, fill=color) # ===== Добавление точки ===== def add_point(event): mode = mode_var.get() # Проверка ограничений для разных режимов if mode == "Quadratic" and len(points) >= 3: return # Не добавляем больше 3 точек для квадратичной elif mode == "Cubic" and len(points) >= 4: return # Не добавляем больше 4 точек для кубической points.append((event.x, event.y)) redraw() # ===== Очистка ===== def clear_points(): points.clear() redraw() # ===== Перерисовка ===== def redraw(): canvas.delete("all") if len(points) == 0: return mode = mode_var.get() if mode == "Bezier": draw_bezier() elif mode == "Cubic": draw_cubic_bezier() elif mode == "Quadratic": draw_quadratic_bezier() elif mode == "Chaikin": draw_chaikin_mode() # ===== Режим БЕЗЬЕ (общий случай) ===== def draw_bezier(): draw_poly(points, "gray") for i, p in enumerate(points): draw_point(p, color="blue", text=f"P{i}") t = t_slider.get() samples = segments_slider.get() steps = de_casteljau(points, t) for level in steps: draw_poly(level, "lightblue") for p in level: draw_point(p, color="black") final_p = steps[-1][0] draw_point(final_p, color="red", text="P(t)") curve = bezier_curve(points, samples) draw_poly(curve, "blue") # ===== Режим КУБИЧЕСКОЙ БЕЗЬЕ (строго 4 точки) ===== def draw_cubic_bezier(): # Используем первые 4 точки (или все, если меньше) cubic_points = points[:4] if len(points) >= 4 else points draw_poly(cubic_points, "gray") for i, p in enumerate(cubic_points): draw_point(p, color="darkorange", text=f"P{i}") # Показываем сообщение, если точек не 4 if len(points) != 4: canvas.create_text(450, 30, text=f"Кубическая кривая требует 4 точки (сейчас {len(points)})", font=("Arial", 14), fill="orange") t = t_slider.get() samples = segments_slider.get() if len(cubic_points) >= 2: steps = de_casteljau(cubic_points, t) for level in steps: draw_poly(level, "#FFCC99") # светлый оранжевый for p in level: draw_point(p, color="black") if steps: final_p = steps[-1][0] draw_point(final_p, color="red", text="P(t)") curve = bezier_curve(cubic_points, samples) draw_poly(curve, "darkorange",) # ===== Режим КВАДРАТИЧНОЙ БЕЗЬЕ ===== def draw_quadratic_bezier(): # Используем первые 3 точки (или все, если меньше) quad_points = points[:3] if len(points) >= 3 else points draw_poly(quad_points, "gray") for i, p in enumerate(quad_points): draw_point(p, color="green", text=f"P{i}") # Показываем сообщение, если точек не 3 if len(points) != 3: canvas.create_text(450, 30, text=f"Квадратичная кривая требует 3 точки (сейчас {len(points)})", font=("Arial", 14), fill="green") t = t_slider.get() samples = segments_slider.get() if len(quad_points) >= 2: steps = de_casteljau(quad_points, t) for level in steps: draw_poly(level, "lightgreen") for p in level: draw_point(p, color="black") if steps: final_p = steps[-1][0] draw_point(final_p, color="red", text="P(t)") curve = bezier_curve(quad_points, samples) draw_poly(curve, "green") # ===== Режим ЧАЙКИНА ===== def draw_chaikin_mode(): draw_poly(points, "gray") for i, p in enumerate(points): draw_point(p, color="purple", text=f"P{i}") it = chaikin_slider.get() curve = chaikin(points, it) draw_poly(curve, "purple") # ===== TKINTER GUI ===== root = tk.Tk() root.title("Bezier, Quadratic, Cubic, Chaikin — Вариант 6") canvas = tk.Canvas(root, width=900, height=600, bg="white") canvas.pack(side="left") controls = tk.Frame(root) controls.pack(side="right", fill="y", padx=10) points = [] canvas.bind("<Button-1>", add_point) tk.Button(controls, text="Очистить", command=clear_points, font=("Arial", 14)).pack(pady=10) # ===== Переключатель режима ===== mode_var = tk.StringVar(value="Bezier") tk.Label(controls, text="Тип кривой:", font=("Arial", 14)).pack() tk.Radiobutton(controls, text="Bezier (любая степень)", variable=mode_var, value="Bezier", command=redraw, font=("Arial", 12)).pack(anchor="w") tk.Radiobutton(controls, text="Cubic Bezier (4 точки)", variable=mode_var, value="Cubic", command=redraw, font=("Arial", 12)).pack(anchor="w") tk.Radiobutton(controls, text="Quadratic Bezier (3 точки)", variable=mode_var, value="Quadratic", command=redraw, font=("Arial", 12)).pack(anchor="w") tk.Radiobutton(controls, text="Chaikin", variable=mode_var, value="Chaikin", command=redraw, font=("Arial", 12)).pack(anchor="w") # ===== Параметры для Безье и квадратичной ===== tk.Label(controls, text="Параметр t", font=("Arial", 14)).pack() t_slider = tk.Scale(controls, from_=0, to=1, resolution=0.01, orient="horizontal", length=200, command=lambda v: redraw()) t_slider.set(0.5) t_slider.pack(pady=5) tk.Label(controls, text="Количество сегментов", font=("Arial", 14)).pack() segments_slider = tk.Scale(controls, from_=20, to=500, resolution=1, orient="horizontal", length=200, command=lambda v: redraw()) segments_slider.set(200) segments_slider.pack(pady=5) # ===== Параметры Чайкина ===== tk.Label(controls, text="Итерации Чайкина", font=("Arial", 14)).pack() chaikin_slider = tk.Scale(controls, from_=1, to=6, resolution=1, orient="horizontal", length=200, command=lambda v: redraw()) chaikin_slider.set(4) chaikin_slider.pack(pady=5) # ===== Информационная панель ===== info_label = tk.Label(controls, text="Кликайте на холст, чтобы добавить точки", font=("Arial", 10), fg="gray") info_label.pack(pady=10) root.mainloop()