Este blog é um complemento do nosso canal no YouTube. Clique em @CanalQb para seguir e acompanhar nossos vídeos!

Python - Cálculos geométricos com finalidade de aplicação em renderização

10 min read
Python - Cálculos geométricos
Canal Qb

Transformações geométricas: Implementação de rotações, translações e escalas em objetos geométricos para renderização em diferentes posições e tamanhos.
import numpy as np
import matplotlib.pyplot as plt

# Função para realizar uma rotação de um ponto em torno de um ponto de referência
def rotacionar_ponto(ponto, angulo, referencia):
    theta = np.radians(angulo)
    R = np.array([[np.cos(theta), -np.sin(theta)],
                  [np.sin(theta), np.cos(theta)]])
    return np.dot(R, ponto - referencia) + referencia

# Função para realizar uma translação em um ponto
def transladar_ponto(ponto, dx, dy):
    return ponto[0] + dx, ponto[1] + dy

# Função para realizar uma escala em um ponto em relação a um ponto de referência
def escalar_ponto(ponto, escala, referencia):
    return referencia[0] + escala * (ponto[0] - referencia[0]), referencia[1] + escala * (ponto[1] - referencia[1])

# Pontos do objeto geométrico
pontos = np.array([[1, 1],
                   [2, 1],
                   [2, 2],
                   [1, 2],
                   [1, 1]])

# Rotação de 45 graus em torno do ponto (1.5, 1.5)
referencia_rotacao = np.array([1.5, 1.5])
angulo_rotacao = 45

# Translação de (1, 1)
dx = 1
dy = 1

# Escala de 1.5 em relação ao ponto (1.5, 1.5)
referencia_escala = np.array([1.5, 1.5])
escala = 1.5

# Aplicar transformações geométricas aos pontos
pontos_rotacionados = np.array([rotacionar_ponto(ponto, angulo_rotacao, referencia_rotacao) for ponto in pontos])
pontos_transladados = np.array([transladar_ponto(ponto, dx, dy) for ponto in pontos])
pontos_escalados = np.array([escalar_ponto(ponto, escala, referencia_escala) for ponto in pontos])

# Plotar os pontos originais e transformados
plt.plot(pontos[:, 0], pontos[:, 1], label='Original')
plt.plot(pontos_rotacionados[:, 0], pontos_rotacionados[:, 1], label='Rotacionado')
plt.plot(pontos_transladados[:, 0], pontos_transladados[:, 1], label='Transladado')
plt.plot(pontos_escalados[:, 0], pontos_escalados[:, 1], label='Escalado')
plt.legend()
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Transformações geométricas')
plt.grid(True)
plt.axis('equal')
plt.show()
Projeções: Cálculo de projeções em perspectiva e ortográficas para transformar objetos 3D em 2D para renderização.
import numpy as np
import matplotlib.pyplot as plt

# Função para realizar a projeção em perspectiva de um ponto 3D para um ponto 2D
def projetar_ponto_perspectiva(ponto, distancia_projecao):
    fator = distancia_projecao / ponto[2]
    return ponto[0] * fator, ponto[1] * fator

# Função para realizar a projeção ortográfica de um ponto 3D para um ponto 2D
def projetar_ponto_ortografica(ponto):
    return ponto[0], ponto[1]

# Pontos do objeto 3D
pontos_3d = np.array([[1, 1, 1],
                      [2, 1, 1],
                      [2, 2, 1],
                      [1, 2, 1],
                      [1, 1, 2],
                      [2, 1, 2],
                      [2, 2, 2],
                      [1, 2, 2]])

# Configurações de projeção
distancia_projecao_perspectiva = 5

# Aplicar projeções aos pontos 3D
pontos_2d_perspectiva = np.array([projetar_ponto_perspectiva(ponto, distancia_projecao_perspectiva) for ponto in pontos_3d])
pontos_2d_ortografica = np.array([projetar_ponto_ortografica(ponto) for ponto in pontos_3d])

# Plotar os pontos 2D resultantes
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 5))

