representation d’un champ de diagraphies …masig.ensg.eu/pdf/diagraphie.pdf · une diagraphie...

40
1 REPRESENTATION D’UN CHAMP DE DIAGRAPHIES AVEC RACCORDEMENTS Master ASIG et IASIG Benoît ANTOINE, Maryse FANTIN Février 2008

Upload: ledan

Post on 09-Jun-2018

218 views

Category:

Documents


0 download

TRANSCRIPT

1

REPRESENTATION D’UN CHAMP DE DIAGRAPHIES AVEC RACCORDEMENTS

Master ASIG et IASIG

Benoît ANTOINE, Maryse FANTIN

Février 2008

2

TABLE DES MATIERES

I. INTRODUCTION 4 A. La Géomatique 4 B. Rapide description des diagraphies 4

1. Définition 4 2. Utilisation 5

II. OBJECTIFS 6 A. Objet à afficher 6 B. Hypothèses 6 C. Outils à employer 6

III. METHODE 7 A. Définition des grandes lignes du projet 7 B. Prise en main de l’outil Fortran95 8

1. Gestion des bases de données 9 a) Ecrire des fichiers .txt 9 b) Lire des fichiers.txt 9

2. Gestion de l’affichage 10 a) Appel des fonctions que renferment les bibliothèques OpenGL dans la limite de ses aptitudes 10 b) Utilisation des bibliothèques d’IHM de Fortran95 10

C. Ecriture des algorithmes et construction des objets 11 1. Concepts 13

a) Construction de la surface au sol 13 b) Trouver le milieu du terrain 14 c) Position des puits et triangulation: généralités et construction de la base de données 15 d) Les courbes de Béziers 17 e) Diagramme de récapitulation 18

2. Graphe d’appel 20 3. Réalisation des algorithmes 21

a) Algorithme de création d’un vecteur de nombres quasi aléatoires compris entre 0 et 1 : 21 b) Obtention des valeurs extrémales des coordonnées terrain, ainsi que de la position du centre et de l’échelle 21 c) Algorithme de l’IHM 21 d) Gestion des évènements de la souris 22

D. Utilisation des bibliothèques OpenGL avec Fortran95 : 23 E. Création de la boîte de dialogue 26

IV. RESULTATS 27 A. L’affichage 27

1. Mode d‘affichage 27 2. Le sol 28 3. Les puits 28 4. Les valeurs 29 5. Les limites de couches 29 6. Les couches 31

B. L’animation 32

3

1. Les rotations 32 2. Les translations 34 3. Réduction/ agrandissement 36

V. DISCUSSION 37 A. Définition des limites du projet 37 B. Phase de réalisation 37 C. Phase de manipulation 38 D. En équipe 39

VI. CONCLUSION 39

VII.REFERENCES 40

4

I. INTRODUCTION A. La Géomatique

La géomatique est composée de l’ensemble des outils et méthodes utilisés pour représenter, analyser et d'intégrer des données géographiques. A notre niveau, les aspects de représentation et de traitement des données sont développés pour répondre au sujet.

B. Rapide description des diagraphies

1. Définition Une diagraphie est une technique de mesure des caractéristiques physiques de roche. Elle peut être de deux types : instantanée ou différée. Elle consiste à effectuer un forage dans un terrain puis à faire parcourir le puits par différents types de sondes.

Figure 1 : Photo d’un forage. Utilisation à des fin s géothermales (Learnz)

5

Selon les données enregistrées par la sonde, il est possible d’évaluer la composition du terrain sur la majeure partie du forage. Le changement de nature de terrain lors du passage d’une couche à une autre se traduit par un saut de valeurs enregistrées par la sonde. Historiquement, cette technique était dénommée carottage électrique et fût inventée par Conrad et Marcel Schlumberger au début du XXème siècle.

2. Utilisation Les techniques de diagraphies permettent entre autre de déterminer la densité, la porosité, la perméabilité ainsi que la teneur en hydrocarbure ou en eau d’un site. Elles peuvent se révéler utiles d’un point de vue géologique pour déterminer par exemple

le pendage des terrains rencontrés. Cependant, étant donné leur coût élevé de mise en place et d’utilisation, elles sont essentiellement utilisées pour déterminer la valeur économique d’un terrain. Un exemple d’application est la localisation des réservoirs d’hydrocarbures par les groupes pétroliers. L’utilisation en hydrogéologie est aussi commune pour localiser les nappes phréatiques et estimer leur capacité ou leur propreté.

Figure 2 : Principe de la diagraphie (Geological survey of Canada)

Figure 3 : Exemple d’utilisation en hydrogéologie (Laynewater)

6

II. OBJECTIFS A. Objet à afficher

Notre projet consiste à afficher un champ de diagraphies. Ceci implique de représenter des puits de forages ainsi que les valeurs de diagraphies. Celles-ci doivent caractériser les matériaux que la sonde rencontre lors de son voyage dans le puits. Plusieurs puits sont forés dans le champ choisi, il existe donc un jeu de valeurs de diagraphie pour tout le site. Lorsque les différentes valeurs de diagraphie sont mises en corrélation, il apparaît des limites de profondeur entre les nombreux terrains qui composent le site. Au final, les limites de terrain seront représentées selon deux modes de vision : normal ou anaglyphique. Ce dernier mode de représentation permettra à l’utilisateur de se donner une idée plus précise de la scène en 3 dimensions.

B. Hypothèses Les hypothèses suivantes ont été posées pour définir les limites du projet :

a) les valeurs de diagraphies sont analysées en amont par un ingénieur géophysicien. Ceci implique que les limites de couches font parties du jeu de données qui nous est fourni par le commanditaire.

b) Le jeu de données comprend donc : • Un nombre de puits connu • La localisation des puits • la profondeur d’un puits: Ppuits • le nombre de valeurs enregistrées: NVAL • les valeurs qui sont enregistrées à chaque fois que la sonde a

parcouru un certain pas Dz constant en profondeur : Dz= Ppuits

/NVAL c) toutes les valeurs de diagraphies sont utilisables d) le puits de diagraphie est rigoureusement vertical

C. Outils à employer Le projet doit être réalisé sous Fortran95 en utilisant la bibliothèque graphique d’OpenGL. A la base de toute programmation, le langage algorithmique ADL a été utilisé pour construire les algorithmes.

