Détail de l'algorithme d'analyse de données TOPOROBOT

Accueil


Le code de calcul développé pour l'analyse de données TOPOROBOT peut se diviser en deux parties:

  1. Un code d'analyse, destiné principalement en la décomposition d'ensembles séries/stations TOPOROBOT en structure Branches/Noeuds.
  2. Le code de calcul proprement dit, qui est le code de calcul de HADES -2000 classique.

Dans HADES -2000, tous les travaux d'édition et de calcul d'un document TOPOROBOT se font en mémoire et sont gérés par une classe TToporobotStructure.

Dans cette page, nous traiterons uniquement la première étape.

Les étapes du traitement:

  1. Construction de la table des Codes
  2. Construction de la table des Séances
  3. Recensement des jonctions
  4. Segmentation du réseau


La classe TToporobotStructure:

La classe centrale TToporobotStructure est une classe complexe composée de tableaux, de listes chaînées doubles classiques et de listes chaînées comportant d'autres listes chaînées.
Les tableaux:
Table des Noeuds
Les listes chaînées simples:
Table des Codes
Table des Séances
Table des Jonctions
Les listes chaînées complexes:
Table des Séries et pour chaque série, sa Table des Stations
Table des Branches et pour chaque série, sa Table des Stations

Les unités:

Déclarations et fonctions générales: Common.pas

L'unité principale de GHTopo: ToporobotClasses.pas


Méthode de lecture du fichier TOPOROBOT:

Les fichiers TOPOROBOT lisibles par HADES -2000 sont des fichiers texte ASCII pur, avec les variantes de format .Tab et .Text.
Un document TOPOROBOT est caractérisé par plusieurs colonnes numériques de début de ligne, correspondant à des préfixes.
La lecture d'un fichier TOPOROBOT se fait en une seule passe.
En cas d'erreur sur une ligne, le numéro de la ligne et son contenu sont affichés et la ligne est ignorée.

Pour lire le fichier, on utilisera l'algorithme suivant:

Tant que la fin du fichier n'est pas atteinte, faire:
Lire une ligne
Récupérer les 255 premiers caractères (imposées par TOPOROBOT)
Convertir les accents et caractères Mac
Si la ligne est vide, poser Prefix = -100
Si la ligne est invalide, poser Prefix = -110
La décomposer en éléments et stocker ceux-ci dans un tableau de chaînes
Convertir en entier le premier élément du tableau (préfixe de tête)
Selon la valeur de Prefix:
-100: Passer à la ligne suivante (ligne vide)
-110: Passer à la ligne suivante (ligne invalide)
-7 : Récupérer l'en-tête de dossier (classeur)
-6 : Récupérer l'entrée principale (Entrées)
-5 : Récupérer les coordonnées et ID des entrées du réseau
-4 : Passer à la ligne suivante (section non définie)
-3 : Passer à la ligne suivante (section non définie)
-2 : Ajouter une séance à la Table des Séances
-1 : Ajouter un Code à la Table des Codes
Par défaut: (On attaque les séries; Prefix >0)
Si Prefix>0 alors
Prefix2 = Colonne 1
Si Prefix2 = -1 alors
Récupérer les paramètres de la série
Ajouter une série
Sinon Si Prefix2>=0 alors
Récupérer les valeurs de la station
Ajouter cette station à la table des stations de la série courante
Sinon
Ne rien faire
Fin Si
Fin Selon
Fin tant que

ffhvhdjfh


Méthode d'analyse:

1. Recensement des jonctions:

Ce travail est très rapide: en effet, une série étant obligatoirement définie par deux jonctions (ou noeuds), il suffit de parcourir la Table des Séries, de composer un ID avec les numéros de série/point de départ et de série/point d'arrivée. Cet ID formaté est stocké dans une liste chaînée temporaire de type TStringList, paramétrée sans doublons et triée.
Puis on parcourt la table provisoire ainsi obtenue pour ajouter chaque jonction à la table des jonctions.
Enfin, on détruit la table provisoire.
Ceci se traduit par la procédure suivante:

procedure TToporobotStructure.RecenserJonctions;
var
Serie: TUneSerie;
Station: TUneVisee;
Ser, St: integer;
ListeJnct: TStringList;
J : TJonction;
begin
AfficherMessage('Recensement des jonctions');
ListeJnct:=TStringList.Create;
ListeJnct.Clear;
ListeJnct.Sorted:=True;
ListeJnct.Duplicates:=dupIgnore;
for Ser:=0 to FNbSeries - 1 do begin
Serie:=GetSerie(Ser);
ListeJnct.Add(Format(FMT_NDSER_PT,[Serie.SerieDep, Serie.PtDep]));
ListeJnct.Add(Format(FMT_NDSER_PT,[Serie.SerieArr, Serie.PtArr]));
end;
FNbJonctions:=ListeJnct.Count;
for St:=0 to FNbJonctions-1 do begin
J.IDJonction:=ListeJnct.Strings[St];
J.NoNoeud:=St;
AddJunction(J);
end;
ListeJnct.Free;
AfficherMessage('Recensement des jonctions OK');
end;

