Voir les contributions

Cette section vous permet de consulter les contributions (messages, sujets et fichiers joints) d'un utilisateur. Vous ne pourrez voir que les contributions des zones auxquelles vous avez accès.


Messages - Pierre59

Pages: 1 ... 16 17 [18] 19 20 ... 23
256
Bonjour

Bonne idée que d'utiliser des patrons de conception. J'ai déjà proposé sur le forum un patron de conception "observateur".

Pour résoudre les problèmes de visibilité en général on passe aux méthodes des classes états un pointeur sur la classe qui implémente la machine à états.

Cordialement

Pierre

257
Vos projets / Re : TCO avec Processing
« le: mars 23, 2019, 09:05:06 am »
Bonjour

Ce problème avec P2D est assez récurrent, pour le régler, dans les nouvelles versions du TCO, j'ai abandonné les formes (PShape) au profit de courbes de Bezier dessinées avec un tracé épais, le résultat pour l'affichage est strictement le même, mais c'est beaucoup plus simple et offre de nombreuses possibilités que je suis en train d'exploiter.

J'en parlerai bientôt. En attendant je peux assez facilement modifier l'onglet "Formes" du TCO, pour inclure ces nouveaux dessins des pavés. Si frdechaume veut bien m'envoyer son programme je le modifierai.

Cordialement

Pierre

258
Les itinéraires pas si faciles que cela en a l'air.

Avec une bonne représentation de la topologie d'un réseau il est assez facile de trouver des chemins entre une voie d'origine et une voie de destination. Avec toutefois deux problèmes classiques :

- en général il y a plusieurs chemins possibles (sur des réseaux pas trop simples) et il faut faire un choix

- il faut éviter les bouclages (beaucoup de nos réseaux sont en boucle)

Un chemin n'est pas forcement un itinéraire. A la SNCF un itinéraire part d'une voie avec un signal CARRE, dans le sens du signal, pour aller vers une voie répertoriée comme fin d'un itinéraire (voies à quai, voies de départ ou d'arrivée, voies de garage, tiroirs, …), voie qui n'a pas forcément de signal. Il faut aussi que toutes les voies empruntées par l'itinéraire soient parcourables dans le sens de l'itinéraire.

Un itinéraire tel que défini précédemment ne sert pas à grand chose, il faut pouvoir l'établir et aussi le détruire. L'établissement nécessite deux phases :

- vérification que l'itinéraire est établissable (vérification des enclanchements)
- établissement effectif de l'itinéraire (manoeuvre des aiguilles et des signaux)

Pour qu'un itinéraire soit établissable plusieurs conditions sont nécessaires :

- pas de cisaillement ou de nez à nez avec d'autres itinéraires déja établis
- en transit rigide toutes les zones de l'itinéraire doivent êtres libres
- en transit souple des zones peuvent êtres occupées, mais les signaux doivent pouvoir présenter le sémaphore
- la zone de la voie d'arrivée doit être libre (pas de train), sinon il faut que le signal à l'origine de l'itinéraire puisse présenter un feu manoeuvre (blanc lunaire)

Si l'itinéraire est établissable alors il faut manoeuvrer les aiguilles, puis ouvrir le ou les signaux en présentant les bons feux.

Un itinéraire est détruit automatiquement par le passage d'un train, mais il doit pouvoir être détruit manuellement sous conditions :