Figure 4 : Représentation SIG d’un champ de diagraphie construit à des fins hydrogéologiques pour localise r une nappe phréatique (Burnside)

7

III. METHODE A. Définition des grandes lignes du projet

Nous devons obtenir un objet 3D où sont référencées les interfaces entre les différents terrains, tout comme les limites des liquides saturant le sol selon l’option choisie. Pour ce faire, nous avons choisi de travailler sur une base de :

• 12 puits • 5 limites de couches (et donc 6 couches) • Un sol en surface rectangulaire et plat dans un premier temps • Une géologie simple : aucune lacune ni terrain de forme

lenticulaire.

Pour commencer, nous avons travaillé sur les algorithmes. Nous avons donc dû déterminer précisément ce que nous voulions réaliser. Nous imaginons dans un premier temps le bloc diagramme comme une superposition de terrains continus de nature différente. Ce bloc est traversé par des puits verticaux. Ceci est illustré par la figure qui suit :

Figure 5 : Représentation schématique du bloc diagr amme traversé par des puits verticaux de

couleur noire. La surface se situe en haut du bloc. Elle surmonte des couches de géométrie variable mais conformes à nos hypothèses. Ces couches sont délimitées par les lignes de différentes couleurs. La réalisation du projet devra se faire selon les étapes suivantes :

• afficher les puits • afficher les valeurs de diagraphie dans chaque puits par la

méthode des courbes de Bézier • calculer les coordonnées écran d’un point dont on connaît les

coordonnées terrain

8

• créer automatiquement des tables qui seront utilisées pour faire les calculs ou pour représenter l’objet

• utiliser un algorithme pour trouver le centre du bloc diagramme

Sachant que pour qu’OpenGL dessine des triangles il faut lui renseigner des points de tels sorte qu’il n’y ait pas de conflit entre deux triangles possédant un même bord, nous pensions devoir utiliser des tables SIG et GD. Un algorithme a donc été créé à cette fin. Aucun algorithme ne peut être codé pour représenter le bloc diagramme sans base de données. Il a donc fallu construire une base de données utilisables par Fortran. Celle-ci est composée de fichier .txt que fortran ouvrira et lira pour copier les valeurs renseignées dans des tables (vecteurs ou matrices) que le programme utilisera. Les fichiers suivants ont été construits :

• Champ : possède les coordonnées cartésiennes (x,y,z) dans l’espace 3D objet des points de surface de tous les puits.

• Couche : renseigne l’altitude absolue de toutes les limites de couches, pour chaque puits.

• LP : renferme la colonne puis la ligne du tableau de valeurs qui correspond à une limite de couche. Un seul tableau pour tous les puits.

• Random : valeurs obtenues à partir d’un algorithme simple basé sur les fonctions random_num, donnant une valeur entre 0 et 1 et date_and_time, qui fournit en sortie les dates et heures d’exécution du programme. Les valeurs sont comprises entre 0.1 et 1. Ce fichier permettra la construction d’un tableau qui gérera les couleurs affichées à l’écran : à chaque exécution, les couleurs des couches sont ainsi différentes.

• Trian : possède des triplets de numéro de puits. Ces triplets serviront à construire les triangles et ainsi permettre la triangulation du terrain. Tous les triangles ont été organisés de telle sorte qu’ils soient directs. Ainsi, si la réalisation du projet nécessite de trouver le vecteur normal au domaine délimité par les côtés d’un triangle, cette vérification ne sera pas à faire.

• Val : enregistre l’ensemble des valeurs de diagraphie pour tous les puits

B. Prise en main de l’outil Fortran95 Fortran95 a été choisi comme le langage de programmation qui servira à construire le champ de diagraphie. Ce langage est essentiellement utilisé pour répondre à des besoins scientifiques. Il commandera les fonctions OpenGL qu’il voudra bien prendre en charge. Fortran95 est conçu essentiellement pour des applications scientifiques, notamment du traitement mathématique de données immenses. Nous avons donc appris à manier ce langage et nous nous sommes appliqués à écrire le plus proprement possible nos codes.

9

Avant toute programmation d’un nouveau code, un espace de travail (workspace) doit être créé dans Fortran. Il y sera associé un projet (Fortran Console Application) ainsi qu’un fichier (Fortran Free Format Source File). Pour ce projet à forte composante d’affichage, Fortran a eu deux principales utilisations:

1. Gestion des bases de données

a) Ecrire des fichiers .txt

Fortran écrit dans des fichiers grâce à la fonction open(). Celle-ci doit avoir plusieurs arguments tels que :

• le numéro qu’elle doit attribuer au fichier, il est plus sage de choisir de grand nombre pour éviter tout conflit avec un fichier qu’elle utilise déjà sans que l’utilisateur en ait connaissance. • l’action qu’elle doit mener sur ce fichier : lire ou écrire, ici WRITE • le type de formatage. • le nom du fichier renseigné en chaîne de caractères ou son chemin exact (‘C:/…. Txt’ ou ‘D:/….txt’). • l’état du fichier : préexistant ou à créer, ici OLD (préexistant) a été choisi parce que les mêmes fichiers sont réutilisés à chaque utilisation du programme. Ecrire de nouveaux fichiers à chaque fois nécessiterait de leur attribuer un nom différent à chaque fois ou de les effacer manuellement à chaque fois que le programme est lancé. Ceci rendrait son utilisation beaucoup moins fluide.

Une partie du code a été choisie comme illustration :

Programme censuré

b) Lire des fichiers.txt

Ici, Fortran utilise toujours open() pour ouvrir les fichiers. Les arguments utilisés sont les suivant : • le numéro qu’elle doit attribuer au fichier • l’action qu’elle doit mener sur ce fichier : ici READ • le type de formatage • le nom du fichier renseigné en chaîne de caractères ou son chemin exact

10

• l’état du fichier : ici OLD (préexistant) parce qu’open ne fait que lire un fichier.

Un extrait de notre code a été choisi pour illustrer cette description :

Programme censuré

2. Gestion de l’affichage

a) Appel des fonctions que renferment les bibliothèques OpenGL dans la limite de ses aptitudes

