Détail de l'algorithme d'analyse de données TOPOROBOT
Le code de calcul développé pour l'analyse de
données TOPOROBOT peut se diviser en deux parties:
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:
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;