Поворот плоского объекта относительно произвольной точки плоскости на заданный угол
Автор: Рубцов Владислав • Октябрь 4, 2022 • Лабораторная работа • 2,764 Слов (12 Страниц) • 267 Просмотры
МИНОБРНАУКИ РОССИИ
САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ
ЭЛЕКТРОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ
«ЛЭТИ» ИМ. В.И. УЛЬЯНОВА (ЛЕНИНА)
Кафедра ИС
ОТЧЕТ
по лабораторной работе№1
по дисциплине «Компьютерная графика»
Тема: Поворот плоского объекта относительно произвольной точки плоскости на заданный угол.
Студенты гр. 9373 | _______________ | Рубцов В.Е. |
_______________ | Грачёва М.А. | |
_______________ | Вихрова Д.С. | |
Преподаватель | _______________ | Матвеева И.В. |
Санкт-Петербург
2022
Цель работы.
Поворот плоского объекта относительно заданной точки.
Задание на работу.
Разработать программу, выполняющее поворот плоской фигуры относительно заданной точки.
Требуется выполнить поворот объекта относительно точки. Это возможно сделать при помощи перемещения произвольной точки в начало координат, выполнения поворота, помещение результата обратно висходный центр вращения.
- Перенос произвольной точки в начало координат при помощи умножения на матрицу сдвига:
- Сдвиг координат:, где m, n–точка[pic 1]
- Поворот относительно точки m, n на заданный угол:
- Поворот: [pic 2]
- Возврат к исходному началу координат
- Возврат:[pic 3]
Поворот осуществляется последовательным перемножением матриц.
Выполнение работы.
Ссылка на видео с демонстрацией работы программы:
https://www.veed.io/view/d6f4e08b-9213-49ec-b5da-6455f990f040
Программа разработана на языке Python с использованием библиотеки tkinter.
Для выполнения программы необходимо ввести координаты точки, относительно которой осуществляется поворот, расстояние до объекта, угол поворотаи нажать кнопку «Поворот».
Для отображения поворота при изменении угла необходимо будет нажать кнопку “Повтор”.
Для выхода из программы необходимо нажать кнопку Esc.
На рис.1-3 представлены результаты выполнения работы программы.
[pic 4]
Рисунок 1 – Поворот на 115 градусов
[pic 5]
Рисунок 2 – Поворот на 0 градусов
[pic 6]
Рисунок 3 – Поворот на 245 градусов
Выводы.
В данной лабораторной работе был рассмотрен и реализован поворот плоской фигуры (треугольника) относительно произвольно заданной точки.
ПРИЛОЖЕНИЕ А
Файл «main.py»
import tkinter as tk
from tkinter import *
from tkinter.messagebox import showerror
import numpy as np
import math
from math import cos, sin
import cmath
import random
def get_intersections(x0, y0, r0, x1, y1, r1):
# circle 1: (x0, y0), radius r0
# circle 2: (x1, y1), radius r1
x0, y0, r0, x1, y1, r1 = float(x0), float(y0), float(r0), float(x1), float(y1), float(r1)
# print(x0, y0, r0, x1, y1, r1)
d = math.sqrt((x1 - x0) ** 2 + (y1 - y0) ** 2)
a = (r0 ** 2 - r1 ** 2 + d ** 2) / (2 * d)
# print(r0 ** 2, a)
h = cmath.sqrt(r0 ** 2 - a ** 2)
x2 = x0 + a * (x1 - x0) / d
y2 = y0 + a * (y1 - y0) / d
x3 = x2 + h * (y1 - y0) / d
y3 = y2 - h * (x1 - x0) / d
x4 = x2 - h * (y1 - y0) / d
y4 = y2 + h * (x1 - x0) / d
return [x3, y3]
class Gui:
def __init__(self, root):
self.root = root
self.X_value = tk.StringVar()
self.X_value.set("0")
self.Y_value = tk.StringVar()
self.Y_value.set("0")
self.distance_value = tk.StringVar()
self.distance_value.set("24")
self.a_value = tk.StringVar()
self.a_value.set("30")
self.b_value = tk.StringVar()
self.b_value.set("40")
self.c_value = tk.StringVar()
self.c_value.set("50")
self.teta_value = tk.StringVar()
self.teta_value.set("0")
z = [0] * 2
self.point1 = z
self.point2 = z
self.point3 = z
temp = tk.Tk()
self.WIDTH = temp.winfo_screenwidth()
self.HEIGHT = temp.winfo_screenheight()
temp.destroy()
self.canvas = tk.Canvas(root, width=self.WIDTH - 400, height=self.HEIGHT - 200, background='white', bd=0)
self.canvas.grid(row=0, column=1)
self.canvas.create_line(-self.WIDTH, 0, self.WIDTH, 0, fill="black", width=1)
self.canvas.create_line(0, -self.HEIGHT, 0, self.HEIGHT, fill="black", width=1)
zeros = [0] * 4
self.line1 = self.canvas.create_line(220, -20, 220, 10, width=3)
self.line2 = self.canvas.create_line(220, 10, 260, -20, width=3)
self.line3 = self.canvas.create_line(260, -20, 220, -20, width=3)
self.point_of_rotation = self.canvas.create_oval(-3, -3, 3, 3, width=1, fill="red")
self.canvas.configure(scrollregion=(int(-(self.WIDTH - 400) / 2) + 2, int(-(self.HEIGHT - 200) / 2) + 1, 0, 0))
# self.canvas.xview_moveto(.5)
# self.canvas.yview_moveto(.5)
# self.canvas.pack(fill="both", expand=True)
frame = Frame(self.root)
frame["border"] = 5
frame['relief'] = 'groove'
frame.grid(row=0, column=0, sticky="n")
self.canvas.bind('<ButtonPress-1>', self.set_coords)
# self.root.bind('<Esc>',
# self.option = tk.OptionMenu(frame, stvar, "one", "two", "three")
label_point = Label(frame, text=" Координаты точки:").grid(row=0, column=0, sticky="nw", padx=20)
label_point_X = Label(frame, text="X:").grid(row=1, column=0, sticky="w", padx=40)
label_point_Y = Label(frame, text="Y:").grid(row=1, column=0, sticky="e", padx=65)
label_distance = Label(frame, text=" Расстояние:").grid(row=4, column=0, sticky="nw", padx=20)
label_r = Label(frame, text="r:").grid(row=5, column=0, sticky="w", padx=40)
label_triangle = Label(frame, text=" Стороны треугольника:").grid(row=6, column=0, sticky="nw", padx=20)
label_a = Label(frame, text="a:").grid(row=7, column=0, sticky="w", padx=40)
label_b = Label(frame, text="b:").grid(row=8, column=0, sticky="w", padx=40)
label_c = Label(frame, text="c:").grid(row=9, column=0, sticky="w", padx=40)
label_angle = Label(frame, text=" Угол (град.):").grid(row=11, column=0, sticky="nw", padx=20)
label_degree = Label(frame, text="\u0398").grid(row=12, column=0, sticky="w", padx=40)
# self.option.grid(row=0, column=1, sticky="nwe")
entry_point_x = Entry(frame, width=5, textvariable=self.X_value).grid(row=1, column=0, sticky=W, padx=62)
entry_point_y = Entry(frame, width=5, textvariable=self.Y_value).grid(row=1, column=0, sticky=E, padx=10)
entry_distance = Entry(frame, width=7, textvariable=self.distance_value).grid(row=5, column=0, sticky=W,
padx=62)
entry_a = Entry(frame, width=5, textvariable=self.a_value).grid(row=7, column=0, sticky=W, padx=62)
entry_b = Entry(frame, width=5, textvariable=self.b_value).grid(row=8, column=0, sticky=W, padx=62)
entry_c = Entry(frame, width=5, textvariable=self.c_value).grid(row=9, column=0, sticky=W, padx=62)
entry_degree = Entry(frame, width=5, textvariable=self.teta_value).grid(row=12, column=0, sticky=W, padx=62)
button_draw_point = Button(frame, text="Отрисовать", command=self.new_coords, height=1, width=10,
highlightcolor="darkgrey", border=5).grid(row=1, column=1,
sticky="we")
button_draw_rotation = Button(frame, text="Поворот", command=self.rotation, height=1, width=10,
highlightcolor="darkgrey", border=5).grid(row=12, column=1,
sticky="we")
button_draw_triangle = Button(frame, text="Отрисовать", command=self.draw_triangle, height=1, width=10,
highlightcolor="darkgrey", border=5).grid(row=5, column=1,
sticky="we")
# figure1 = self.canvas.create_rectangle(80, 80, 120, 120, fill="blue")
def new_coords(self):
x = int(float(self.X_value.get()))
y = int(float(self.Y_value.get()))
reversed_y = -y
self.canvas.coords(self.point_of_rotation, x - 3, reversed_y - 3, x + 3, reversed_y + 3)
def set_coords(self, e):
x = int((e.x - (self.WIDTH - 400) / 2))
y = int(-(e.y - (self.HEIGHT - 200) / 2))
reversed_y = -y
self.canvas.coords(self.point_of_rotation, x - 3, reversed_y - 3, x + 3, reversed_y + 3)
self.X_value.set(str(x))
self.Y_value.set(str(y))
def check_triangle(self, a, b, c):
if a + b > c and b + c > a and c + a > b:
return True
else:
return False
@staticmethod
def rot(a, b):
print(a, b)
a_len = len(a)
a_row_l = len(a[0])
res = a.copy()*0
for k in range(a_len):
for i in range(a_len):
for j in range(a_row_l):
res[k][i] = res[k][i] + a[k][j] * b[j][i]
return res[:, :2]
def rotation(self):
self.draw_triangle
m = float(self.X_value.get())
n = float(self.Y_value.get())
print("m, n", m, n)
deg = int(self.teta_value.get())
print("deg", deg)
x = deg*math.pi / 180
# print(np.array(self.point1),np.array(self.point1),np.array(self.point1))
points = np.array([[self.point1[0]] + [-(self.point1[1])] + [1],
[self.point2[0]] + [-(self.point2[1])] + [1],
[self.point3[0]] + [-(self.point3[1])] + [1]])
print(x)
# print()
print(points)
vec1 = np.array([[cos(x), sin(x), 0],
[-sin(x), cos(x), 0],
[-m * (cos(x) - 1) + n * sin(x), -n * (cos(x) - 1) - m * sin(x), 1]])
res = self.rot(points, vec1)
print(vec1)
# res = np.matmul(points, vec1)
print(res)
point1 = res[0, :2]
point2 = res[1, :2]
point3 = res[2, :2]
# print(point1)
l1 = np.concatenate([point1, point2])
l2 = np.concatenate([point2, point3])
l3 = np.concatenate([point3, point1])
print(l1)
self.canvas.coords(self.line1, [l1[0], -l1[1], l1[2], -l1[3]])
self.canvas.coords(self.line2, [l2[0], -l2[1], l2[2], -l2[3]])
self.canvas.coords(self.line3, [l3[0], -l3[1], l3[2], -l3[3]])
# self.canvas.coords(self.line1, l1)
# self.canvas.coords(self.line2, l2)
# self.canvas.coords(self.line3, l3)
# print(res)
def draw_triangle(self):
x = float(self.X_value.get())
y = float(self.Y_value.get())
# print("Y val = ", y)
y_reversed = float(-y)
# print(y_reversed)
a = float(self.a_value.get())
b = float(self.b_value.get())
c = float(self.c_value.get())
# print(a, b ,c)
if self.check_triangle(a, b, c):
dist = int(self.distance_value.get())
point1 = [float(x) + dist, float(y_reversed)]
point2 = [float(x) + dist, float(y_reversed + a)]
point3 = get_intersections(point1[0], point1[1], b, point2[0], point2[1], c)
# print(point1[0], point1[1], c, point2[0], point2[1], b)
point3[0], point3[1] = round(point3[0].real, 2) , \
round(point3[1].real, 2)
self.point1 = point1
self.point2 = point2
self.point3 = point3
l1 = point1 + point2
l2 = point2 + point3
l3 = point3 + point1
# print(l1, l2, l3)
self.canvas.coords(self.line1, l1)
self.canvas.coords(self.line2, l2)
self.canvas.coords(self.line3, l3)
else:
tk.messagebox.showerror(title="Некорректные значения", message="Сумма двух сторон меньше третьей")
if __name__ == '__main__':
app = tk.Tk()
screen_width = app.winfo_screenwidth()
screen_height = app.winfo_screenheight()
# root.configure(background='grey')
app.geometry(f"{screen_width - 100}x{screen_height - 150}+{50}+{50}")
gui = Gui(app)
app.mainloop()
...