ax1.plot(pontos_2d_perspectiva[:, 0], pontos_2d_perspectiva[:, 1], 'ro')
ax1.set_title('Projeção em Perspectiva')
ax1.set_xlabel('X')
ax1.set_ylabel('Y')
ax1.grid(True)
ax1.axis('equal')

ax2.plot(pontos_2d_ortografica[:, 0], pontos_2d_ortografica[:, 1], 'bo')
ax2.set_title('Projeção Ortográfica')
ax2.set_xlabel('X')
ax2.set_ylabel('Y')
ax2.grid(True)
ax2.axis('equal')

plt.tight_layout()
plt.show()
Interseções de objetos: Cálculo de interseções entre objetos para evitar a sobreposição de polígonos na renderização.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon

# Função para verificar se dois polígonos se intersectam
def poligonos_se_intersectam(poligono1, poligono2):
    polygon1 = Polygon(poligono1)
    polygon2 = Polygon(poligono2)
    return polygon1.intersects(polygon2)

# Polígonos de exemplo
poligono1 = np.array([[1, 1],
                      [2, 1],
                      [2, 2],
                      [1, 2]])

poligono2 = np.array([[1.5, 1.5],
                      [2.5, 1.5],
                      [2.5, 2.5],
                      [1.5, 2.5]])

poligono3 = np.array([[2, 1.5],
                      [3, 1.5],
                      [3, 2.5],
                      [2, 2.5]])

# Verificar interseções entre os polígonos
intersecao_1_2 = poligonos_se_intersectam(poligono1, poligono2)
intersecao_1_3 = poligonos_se_intersectam(poligono1, poligono3)
intersecao_2_3 = poligonos_se_intersectam(poligono2, poligono3)

# Imprimir resultado
print("Interseção entre polígono 1 e polígono 2:", intersecao_1_2)
print("Interseção entre polígono 1 e polígono 3:", intersecao_1_3)
print("Interseção entre polígono 2 e polígono 3:", intersecao_2_3)

# Plotar os polígonos
fig, ax = plt.subplots()

poligonos = [poligono1, poligono2, poligono3]
cores = ['r', 'g', 'b']
legendas = ['Polígono 1', 'Polígono 2', 'Polígono 3']

for i, poligono in enumerate(poligonos):
    patch = Polygon(poligono, facecolor=cores[i], alpha=0.5)
    ax.add_patch(patch)

ax.set_xlim([0, 4])
ax.set_ylim([0, 4])
ax.set_aspect('equal', 'box')
ax.set_title('Interseções entre polígonos')
ax.set_xlabel('X')
ax.set_ylabel('Y')

plt.legend(legendas)
plt.grid(True)
plt.show()
Sombreamento: Cálculo de sombreamento para simular a iluminação em um ambiente 3D.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# Função para calcular o sombreamento em um ponto com base na posição da fonte de luz
def calcular_sombreamento(ponto, fonte_de_luz):
    vetor_normal = np.array([0, 0, 1])  # Vetor normal fixo para este exemplo
    vetor_luz = fonte_de_luz - ponto
    vetor_luz_normalizado = vetor_luz / np.linalg.norm(vetor_luz)
    sombreamento = np.dot(vetor_normal, vetor_luz_normalizado)
    return sombreamento

# Pontos do objeto 3D
x = np.array([1, 2, 2, 1])
y = np.array([1, 1, 2, 2])
z = np.array([0, 0, 0, 0])

# Posição da fonte de luz
fonte_de_luz = np.array([0, 0, 5])

# Calcular sombreamento para cada ponto
sombreamento = np.array([calcular_sombreamento(ponto, fonte_de_luz) for ponto in zip(x, y, z)])

# Plotar o objeto 3D com sombreamento
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

# Plotar os pontos do objeto
ax.plot_trisurf(x, y, z, triangles=[[0, 1, 2], [0, 2, 3]], cmap='gray', shade=False)

# Ajustar a cor dos triângulos com base no sombreamento
ax.collections[0].set_facecolors(plt.cm.gray(sombreamento))

# Configurações de visualização
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('Sombreamento em um ambiente 3D')
ax.view_init(elev=20, azim=-45)

