Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

КомпГр_ЛР5_Заболотников_Петрова_Романова_9373

.pdf
Скачиваний:
24
Добавлен:
20.06.2023
Размер:
683.03 Кб
Скачать

МИНОБРНАУКИ РОССИИ САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ ЭЛЕКТРОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ «ЛЭТИ» ИМ. В.И. УЛЬЯНОВА (ЛЕНИНА) Кафедра информационных систем

ОТЧЕТ по лабораторной работе№5

по дисциплине «Компьютерная графика» Тема: Исследование алгоритмов выявления видимости сложных сцен

Студент гр. 9373

_______________

Заболотников М. Е.

Студентка гр. 9373

_______________

Петрова С. В.

Студентка гр. 9373

_______________

Романова Е. С.

Преподаватель

_______________

Матвеева И.В.

Санкт-Петербург

2022

Цель работы.

Обеспечить реализацию алгоритма выявления видимых граней и ребер для одиночного выпуклого объемного тела.

Задание на работу.

Необходимо написать программу, которая убирает невидимые грани у одиночного выпуклого тела, в данном случае у правильного параллелепипеда.

Общие сведения.

Для выполнения работы потребовались следующие теоретические

сведения.

Матрицы поворотов вокруг осей на угол :

1

0

0

1) Вокруг оси OX: |0

 

−|

0

 

 

 

 

0

 

2)

Вокруг оси OY: | 0

1

 

0 |

 

0

 

 

 

0

3)

Вокруг оси OZ: |

 

0|

 

0

0

 

1

В математике перекрестное произведение или векторное произведение представляет собой двоичную операцию над двумя векторами в трехмерном ориентированном евклидовом векторном пространстве. Учитывая два линейно независимых вектора a и b, перекрестное произведение, a × b (читается "a cross b") является вектором, который перпендикулярен как a, так и b, и, следовательно, перпендикулярен плоскости, содержащей их. Он имеет множество применений в математике, физике, инженерии и компьютерном программировании.

Если два вектора имеют одинаковое направление или имеют прямо противоположное направление друг от друга (то есть они не являются линейно независимыми), или если любой из них имеет нулевую длину, то их

2

перекрестное произведение равно нулю. В более общем смысле величина произведения равна площади параллелограмма с векторами сторон; в

частности, величина произведения двух перпендикулярных векторов равна произведению их длин.

Ход работы.

Рассмотрим работу программы, которая заключается вызове функции,

отвечающей за поворот фигуры и функции для проверки невидимости граней одиночного выпуклого объемного тела.

Выполнение работы.

Ссылка на видео с демонстрацией работы программы: https://www.youtube.com/watch?v=CVsyEPP7_T0

Программа была написана в приложении Jupiter на языке Python с

использованием графических библиотек.

Для работы с программой необходимо указать углы поворота по оси и нажать на «Отобразить». Сбоку появится правильный параллелепипед,

повернутый на указанный угол с видимыми ребрами.

Тесты работы программы.

На рис.1 – 4 представлены результаты выполнения работы программы:

Рисунок 1 – Вращение фигуры (1 часть)

3

Рисунок 2 – Вращение фигуры (2 часть)

Рисунок 3 – Вращение фигуры (3 часть)

Рисунок 4 – Вращение фигуры (4 часть)

4

Выводы.

В данной работе была обеспечена реализация алгоритма выявления видимых граней и ребер для одиночного выпуклого объемного тела. Для демонстрации корректности работы программы реализован поворот рассматриваемого тела вокруг осей OX, OY и OZ.

5

ПРИЛОЖЕНИЕ А Файл «Komp_GR.ipynb»

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

points = [(100,200,0),( 200,200,0), (200,0,0),(100,0,0), (100,200,100),( 200,200,100), (200,0,100),(100,0,100)]

points_2d = [(100,200),( 200,200), (200,0),(100,0), (100,200),( 200,200), (200,0),(100,0)]

faces = [(0,1,2,3),(5,4,7,6),(4,0,3,7),(1,5,6,2),(4,5,1,0),(3,2,6,7)] def rot(a, b):

a_len = 3 a_row_l = 3

res = a.copy()*0 res[0]=a[0]*b[0,0]+a[1]*b[1,0]+a[2]*b[2,0] res[1]=a[0]*b[0,1]+a[1]*b[1,1]+a[2]*b[2,1] res[2]=a[0]*b[0,2]+a[1]*b[1,2]+a[2]*b[2,2] return res

def rotation(self,p):

(x, y, z) = (p[0], p[1], p[2]) Temp_matrix = np.empty((1, 3)) angle_x = int(self.X_value.get()) angle_y = int(self.Y_value.get()) angle_z= int(self.Z_value.get())

angle_x = angle_x*math.pi / 180 angle_y = angle_y*math.pi / 180 angle_z = angle_z*math.pi / 180

matr_rot_ox = np.array([[1,0,0],

[0, cos(angle_x), -sin(angle_x)], [0, sin(angle_x), cos(angle_x)]])