Pour être utilisables, les bibliothèques doivent être ajoutées à l’espace de travail de Fortran dans le dossier Resource Files. Au début de chaque module ou programme qui utilisera des fonctions d’OpenGL, il sera nécessaire d’indiquer que ses bibliothèques doivent être mises à disposition. Pour cela ‘use’ précédera open_gl, opengl_gl, opengl_glu et opengl_glut en chaque tête de module ou programme. La plupart des fonctions sont appelées par call (+ nom de la fonction). Néanmoins, certaines tels que glutCreateWindow retourne un entier. Elles doivent donc être affectées à un entier dont le type (integer) doit être précisé dans les déclarations.

b) Utilisation des bibliothèques d’IHM de Fortran95

11

C. Ecriture des algorithmes et construction des objet s

ETAPES MENANT À LA MISE EN PLACE DES ALGORITHMES

Fichier texte fourni avec toutes les données nécessaires à l’affichage géomatique du champ de diagraphie

Tables de valeurs

Tables de pointeurs qui mènent au bon endroit dans les tables de valeurs

Ce qui doit être affiché

IHM : Ce qui est demandé par l’utilisateur

Affichage écran de tout ce qui a été demandé

Définir le format du fichier texte Mise en place d’un algorithme pour obtenir des valeurs pseudo aléatoires

Z1

Z2

Z3 Z4

Z5 Z6

- Position - Objets - Valeurs des diagraphies dans chaque puits

LP : position dans la table VAL …

- Puits : NP - Limites de couches : Lesquelles ? Enregistrement : oui/non Stéréo : o/n - Calcul des mouvements

Choix : - Nombre de puits - Affichage des enregistrements ou pas - Affichage de tout le bloc en stéréo - Limite de couches à afficher

Utilisation de fonctions OpenGL

12

Z1 : Lecture de fichiers texte. Constitution des tableaux Champ, Couche, Trian et VAL. Mise en place d’un algorithme de construction de tables de réels aléatoires. Enregistrement potentiel de toutes les actions dans une dayfile. Z2 : Calcul des données utiles, telles que la position dans l’espace des valeurs de diagraphie. Z3 : Mise en place de table de pointeurs. Exemple : LP, qui indique le rang dans le tableau VAL de la ième couche. Z4 : Détermination des variables, telles que :

• NP : Nombre de puits • NL : Nombre de limites • NVAL : Nombre de valeurs de diagraphie

Affichage uniquement des données demandées par l’utilisateur, par l’intermédiaire de l’IHM (Z5). Calcul des mouvements et de l’affichage qui en résulte. Gestion des évènements souris et clavier. Z5 : IHM : Choix de l’utilisateur quant aux données à afficher : les puits, les valeurs de diagraphie, le rectangle d’emprise du terrain, les couches ou encore les limites de couches. Possibilités d’affichage de l’IHM :

• Puits : 2 possibilités : oui/non • Enregistrements : 2 possibilités : oui/non • Limites de couche : tout ou rien, ou affichage des limites de couches voulues uniquement. • Couches : tout ou rien, ou affichage des couches voulues uniquement. • Stéréoscopie : 2 possibilités : oui/non. Si oui, on double les données à prendre en compte.

Demandes de l’utilisateur pour une rotation, translation ou encore un zoom (modification de l’échelle). Possibilités de revenir à la position initiale. Z6 : Utilisation des fonctions d’OpenGL pour l’affichage des données à l’écran.

13

Nos algorithmes ont pour la plupart repris des fonctionnalités qu’OpenGL prend en charge. Ceux-ci se sont donc avérés moins productif que prévu à l’origine. La liste des algorithmes qui ont été écrits est la suivante :

• affichage des puits • affichage des valeurs de diagraphie dans chaque puits par la

méthode des courbes de Béziers • calcul des coordonnées écran d’un point, dont on connaît les

coordonnées terrain • calcul des coordonnées écran d’un point de surface de chaque puits

dont on connaît les coordonnées 3D • calcul des coordonnées écran de l’ensemble des points de mesure de

chaque puits • création automatique des tables référençant la localisation des limites

de couches pour tous les puits • création automatique des tables qui possèdent les valeurs extrêmes

d’altitude (min et max) pour chaque puits, puis pour chaque limite de couche

• création automatique de la table des valeurs de diagraphie pour chaque puits

• trouver le centre du bloc diagramme Pour pouvoir construire les différents objets de notre projet, nous utilisons les bases de données que nous avons construites. Nous avons procédé comme suit :

1. Concepts

a) Construction de la surface au sol

Cette surface doit encadrer tous les puits. Pour ce faire, il nous faut comparer toutes les valeurs d’ordonnées et d’abscisses des puits. Les coordonnées maximales et minimales pour l’ensemble des puits seront gardées. Un nombre leur est ajouté ou retranché pour qu’aucun puits ne se trouve sur un bord. Les coordonnées extrêmes obtenues seront utilisées pour définir les sommets de la surface au sol. La figure 6 illustre ce propos.

14

Figure 6 : Méthode de construction de la surface au sol

b) Trouver le milieu du terrain Pour trouver le milieu du terrain, un algorithme simple a été construit. Il est basé sur un principe simple de comparaison de valeurs pour toutes les coordonnées des puits. Les valeurs extrêmes obtenues en abscisses, ordonnées et profondeur sont manipulées de telles sortes qu’on obtienne la position au milieu du bloc diagramme. Toute la procédure est illustrée sur le schéma qui suit.

15

Figure 7: Méthode de détermination des coordonnées de milieu de terrain : trouver le centre du

bloc diagramme

c) Position des puits et triangulation: généralités et construction de la base de données

Lors de la phase d’écriture des algorithmes, un module de construction des tables SIF et GD (respectivement sommets initiaux/sommets finaux et gauche/droite) a été créé. Il pourra être utilisé par un autre module pour déterminer le sens de parcours des sommets des triangles pour qu’ils soient directs. Le raisonnement a été le suivant pour construire la table GD:

• soit T1 le premier triangle dont les trois sommets sont enregistrés dans la table TRIAN. Ces informations seront situées dans la 1ère ligne du tableau, sur les 3 colonnes.

• soit SI le sommet initial du triangle (1er sommet dans la 1ère colonne du tableau). Il nous faut comparer SI avec les 2 autres sommets référencés dans la table des triangles.