2. Décomposition du réseau en noeuds et branches:

Cette étape est la plus délicate de l'analyse. La difficulté réside au découpage des séries aux bons endroits.
Les passages en mauve constituent du code de log et n'interviennent pas dans le traitement.

procedure TToporobotStructure.RecenserBranches;
const
STR_FMT_STATIONS = '>> %d/%d |%.3d %.3d| %.2f %.2f %.2f | %.2f %.2f %.2f %.2f | %s';
var
Serie: TUneSerie;
Visee: TUneVisee;
Ser, Vis: integer;
pTXT : TextFile;
Br : integer;
Nd : integer;
Branche0,
Branche1: TBranche;
begin
AfficherMessage('Recensement Branches');
AssignFile(pTXT, 'ESSAI_BRANCHES.TXT');
ReWrite(pTXT);
// en_tête
WriteLn(pTXT, Format('%s - %.2f %.2f %.2f',[
self.FNomCavite,
self.FCoordX,
self.FCoordY,
self.FCoordZ
]));
// première branche
Branche0.NoBranche:=1;
Branche0.NomBranche:=Format('Branche %d',[1]);
Branche0.NoeudDepart:=0;
Branche0.NoeudArrivee:=1;
Branche0.DeltaX:=0.01;
Branche0.DeltaY:=0.01;
Branche0.DeltaZ:=0.01;
AddBranche(Branche0);
Br:=2;
WriteLn(pTXT,'Branche 0: Du Noeud 0 au Noeud 1 (0/0..1/0)');
WriteLn(pTXT,'1/0 - 0.00 0.00 0.00');
WriteLn(pTXT,'--> Noeud 1 (1/0)');
// balayage
for Ser:=1 to FNbSeries-1 do begin
Serie:=GetSerie(Ser);
Nd:=GetNoeud(Serie.SerieDep, Serie.PtDep);
// début de série = nouvelle branche
Branche0.NoBranche:=Br;
Branche0.NomBranche:=Format('Branche %d',[Br]);
Branche0.NoeudDepart:=Nd;
AddBranche(Branche0);
WriteLn(pTXT, Format('|==> Branche %d - Départ en : Nd%d',[Br,Nd]));
for Vis:=1 to Serie.NbPoints-1 do begin
Visee:=GetStation(Ser, Vis);
Nd:=
GetNoeud(Ser, Vis);
AddBrStation(Br, Visee);
Branche1:=GetBranche(Br);
Branche0.PointsTopo:=Branche1.PointsTopo;
Branche0.NbPoints:=Branche1.NbPoints;
WriteLn(pTXT, Format(STR_FMT_STATIONS,
[Ser, Vis,
Visee.Expe, Visee.Code,
Visee.Longueur, Visee.Azimut, Visee.Pente,
Visee.LG, Visee.LD, Visee.HZ, Visee.HN,
Visee.Commentaires
]));
if (Nd>-1) AND (Vis < Serie.NbPoints-1) then begin
Branche0.NoeudArrivee:=Nd;
PutBranche(Br, Branche0);
WriteLn(pTXT,Format('==>| Branche %d - Arrivée en: Nd%d',[Br,Nd]));
Br:=Br+1;
Branche0.NoBranche:=Br;
Branche0.NomBranche:=Format('Branche %d',[Br]);
Branche0.NoeudDepart:=Nd;
AddBranche(Branche0);
WriteLn(pTXT,Format('|==> Branche %d - Départ en : Nd%d',[Br,Nd]));
end;
// fin de série = fin de branche: cloturer la branche
if Vis = Serie.NbPoints-1 then begin
Nd:=GetNoeud(Serie.SerieArr, Serie.PtArr);
Branche0.NoeudArrivee:=Nd;
PutBranche(Br, Branche0);
WriteLn(pTXT,Format('==>| Branche %d - Arrivée en: Nd%d',[Br,Nd]));
Br:=Br+1;
end;
end; // for Vis
end; // for Ser
CloseFile(pTXT);
AfficherMessage('Recensement Branches OK');
end;

Une fois le réseau décomposé en noeuds et branches, on peut soit calculer le réseau, soit le convertir au format HADES -2000, soit les deux ;)


Les fonctions utilisées:

Retourne le numéro de noeud en fonction du numéro de série et de station

function TToporobotStructure.GetNoeud(const Serie: integer; Station: integer): integer;
var
i : integer;
Jonc: TJonction;
S : string;
begin
Result:=-1;
for i:=0 to self.FNbJonctions-1 do
begin
Jonc:=self.GetJonction(i);
S:=Format(FMT_NDSER_PT,[Serie, Station]);
if S = Jonc.IDJonction then
begin
Result:=i;
exit;
end;
end;
end;