import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from scipy.spatial import ConvexHull
import warnings
warnings.filterwarnings('ignore')

# Leer el archivo manualmente
data = []
with open('resultados1.txt', 'r', encoding='utf-8') as f:
    header = f.readline().strip().split('\t')
    for line in f:
        values = line.strip().split()
        if len(values) >= 15:
            data.append(values)

# Convertir datos
def convert_value(x):
    try:
        return float(x.replace(',', '.').strip())
    except:
        return np.nan

tf = np.array([convert_value(row[2]) for row in data])
tw = np.array([convert_value(row[3]) for row in data])
flecha = np.array([convert_value(row[8]) for row in data])

# Filtrar NaN
valid = ~(np.isnan(tf) | np.isnan(tw) | np.isnan(flecha))
tf = tf[valid]
tw = tw[valid]
flecha = flecha[valid]

# RESTRICCIÓN DE DISEÑO
LIMITE_FLECHA = -25.0

# Separar válidos e inválidos
valid_idx = flecha >= LIMITE_FLECHA
invalid_idx = flecha < LIMITE_FLECHA

tf_valid = tf[valid_idx]
tw_valid = tw[valid_idx]
flecha_valid = flecha[valid_idx]

tf_invalid = tf[invalid_idx]
tw_invalid = tw[invalid_idx]
flecha_invalid = flecha[invalid_idx]

print("="*80)
print("VISUALIZACIÓN 3D CON PLANO DE RESTRICCIÓN DE DISEÑO")
print("="*80)
print(f"\nRestriction: Flecha_Media >= {LIMITE_FLECHA} mm")
print(f"Valid points: {len(tf_valid)} ({100*len(tf_valid)/len(tf):.1f}%)")
print(f"Invalid points: {len(tf_invalid)} ({100*len(tf_invalid)/len(tf):.1f}%)")

# Crear figura con múltiples vistas
fig = plt.figure(figsize=(20, 14))

# Definir plano de restricción
xx = np.linspace(tf.min(), tf.max(), 30)
yy = np.linspace(tw.min(), tw.max(), 30)
XX, YY = np.meshgrid(xx, yy)
ZZ = np.full_like(XX, LIMITE_FLECHA)

# Vista 1: Ángulo 45°
ax1 = fig.add_subplot(2, 3, 1, projection='3d')
ax1.plot_surface(XX, YY, ZZ, alpha=0.25, color='orange', label='Plano de restricción')
ax1.plot_wireframe(XX, YY, ZZ, color='darkorange', alpha=0.4, linewidth=0.5)
ax1.scatter(tf_invalid, tw_invalid, flecha_invalid, c='red', marker='x', s=80, alpha=0.4, label='Inválidos')
ax1.scatter(tf_valid, tw_valid, flecha_valid, c='lightgreen', marker='o', s=60, alpha=0.6, edgecolors='darkgreen', linewidth=0.3, label='Válidos')
ax1.set_xlabel('tf (mm)', fontweight='bold')
ax1.set_ylabel('tw (mm)', fontweight='bold')
ax1.set_zlabel('Flecha (mm)', fontweight='bold')
ax1.set_title('Vista 45°', fontweight='bold', fontsize=11)
ax1.view_init(elev=20, azim=45)
ax1.legend(fontsize=9, loc='upper left')

# Vista 2: Ángulo 135°
ax2 = fig.add_subplot(2, 3, 2, projection='3d')
ax2.plot_surface(XX, YY, ZZ, alpha=0.25, color='orange')
ax2.plot_wireframe(XX, YY, ZZ, color='darkorange', alpha=0.4, linewidth=0.5)
ax2.scatter(tf_invalid, tw_invalid, flecha_invalid, c='red', marker='x', s=80, alpha=0.4)
ax2.scatter(tf_valid, tw_valid, flecha_valid, c='lightgreen', marker='o', s=60, alpha=0.6, edgecolors='darkgreen', linewidth=0.3)
ax2.set_xlabel('tf (mm)', fontweight='bold')
ax2.set_ylabel('tw (mm)', fontweight='bold')
ax2.set_zlabel('Flecha (mm)', fontweight='bold')
ax2.set_title('Vista 135°', fontweight='bold', fontsize=11)
ax2.view_init(elev=20, azim=135)

