Buckets:
| """ | |
| Créer une version améliorée de mesh_interactive_2d.html avec galerie d'images | |
| """ | |
| import plotly.graph_objects as go | |
| from dolfinx import mesh | |
| from mpi4py import MPI | |
| import numpy as np | |
| import base64 | |
| import os | |
| def image_to_base64(image_path): | |
| """Convertir une image en base64 pour l'inclure dans le HTML""" | |
| if os.path.exists(image_path): | |
| with open(image_path, 'rb') as img_file: | |
| return base64.b64encode(img_file.read()).decode('utf-8') | |
| return None | |
| def create_enhanced_2d_mesh_html(): | |
| """Créer un maillage 2D interactif avec galerie d'images""" | |
| # Créer un maillage | |
| domain = mesh.create_rectangle( | |
| MPI.COMM_WORLD, | |
| [np.array([0, 0]), np.array([2, 1])], | |
| [20, 10], | |
| mesh.CellType.triangle | |
| ) | |
| points = domain.geometry.x | |
| cells = domain.geometry.dofmap | |
| # Créer la figure plotly | |
| fig = go.Figure() | |
| # Ajouter les arêtes des triangles | |
| for cell_idx in range(len(cells)): | |
| cell_vertices = cells[cell_idx] | |
| vertices = np.append(cell_vertices, cell_vertices[0]) | |
| fig.add_trace(go.Scatter( | |
| x=points[vertices, 0], | |
| y=points[vertices, 1], | |
| mode='lines', | |
| line=dict(color='blue', width=0.5), | |
| showlegend=False, | |
| hoverinfo='skip' | |
| )) | |
| # Ajouter les nœuds | |
| fig.add_trace(go.Scatter( | |
| x=points[:, 0], | |
| y=points[:, 1], | |
| mode='markers', | |
| marker=dict(color='red', size=3), | |
| name='Nœuds', | |
| hovertemplate='Nœud: (%{x:.3f}, %{y:.3f})<extra></extra>' | |
| )) | |
| # Mise en forme | |
| fig.update_layout( | |
| title='Maillage 2D Interactif (Plotly)', | |
| xaxis_title='x', | |
| yaxis_title='y', | |
| hovermode='closest', | |
| width=1200, | |
| height=600, | |
| showlegend=True, | |
| plot_bgcolor='white', | |
| xaxis=dict(showgrid=True, gridcolor='lightgray'), | |
| yaxis=dict(scaleanchor="x", scaleratio=1, showgrid=True, gridcolor='lightgray') | |
| ) | |
| # Générer le HTML de base de Plotly | |
| plotly_html = fig.to_html(include_plotlyjs='cdn', div_id='plotly-div') | |
| # Liste des images à inclure | |
| images = [ | |
| { | |
| 'path': 'mesh_2d_rectangle.png', | |
| 'title': 'Maillage 2D Rectangle', | |
| 'description': 'Maillage 2D avec nœuds visibles' | |
| }, | |
| { | |
| 'path': 'mesh_2d_detailed.png', | |
| 'title': 'Vue Détaillée', | |
| 'description': 'Vue complète et zoom sur une région' | |
| }, | |
| { | |
| 'path': 'mesh_2d_numbered.png', | |
| 'title': 'Maillage Numéroté', | |
| 'description': 'Numéros de cellules et nœuds affichés' | |
| }, | |
| { | |
| 'path': 'mesh_anatomy_2x2.png', | |
| 'title': 'Anatomie du Maillage', | |
| 'description': 'Structure détaillée d\'un maillage 2×2' | |
| }, | |
| { | |
| 'path': 'mesh_refinement_comparison.png', | |
| 'title': 'Comparaison Raffinements', | |
| 'description': 'Effet du nombre d\'éléments (2×2 à 16×16)' | |
| }, | |
| { | |
| 'path': 'mesh_element_types.png', | |
| 'title': 'Types d\'Éléments', | |
| 'description': 'Triangles vs Quadrilatères' | |
| }, | |
| { | |
| 'path': 'mesh_quality_analysis.png', | |
| 'title': 'Analyse de Qualité', | |
| 'description': 'Rapport d\'aspect et angles minimaux' | |
| }, | |
| { | |
| 'path': 'viewer_mesh_full.png', | |
| 'title': 'Vue Complète', | |
| 'description': 'Maillage complet avec tous les détails' | |
| }, | |
| { | |
| 'path': 'viewer_mesh_zoom.png', | |
| 'title': 'Vue Zoomée', | |
| 'description': 'Détails d\'une région spécifique' | |
| } | |
| ] | |
| # Convertir les images en base64 | |
| images_base64 = [] | |
| for img_info in images: | |
| img_b64 = image_to_base64(img_info['path']) | |
| if img_b64: | |
| images_base64.append({ | |
| 'data': img_b64, | |
| 'title': img_info['title'], | |
| 'description': img_info['description'] | |
| }) | |
| # Créer le HTML complet avec galerie | |
| html_content = f""" | |
| <!DOCTYPE html> | |
| <html lang="fr"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Maillage 2D Interactif - FEniCS</title> | |
| <style> | |
| body {{ | |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| margin: 0; | |
| padding: 20px; | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| min-height: 100vh; | |
| }} | |
| .container {{ | |
| max-width: 1400px; | |
| margin: 0 auto; | |
| }} | |
| h1 {{ | |
| text-align: center; | |
| color: white; | |
| margin-bottom: 30px; | |
| text-shadow: 2px 2px 4px rgba(0,0,0,0.3); | |
| font-size: 2.5em; | |
| }} | |
| .plotly-container {{ | |
| background: white; | |
| border-radius: 15px; | |
| padding: 20px; | |
| margin-bottom: 40px; | |
| box-shadow: 0 8px 32px rgba(0,0,0,0.2); | |
| }} | |
| .gallery-title {{ | |
| color: white; | |
| font-size: 2em; | |
| margin: 40px 0 20px 0; | |
| text-align: center; | |
| text-shadow: 2px 2px 4px rgba(0,0,0,0.3); | |
| }} | |
| .gallery {{ | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); | |
| gap: 25px; | |
| margin-bottom: 40px; | |
| }} | |
| .gallery-item {{ | |
| background: rgba(255, 255, 255, 0.95); | |
| border-radius: 12px; | |
| overflow: hidden; | |
| box-shadow: 0 4px 15px rgba(0,0,0,0.2); | |
| transition: all 0.3s ease; | |
| cursor: pointer; | |
| }} | |
| .gallery-item:hover {{ | |
| transform: translateY(-8px); | |
| box-shadow: 0 8px 25px rgba(0,0,0,0.3); | |
| }} | |
| .gallery-item img {{ | |
| width: 100%; | |
| height: 250px; | |
| object-fit: contain; | |
| background: white; | |
| padding: 10px; | |
| }} | |
| .gallery-item-info {{ | |
| padding: 15px; | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: white; | |
| }} | |
| .gallery-item-title {{ | |
| font-size: 1.2em; | |
| font-weight: bold; | |
| margin-bottom: 8px; | |
| }} | |
| .gallery-item-description {{ | |
| font-size: 0.9em; | |
| opacity: 0.9; | |
| line-height: 1.4; | |
| }} | |
| .modal {{ | |
| display: none; | |
| position: fixed; | |
| z-index: 1000; | |
| left: 0; | |
| top: 0; | |
| width: 100%; | |
| height: 100%; | |
| background-color: rgba(0,0,0,0.9); | |
| overflow: auto; | |
| }} | |
| .modal-content {{ | |
| margin: 2% auto; | |
| display: block; | |
| max-width: 95%; | |
| max-height: 90vh; | |
| object-fit: contain; | |
| }} | |
| .close {{ | |
| position: absolute; | |
| top: 20px; | |
| right: 40px; | |
| color: #f1f1f1; | |
| font-size: 50px; | |
| font-weight: bold; | |
| cursor: pointer; | |
| transition: 0.3s; | |
| }} | |
| .close:hover {{ | |
| color: #bbb; | |
| }} | |
| .modal-caption {{ | |
| text-align: center; | |
| color: #ccc; | |
| padding: 20px; | |
| font-size: 1.2em; | |
| }} | |
| .back-button {{ | |
| display: inline-block; | |
| background: white; | |
| color: #667eea; | |
| padding: 12px 30px; | |
| border-radius: 25px; | |
| text-decoration: none; | |
| font-weight: bold; | |
| margin: 20px; | |
| transition: all 0.3s; | |
| }} | |
| .back-button:hover {{ | |
| background: #667eea; | |
| color: white; | |
| transform: scale(1.05); | |
| }} | |
| .info-box {{ | |
| background: rgba(255, 255, 255, 0.1); | |
| backdrop-filter: blur(10px); | |
| border-radius: 15px; | |
| padding: 20px; | |
| margin: 20px 0; | |
| color: white; | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| }} | |
| .info-box h3 {{ | |
| margin-top: 0; | |
| color: white; | |
| }} | |
| @media (max-width: 768px) {{ | |
| .gallery {{ | |
| grid-template-columns: 1fr; | |
| }} | |
| h1 {{ | |
| font-size: 1.8em; | |
| }} | |
| }} | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <a href="index.html" class="back-button">← Retour à l'accueil</a> | |
| <h1>🔬 Maillage 2D Interactif</h1> | |
| <div class="info-box"> | |
| <h3>📊 Visualisation Interactive</h3> | |
| <p>Cette visualisation montre un maillage 2D triangulaire généré avec FEniCS/DOLFINx. | |
| Utilisez votre souris pour zoomer et explorer le maillage. Survolez les nœuds pour voir leurs coordonnées.</p> | |
| <ul> | |
| <li><strong>Éléments:</strong> 400 triangles</li> | |
| <li><strong>Nœuds:</strong> 231 sommets</li> | |
| <li><strong>Type:</strong> Maillage structuré triangulaire</li> | |
| </ul> | |
| </div> | |
| <div class="plotly-container"> | |
| {plotly_html} | |
| </div> | |
| <h2 class="gallery-title">📸 Galerie d'Images - Visualisations Complémentaires</h2> | |
| <div class="info-box"> | |
| <h3>ℹ️ À propos de cette galerie</h3> | |
| <p>Voici différentes visualisations du maillage 2D montrant divers aspects techniques et pédagogiques. | |
| Cliquez sur une image pour la voir en grand.</p> | |
| </div> | |
| <div class="gallery"> | |
| """ | |
| # Ajouter les images à la galerie | |
| for idx, img in enumerate(images_base64): | |
| html_content += f""" | |
| <div class="gallery-item" onclick="openModal({idx})"> | |
| <img src="data:image/png;base64,{img['data']}" alt="{img['title']}"> | |
| <div class="gallery-item-info"> | |
| <div class="gallery-item-title">{img['title']}</div> | |
| <div class="gallery-item-description">{img['description']}</div> | |
| </div> | |
| </div> | |
| """ | |
| html_content += """ | |
| </div> | |
| </div> | |
| <!-- Modal pour afficher les images en grand --> | |
| <div id="imageModal" class="modal" onclick="closeModal()"> | |
| <span class="close">×</span> | |
| <img class="modal-content" id="modalImg"> | |
| <div class="modal-caption" id="modalCaption"></div> | |
| </div> | |
| <script> | |
| // Données des images | |
| const images = [ | |
| """ | |
| # Ajouter les données des images pour JavaScript | |
| for idx, img in enumerate(images_base64): | |
| comma = "," if idx < len(images_base64) - 1 else "" | |
| html_content += f""" | |
| {{ | |
| src: 'data:image/png;base64,{img['data']}', | |
| title: '{img['title']}', | |
| description: '{img['description']}' | |
| }}{comma} | |
| """ | |
| html_content += """ | |
| ]; | |
| function openModal(index) { | |
| const modal = document.getElementById('imageModal'); | |
| const modalImg = document.getElementById('modalImg'); | |
| const caption = document.getElementById('modalCaption'); | |
| modal.style.display = 'block'; | |
| modalImg.src = images[index].src; | |
| caption.innerHTML = `<strong>${images[index].title}</strong><br>${images[index].description}`; | |
| } | |
| function closeModal() { | |
| document.getElementById('imageModal').style.display = 'none'; | |
| } | |
| // Fermer avec Escape | |
| document.addEventListener('keydown', function(e) { | |
| if (e.key === 'Escape') { | |
| closeModal(); | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> | |
| """ | |
| # Sauvegarder le fichier | |
| with open('mesh_interactive_2d.html', 'w', encoding='utf-8') as f: | |
| f.write(html_content) | |
| print("✓ Fichier mesh_interactive_2d.html créé avec galerie d'images") | |
| print(f" - {len(images_base64)} images incluses") | |
| print(" - Visualisation Plotly interactive") | |
| print(" - Galerie modale cliquable") | |
| if __name__ == "__main__": | |
| create_enhanced_2d_mesh_html() | |
Xet Storage Details
- Size:
- 12.7 kB
- Xet hash:
- 91d64e059fdc2dcd104c4036271ae11821354f26f31df37f178e557d9e8cc0b6
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.