plt.show()
Texturas: Implementação de texturas para aplicar padrões e imagens em objetos 3D para uma renderização mais realista.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# Função para aplicar uma textura em um objeto 3D
def aplicar_textura(objeto_3d, textura):
    objeto_3d.set_facecolor(textura)

# Pontos do objeto 3D
x = np.array([1, 2, 2, 1])
y = np.array([1, 1, 2, 2])
z = np.array([0, 0, 0, 0])

# Definir as coordenadas de textura
u = np.array([0, 1, 1, 0])
v = np.array([0, 0, 1, 1])

# Carregar a imagem de textura
textura = plt.imread('exemplo_textura.jpg')

# Plotar o objeto 3D com a textura
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

# Plotar os pontos do objeto
objeto_3d = ax.plot_trisurf(x, y, z, triangles=[[0, 1, 2], [0, 2, 3]], shade=False)

# Aplicar a textura ao objeto 3D
aplicar_textura(objeto_3d, textura)

# Configurações de visualização
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('Texturas em um objeto 3D')

plt.show()
Curvas e superfícies: Implementação de curvas e superfícies para criar objetos 3D complexos para renderização.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# Função para criar uma superfície a partir de uma equação matemática
def criar_superficie(equacao, intervalo_x, intervalo_y):
    x = np.linspace(intervalo_x[0], intervalo_x[1], 100)
    y = np.linspace(intervalo_y[0], intervalo_y[1], 100)
    X, Y = np.meshgrid(x, y)
    Z = equacao(X, Y)
    return X, Y, Z

# Função para criar uma curva a partir de uma equação paramétrica
def criar_curva(equacao_x, equacao_y, equacao_z, intervalo):
    t = np.linspace(intervalo[0], intervalo[1], 100)
    x = equacao_x(t)
    y = equacao_y(t)
    z = equacao_z(t)
    return x, y, z

# Equações matemáticas para criar uma superfície e uma curva
def equacao_superficie(x, y):
    return np.sin(x) * np.cos(y)

def equacao_curva_x(t):
    return np.cos(t)

def equacao_curva_y(t):
    return np.sin(t)

def equacao_curva_z(t):
    return t

# Criação da superfície
intervalo_x = [-np.pi, np.pi]
intervalo_y = [-np.pi, np.pi]
X, Y, Z = criar_superficie(equacao_superficie, intervalo_x, intervalo_y)

# Criação da curva
intervalo_curva = [-np.pi, np.pi]
x_curva, y_curva, z_curva = criar_curva(equacao_curva_x, equacao_curva_y, equacao_curva_z, intervalo_curva)

# Plotagem da superfície e da curva
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

# Plotar a superfície
ax.plot_surface(X, Y, Z, cmap='viridis')

# Plotar a curva
ax.plot(x_curva, y_curva, z_curva, 'r')

# Configurações de visualização
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('Curvas e Superfícies em um objeto 3D')

plt.show()
Clipping: Implementação de clipping para recortar objetos que estão fora da área de visualização para aumentar a eficiência da renderização.
import numpy as np
import matplotlib.pyplot as plt

# Função para realizar o clipping de um objeto em relação à janela de visualização
def clipping(objeto, janela):
    objeto_recortado = []

    for i in range(len(objeto)):
        ponto_atual = objeto[i]
        ponto_proximo = objeto[(i + 1) % len(objeto)]

        if dentro_janela(ponto_atual, janela):
            objeto_recortado.append(ponto_atual)

        if cruzou_janela(ponto_atual, ponto_proximo, janela):
            ponto_intersecao = calcular_intersecao(ponto_atual, ponto_proximo, janela)
            objeto_recortado.append(ponto_intersecao)

    return objeto_recortado

# Função para verificar se um ponto está dentro da janela de visualização
def dentro_janela(ponto, janela):
    x, y = ponto
    x_min, y_min, x_max, y_max = janela

    return x_min <= x <= x_max and y_min <= y <= y_max

# Função para verificar se uma aresta cruza a janela de visualização
def cruzou_janela(ponto1, ponto2, janela):
    x1, y1 = ponto1
    x2, y2 = ponto2
    x_min, y_min, x_max, y_max = janela

    if (x1 < x_min and x2 > x_max) or (x1 > x_max and x2 < x_min):
        return True

    if (y1 < y_min and y2 > y_max) or (y1 > y_max and y2 < y_min):
        return True

    return False