matr_rot_oy = np.array([[cos(angle_y),0,sin(angle_y)], [0, 1, 0],

6

[-sin(angle_y), 0, cos(angle_y)]])

matr_rot_oz = np.array([[cos(angle_z),-sin(angle_z),0], [sin(angle_z), cos(angle_z), 0], [0, 0, 1]])

points_2 = np.array([x,y,z])

res = rot(points_2, matr_rot_ox) res = rot(res, matr_rot_oy)

res = rot(res, matr_rot_oz) Temp_matrix[0][0]=res[0] Temp_matrix[0][1]=res[1] Temp_matrix[0][2]=res[2]

return Temp_matrix

def cross(a, b): #перекрестное произведение

return [a[1]*b[2] - a[2]*b[1], a[2]*b[0] - a[0]*b[2], a[0]*b[1] - a[1]*b[0]]

def createFace(self,points):

a, b, c, d = points[0], points[1], points[2], points[3]

v1 = b[0]-a[0], b[1]-a[1], b[2]-a[2] v2 = c[0]-a[0], c[1]-a[1], c[2]-a[2] n = cross(v1, v2)

if n[2] < 0: return

coords = ((b[0], b[1]), (a[0], a[1]), (d[0], d[1]),(c[0], c[1])) self.canvas.create_polygon(coords,fill='orange', outline='blue')

def flattenPoint(point):

(x, y, z) = (point[0][0], point[0][1], point[0][2]) return (x, y, z)

def createOutline(self,points):

a, b, c, d = points[0], points[1], points[2], points[3]

v1 = b[0]-a[0], b[1]-a[1], b[2]-a[2] v2 = c[0]-a[0], c[1]-a[1], c[2]-a[2]

7

n = cross(v1, v2) if n[2] < 0:

return

coords = ((b[0], b[1]), (a[0], a[1]), (d[0], d[1]),(c[0], c[1])) #self.canvas.create_polygon(coords,fill='', outline='blue')

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") #угол поворот оси OY self.Z_value = tk.StringVar() self.Z_value.set("0") #угол поворот оси О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=0.1) #ОСИ

#self.canvas.create_line(0, -self.HEIGHT, 0, self.HEIGHT, fill="black", width=0.1)#ОСИ

#self.canvas.create_line(1000, -1000, 0, 1000, fill="black", width=0.5) #ОСИ

zeros = [0] * 4

self.canvas.create_polygon(points_2d,fill='orange', outline='blue')

self.canvas.configure(scrollregion=(int(-(self.WIDTH - 400) / 2) + 2, int(-(self.HEIGHT - 200) / 2) + 1, 0, 0))

frame = Frame(self.root)

8

frame["border"] = 5 frame['relief'] = 'groove'

frame.grid(row=0, column=0, sticky="n")

label_agent = Label(frame, text=" Угол поворота по оси").grid(row=0, column=0, sticky="nw", padx=20)

label_OX = Label(frame, text="OX").grid(row=1, column=0, sticky="w",

padx=40)

label_OY = Label(frame, text="OY").grid(row=2, column=0, sticky="w",

padx=40)

label_OZ = Label(frame, text="OZ").grid(row=3, column=0, sticky="w",

padx=40)

entry_OX = Entry(frame, width=5, textvariable=self.X_value).grid(row=1, column=0, sticky=W, padx=62)

entry_OY = Entry(frame, width=5, textvariable=self.Y_value).grid(row=2, column=0, sticky=W, padx=62)

entry_OZ = Entry(frame, width=5, textvariable=self.Z_value).grid(row=3, column=0, sticky=W, padx=62)

#ИЗМЕНИТЬ ФУНКЦИИ

button_rotation = Button(frame, text="Отобразить", command=self.draw_cube, height=1, width=10,

highlightcolor="darkgrey",

border=5).grid(row=3, column=1,

sticky="we")

def draw_cube(self): self.canvas.delete("all") #очистка экрана

#self.canvas.create_line(-self.WIDTH, 0, self.WIDTH, 0, fill="black", width=0.1) #ОСИ

#self.canvas.create_line(0, -self.HEIGHT, 0, self.HEIGHT, fill="black", width=0.1)#ОСИ

#self.canvas.create_line(1000, -1000, 0, 1000, fill="black", width=0.5) #ОСИ

coords = []

for point in points: Tmp_matr=rotation(self,point)

9

point = Tmp_matr coords.append(flattenPoint(point))

for face in faces:

createFace(self,(coords[face[0]], coords[face[1]], coords[face[2]], coords[face[3]]))

for face in faces:

createOutline(self,(coords[face[0]], coords[face[1]], coords[face[2]], coords[face[3]]))

if __name__ == '__main__': app = tk.Tk()

screen_width = app.winfo_screenwidth() screen_height = app.winfo_screenheight()

app.geometry(f"{screen_width - 100}x{screen_height - 150}+{50}+{50}") gui = Gui(app)

app.mainloop()

10