• Selon le sens du vecteur résultat du produit vectoriel entre le vecteur a (allant de SI à SF) et le vecteur vect1 (allant de SI au 3ème sommet du triangle), le domaine (triangle) se situera à droite ou à gauche du vecteur a.

• La figure 8 illustre la méthode employée.

16

Figure 8: Utilité des tables SIF pour la constructi on de la table GD. L’arc a est à droite du domaine 1 : le sens du vecteur Z bleu est négatif s elon l’axe Zp. Il est à gauche du domaine 2 : le sens du vecteur Z vert est positif.

Le sens de rotation du triangle sera déterminé en utilisant la même méthode. En effet, soit un triangle donné (une ligne donnée du tableau TRIAN), et deux vecteurs : a (allant du 1er au 2ème sommet, soit de S1 à S2 dans TRIAN) et vect1 (allant du 1er au 3ème sommet, soit de S1 à S3). Si le produit vectoriel des vecteurs a et vect1 donne un vecteur résultant négatif selon l’axe vertical, le sens de rotation direct sera S1-> S2-> S3. Dans le cas contraire, il sera S1S3S2.

Cependant, parce que nous avons pris le parti de construire une base de données fixe pour la durée du projet, nous n’avons pas utilisé les algorithmes précédents. En effet, nous avons directement créé les domaines de telle sorte que le sens d’apparition des sommets soit direct pour chaque ligne du tableau. Ainsi, nous avons préparé l’éventuelle utilisation de fonctions d’éclairage qui nécessiteraient de connaître la norme de chaque domaine. Dans ce cas, tous les domaines du terrain doivent avoir une norme qui doit globalement avoir le même sens. Par la suite, le produit vectoriel entre le vecteur lumière et la norme des domaines déterminera la zone du domaine à couvrir d’ombre des limites de couches si besoin est.

17

Figure 9: Localisation des puits de diagraphie sur le terrain. Chaque nombre correspond à un puits. Chaque T suivi d’un nombre correspond à un n uméro de triangle (considéré comme domaine ici).

d) Les courbes de Béziers

Les valeurs de diagraphie sont enregistrées pour chaque puits. La courbe qui doit les représenter doit donc courir le long du puits qu’elle caractérise. Pour ce faire, nous choisissons d’ajouter la valeur de diagraphie aux abscisses du puits concerné. Les coordonnées selon la verticale seront données par le pas DZ d’enregistrement des valeurs ainsi que le rang de la valeur. Ainsi la 6ème valeur enregistrée se trouvera à la profondeur de : Z ici= Z Altitude en surface - 6*DZ. Une fois que les coordonnées de tous les points sont déterminées, ils seront reliés de telle sorte que la courbe obtenue passe le plus près possible de chaque point. Dans la réalité, la courbe ne passe exactement sur aucun point, à l’exception des deux extrémités. La figure 10 représente la méthode employée pour tracer les courbes. Finalement, lors de la phase de codage, nous avons été confrontés à des étapes de programmation sous Fortran 95 non maitrisées. N’ayant pu coder la représentation 3D des valeurs par la méthode des courbes de Béziers, nous avons donc simplement reliés un ensemble de points dont les coordonnées étaient enregistrées dans un tableau CDB (courbe de Béziers).

18

Figure 10: Méthode de construction des courbes de v aleurs de diagraphie: utilisation des

courbes de Béziers

e) Diagramme de récapitulation

19

20

2. Graphe d’appel

21

3. Réalisation des algorithmes

a) Algorithme de création d’un vecteur de nombres quasi aléatoires compris entre 0 et 1 :

ALGORITHME censuré

b) Obtention des valeurs extrémales des coordonnées terrain, ainsi que de la position du centre et de l’échelle

ALGORITHME censuré

c) Algorithme de l’IHM Les commandes de la boîte de dialogue qui seront employables par l’utilisateur seront de quatre types :

- ‘push button’ ou bouton pressoir : ce type servira à commander des actions simples qui peuvent répondre à l’état d’un booléen comme le mode de vision (normal ou anaglyphique) ou l’initialisation (réaffichage de l’objet tel qu’il était à l’origine).

- ‘check-boxe’ : 2 états sont disponibles pour cette commande : vrai ou faux. Il s’agit donc encore de booléens cachés derrière ce type. Nous avons choisi de les utiliser pour gérer l’affichage des objets selon la volonté de l’utilisateur.

- Scrollbar : le curseur positionné sur cette barre prend des valeurs entières comprises entre une valeur minimale et une valeur maximale. La position du curseur peut donc servir à faire évoluer une variable. Nous avons choisi de les appliquer aux mouvements verticaux et horizontaux de l’objet, tout comme aux rotations selon les 3 axes de l’espace.

- Slider : seule l’apparence diffère de la scrollbar. Les principes de fonctionnement sont les mêmes. Il aura donc la même utilité que cette dernière. Sa fonction sera ici de régler l’écart entre l’objet rouge et l’objet vert lorsque le mode anaglyphique est choisi

Le premier algorithme a pour fonction de créer la boîte de dialogue et d’y associer les divers boutons de commandes :

ALGORITHME censuré

22

d) Gestion des évènements de la souris Les algorithmes qui suivent, permettent à l’utilisateur de modifier l’affichage de l’objet grâce à la souris. Ainsi, lorsqu’il active la souris, il peut faire tourner l’objet selon le mouvement de la souris. La souris est un outil qui possède 3 boutons (droite, milieu, gauche) et 2 états (actif, inactif). Nous voulons attribuer un mouvement de rotation à l’objet lorsque le bouton de gauche est activé et que la souris se déplace. Le bouton droit permettra quant à lui de zoomer.

ALGORITHME censuré Parce que l’amplitude des transformations (rotations ou translations) est liée au déplacement de la souris, il est nécessaire de connaître la position de celle-ci même lorsqu’ aucun de ses boutons n’est actif. En effet, si la dernière position enregistrée correspond à l’arrêt du clic de la souris, lorsque l’utilisateur cliquera sur l’image, la différence se fera entre l’ancienne valeur à l’arrêt du clic et les nouvelles coordonnées écran du clic. Il en résultera un saut d’objet à l’écran.

ALGORITHME censuré

23

D. Utilisation des bibliothèques OpenGL avec Fortran95 :

