Imagens Vetoriais e Transformações
Links Relacionados: Matemática e Física para Jogos
Representação
O plano é um espaço bidimensional composto de dois vetores, x e y. Para representar elementos vetoriais no plano, é necessário primeiramente representar cada ponto (x, y) ligados por linhas.
Código em C++
class Point2D {
public:
float x;
float y;
};
Código em Python
class Point2D:
def __init__(self, x: float, y: float):
self.x: float = x
self.y: float = y
O espaço tridimensional, por sua vez, é composto por três vetores. Desta forma, para representar os elementos vetoriais neste espaço é necessário acrescentar o eixo z aos já conhecidos x e y. Dessa forma, cada ponto pode ser representado por (x, y, z).
Código em C++
class Ponto3D {
public:
float x;
float y;
float z;
};
Código em Python
class Point3D:
def __init__(self, x: float, y: float, z: float):
self.x: float = x
self.y: float = y
self.z: float = z
Desenhando um Triângulo em um espaço bidimensional
Código em C++
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <iostream>
class Ponto
{
public:
float x;
float y;
Ponto (float _x, float _y) : x(_x), y(_y) {}
};
int main()
{
sf::RenderWindow* app = new sf::RenderWindow(sf::VideoMode(800, 600, 32), "Triangulo 2D");
Ponto* triangulo[3];
triangulo[0] = new Ponto(50, 100);
triangulo[1] = new Ponto(100, 50);
triangulo[2] = new Ponto(150, 100);
while (app->IsOpened())
{
sf::Event* event = new sf::Event();
while (app->GetEvent(*event))
{
if (event->Type == sf::Event::Closed)
{
app->Close();
}
}
if (app->GetInput().IsKeyDown(sf::Key::Escape))
{
return EXIT_SUCCESS;
}
app->Clear(sf::Color(255, 255, 255));
for (int i = 0; i < 3; i++)
{
int j = i + 1;
if (j > 2) j = 0;
sf::Shape line = sf::Shape::Line(triangulo[i]->x, triangulo[i]->y,
triangulo[j]->x, triangulo[j]->y,
1, sf::Color(0, 0, 0));
app->Draw(line);
}
app->Display();
}
return EXIT_SUCCESS;
}
Código em Python
import sys
import pygame
WIDTH: int = 800
HEIGHT: int = 600
Color_screen: pygame.Color = (255, 255, 255)
Color_line: pygame.Color = (0, 0, 0)
class Point:
def __init__(self, x: float, y: float):
self.x: float = x
self.y: float = y
def main():
global CONICAL
screen = pygame.display.set_mode((WIDTH, HEIGHT))
triangle : list[Point] = [
Point(50, 100),
Point(100, 50),
Point(150, 100)
]
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit(0)
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
sys.exit(0)
screen.fill(Color_screen)
pygame.draw.line(screen, Color_line, (triangle[0].x, triangle[0].y), (triangle[1].x, triangle[1].y))
pygame.draw.line(screen, Color_line, (triangle[1].x, triangle[1].y), (triangle[2].x, triangle[2].y))
pygame.draw.line(screen, Color_line, (triangle[2].x, triangle[2].y), (triangle[0].x, triangle[0].y))
pygame.display.flip()
if __name__ == "__main__":
main()
Transformações Vetoriais
Para fazer transformações em elementos vetoriais, na computação gráfica, são utilizadas as operações com matrizes.
Translação
A translação é a operação que move determinado objeto de um local à outro no plano.
A operação da translação ocorre com a soma da matriz de translação com todos os pontos do objeto. A matriz de translação é a seguinte:
tal que:
Logo, a fórmula matemática da operação de translação fica da seguinte forma:
tal que:
Escala
A escala no plano é a operação que modifica o tamanho de um objeto no plano.
A operação da escala ocorre com a multiplicação da matriz de Escala com todos os pontos do objeto. A matriz de escala é a seguinte:
tal que:
Logo, a fórmula matemática da operação de translação fica da seguinte forma:
tal que:
Resumindo:
O Problema do deslocamento
Porém, temos um problema. Ao aplicar a escala, estamos modificando também a posição do nosso elemento. Para contornar o problema, devemos definir um ponto que é visto como o ponto de origem deste elemento, ou também chamado de Pivô.
Dessa forma, antes de efetuar a operação de escala, devemos mover nossa imagem com o pivô para a origem (0, 0). Para essa mudança, basta escolher um ponto que será o pivô ou criar um ponto apenas para ser o pivô da imagem. Diminuir todos os pontos pelo x do pivô, efetuar a operação e somar novamente pelos pontos do pivô.
Observe o seguinte algoritmo de exemplo:
pivo.x = ponto[0].x
pivo.y = ponto[0].y
translacao(-pivo.x, -pivo.y)
escala(2.0, 2.0)
translacao(pivo.x, pivo.y)
Veja que no exemplo acima utilizamos a operação de translação e de escala já apresentadas.
Rotação
A rotação, no plano, é a operação que rotaciona determinado objeto no plano.
A operação de rotação ocorre com a multiplicação da matriz de Rotação com todos os pontos do objeto. A matriz de rotação é a seguinte:
| cos(ang) sen(ang) | |-sen(ang) cos(ang) |
tal que:
ang é o ângulo, em radianos, que se quer rotacionar o objeto, sen é a operação do seno sobre o ângulo e cos é a operação do cosseno sobre o ângulo.
Logo, a fórmula matemática da operação de translação se dá pela multiplicação da matriz do ponto pela matriz de rotação:
| cos(ang) sen(ang) | | -sen(ang) cos(ang) | [ x y ] [(x*cos(ang))+(y*(-sen(ang))) (x*sen(ang))+(y*cos(ang)) ]
tal que:
x' = (x * cos(ang)) + (y * -sen(ang)) y' = (x * sen(ang)) + (y * cos(ang))
Observe que agora temos x' e y'. Isso por que em ambas as oeprações estamos utilizando o x e y originais.
Se modificarmos o x na primeira operação, na segunda ele já vai estar modificado, o que distorce o elemento. A solução é criar variáveis auxiliares para não alterar os valores originais até o término do processo.
Outra coisa importante é que, assim como na escala, devemos transladar nosso objeto para o ponto de origem do espaço, baseando-se em um pivô do elemento.
Distância Euclidiana
A distância Euclidiana é a distância entre dois pontos. No caso do espaço bidimensional (vetores x e y), podemos ter a distância euclidiana como a seguinte fórmula:
raiz( (x2 - x1)2 + (y2 - y1)2)
Funções Trigonométricas
Considere o Triângulo da figura ao lado. Para o ângulo α, chamamos o lado cujo comprimento é x de lado adjacente, e chamamos o lado cujo comprimento é y de lado oposto. O lado oposto ao ângulo direito, cujo comprimento satisfaz o teorema de pitágoras (h2 = x2 + y2, é chamado de hipotenusa. As seis funções trigonométricas são definidas pelo ângulo como as razões de comprimentos de lado.
Nome da Função | Definição |
---|---|
seno | sen α = y / h |
cosseno | cos α = x / h |
tangente | tg α = y / h = sen α / cos α |
cossecante | csc α = h / y = 1 / sen α |
secante | sec α = h / x = 1 / cos α |
cotangente | cot α = x / y = 1 / tg α |
As funções cossecante, secante e cotangente são raramente utilizadas na programação. Dessa forma, vamos estudar mais as funções de seno, cosseno e tangente.
O que torna as funções trigonométricas úteis é que para um dado ângulo α, as razões de comprimento dos lados de um triângulo retângulo contendo o ângulo α são sempre as mesmas. Assim, as funções seno, cosseno e tangente dependem apenas do ângulo α, e não do tamanho real do triângulo.
radianos | graus | sen α | cos α | tg α |
---|---|---|---|---|
0 | 0º | 0 | 1 | 0 |
π/6 | 30º | 1/2 | raiz(3)/2 | raiz(3)/3 |
π/4 | 45º | raiz(2)/2 | raiz(2)/2 | 1 |
π/3 | 60º | raiz(3)/2 | 1/2 | raiz(3) |
π/2 | 90º | 1 | 0 | indefinido |
Exercícios
1. Implemente as funções que calculam:
1.a. A distância euclidiana entre dois pontos
1.b. A conversão de graus para radianos
Com base na representação do ponto e no exemplo do triângulo apresentado nessa sessão, faça os seguintes exercícios:
2. Implemente a função de translação. No programa principal, cada vez que pressionar as teclas das setas:
2.a. Cima: translade 10 pixeis para cima
2.b. Baixo: translade 10 pixels para baixo
2.c. Direita: translade 10 pixels para a direita
2.d. Esquerda: translade 10 pixels para a esquerda
3. Implemente a função de escala. No programa principal, efetue as seguintes operações:
3.a. Tecla PgUp: Faça o triângulo aumentar em 10%
3.b. Tecla PgDn: Faça o triângulo diminuir em 10%
observe que há o problema do deslocamento. Evite isso deixando um ponto como pivô.
4. Implemente a função de rotação. No programa principal, efetue as seguintes operações:
4.a. Tecla d: rotacione 15 graus para a direita
4.b. Tecla e: rotacione 15 graus para a esquerda