# Vista 3: Vista desde arriba (proyección 2D)
ax3 = fig.add_subplot(2, 3, 3, projection='3d')
ax3.plot_surface(XX, YY, ZZ, alpha=0.25, color='orange')
ax3.plot_wireframe(XX, YY, ZZ, color='darkorange', alpha=0.4, linewidth=0.5)
ax3.scatter(tf_invalid, tw_invalid, flecha_invalid, c='red', marker='x', s=80, alpha=0.4)
ax3.scatter(tf_valid, tw_valid, flecha_valid, c='lightgreen', marker='o', s=60, alpha=0.6, edgecolors='darkgreen', linewidth=0.3)
ax3.set_xlabel('tf (mm)', fontweight='bold')
ax3.set_ylabel('tw (mm)', fontweight='bold')
ax3.set_zlabel('Flecha (mm)', fontweight='bold')
ax3.set_title('Vista Cenital (Desde arriba)', fontweight='bold', fontsize=11)
ax3.view_init(elev=85, azim=45)

# Vista 4: Proyección tf vs Flecha
ax4 = fig.add_subplot(2, 3, 4)
ax4.axhline(y=LIMITE_FLECHA, color='orange', linewidth=3, linestyle='--', label=f'Plano restricción (z={LIMITE_FLECHA})')
ax4.axhspan(flecha_invalid.min() if len(flecha_invalid) > 0 else -100, LIMITE_FLECHA, alpha=0.2, color='red', label='Región inválida')
ax4.axhspan(LIMITE_FLECHA, flecha_valid.max() if len(flecha_valid) > 0 else 0, alpha=0.2, color='green', label='Región válida')
ax4.scatter(tf_invalid, flecha_invalid, c='red', marker='x', s=100, alpha=0.5, linewidth=2, label=f'Puntos inválidos ({len(tf_invalid)})')
ax4.scatter(tf_valid, flecha_valid, c='lightgreen', marker='o', s=80, alpha=0.6, edgecolors='darkgreen', linewidth=0.5, label=f'Puntos válidos ({len(tf_valid)})')
ax4.set_xlabel('tf - Espesor ala (mm)', fontweight='bold')
ax4.set_ylabel('Flecha_Media (mm)', fontweight='bold')
ax4.set_title('Proyección 2D: tf vs Flecha', fontweight='bold', fontsize=11)
ax4.grid(True, alpha=0.3)
ax4.legend(fontsize=9)
ax4.set_xlim(tf.min()-0.01, tf.max()+0.01)

# Vista 5: Proyección tw vs Flecha
ax5 = fig.add_subplot(2, 3, 5)
ax5.axhline(y=LIMITE_FLECHA, color='orange', linewidth=3, linestyle='--', label=f'Plano restricción (z={LIMITE_FLECHA})')
ax5.axhspan(flecha_invalid.min() if len(flecha_invalid) > 0 else -100, LIMITE_FLECHA, alpha=0.2, color='red', label='Región inválida')
ax5.axhspan(LIMITE_FLECHA, flecha_valid.max() if len(flecha_valid) > 0 else 0, alpha=0.2, color='green', label='Región válida')
ax5.scatter(tw_invalid, flecha_invalid, c='red', marker='x', s=100, alpha=0.5, linewidth=2, label=f'Puntos inválidos ({len(tw_invalid)})')
ax5.scatter(tw_valid, flecha_valid, c='lightgreen', marker='o', s=80, alpha=0.6, edgecolors='darkgreen', linewidth=0.5, label=f'Puntos válidos ({len(tw_valid)})')
ax5.set_xlabel('tw - Espesor alma (mm)', fontweight='bold')
ax5.set_ylabel('Flecha_Media (mm)', fontweight='bold')
ax5.set_title('Proyección 2D: tw vs Flecha', fontweight='bold', fontsize=11)
ax5.grid(True, alpha=0.3)
ax5.legend(fontsize=9)
ax5.set_xlim(tw.min()-0.01, tw.max()+0.01)

# Vista 6: Proyección tf vs tw (plano horizontal)
ax6 = fig.add_subplot(2, 3, 6)
scatter_invalid_2d = ax6.scatter(tf_invalid, tw_invalid, c='red', marker='x', s=100, alpha=0.5, linewidth=2, label=f'Inválidos ({len(tf_invalid)})')
scatter_valid_2d = ax6.scatter(tf_valid, tw_valid, c='lightgreen', marker='o', s=80, alpha=0.6, edgecolors='darkgreen', linewidth=0.5, label=f'Válidos ({len(tf_valid)})')
ax6.set_xlabel('tf - Espesor ala (mm)', fontweight='bold')
ax6.set_ylabel('tw - Espesor alma (mm)', fontweight='bold')
ax6.set_title('Proyección 2D: tf vs tw', fontweight='bold', fontsize=11)
ax6.grid(True, alpha=0.3)
ax6.legend(fontsize=9)

plt.suptitle(f'Análisis de Restricción de Diseño: Flecha_Media ≥ {LIMITE_FLECHA} mm', 
             fontsize=14, fontweight='bold', y=0.995)
