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