- pas d'enclanchement d'approche (train ayant vu l'avertissement du carré ouvert)
- pas de zones occupées (pas de train dessus)

Il peut être pratique de pouvoir enregistrer les itinéraires non établissables (voire de les sur-enregistrer).

Certains appareils de voie (TJD, TJS, aiguille triple ou croisement) peuvent compliquer la définition de la topologie du réseau ainsi que l'établissement des itinéraires.

Cordialement

Pierre

259
Discussions ouvertes / Patron de conception
« le: février 07, 2019, 03:43:54 pm »
Bonjour

Je vais vous parler ici des "Patrons de Conception" (Design Pattern) en langage orienté objet et tout particulièrement du patron "observateur". Un patron de conception est une solution standard, indépendante du langage, pour résoudre un problème de conception. L'idée, pour le patron observateur, est qu'un objet puisse observer un autre objet pour savoir quand son état change. Il y a deux approches possibles :

- soit l'objet observateur teste périodiquement l'objet observé
- soit l'objet observé notifie son changement à l'objet observateur

Pour la première solution ce qui peut venir à l'esprit est de questionner périodiquement l'objet observé, c'est de l'attente active, elle peut être éventuellement déléguée à un thread, mais outre la consommation de ressources elle présente un temps de latence dû au questionnement périodique. Ce n'est pas la bonne solution.

La deuxième solution est plus intéressante mais plus technique à mettre en oeuvre, elle a l'avantage de ne pas gaspiller de ressources et de ne pas avoir de temps de latence.L'objet observé notifie directement son changement d'état.

Tous les exemples seront donnés en C++ (pas en Arduino) et Processing (Java), juste pour pouvoir faire facilement des affichages.

Patron de conception observateur

Le patron de conception observateur (Design pattern Observer) donne une solution très souple pour réaliser ces échanges d'information entre deux objets et plus généralement entre des objets hétérogènes.

Partons sur deux objets pour commencer, l'objet qui observe l'autre est l'observateur, l'autre est l'observé. Il va falloir des nouvelles classe pour préciser les méthodes standard utilisée et donner des types à nos deux objets (pour le polymorphisme).

Commençons par l'observateur, celui ci a juste besoin d'une méthode qui sera appelée par l'observé quand son état change, l'observé n'a pas à savoir ce que l'observateur fera de l'information, c'est à l'observateur d'implémenter l'utilisation de cette information. Pour rendre le mécanisme général on a besoin d'une classe abstraite :

class Observateur { // observe les changements d'etat d'un objet
public:
virtual void etatChange(Observable* o)=0; // methode appelee sur l'observateur lors de changement d'etat
};

----------

interface Observateur { // observe les changements d'etat d'un objet
  void etatChange(Observable o); // methode appelee sur l'Observateur lors de changement d'etat
}

En C++ une classe abstraite se fait avec une méthode virtuelle dite pure ( =0; ). La méthode abstraite etatChange() a un paramètre  pointeur sur un objet observé (avec le polymorphisme, n'importe quel objet pourra être utilisé). En Java qui n'a pas d'héritage multiple, une classe n'ayant que des méthodes abstraites est un interface (permettant ainsi un ersatz d' héritage multiple indispensable ici).

Passons à l'observé, il a besoin d'une méthode pour notifier un changement à l'observateur, il faut aussi une méthode pour permettre à l'observateur de s'enregistrer auprès de lui. Plus délicat il faut une structure de données pour mémoriser les différents observateurs (il peut en avoir un nombre quelconque et de type quelconque). Un simple tableau ne convient pas, il faut un tableau extensible, fortuitement on trouve de tels objets en bibliothèque, "vecteur" en C++, "ArrayList" en Java. Cela donne :

class Observable {
vector<Observateur*> observateurs; // liste des observateurs

public:
void ajouterObservateur(Observateur* e) { observateurs.push_back(e); } // ajouter un observateur
    void notifier(bool b) { for (auto & e : observateurs) e->etatChange(this); } // notifier aux observateurs
};

----------

class Observable {
  ArrayList<Observateur> Observateurs=new ArrayList<Observateur>(); // liste des Observateurs
 
  void ajouterObservateur(Observateur e) { Observateurs.add(e); } // ajouter un Observateur
  void notifier(boolean b) { for (Observateur e: Observateurs) e.etatChange(this); } // notifier aux Observateurs
}

La méthode ajouterObservateur() rajoute le pointeur sur l'observateur au tableau extensible, la méthode notifier() appelle la méthode etatChange() sur tous les observateurs (noter le paramètre qui fourni à l'observateur un pointeur sur l'objet à l'initiative du changement d'état). En Java c'est très semblable à la version en C++, sauf pour la gestion des pointeurs et de l'écriture du "forall".

Utilisation

Voyons quelques exemples d'utilisation (inspirés du gestionnaire du Locoduinodrome), commençons par le dialogue entre une balise et une zone, pour cela il faut deux classes une pour les balises et une pour les zones :

class Balise : public Observateur {
bool etat=false;
public:
Balise(Zone& zone) { zone.ajouterObservateur(this); } // constructeur

void etatChange(Observable* o) { cout<<"balise : la zone observee a change\n"; }
};

class Zone : public Observable {
bool etat=false;
public:
Zone() {} // constructeur

void occuper() { etat=true;}
void liberer() { etat=false; notifier(etat); }
};

----------

class Balise implements Observateur {
  boolean etat=false;
  Balise(Zone z) { z.ajouterObservateur(this); } // constructeur
 
  void etatChange(Observable o) { println("balise : la zone observee a change"); } 
}

class Zone extends Observable {
  boolean etat=false;
 
  Zone() {} // constructeur
 
  void occuper() { etat=true;}
  void liberer() { etat=false; notifier(etat); }
}

La classe balise hérite de la classe abstraite Observateur et implémente la méthode abstraite etatChange(), méthode qui fait ici juste un affichage. Le constructeur reçoit une zone en paramètre et s'enregistre auprès de cette zone comme observateur.

La classe Zone hérite de la classe Observable qui lui fournit la gestion toute faite de la liste des observateurs. La méthode liberer() notifie l'information à tous les observateurs.

Reste plus que à faire un essai, pour cela il faut au moins une instance de Balise et une instance de Zone :

Zone zone;
Balise balise(zone);

----------

Zone zone=new Zone();
Balise balise=new Balise(zone);

on obtient à l'exécution dans la console :

balise : la zone observee a change
Bien évidemment on pourrait afficher aussi le nom des zones si elles avaient un nom. On pourrait aussi enregistrer d'autres balises sur d'autres zones (ou la même).

Autre utilisation

Les itinéraires ont aussi besoin de la libération des zones pour se détruire (libération de la dernière zone de l'itinéraire). On écrit facilement une classe Itineraire (sur le modèle de Balise) :

class Itineraire : public Observateur {
public:
Itineraire(Zone& zone) { zone.ajouterObservateur(this); } // constructeur

void etatChange(Observable* o) { cout<<"itineraire : detruit\n"; }
};

----------

class Itineraire implements Observateur {
 
  Itineraire(Zone zone) { zone.ajouterObservateur(this); } // constructeur

  void etatChange(Observable o) { println("itineraire : detruit"); }
}

il faut une instance :

Itineraire itineraire;

----------

Itineraire itineraire=new Itineraire();

et cela donne :

balise : la zone a change
itineraire : detruit

On a mis dans la liste des observés deux types différents, des balises et des itinéraires, c'est tout à fait normal car les balises et les itinéraires ont tous un type commun Observateur (on joue sur le polymorphisme). Ceci est rendu possible par le subtil jeu des types des classes Observateur et Observable et l'héritage multiple (ceci est un bon exemple de son utilité).

Dernière utilisation

Supposons que les zones aient besoin de savoir quand une aiguille est bougée. Il faut une classe Aiguille, sur le modèle de Zone :

class Aiguille : public Observable {
bool etat;
public:
void manoeuvrer() { etat=!etat; notifier(etat); }
};

----------

class Aiguille extends Observable {
  boolean etat;
 
  void manoeuvrer() { etat=!etat; notifier(etat); }
}

Maintenant zone devient aussi un observateur tout en continuant d'être observable, cela donne :

class Zone : public Observable,Observateur {
bool etat=false;
public:
Zone(Aiguille& aiguille) { aiguille.ajouterObservateur(this); } // constructeur

void etatChange(Observable* o) { cout<<"zone : l'aiguille a change\n"; }

void occuper() { etat=true;}
void liberer() { etat=false; notifier(etat); }
};

----------

class Zone extends Observable implements Observateur {
  boolean etat=false;
 
  Zone(Aiguille aiguille) {aiguille.ajouterObservateur(this); } // constructeur
 
  void occuper() { etat=true;}
  void liberer() { etat=false; notifier(etat); }

  void etatChange(Observable o) { println("zone : l'aiguille a change"); } 
}

zone hérite de deux classe (héritage multiple) donc a trois types pour l'objet : Zone,  Observable et Observateur

Bilan

Ce patron est très souple mais très puissant, il permet des évolutions faciles à mettre en oeuvre. Dans la classe Observable on pourrait avoir plus de méthodes pour gérer la liste des observateurs (suppression par exemple …). On peut aussi spécialiser par héritage les classes Observateur et Observable.

Ce patron est utilisé dans les interfaces graphiques pour gérer les évènements, de souris par exemple. Il pourrait être aussi utilisé dans un gestionnaire de réseau.

Pierre

260
Bonjour

On peut même mettre des méthodes dans les structures. Mais pas de protections ni d'héritage possibles.

Pierre

261
Bonjour

Un exemple simple et petit de polymorphisme se trouve dans SlowMotionServo.
C'est certes écrit tout à fait comme il faut vis à vis de la programmation objet, mais cela ne peut pas vraiment servir comme exemple simple dans un cours. Il y a bien les bonnes bases, une classe abstraite, au moins une classe dérivée et une utilisation d'objets polymorphes. Mais j'y vois de gros inconvénients :

- c'est beaucoup trop compliqué, car "pollué" par beaucoup de code non en rapport avec la POO et laborieux à expliquer.

- c'est pas vraiment convaincant vis à vis de l'héritage et du polymorphisme. Cela s'écrit trop facilement sans héritage avec un simple "switch", alors pourquoi faire l'effort de passer à la POO (c'est quand même difficile !). Un bon exemple devrait montrer l'intérêt de la POO en évitant de nombreux tests un peu partout dans le code.

- cela ne montre pas le fait que l'on puisse rajouter facilement des objets sans retoucher au reste du programme.

- …

J'ai des exemples qui conviennent mieux et qui sont plus abordables, mais il faut une page de programme, donc ce n'est pas vraiment simple.

Amicalement

Pierre

262
Bonjour

Je suis tout à fait d'accord que la POO n'est pas liée à un langage particulier, mais pour pratiquer ou pour communiquer des exemples il faut bien choisir un langage. En ce sens C++ n'est pas le meilleur choix, il offre trop de possibilités dans les passages de paramètres et les résultats (par valeur, référence, pointeurs, …), il y a aussi des contraintes dans l'ordre des déclarations, des difficulté pour gérer la mémoire (free, destructeurs, …) … ce qui conduit à prendre en compte des problèmes techniques pas toujours simples à résoudre. Si on veut faire de la POO en C++, je pense que le plus simple est d'utiliser systématiquement des pointeurs sur les objets et se restreindre au minimum nécessaire. Je sais que les pointeurs peuvent effrayer certains, mais c'est indispensable pour profiter pleinement du polymorphisme.

Je rappelle que la POO est basée sur trois principes essentiels : l'encapsulation, l'héritage et le polymorphisme et que c'est le polymorphisme qui donne toute sa puissance à la POO (malheureusement je n'ai jamais trouvé un exemple simple pour illustrer le polymorphisme) :

- l'encapsulation c'est le regroupement de variables et des bouts de programme manipulant ces variables (sous forme fonctions) sous forme d'objets. Elle donne aussi des types aux objets permettant au compilateur des faire pas mal de contrôles et au programmes de les manipuler facilement.

- l'héritage permet de récupérer des objets existants en les adaptant à de nouveaux besoins, pour former de nouveaux objets, cela a aussi l'énorme avantage de factoriser des parties communes de plusieurs objets  évitant ainsi les duplications de parties de programme, donc facilitant l'écriture et la maintenance. L'héritage à un autre effet il donne plusieurs types simultanés aux objets, les objet sont ainsi polymorphes (ils ont plusieurs types, plusieurs formes) et cet état de fait est très courant dans les applications.

- le polymorphisme est un mécanisme essentiel, utilisant l'aspect polymorphe d'objets, permettant de mettre un objet à la place d'un autre avec adaptation automatique aux particularités des objets. C'est ce mécanisme qui fait toute la puissance de la POO. Malheureusement ce mécanisme n'est pas trop mis en valeur dans les cours de POO, où on se contente souvent d'encapsulation, avec un saupoudrage d'héritage. Mais comme je l'ai évoqué avant il faut d'assez gros exemples pour saisir toute la puissance conceptuelle de ces mécanismes.

Un langage plus adapté que C++, peut être Processing (ou directement Java) qui a été conçu pour faire de la POO, contrairement au C++ où la partie objet a été rajoutée par la suite. Mais quand on connait bien un langage il est peut être plus facile de partir de ce langage pour passer à la POO. Moi qui suis habitué à Java,  j'ai toujours un peu de mal à repasser au C++ à cause des petits problèmes de syntaxe, mais conceptuellement cela ne change pas.

Pierre

263
Vos projets / Re : Re : TCO avec Processing
« le: décembre 10, 2018, 08:58:00 am »
Après, je ne pige pas tout.
Z14, encadré par C5 et C3 ne serait pas une zone de manœuvre. C'est bizarre. Ce serait logique. Et ça expliquerait Cv5 et Cv6. J'ai dû louper une marche.
Z14 peut servir comme voie d'évitement, on peut y entrer directement à partir des voies principales et sortir directement sur les voies principales, d'où les carrés C5 et C3. Elle peut aussi servir de zone de manoeuvre, dans ce cas C5 et/ou C3 peuvent présenter un feu manoeuvre (blanc lunaire)

Pour Z28 c'est un peu pareil, mais que dans un seul sens et C2 peut présenter un feu blanc pour les manoeuvres.
Et, à mon avis, Cv5 et Cv6 sont des signaux bas.
Cv5 et Cv6 sont bien normalement des signaux bas, cela permet des manoeuvres de changement de machine, de modifications sur une rame de voitures/wagons ... Pour ce faire C1, C2, C8 et C4 peuvent présenter un feu blanc.

Cette disposition avec des carrés violets bas est courante dans les gares. Dans ce cas le départ en manoeuvre se fait pratiquement toujours par les voies de sortie (pas par les voies de rentrée), le retour en gare est autorisé par le carré violet bas (feu blanc).

Certaines gares en voie unique ont aussi ce dispositif, mais dans ce cas les voies d'entrée et de sorties sont confondues, ce qui implique qu'un train arrivant en gare rencontre normalement un carré puis un carré violet qui est ouvert (feu blanc) si le carré est ouvert.

Pierre

264
Bonjour

j'ai, comme d'habitude, quelques remarques à faire.

Concernant les "numero_train" codant des informations en tranches en collaboration avec la couleur, ce me semble une régression dans l'utilisation de la programmation objet. Si on a besoin d'infos sur les trains dans les pavés on ajoute au pavé une référence sur un objet train !

Concernant les carrés (et les carrés violets) c'est certes les seuls signaux sur lesquels il y a action "manuelle" qui est tout à fait normale, deux actions "manuelles" sont possibles ouverture du carré ou fermeture du carré. Ces actions se font souvent indirectement par la création ou la destruction d'itinéraires. La réalisation effective des ces actions  (faites ou pas faisables)  est du ressort des enclenchements qui sont justement là pour empêcher des actions non conformes. Par exemple dans un poste d'aiguillage électromécanique unifié, il y a un levier par signal, la manoeuvre de ce levier (donc du signal) est contrainte par des enclenchements, des enclenchements mécaniques vis à vis des autres leviers (d'aiguille, de signaux, d'autorisations, …) et par des enclenchements électriques (occupations des zones, enclenchements d'approche, …), Dans les postes plus modernes (PRS) les principes d'enclenchement sont les mêmes mais sont tous réalisés électriquement. Ces principes permettent de gérer les carrés dans tous les cas !

Concernant les itinéraires à tracé permanent, ton histoire de "phénix" n'est pas très convaincante. Voici la définition d'un itinéraire permanent, un itinéraire permanent n'est pas détruit après le passage d'un train ce qui implique que les carrés ne soient pas fermés à l'aubination, mais mis au sémaphore.

Amicalement

Pierre
 

265
Débuter / Re : Comment mettre 2 programmes sur le même écran
« le: novembre 01, 2018, 12:48:04 pm »
Rebonjour

Encore plus simple, on peut lancer simultanément l'IDE Arduino et une copie du même IDE.

Pierre

266
Débuter / Re : Comment mettre 2 programmes sur le même écran
« le: novembre 01, 2018, 11:36:11 am »
Bonjour

On peut aussi lancer deux versions différentes de l'IDE Arduino, on a ainsi deux consoles.

J'ai essayé avec la 1.8.6 et la 1.8.7

Pierre

267
Bonjour

Qui a dit que Processing c'était "lourd". Voici le dessin du Locoduinodrome en Processing, le programme est complet, rien à rajouter. Bien évidemment il utilise des courbes de Bezier. Il ne fait que le dessin, mais il serait facile de rajouter des signaux et les manoeuvres des aiguilles.

void setup() {
  size(1500,750); // taille de la fenetre
}

void draw() {
  stroke(127); strokeWeight(10); strokeCap(SQUARE); noFill(); // styles (couleur (gris), largeur (10), raccords (carres), ...)
 
  line(550,600,850,600); // Z0
 
  line(550,550,850,550); // Z1
 
  stroke(0); bezier(400,600,  400+75,600, 550-75,550, 550,550); // Z2 noir
  stroke(127); line(400,600,550,600); //                              gris
 
  bezier(400,100, 75,100, 75,600, 400,600); // Z3
 
  bezier(1000,100, 1325,100, 1325,600, 1000,600); //Z4

  stroke(0); line(850,600,1000,600); // Z5                            noir
  stroke(127); bezier(850,550, 850+75,550, 1000-75,600, 1000,600); // gris
     
  stroke(#FF0000); line(400,100,1000,100); // Z6 rouge
}

Voir ci dessous ce qu'affiche le programme .

Pierre

268
Bonjour

Normalement la progression des trains est matérialisée sur le TCO par la coloration (en rouge) des zones où est le train (avec décoloration quand le train quitte une zone. C'est la rétrosignalisation qui fournit les occupation et libérations de zones. C'est le système de base, pas besoin d'objet train.

Si on veut faire en plus du suivi des trains (pour savoir quel train est dans quelle zone), il faut bien entendu un objet train (qui reste petit dans ce cas là).

Il est très pratique de pouvoir faire circuler sur le TCO des trains virtuels (comme sur le Locodrome), pour faire de la mise au point (TCO et gestionnaire), pour tester un réseau avant de le construire ou tout simplement pour jouer sans réseau. Dans ce cas l'objet train est assez conséquent.

L'idéal serait de pouvoir visualiser des trains sur le TCO synchronisés avec les trains réels, c'est à dire déplacer les trains virtuels sur le TCO en fonction des déplacements des trains réels. C'est assez délicat mais on y travaille.

Cordialement

Pierre




269

Bonjour

J'ai suivi la discussion sans trop intervenir car entre les cimes enneigées et la grande bleue je n'avais pas trop l'esprit à cela.

Il me semble qu'il manque au moins trois choses à ton réseau de test :

- une TJS, les TJS (contrairement aux TJD) m'ont posées pas mal de problèmes dans dans la recherche d'itinéraires car il y a un cas pas possible (par rapport à une TJD), cela devrait aussi poser problème dans la recherche du signal suivant.

- un croisement, cela peut poser des problèmes d'incompatibilité d'itinéraires, entre autres

- en réalité (à la SNCF) beaucoup de voies ont un sens (disons la moitié), une voie unique peut être parcourue dans les deux sens, pour une voie double chaque voie à un sens, cela implique qu'il y ait des signaux que dans un sens (sauf pour les voies doubles équipées d'IPCS). Même des voies de gares peuvent avoir un sens, par exemple pour un évitement.

Ensuite j'ai plein de petites remarques :

- la SNCF utilise deux types de carrés, des carrés et des carrés violets (hauts ou bas), les carrés violets sont implantés dans les zones de manoeuvre, il me semble difficile de choisir automatiquement le type de carré, ni de décider s'il faut implanter un carrée violet bas ou pas pour faire des manoeuvres par refoulement sur les voies principales. Il arrive aussi souvent qu'il n'y ai qu'un carré violet pour deux voies

- pour les départs en manoeuvre les signaux ne présentent pas la voie libre ou l'avertissement, mais le feu manoeuvre (blanc lunaire), les carrés violets présentent normalement à l'ouverture un feu manoeuvre, mais il arrive couramment que des carrés (non violets) puissent aussi présenter un feu manoeuvre

- à la SNCF les carrés et les carrés violets sont fermés par défaut, seul l'établissement d'un itinéraire peut les ouvrir

- les sémaphores sont très très souvent implantés en pleine voie sans qu'il y ait d'appareils de voie

- le cas des zones Z13, Z20 et Z21 est symptomatique, il est très courant que quelques carrés protègent un ensemble d'appareils de voie, ensemble pouvant être important dans les grandes gares, par contre le cas des zones Z5 et Z9 est caricatural et me semble très loin de la réalité.

- on a pas le choix entre des signaux lumineux ou des signaux mécaniques, ou même une absence de signaux, on ne peux pas choisir entre du BAL ou du BAPR, …

En résumé il me semble qu'il est quasiment impossible d'implanter correctement les signaux automatiquement, désolé.

Amicalement

Pierre

270
Bonjour

Super, je vois que tu avance bien.

Pour obtenir un déplacement plus fluide des trains, j'avance toujours d'un seul point, mais pour respecter la vitesse le délai entre un point et le suivant dépend de la vitesse (0 à 127).

Pour les itinéraires j'essaie de respecter le plus possible ce que fait la SNCF, avec un point de départ et un point d'arrivée, les points de départ sont toujours devant un signal.

Ton système comptant les points avant un signal est assez astucieux pour faire les ralentissements. Mais un gestionnaire gérant des trains réels et non pas des trains virtuels ne peut pas trop utiliser ce système sauf peut être en implantant des balises sur le réseau.

Bon courage

Amitiés

Pierre

Pages: 1 ... 16 17 [18] 19 20 ... 23