# Função para calcular a interseção entre uma aresta e a janela de visualização
def calcular_intersecao(ponto1, ponto2, janela):
    x1, y1 = ponto1
    x2, y2 = ponto2
    x_min, y_min, x_max, y_max = janela

    if x1 != x2:
        m = (y2 - y1) / (x2 - x1)
        c = y1 - m * x1

        if x1 < x_min:
            x_intersecao = x_min
            y_intersecao = m * x_min + c
        else:
            x_intersecao = x_max
            y_intersecao = m * x_max + c
    else:
        x_intersecao = x1
        if y1 < y_min:
            y_intersecao = y_min
        else:
            y_intersecao = y_max

    return [x_intersecao, y_intersecao]

# Pontos do objeto a ser renderizado
objeto = [[1, 1], [4, 1], [3, 4], [2, 4]]

# Janela de visualização (área a ser mantida)
janela = [2, 2, 3, 3]

# Realizar o clipping do objeto em relação à janela de visualização
objeto_recortado = clipping(objeto, janela)

# Plotar o objeto original e o objeto recortado
fig, ax = plt.subplots()

# Plotar o objeto original
x, y = zip(*objeto)
ax.plot(x, y, 'b', label='Objeto Original')

# Plotar o objeto recortado
x_recortado, y_recortado = zip(*objeto_recortado)
ax.plot(x_recortado, y_recortado, 'r', label='Objeto Recortado')

# Plotar a janela de visualização
x_janela = [janela[0], janela[2], janela[2], janela[0], janela[0]]
y_janela = [janela[1], janela[1], janela[3], janela[3], janela[1]]
ax.plot(x_janela, y_janela, 'g--', label='Janela de Visualização')

# Configurações de visualização
ax.set_xlim([0, 5])
ax.set_ylim([0, 5])
ax.set_aspect('equal')
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_title('Clipping - Recorte de Objetos')

# Legenda
ax.legend()

plt.show()
Algoritmos de rasterização: Implementação de algoritmos de rasterização para converter objetos vetoriais em pixels para renderização em um dispositivo de exibição.
import numpy as np
import matplotlib.pyplot as plt

# Função para realizar a rasterização de um polígono
def rasterizar_poligono(vertices):
    x_min, y_min = np.min(vertices, axis=0)
    x_max, y_max = np.max(vertices, axis=0)
    largura = int(x_max - x_min) + 1
    altura = int(y_max - y_min) + 1

    imagem = np.zeros((altura, largura), dtype=np.uint8)

    for i in range(len(vertices)):
        ponto_atual = vertices[i]
        ponto_proximo = vertices[(i + 1) % len(vertices)]

        x1, y1 = ponto_atual
        x2, y2 = ponto_proximo

        dx = abs(x2 - x1)
        dy = abs(y2 - y1)

        if x1 < x2:
            sx = 1
        else:
            sx = -1

        if y1 < y2:
            sy = 1
        else:
            sy = -1

        erro = dx - dy

        while True:
            imagem[int(y1 - y_min), int(x1 - x_min)] = 255

            if x1 == x2 and y1 == y2:
                break

            erro_2 = 2 * erro

            if erro_2 > -dy:
                erro -= dy
                x1 += sx

            if erro_2 < dx:
                erro += dx
                y1 += sy

    return imagem

# Definição dos vértices do polígono
vertices = np.array([[2, 1], [5, 4], [4, 7], [1, 6]])

# Rasterização do polígono
imagem_rasterizada = rasterizar_poligono(vertices)

# Plotagem da imagem rasterizada
plt.imshow(imagem_rasterizada, cmap='gray', origin='lower')

# Configurações de visualização
plt.xlabel('Pixels')
plt.ylabel('Pixels')
plt.title('Rasterização de um Polígono')

plt.show()

Talvez você goste destas postagens

Postar um comentário

Comente só assim vamos crescer juntos!
NextGen Digital Welcome to WhatsApp chat
Howdy! How can we help you today?
Type here...