#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
================================================================================
INSTITUTO NACIONAL DE CIÊNCIA E TECNOLOGIA EM TECNOLOGIAS FOTÔNICAS (IN-Foton)
LABORATÓRIO DE TELECOMUNICAÇÕES (LabTel) / DEPARTAMENTO DE ENGENHARIA ELÉTRICA (DEE)
UNIVERSIDADE FEDERAL DO ESPÍRITO SANTO (UFES)
================================================================================
Projeto Educacional: Portal IN-Foton / LabTel (in-foton.org)
Módulo: [MOD-MTL] Análise de Linhas de Transmissão com Multicondutores (Material Bônus)
Coordenação e Autoria: Prof. Marcelo Eduardo Vieira Segatto

Descrição:
Gera a ilustração tridimensional oficial e padronizada da microfita acoplada
tripla da Figura 5.32 do livro de Clayton R. Paul.
- Representação isométrica 3D rigorosa em 2.5D sem distorções de perspectiva;
- Substrato dielétrico verde FR-4 com plano de terra GND contínuo em cobre;
- Três fitas condutoras coplanares em cobre com cotas dimensionais completas
  (w = 3.03 mm, s = 1.50 mm, h = 1.575 mm, Lz = 59.7 cm);
- Identificação visual das três portas (Linha 1, Linha 2 Central, Linha 3);
- Exportação em vetor PDF de alta resolução para impressão/LaTeX e PNG para web.

Código 100% autônomo e autocontido (não requer dependências proprietárias).
Licença: Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional (CC BY-SA 4.0)
         e Licença MIT para execução e reutilização do código computacional.