Les outils qu’OpenGL proposent sont intéressants. Il a été nécessaire d’utiliser des livres tels qu’OpenGL 1.2, guide officiel par M.Woo, J.Neider, T.Davis, et D.Shreiner (Editions CampusPress Référence). Malgré tout, nous avons réaliser que tous les exemples de ce livre sont écrits en C. Voici la liste des principales fonctions OpenGL utilisées : Table de nombres aléatoires :

- random_number() donne un nombre réel compris entre 0 et 1. Il est tiré d’une table conséquente de réels enregistrés dans le compilateur. - date_and_time() fournit les données de temps et de date au moment de l’exécution du programme. Elle donne dans l’ordre : l’année, le mois, le rang du jour dans le mois, l’heure, la minute, la seconde et la milliseconde d’exécution du programme.

Gestion de fichiers texte :

- open() ouvre le fichier demandé. - write() permet d’écrire dans le fichier demandé. Elle efface entièrement le fichier texte avant de réécrire dessus. - read() permet de lire dans le fichier déterminé.

Gestion des Buffers :

- glClear(GL_COLOR_BUFFER_BIT) permet d’effacer le buffer stockant les couleurs et ainsi définit le fond de la scène. - glClear(GL_DEPTH_BUFFER_BIT) permet d’effacer le contenu du Z-Buffer. - glDepthFunc(GL_LESS) dessine le point si la valeur est plus petite que celle enregistrée dans le Z-Buffer. - glEnable(GL_DEPTH_TEST) active le Z-Buffer. Ainsi, si deux objets sont l’un en dessus de l’autre, alors seul l’objet situé le plus près de l’observateur est affiché.

Gestion des matrices de rotation :

- glMatrixMode() détermine le type de la matrice de rotation. - glLoadIdentity() réinitialise la matrice de rotation. - glpushMatrix() enregistre la matrice de rotation. - glpopmatrix() récupère la dernière sauvegarde de la matrice de rotation.

Modification des coordonnées objets :

- glScalef() modifie l’échelle de l’espace objet suivant les 3 axes. - glrotatef() effectue une rotation sur les coordonnées objet, suivant un axe et un angle déterminés. - gltranslatef() effectue une translation des coordonnées objet, selon un axe et une distance. - gluperspective() détermine le volume de vue dans lequel sera affiché l’objet.

24

Gestion du tracé des objets : - glLineWidth() détermine la largeur des lignes tracées - glPointSize() détermine la taille des sommets - glColor4f() détermine la couleur des objets - glBegin(GL_LINES) permet de tracer des lignes reliant les sommets 2 à 2. - glBegin(GL_LINE_STRIP) permet de tracer des lignes reliant les sommets suivant une liste donnée. - glBegin(GL_LINE_LOOP) est identique à GL_LINE_LOOP, mais avec la propriété supplémentaire de relier les 2 extrémités entre elles. - glBegin(GL_POLYGON) permet de tracer des polygones convexes. - glBegin(GL_TRIANGLES) permet de tracer des triangles en tenant compte des points 3 à 3. - glVertex3f() place un point dans l’espace objet.

Gestion de l’IHM :

- dlginit(): initialise la boîte de dialogue - dlgset(): associe les boutons à la boîte de dialogue - dlgsetsub(): associe les boutons à l’activation d’une subroutine - dlgmodeless(): définit le type de boîte de dialogue - dlgget(): permet d’obtenir la valeur correspondant à la position du curseur sur une scrollbar ou sur un slider.

Gestion des évènements clavier et souris :

- glutKeyboardFunc() permet de spécifier au programme le nom de la subroutine qui gère les évènements clavier. Ainsi, elle prend en paramètre d’entrée le nom de la subroutine considérée. - glutmotionfunc() gère les évènements engendrés par le déplacement de la souris, lorsque qu’au moins un bouton de celle-ci est appuyé. - glutpassivemotionfunc() gère les évènements engendrés par le déplacement de la souris, lorsque qu’aucun bouton de celle-ci n’est appuyée.

Gestion de la fenêtre d’affichage :

- glutInit() initialise la bibliothèque GLUT. - glutInitDisplayMode() spécifie le mode d'affichage de la fenêtre. Par exemple, permet de définir le jeu de couleur utilisé (RVB, CMJN, soit les 3 valeurs allant de 0 à 255, ou sinon les valeurs allant de 0 à 1). - glutInitWindowSize(), détermine la taille de la fenêtre d’affichage - glutInitWindowPosition(), détermine la position de la fenêtre d’affichage au niveau de l’écran de l’ordinateur - glClearColor(), détermine la couleur de fond de la fenêtre d’affichage - glutCreateWindow(), crée la fenêtre d’affichage

Fonctions d’affichage des données :

- glutSwapBuffers(), force l’affichage du résultat. - glutDisplayFunc(), est la fonction de rappel d’affichage pour la fenêtre courante. - glutMainLoop() permet d'entrer dans la boucle de GLUT de traitement des événements. Dans cette boucle, les fonctions de rappel qui ont été enregistrées sont appelées à tour de rôle.

25

Autres fonctions : - gluLookAt() détermine le point de vue de l’observateur. - glShadeModel(GL_SMOOTH) permet de lisser les objets, pour éviter l’apparition non voulue de face. On peut citer comme exemple celui des sphères, dont on veut éviter de voir qu’elles sont constituées de facettes. - glEnable(GL_BLEND) permet de mieux combiner les couleurs au niveau d’un pixel. - glutPostRedisplay() permet le rafraîchissement de l’affichage de l’objet.

26

E. Création de la boîte de dialogue

L’IHM a été divisée en deux parties :

• Une pour la commande d’affichage • Une pour la commande d’animation

Dans la partie AFFICHAGE, l’utilisateur commande le mode d’affichage, en vision anaglyphique ou normale, par un bouton pression ‘Anaglyphique’. Pour ajuster l’affichage à la vue de l’utilisateur, nous avons choisi de lui donner la possibilité de régler l’écart entre l’objet rouge et l’objet vert en utilisant un slider. De même, l’utilisateur pourra choisir le type d’objet qu’il affiche (puits, valeurs, limites de couches…) grâce à des check-boxes. La partie ANIMATION lui permet d’avoir le contrôle des objets affichés. L’utilisateur peut régler la position de l’objet à l’écran, effectuer des translations verticales et horizontales, procéder à des rotations selon les 3 axes de l’espace ou choisir de réinitialiser l’affichage. De plus, il pourra choisir de réduire ou agrandir l’objet grâce au slider du zoom. Les fonctions ci-dessus sont attachées à des scroll-bar et un bouton pression pour l’initialisation qui commande le retour à l’affichage initial de l’objet.

