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