Ultimas do CanalQb

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

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()

Nenhum comentário

Comente só assim vamos crescer juntos!

Observação: somente um membro deste blog pode postar um comentário.