Simulateur Ferroviaire
Reconstruction et visualisation d'un réseau ferroviaire à partir de données GeoJSON — Win32 / WebView2 / Leaflet
Chargement...
Recherche...
Aucune correspondance
Engine — Moteur de l'application

Core — Cœur applicatif

Gestion des composants fondamentaux et de la logique applicative transverse.

Classe Rôle
Application Cycle de vie Win32 (enregistrement de classe, boucle de messages)
Logger Journalisation structurée (INFO / DEBUG / WARNING / ERROR / FAILURE)
TopologyData Conteneur std::unique_ptr<StraightBlock> + std::unique_ptr<SwitchBlock> + index de lookup
TopologyRepository Singleton (Meyers). Accès global à TopologyData via TopologyRepository::instance().data()
TopologyRenderer Classe statique — génère les scripts JS d'injection pour le WebView Leaflet

TopologyData

Pourquoi std::unique_ptr ? Les blocs sont polymorphes (Element*). Le stockage par valeur entraînerait du slicing et interdirait le déplacement. Le stockage par std::unique_ptr garantit :

  • polymorphisme correct (destructeur virtuel respecté),
  • propriété exclusive et cycle de vie déterministe,
  • interdiction de copie accidentelle.

TopologyData expose deux index construits en fin de pipeline via buildIndex() :

Index Type Usage
TopologyData::switchIndex std::unordered_map<string, SwitchBlock*> Lookup O(1) par ID
TopologyData::straightIndex std::unordered_map<string, StraightBlock*> Lookup O(1) par ID

buildIndex() doit être appelé après que toutes les adresses sont stables. clear() vide également les index.

TopologyRenderer

TopologyRenderer est une classe statique qui :

Méthode Rôle
renderAllStraightBlocks() Efface et redessine tous les StraightBlock
renderAllSwitchBranches() Efface et redessine toutes les branches de switch
renderAllSwitchBlocksJunctions() Efface et redessine tous les marqueurs de jonction
updateSwitchBlocks() Met à jour visuellement un switch et ses partenaires double
exportToFile() Export GeoJSON complet vers un fichier

HMI — Interface utilisateur

Couche graphique Win32 + WebView2.

Classe Rôle
MainWindow Fenêtre principale, routage des messages Win32, coordination UI ↔ métier
ProgressBar Wrapper du contrôle natif PROGRESS_CLASS
WebViewPanel Affichage cartographique Leaflet embarqué via WebView2
PCCPanel Panneau PCC superposé togglable (F2 / menu Vue), child window Win32
TCORenderer Renderer GDI statique du schéma TCO — consomme PCCGraph
AboutDialog Boîte de dialogue modale "À propos"
FileOpenDialog Sélecteur de fichier GeoJSON (GetOpenFileNameA)
FileSaveDialog Dialogue de sauvegarde GeoJSON (GetSaveFileNameA)

Panneau PCC

Le panneau PCC est une WS_CHILD window superposée au WebViewPanel, togglée via F2 ou le menu Vue → Panneau PCC. Il est masqué par défaut et ne perturbe pas la carte Leaflet.

PCCPanel possède un PCCGraph qu'il reconstruit à chaque chargement GeoJSON via PCCGraphBuilder et PCCLayout. Le rendu est délégué à TCORenderer. Le logger HMI est partagé par injection de référence depuis MainWindow.

Séquence d'appel complète :

MainWindow::onParsingSuccess()
├─► m_webViewPanel.executeScript(...) — rendu Leaflet inchangé
└─► m_pccPanel.refresh()
├─► rebuild()
│ ├─► build(m_graph, m_logger)
│ └─► compute(m_graph, m_logger)
└─► InvalidateRect() → WM_PAINT
└─► draw(hdc, rc, m_graph, m_logger)

Cycle de vie :

Méthode Déclencheur
PCCPanel::create() MainWindow::create() — après WebViewPanel::create()
PCCPanel::toggle() F2 ou IDM_VIEW_PCC — place le panneau en HWND_TOP
PCCPanel::resize() MainWindow::onSizeUpdate()
PCCPanel::refresh() MainWindow::onParsingSuccess()

TCORenderer

Classe utilitaire statique. Consomme const PCCGraph& — n'accède pas à TopologyRepository.

Conventions de couleurs (style TCO SNCF) :

État Couleur
Fond Noir RGB(0,0,0)
Voie libre (FREE) Blanc cassé RGB(220,220,220)
Voie occupée (OCCUPIED) Rouge RGB(220,50,50)
Voie inactive (INACTIVE) Gris RGB(80,80,80)
Branche normale active Vert RGB(0,200,80)
Branche déviation active Jaune RGB(220,200,0)

Projection positions logiques X/Y → pixels :

pixelX = marginX + logicalX * cellWidth
pixelY = centerY - logicalY * cellHeight (Y inversé)
Méthode Rôle
draw() Point d'entrée — fond + arêtes + nœuds
computeProjection() Calcul bornes X/Y logiques et taille des cellules
drawEdges() Un segment GDI par PCCEdge, colorisé par rôle et état
drawNodes() Un disque GDI par PCCNode

Binding bidirectionnel Leaflet ↔ C++

C++ → Leaflet : WebViewPanel::executeScript() injecte des appels JS générés par TopologyRenderer.

Leaflet → C++ : window.chrome.webview.postMessage()WebViewPanel::onWebMessageReceived()MainWindow::onWebMessage().

Clic sur jonction switch
→ postMessage({type:"switch_click", id:"sw/0"})
→ MainWindow::onSwitchClick() [switchIndex.find() O(1)]
→ SwitchBlock::toggleActiveBranch() [+ propagation partenaires]
→ TopologyRenderer::updateSwitchBlocks()
→ WebViewPanel::executeScript()
→ window.switchApplyState()
type Champs Handler C++
switch_click id MainWindow::onSwitchClick()

Coordonnées

Classe Système
CoordinateLatLon Géographique WGS-84 (latitude, longitude)
CoordinateXY Métrique UTM (x = est, y = nord)