Figure 11 : capture d'écran de l'interface homme/machine ou IHM

27

Les différents modes de commande de l’IHM choisis sont relativement simples à utiliser. De manière générale, chaque bouton active un moteur composé de cases. Lorsque le bouton est activé, il commande par le biais de ce moteur une partie du code qui régit l’opération de transformation (translation, rotations, initialisation).

IV. RESULTATS Les outils qu’OpenGL proposent sont intéressants pour la création des objets que nous avons choisis. La liste des objets affichés est associée à une capture d’écran de notre affichage pour chaque type d’objet. Notre programme est fait de telle sorte qu’à chaque nouvelle exécution les couleurs des couches soient différentes. Ceci explique pourquoi les couches du bloc diagramme apparaissent sur les captures d’écran suivantes avec des couleurs différentes.

A. L’affichage

1. Mode d‘affichage Nous avons choisi de pouvoir afficher le terrain selon 2 modes : l’un normal qui fait apparaître l’objet en perspective. L’autre anaglyphique qui fait apparaît l’objet en 3 dimensions à condition que l’observateur utilise des lunettes appropriées.

- Normal :

L’affichage normal aura l’avantage de montrer les épaisseurs de couches. C’est celui qui donnera le mieux une estimation des volumes qui composent le bloc diagramme.

Figure 12: Affichage normal du bloc diagramme. Tous les objets apparaissent en volumes

pleins plus ou moins transparents. - Anaglyphique :

Le mode d’affichage anaglyphique montrera bien plus précisément les reliefs qui composent l’objet. Pour cela, l’objet doit être filaire. Il doit être affiché deux fois à l’écran. Une fois à gauche et en rouge, une autre fois à droite et en vert. Un

28

observateur muni de lunette avec un filtre rouge pour un œil et un filtre vert pour l’autre œil verra l’objet apparaître en 3 dimensions pour peu que l’écart soit ajusté à son regard. C’est pourquoi nous avons choisi de mettre une commande sur l’IHM pour que l’utilisateur puisse régler l’écartement entre les deux objets à son gré.

Figure 13: Bloc diagramme affiché en vision anaglyp hique. Deux images sont superposées :

une rouge à gauche et une verte à droite.

2. Le sol Il est représenté par un rectangle. Pour réaliser cette surface, la fonction d’OpenGL qui permet l’affichage des rectangles est utilisée. Les quatre points utilisés sont ceux de qui encadrent les extrema des coordonnées de puits renseignées par le fichier champ.txt

Figure 14: Surface du bloc diagramme

3. Les puits

29

Ils sont représentés par des lignes épaisses verticales. Ils possèdent la même longueur et sont positionnés grâce aux coordonnées enregistrées dans le fichier champ.txt.

Figure 15: Puits

4. Les valeurs

Les valeurs doivent s’agencer au côté du puits qu’elles caractérisent. Pour les positionner au bon endroit, les valeurs sont considérées comme étant une ligne. Les différents points qui la composent possèdent la même ordonnée que le puits, mais leur abscisse correspondra à celle du puits à laquelle une valeur val est ajoutée. Celle-ci est donnée par le fichier val.txt. La profondeur décroit proportionnellement en fonction du numéro de la valeur dans le puits et du coefficient de profondeur DZ.

Figure 16: Valeurs de diagraphie: courbes courant p rès des puits qu'elles caractérisent

5. Les limites de couches

Vues de dessus, les limites de couches ressemblent à une superposition de surfaces planes composées de triangles. Ceci est dû au fait que l’abscisse et l’ordonnée des sommets qui la composent ne varient pas d’une couche à l’autre. En réalité, la profondeur varie ce qui confère aux surfaces un relief. Nous considérons chaque triangle comme étant un domaine. L’un des sommets du triangle sera le sommet initial et le sommet final de l’arc (périphérie du triangle). Les 2 autres sommets du triangle seront considérés comme étant des points annexes.

30

Chaque sommet de triangle correspond à l’emplacement d’un puits à une certaine profondeur.

Figure 17: Vue de dessus des limites de couches en vision anaglyphique. Chaque sommet des

triangles correspond à la position d'un puits

La seule restriction imposée est que pour un puits donné, le sommet d’une couche ne doit pas être à une altitude supérieure de celui qui le précède. De même, son altitude ne doit pas être inférieure à celle du sommet qui le suit.

Figure 18: Vision anaglyphique des limites de couch es, vue de côté

Chaque limite de couche correspond à un raccordement entre les différents puits au niveau de changement brusque de même sens et de même ordre dans les valeurs de diagraphies. Les figures suivantes montrent le résultat en vision normale. L’utilisateur peut choisir entre un affichage complet de toutes les couches et un affichage ciblé des couches qui l’intéressent (figures 19 et 20).

31

Figure 19: en affichage normal, les limites de couc hes apparaissent de façon nette aux

changements brusques de valeurs de diagraphie

Figure 20: Il est possible de choisir les limites d e couches affichées. Ici, une limite de couche

sur deux a été gardée

6. Les couches

Elles sont représentées par un volume compris entre 2 limites de couches. En utilisant la boîte de dialogue, l’utilisateur peut choisir les couches qu’il veut afficher. La transparence plus ou moins prononcé des volumes permettent d’identifier la position des puits ou de suivre les variations de valeurs des limites de diagraphie.

32

Figure 21: Représentation des couches existant sur tout le terrain

Figure 22: Certaines couches du bloc diagramme préc édent ont été masquées

B. L’animation L’affichage d’un objet 3D ne serait pas très utile si l’utilisateur n’avait pas la possibilité de manipuler cet objet. En effet, c’est grâce à cette manipulation que l’observateur pourra se rendre pleinement compte des dimensions et reliefs du terrain. Nous avons choisi 3 grands types de transformations : la rotation, la translation et la modification d’échelle.