Requisitos: Python 3.8+, numpy, matplotlib
Uso: python gerar_fig_3d_tripla_microstrip.py
================================================================================
"""

import os
import sys
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.patches as patches

# Diretório de saída local
DIR_OUTPUT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "outputs")
os.makedirs(DIR_OUTPUT, exist_ok=True)

# -------------------------------------------------------------------------
# MOTOR GEOMÉTRICO ISOMÉTRICO 3D (PADRÃO IN-Foton / LabTel)
# -------------------------------------------------------------------------
COS30 = np.cos(np.radians(30.0))
SIN30 = np.sin(np.radians(30.0))

def iso(x, y, z):
    """Converte coordenadas 3D (x, y, z) em projeção isométrica 2D plana."""
    px = (x - y) * COS30
    py = (x + y) * SIN30 + z
    return px, py

# Paleta de Cores Padronizada (Padrão Institucional IN-Foton)
COLOR_SUB_TOP   = "#D5E8D4"  # Verde FR-4 superior (DrawIO / PCB)
COLOR_SUB_FRONT = "#82B366"  # Verde lateral frontal
COLOR_SUB_LEFT  = "#5A8246"  # Verde lateral esquerda
COLOR_SUB_EDGE  = "#274E13"  # Contorno verde escuro

COLOR_CU_TOP    = "#F59E0B"  # Cobre âmbar brilhante (face superior)
COLOR_CU_FRONT  = "#D97706"  # Cobre face frontal
COLOR_CU_LEFT   = "#B45309"  # Cobre face lateral
COLOR_CU_EDGE   = "#78350F"  # Contorno de cobre escuro

def draw_substrate_and_gnd(ax, L, W, h, t_gnd=0.15):
    """Desenha o bloco volumétrico do substrato verde e o plano de terra GND."""
    # 1. Plano de Terra GND (z entre -t_gnd e 0)
    pts_gnd_f = [iso(0, 0, -t_gnd), iso(L, 0, -t_gnd), iso(L, 0, 0), iso(0, 0, 0)]
    ax.add_patch(patches.Polygon(pts_gnd_f, closed=True, facecolor=COLOR_CU_FRONT, edgecolor=COLOR_CU_EDGE, lw=0.8, zorder=1))
    pts_gnd_l = [iso(0, 0, -t_gnd), iso(0, W, -t_gnd), iso(0, W, 0), iso(0, 0, 0)]
    ax.add_patch(patches.Polygon(pts_gnd_l, closed=True, facecolor=COLOR_CU_LEFT, edgecolor=COLOR_CU_EDGE, lw=0.8, zorder=1))

    # 2. Bloco do Substrato Dielétrico FR-4 (z entre 0 e h)
    pts_sub_f = [iso(0, 0, 0), iso(L, 0, 0), iso(L, 0, h), iso(0, 0, h)]
    ax.add_patch(patches.Polygon(pts_sub_f, closed=True, facecolor=COLOR_SUB_FRONT, edgecolor=COLOR_SUB_EDGE, lw=1.1, zorder=2))
    pts_sub_l = [iso(0, 0, 0), iso(0, W, 0), iso(0, W, h), iso(0, 0, h)]
    ax.add_patch(patches.Polygon(pts_sub_l, closed=True, facecolor=COLOR_SUB_LEFT, edgecolor=COLOR_SUB_EDGE, lw=1.1, zorder=2))
    pts_sub_t = [iso(0, 0, h), iso(L, 0, h), iso(L, W, h), iso(0, W, h)]
    ax.add_patch(patches.Polygon(pts_sub_t, closed=True, facecolor=COLOR_SUB_TOP, edgecolor=COLOR_SUB_EDGE, lw=1.1, zorder=3))

def draw_planar_trace(ax, poly_xy, h=1.2, zorder_base=6):
    """Desenha uma pista metálica de espessura zero sobre a face superior do substrato."""
    top_2d = [iso(x, y, h) for x, y in poly_xy]
    ax.add_patch(patches.Polygon(top_2d, closed=True, facecolor=COLOR_CU_TOP, edgecolor=COLOR_CU_EDGE, lw=1.0, zorder=zorder_base))

def main():
    print("="*80)
    print("IN-Foton / LabTel / UFES — RENDERIZADOR 3D DE MICROFITA TRIPLA (CLAYTON PAUL)")
    print("Coordenação: Prof. Marcelo Eduardo Vieira Segatto")
    print("="*80)

    fig, ax = plt.subplots(figsize=(11.0, 6.8), dpi=300)
    ax.set_aspect("equal")
    ax.axis("off")
    fig.patch.set_facecolor('#FFFFFF')

    # Dimensões normalizadas
    L_sub = 16.0  # direção longitudinal z
    W_sub = 9.0   # largura transversal x
    h_sub = 1.2   # espessura do substrato
    t_gnd = 0.15  # espessura do terra GND

    # 1. Desenha o substrato verde e o plano de terra inferior
    draw_substrate_and_gnd(ax, L=L_sub, W=W_sub, h=h_sub, t_gnd=t_gnd)

    # 2. Pistas de microfita em cobre
    w_strip = 1.8
    s_sep   = 1.0

    y_c2 = W_sub / 2.0                 # Linha 2 (Centro) = 4.5
    y_c1 = y_c2 - (w_strip + s_sep)    # Linha 1 = 1.7
    y_c3 = y_c2 + (w_strip + s_sep)    # Linha 3 = 7.3

    fitas = [
        (y_c1, "Linha 1 (Lateral)", "#0284C7"),
        (y_c2, "Linha 2 (Central - Excitada)", "#DC2626"),
        (y_c3, "Linha 3 (Lateral)", "#16A34A")
    ]

    for y_center, nome_linha, cor_tag in fitas:
        y_bot = y_center - w_strip / 2.0
        y_top = y_center + w_strip / 2.0
        poly_pts = [
            (0.0, y_bot),
            (L_sub, y_bot),
            (L_sub, y_top),
            (0.0, y_top)
        ]
        draw_planar_trace(ax, poly_pts, h=h_sub, zorder_base=6)

    # 3. Badges verticais diretamente sobre as Linhas
    x_tag = 4.0
    pt3 = iso(x_tag, y_c3, h_sub)
    ax.annotate("Linha 3 (Lateral)\n$Z_0 = 50\\,\\Omega$",
                xy=pt3, xytext=(pt3[0] - 0.2, pt3[1] + 1.8),
                arrowprops=dict(arrowstyle="->", color="#15803D", lw=1.2),
                fontsize=8.5, fontweight="bold", color="#15803D", ha="center",
                bbox=dict(boxstyle="round,pad=0.25", facecolor="#F0FDF4", edgecolor="#16A34A", lw=1.0, alpha=0.95),
                zorder=25)

    pt2 = iso(x_tag, y_c2, h_sub)
    ax.annotate("Linha 2 (Central)\nPorta Excitada",
                xy=pt2, xytext=(pt2[0] - 0.2, pt2[1] + 1.8),
                arrowprops=dict(arrowstyle="->", color="#B91C1C", lw=1.2),
                fontsize=8.5, fontweight="bold", color="#B91C1C", ha="center",
                bbox=dict(boxstyle="round,pad=0.25", facecolor="#FEF2F2", edgecolor="#DC2626", lw=1.0, alpha=0.95),
                zorder=25)

    pt1 = iso(x_tag, y_c1, h_sub)
    ax.annotate("Linha 1 (Lateral)\n$Z_0 = 50\\,\\Omega$",
                xy=pt1, xytext=(pt1[0] - 0.2, pt1[1] + 1.8),
                arrowprops=dict(arrowstyle="->", color="#0369A1", lw=1.2),
                fontsize=8.5, fontweight="bold", color="#0369A1", ha="center",
                bbox=dict(boxstyle="round,pad=0.25", facecolor="#F0F9FF", edgecolor="#0284C7", lw=1.0, alpha=0.95),
                zorder=25)

    # 4. Cotas Dimensionais na face frontal (x = 0)
    p_w1 = iso(0.0, y_c1 - w_strip/2.0, h_sub)
    p_w2 = iso(0.0, y_c1 + w_strip/2.0, h_sub)
    ax.annotate("", xy=p_w1, xytext=p_w2,
                arrowprops=dict(arrowstyle="<->", color="#0F172A", lw=1.2), zorder=20)
    ax.text((p_w1[0] + p_w2[0])/2.0 + 0.35, (p_w1[1] + p_w2[1])/2.0 - 0.35,
            r"$w = 3.03\text{ mm}$", fontsize=9.0, fontweight="bold", color="#0F172A", zorder=21)

    p_s1 = iso(0.0, y_c1 + w_strip/2.0, h_sub)
    p_s2 = iso(0.0, y_c2 - w_strip/2.0, h_sub)
    ax.annotate("", xy=p_s1, xytext=p_s2,
                arrowprops=dict(arrowstyle="<->", color="#991B1B", lw=1.2), zorder=20)
    ax.text((p_s1[0] + p_s2[0])/2.0 + 0.35, (p_s1[1] + p_s2[1])/2.0 - 0.35,
            r"$s = 1.50\text{ mm}$", fontsize=9.0, fontweight="bold", color="#991B1B", zorder=21)

    p_h0 = iso(0.0, W_sub, 0.0)
    p_h1 = iso(0.0, W_sub, h_sub)
    p_h0_off = (p_h0[0] - 0.4, p_h0[1])
    p_h1_off = (p_h1[0] - 0.4, p_h1[1])
    ax.plot([p_h0[0], p_h0_off[0]], [p_h0[1], p_h0_off[1]], color="#64748B", lw=0.7, linestyle=":", zorder=18)
    ax.plot([p_h1[0], p_h1_off[0]], [p_h1[1], p_h1_off[1]], color="#64748B", lw=0.7, linestyle=":", zorder=18)
    ax.annotate("", xy=p_h0_off, xytext=p_h1_off,
                arrowprops=dict(arrowstyle="<->", color="#1E293B", lw=1.1), zorder=20)
    ax.text(p_h1_off[0] - 0.25, (p_h0_off[1] + p_h1_off[1])/2.0,
            r"$h = 1.575\text{ mm}$" + "\n" + r"($\varepsilon_r = 4.40$)",
            fontsize=8.5, fontweight="bold", color="#1E293B", ha="right", va="center", zorder=21)

    p_L0 = iso(0.0, 0.0, -t_gnd - 0.5)
    p_L1 = iso(L_sub, 0.0, -t_gnd - 0.5)
    ax.annotate("", xy=p_L0, xytext=p_L1,
                arrowprops=dict(arrowstyle="<->", color="#0F172A", lw=1.2), zorder=20)
    ax.text((p_L0[0] + p_L1[0])/2.0 + 0.3, (p_L0[1] + p_L1[1])/2.0 - 0.65,
            r"Comprimento Longitudinal $L_z \approx L_{\mathrm{beat}} = 59.7\text{ cm}$",
            fontsize=9.5, fontweight="bold", color="#0F172A", ha="center", zorder=21)

    p_gnd_label = iso(L_sub * 0.70, 0.0, -t_gnd / 2.0)
    ax.text(p_gnd_label[0] + 0.8, p_gnd_label[1] - 0.45,
            "Plano de Terra GND de Cobre ($y = 0$)", fontsize=8.8, fontweight="bold", color="#78350F",
            bbox=dict(boxstyle="round,pad=0.2", facecolor="#FFFBEB", edgecolor="#D97706", lw=1.0, alpha=0.95), zorder=25)

    p_top_corner = iso(L_sub, W_sub, h_sub)
    ax.text(0.5, p_top_corner[1] + 1.8, "Estrutura 3D Padronizada: Microfita Tripla (Figura 5.32 de Clayton Paul)",
            fontsize=12.5, fontweight="bold", color="#0972B6", ha="center", zorder=30)
    ax.text(0.5, p_top_corner[1] + 1.0, "Substrato Dielétrico FR-4 Verde, Plano de Terra GND e 3 Fitas de Cobre em 2.4 GHz",
            fontsize=9.5, color="#475569", ha="center", zorder=30)

    ax.set_xlim(-12.0, 15.5)
    ax.set_ylim(-2.5, p_top_corner[1] + 2.5)

    plt.tight_layout()

    out_pdf = os.path.join(DIR_OUTPUT, "Fig_Microstrip_Tripla_Multicondutora_3D.pdf")
    out_png = os.path.join(DIR_OUTPUT, "Fig_Microstrip_Tripla_Multicondutora_3D.png")

    fig.savefig(out_pdf, bbox_inches="tight", pad_inches=0.12)
    fig.savefig(out_png, bbox_inches="tight", dpi=300, pad_inches=0.12)
    plt.close(fig)

    print(f"✔ Imagens 3D geradas com sucesso:")
    print(f"  -> {out_pdf}")
    print(f"  -> {out_png}")
    print("="*80)

if __name__ == "__main__":
    main()