plt.tight_layout(rect=[0, 0, 1, 0.99])
plt.savefig('multiples_vistas_restriccion.png', dpi=300, bbox_inches='tight')
print("\n✓ Visualización guardada como 'multiples_vistas_restriccion.png'")

# Crear gráfico de comparación: válido vs inválido
fig2, axes = plt.subplots(1, 3, figsize=(16, 5))

# Histogramas de distribuciones
axes[0].hist(flecha_invalid, bins=20, alpha=0.6, color='red', label='Inválidos', edgecolor='darkred')
axes[0].hist(flecha_valid, bins=20, alpha=0.6, color='green', label='Válidos', edgecolor='darkgreen')
axes[0].axvline(x=LIMITE_FLECHA, color='orange', linewidth=3, linestyle='--', label=f'Límite = {LIMITE_FLECHA} mm')
axes[0].set_xlabel('Flecha_Media (mm)', fontweight='bold')
axes[0].set_ylabel('Frecuencia', fontweight='bold')
axes[0].set_title('Distribución de Deflexiones', fontweight='bold')
axes[0].legend()
axes[0].grid(True, alpha=0.3)

# Comparación de ranges
categories = ['tf (ala)', 'tw (alma)', 'Flecha']
valid_min = [tf_valid.min(), tw_valid.min(), flecha_valid.min()]
valid_max = [tf_valid.max(), tw_valid.max(), flecha_valid.max()]
invalid_min = [tf_invalid.min(), tw_invalid.min(), flecha_invalid.min()]
invalid_max = [tf_invalid.max(), tw_invalid.max(), flecha_invalid.max()]

x = np.arange(len(categories))
width = 0.2

bars1 = axes[1].bar(x - width*1.5, valid_min, width, label='Válidos (mín)', color='lightgreen', edgecolor='darkgreen')
bars2 = axes[1].bar(x - width/2, valid_max, width, label='Válidos (máx)', color='darkgreen', edgecolor='black')
bars3 = axes[1].bar(x + width/2, invalid_min, width, label='Inválidos (mín)', color='lightcoral', edgecolor='darkred')
bars4 = axes[1].bar(x + width*1.5, invalid_max, width, label='Inválidos (máx)', color='darkred', edgecolor='black')

axes[1].set_ylabel('Valor', fontweight='bold')
axes[1].set_title('Rango de Valores por Región', fontweight='bold')
axes[1].set_xticks(x)
axes[1].set_xticklabels(categories)
axes[1].legend(fontsize=9)
axes[1].grid(True, alpha=0.3, axis='y')

# Estadísticas resumen
axes[2].axis('off')
stats_text = f"""RESUMEN DE RESTRICCIÓN DE DISEÑO

Límite de Deflexión: Flecha_Media ≥ {LIMITE_FLECHA} mm

PUNTOS VÁLIDOS (Flecha ≥ {LIMITE_FLECHA}):
  • Cantidad: {len(tf_valid)} puntos ({100*len(tf_valid)/len(tf):.1f}%)
  • tf range: [{tf_valid.min():.6f}, {tf_valid.max():.6f}] mm
  • tw range: [{tw_valid.min():.6f}, {tw_valid.max():.6f}] mm
  • Flecha range: [{flecha_valid.min():.2f}, {flecha_valid.max():.2f}] mm

PUNTOS INVÁLIDOS (Flecha < {LIMITE_FLECHA}):
  • Cantidad: {len(tf_invalid)} puntos ({100*len(tf_invalid)/len(tf):.1f}%)
  • tf range: [{tf_invalid.min():.6f}, {tf_invalid.max():.6f}] mm
  • tw range: [{tw_invalid.min():.6f}, {tw_invalid.max():.6f}] mm
  • Flecha range: [{flecha_invalid.min():.2f}, {flecha_invalid.max():.2f}] mm

TOTAL: {len(tf)} puntos
"""
axes[2].text(0.1, 0.95, stats_text, transform=axes[2].transAxes, fontsize=10,
            verticalalignment='top', fontfamily='monospace',
            bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.8))

plt.suptitle('Comparación de Regiones: Válida vs Inválida', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.savefig('comparacion_regiones.png', dpi=300, bbox_inches='tight')
print("✓ Comparación guardada como 'comparacion_regiones.png'")

print("\n" + "="*80)
print("ARCHIVOS GENERADOS:")
print("="*80)
print("  1. grafico_3d_pareto_con_restriccion.png - Vista 3D con plano de restricción")
print("  2. multiples_vistas_restriccion.png - 6 vistas diferentes del problema")
print("  3. comparacion_regiones.png - Análisis comparativo de regiones")
print("="*80)

plt.show()