1. Les rotations Les rotations selon les 3 axes de l’espace ont été assurées. L’axe des abscisses est considéré comme étant l’axe horizontal par rapport à l’observateur. L’axe des ordonnées sera l’axe vertical pour l’utilisateur. Le dernier axe, celui de la profondeur, sera celui qui court de l’objet vers l’utilisateur. Pour pouvoir comparer ces trois commandes, nous comparerons chaque transformation à la position initiale de l’objet (figure 23).

33

Figure 23: position initiale de l'objet

- Rotation selon l’horizontale : rotation autour de l’axe x. Les coordonnées des tous les éléments qui composent l’objet subissent une multiplication matricielle avec une matrice de rotation selon x. il en résulte un basculement de l’avant de l’objet soit vers le bas, soit vers le haut selon l’angle de rotation choisi.

Figure 24: position après rotation selon les abscis ses (axe horizontal par rapport à

l’observateur)

- Rotation selon la verticale : rotation autour de l’axe y.

34

Cette transformation résulte en un mouvement de l’avant de l’objet vers la droite ou vers la gauche. Il s’agit ici aussi d’une multiplication matricielle qui est mise en œuvre.

Figure 25: position finale après rotation selon les ordonnées (axe vertical par rapport à

l'observateur)

- rotation selon la profondeur : rotation autour de l’axe z. Comme toute rotation, il s’agit ici aussi d’une multiplication matricielle.

Figure 26: position finale de l'objet après rotatio n selon l'axe de la profondeur (axe allant de

l'objet à l'observateur)

2. Les translations Toute translation utilisera encore une fois le principe des multiplications de matrices pour des raisons d’homogénéité avec les autres transformations. En réalité, il s’agit d’utiliser un vecteur de dimension 3 qui ajoutera à chaque coordonnée de tous les

35

points un pas. Ce pas correspond à la valeur des coordonnées du vecteur translation.

- Position initiale de l’objet : image qui sert de référence pour identifier la transformation après translation.

Figure 27: position initiale de l'objet avant toute translation

- Translation selon l’axe vertical :

Pour obtenir ce résultat, toutes les ordonnées de tous les points de l’objet se sont vues ajouter un pas transY.

Figure 28: position finale de l'objet après une tra nslation verticale

36

- Translation selon l’horizontale :

Toutes les abscisses des points se sont vues ajouter un pas de translation transX.

Figure 29: position finale de l'objet après une tra nslation horizontale

3. Réduction/ agrandissement

De même que pour les rotations et translations, la modification d’échelle est donnée par une multiplication matricielle d’une matrice carrée à 4 dimensions.

Figure 30: Objet tel qu'il apparaît après un agrand issement de l'échelle

37

V. DISCUSSION

A. Définition des limites du projet Notre première étape a été de définir les limites de notre projet. L’essentiel des difficultés a résidé dans le fait que notre projet porte essentiellement sur l’affichage et beaucoup moins sur le traitement de données. Il nous a donc été nécessaire de définir quel était le niveau de détail requis pour que l’application puisse être intéressante d’un point de vue interprétatif. Pour cela, nous avons ciblé notre recherche sur des algorithmes de calculs qui ne reprennent pas des fonctions existantes d’OpenGL. Aujourd’hui que le projet est fini, nous réalisons que nous avons utilisé peu de nos algorithmes. Tel est le cas pour l’algorithme de construction des tables SIF et GD, tout comme ceux qui permettent d’obtenir les coordonnées écran depuis les coordonnées 3D dans l’espace objet. A cette phase de définition des limites s’ajoute la définition des fonctionnalités auxquelles un utilisateur pourrait faire appel. Pour cela, il nous a fallu nous mettre dans la peau d’un utilisateur pour penser au mieux la gestion de l’affichage et de l’animation.

B. Phase de réalisation Cette étape passe obligatoirement par une période de prise en main de l’outil Fortran95 avant de réussir à manipuler des objets 3D grâce à OpenGL. Malgré les difficultés rencontrées initialement, nous avons réussi à obtenir un résultat en affichage normal d’un objet en perspective tout comme un affichage en vision anaglyphique. Malgré tout, il reste quelques difficultés que nous n’avons pas su résoudre. En premier lieu, l’affichage en vision anaglyphique reste problématique. En effet, nous avons évidemment réalisé qu’une simple translation de l’objet et son affichage dans une autre couleur ne suffit pas à donner un résultat suffisant. Si cette seule opération est réalisée, alors lors de la rotation, les objets rouge et vert subissent tout deux la transformation. Il en résulte une inversion dans l’affichage des couleurs : l’objet vert, initialement à droite de l’objet rouge passe à sa gauche. Deux solutions se sont présentées à nous :

- inverser les couleurs lorsque l’objet subit une rotation d’une valeur d’angle comprise dans l’intervalle d’inversion. Cependant, parce que nous autorisons les rotations dans les 3 dimensions de l’espace, nous sommes confrontés à un problème de définition des intervalles d’inversion que nous n’avons su résoudre.

- Obtenir l’affichage de deux objets identiques cette fois-ci dans deux procédures. L’idée était de créer un premier objet, d’initialiser les matrices qui lui sont associées pour l’affichage, d’opérer les transformations voulues et d’afficher le résultat à l’écran. La même procédure sera appliquée au deuxième objet, image du premier après translation. Pour ce faire, nous avons choisi d’implanter ces deux procédures dans une boucle allant de 1

38

à 2. Cette boucle contient un case qui l’objet vert ou rouge selon l’état de la boucle. Ce procédé s’est montré efficace sur un objet simple tel qu’un cube. En effet, l’objet rouge restait constamment à la gauche de l’objet vert. Les transformations qui leur étaient appliquées avaient la même amplitude, par conséquent les deux objets restaient côte à côte. Cependant, nous n’avons su implanter cette procédure dans le bloc diagramme complet.

Une autre difficulté rencontrée a été celle des multiplications matricielles lors d’un enchaînement de transformations. En effet, dans le cas des rotations, nous avons réalisé que lors d’une succession de rotation, une multiplication de matrices s’opérait et les axes résultants devenaient différent des axes initiaux. Pour éviter un tel écueil, il aurait fallu utiliser un repère différent de celui de l’espace objet, ou même de celui de l’objet. Ainsi, nous aurions dû utiliser un repère dont l’axe des profondeurs serait celui allant de l’objet cible vers l’utilisateur, dont l’horizontale serait donnée par un produit vectoriel entre la verticale et l’axe des profondeurs. Avec un tel repère, toute transformation appliquée ne paraît pas subir de multiplication de matrice. Le même type de difficulté d’implantation s’est présenté lors de la mise en fonction d’un retour à l’affichage initial. La procédure était opérationnelle sur un objet simple comme le cube : l’objet retournait à sa place initiale et dans la position initiale. Lors de l’implantation dans le code du terrain, seule le retour à la position initiale a été réussi. De même, nous n’avons pu tracer réellement des courbes de Béziers. Nous avons donc dû nous résoudre à les remplacer par des segments joignant les points correspondant aux valeurs des puits. D’autres difficultés, cette fois inhérentes au fonctionnement du compilateur, nous ont ralenti dans notre progression. La fabrication d’un système de tirage aléatoire de nombres réels. La subroutine que nous avons construite, est basée sur la fonction random_num (qui n’a rien d’aléatoire : les chiffres de sortie sont toujours les mêmes dans le même ordre) ainsi que sur l’heure d’exécution du programme pour introduire une donnée variable. En théorie, il ne sera possible d’obtenir le même tableau de valeurs qu’uniquement dans le cas où le programme est exécuté à la même milliseconde du même jour de l’année. Mais, malheureusement, l’aléatoire n’existe pas en informatique.

C. Phase de manipulation Nous avons été confrontés au problème de la portabilité : les mêmes fonctions provenant des mêmes bibliothèques ne sont pas toujours fonctionnelles selon la machines utilisée. Un exemple précis serait l’association de fonctions aux boutons de la souris. Normalement, si une fonction différente est assignée à chacun des boutons de la souris, chaque bouton doit activer sa propre fonction. Or, nous avons dû constater que tous les boutons de notre souris donnent le même résultat même si des fonctions différentes leur sont affectées. La seule fonction activée sera celle du bouton gauche.

39

D. En équipe Les difficultés qui suivent, sont cette fois-ci entièrement liées à nos aptitudes. En effet, il est plus ou moins difficile selon les individus d’appréhender correctement les 2 repères utilisés sous OpenGL : le repère de l’objet (ou repère terrain) et le repère de la zone d’affichage. La confusion entre les deux reste parfois un écueil à éviter. De plus, s’agissant de notre premier projet de programmation de près de 2000 lignes, il nous est apparu bien clairement les raisons pour lesquelles il faut apporter du soin à la façon dont le programme est fait. Le code doit être clairement commenté et structuré de telle sorte qu’il puisse être repris par n’importe qui. L’organisation sera le reflet de la structure de l’algorithme. Les variables doivent être déclarées en en-tête et commentées de telles qu’elles soient compréhensibles par tous. En effet, nous avons vite compris l’intérêt des règles qui viennent d’être énoncées surtout lorsqu’il s’agit d’implanter des morceaux de programme d’un membre du projet dans le travail de l’autre membre. De même nous aurions dû convenir de noms de variables pour éviter tout conflit à résoudre lors de cette implantation. L’implantation des subroutines gérant l’anaglyphe et le retour à la position initiale sont deux exemples flagrants du problème énoncé ci-dessus.

VI. CONCLUSION Notre sujet est essentiellement axé sur l’affichage d’un objet 3D et s’est montré intéressant pour plusieurs raisons. Tout d’abord, s’agissant de notre première expérience de programmation d’un objet en 3D, il a consisté en de nouvelles connaissances à acquérir et à maîtriser. De plus, ayant été traité peu de fois dans les promotions antérieures, nous n’avons pu nous baser sur les travaux d’anciens pour penser notre projet. Tout a été donc à penser et à construire. De plus, toutes les difficultés rencontrées inhérentes à nos aptitudes ou à notre façon de procéder ont été très formatrices. Elles constituent des écueils à éviter pour les projets suivants dont nous sommes entièrement conscients. Un exemple parlant est celui des noms d’identificateurs à convenir pour faciliter la mise en commun des codes de chacun des membres de l’équipe. Un autre exemple est celui de la transcription d’un concept algorithmique qui parait pourtant évident dans la réalité à un code en Fortran. Ainsi, la traduction en Fortran du concept algorithmique Ale(0), donnant un réel compris entre 0 et 1, qui n’est pas si aisée. Même si l’utilisation des champs de diagraphies appartient à un domaine très spécialisé, il n’en est pas moins que les connaissances acquises sont transférables :

- Dans le cas de la gestion de bases de données, il nous aura fallu les construire avant de pouvoir les utiliser et éventuellement les modifier.

- Parce que nous avons construit la base de données nous avons dû gérer : o le positionnement des éléments qui composent notre objet o la visualisation 3D sur papier avant de pouvoir afficher le résultat à

l’écran. Ceci a consisté en la construction d’une BD non aléatoire entièrement sur papier avant même de l’afficher sur l’écran. Il a donc fallu s’assurer de la bonne coordination des tables qui composent cette BD ce qui fut relativement difficile.

40

- L’étape de construction d’une boîte de dialogue nous a permis de nous mettre dans la peau d’un utilisateur lambda. Nous avons considéré que celui-ci a pour seul but de pouvoir effectuer les modifications qu’il souhaite sans pour autant modifier le code de l’application.

Ce projet constitue notre première vraie expérience de programmation. Nous en retirons donc beaucoup de bénéfices. Ainsi, nous sommes entièrement convaincus que la structuration et le commentaire d’un programme sont des qualités impérativement requises pour tout projet. En effet, la récupération de tout programme qui ne répondra pas aux impératifs précédemment énoncés se verra très difficile voire quasi impossible.

VII. REFERENCES Les images trouvées : Bore hole : http://geothermal61.learnz.org.nz/pan/big/b-drill-rig.jpg Geological survey of Canada: http://gsc.nrcan.gc.ca/borehole/index_e.php Layne water: www.laynewater.com/borehole_geophysics.html . Burnside: http://www.rjburnside.com/GIS.aspx Ardara: www.ardara-me.com/borehole.html . Musée du pétrole, Schlumberger : http://www.musee-du-petrole.com/schlumberger.htm