Les graphiques 3D en perspective T.Friedrich, C.Pegoretti, S.Tournois Résumé : on étudie la programmation d'un objet 3D pour en faire une projection dans un plan 2D, avec la possibilité de diriger l'axe de vision. On illustre cet exposé de quelques exemples simples de projection. Abstract : we investigate the programming of a 3D object in order to make its projection in a 2D plane, with the possibility of steering the vision axis. We illustrate this account with a few simple projection examples. Introduction Il existe 2 grandes familles de transformations géométriques planes : Ù Les projections parallèles : elles possèdent un centre de projection situé à l'infini et elles sont donc définies par une direction de projection. Ces transformations respectent les règles de la géométrie. Ces projections sont très utilisées car il est possible de mesurer sur le dessin. Ù Les perspectives : contrairement aux projections parallèles elles possèdent un centre de projection situé à une distance finie qui correspond à la position de l'œil de l'observateur ainsi que leur propre géométrie. Lorsqu'un objet est représenté en perspective, ses caractéristiques géométriques ne sont plus respectées ce qui implique que l'on ne peut plus en extraire d'information dimensionnelle. Cependant c'est cette dernière qui se rapproche le plus de notre vision et qui marque le plus l'impression de profondeur. Pour simplifier la programmation nous nous sommes limités à la représentation «fil de fer». Analyse du problème ü Choix de la méthode Nous nous sommes penchés sur les possibilités de réaliser l'objet 3D. La perspective a été retenue pour son aspect plus naturel. Il restait le problème du centre de projection à savoir s'il restait fixe par rapport à l'objet ou le contraire. La deuxième configuration nous semblait plus réaliste. Il est vrai que pour les objets volumineux l'observateur doit tourner autour de l'objet. Pour obtenir la vision spatiale nous avons choisi de caractériser le centre de projection en coordonnées sphériques ce qui rend sa manipulation plus simple pour sélectionner les angles de vue désirés. Le plan de projection est orthogonal à l'axe Z du repère (2) qui pointe vers le centre du repère (1) à une distance d de celui-ci. Pour la partie plus mathématique, nous avions la possibilité de choisir les coordonnées cartésiennes (x, y, z) ou les coordonnées homogènes (x, y, z, 1). Nous avons donc choisi les coordonnées homogènes pour leurs propriétés car on peut multiplier une matrice de translation et une matrice de rotation. Ceci permet d'obtenir une matrice de passage 4x4 par une succession de multiplications.
2 Calcul scientifique avec Mathematica z xp yp Z Y X θ ϕ y x ü Partie théorique Le problème est de trouver la matrice de passage. Nous transformons le repère (1) en un repère (2) à l'aide d'une translation, de deux rotations et un changement d'axes de sorte à faire du repère (2) un repère direct. Suite à ces transformations nous obtenons la matrice de passage 4ä4 suivante : i - Sin q -Cos q Sin j -Cos q Cos j 0 y Cos q -Sin q Sin j Sin q Cos j 0 M = 0 Cos j -Sin j 0 j z k 0 0 R 1 { On a donc les coordonnées de l'objet dans le nouveau repère : (X, Y, Z, 1) = (x, y, z, 1).M Maintenant que nous avons les coordonnées dans le nouveau repère, il ne nous reste plus qu'à calculer les coordonnées des points dans le plan de projection : xp=(d.x)/z et yp=(d.y)/z Ceci nous fournit un couple de points que nous allons relier pour former l'image de l'objet 3D (xp, yp). La division par Z provoque un grandissement ou un rapetissement de l'objet selon que l'écran est derrière ou devant lui. On pourra remarquer que l'objet peut être n'importe où, excepté en Z=0. Conception d'un programme Nous avons essayé de simplifier notre programme le plus possible pour qu'il ne soit pas trop difficile à utiliser. La partie la plus pénible pour l'utilisateur, dirons-nous, sera d'entrer les coordonnées des points. Nous avons choisi une configuration où il faut entrer les arêtes des objets une à une et donc entrer un point origine et un point extrêmité. Il faudra également entrer les couleurs de traits que l'on veut, l'épaisseur (annexe). Bien que nous utilisions les coordonnées homogènes, l'utilisateur ne devra entrer que les coordonnées dans le repère (1), sous forme de primitives Point et/ou Line. arête={line[{{1,1,0},{0,1,0}}],line[{{1,0,1},{1,0,0}}]} Ayant trouvé la matrice de passage nous avons déterminé une fonction transform qui lorsque nous donnons les coordonnées d'un point V, les coordonnées du centre de projection T et la distance d du plan de projection, retourne un couple de points (xp, yp) à l'aide de :
2001.Perspectives.nb 3 transform[v_,{t1_,t2_,t3_},d_]:= d*(take[#,2]/#[[3]]&[append[v,1].{ {-Sin[t2],-Cos[t2]*Sin[t3], -Cos[t2]*Cos[t3], 0}, {Cos[t2],-Sin[t2]*Sin[t3],-Sin[t2]*Cos[t3],0}, {0,Cos[t3],-Sin[t3],0}, {0,0,t1,1} }]) Ensuite nous avons déterminé une autre fonction qui lorsqu'elle rencontre une primitive graphique du style Line ou Point, applique transform de manière appropriée (polymorphisme) : perspective[point[v_],t_,d_]:= Point[transform[V,T,d]] perspective[line[l_],t_,d_]:= Line[Map[transform[#,T,d]&,L]] Pour le cas où le programme rencontre une autre primitive que Point ou Line, on ajoute une définition qui retourne la primitive inchangée : perspective[x_,_,_]:=x Les définitions précédentes ne sont pas destinées à l'utilisateur, mais intégrées dans le programme pour le fonctionnement interne. Nous arrivons à la définition que l'utilisateur devra invoquer pour obtenir un objet graphique qui n'est autre que l'objet projeté. Il faut entrer une liste L de primitives ainsi éventuellement qu'une option compatible entre Gaphics et Graphics3D (annexe) : perspective[graphics3d[l_,opt ],T_,d_]:= Graphics[Map[perspective[#,T,d]&,L],opt] Il ne reste plus qu'à appliquer Show à cette structure pour que la liste d'arêtes ou l'objet 3D soit projeté sur un plan. Applications Nous allons montrer un cube et une maison. Le cube a été réalisé avec une couleur qui a été entrée dans la liste de directives et une option Axes : cube = 8RGBColor@0, 0, 1D, Line@880, 0, 0<, 81, 0, 0<<D, Line@880, 0, 0<, 80, 1, 0<<D, Line@880, 0, 0<, 80, 0, 1<<D, Line@881, 1, 0<, 81, 1, 1<<D, Line@881, 1, 0<, 80, 1, 0<<D, Line@881, 1, 0<, 81, 0, 0<<D, Line@881, 0, 1<, 81, 1, 1<<D, Line@881, 0, 1<, 80, 0, 1<<D, Line@881, 0, 1<, 81, 0, 0<<D, Line@880, 1, 1<, 80, 0, 1<<D, Line@880, 1, 1<, 81, 1, 1<<D, Line@880, 1, 1<, 80, 1, 0<<D<; Show@perspective@Graphics3D@cube, Axes Ø TrueD, 810, 25 Degree, 60 Degree<, 5DD; 0.2-0.2-0.1 0.1 0.2 0.3 0.4 0.5-0.2-0.4-0.6 La maison a été réalisée avec un niveau de gris et une épaisseur de trait insérés dans la liste de directives :
4 Calcul scientifique avec Mathematica Maison = 8Thickness@0.02D, GrayLevel@0.5D, Line@880, 0, 0<, 81, 0, 0<<D, Line@880, 0, 0<, 80, 1, 0<<D, Line@880, 0, 0<, 80, 0, 2<<D, Line@881, 1, 0<, 81, 1, 2<<D, Line@881, 1, 0<, 80, 1, 0<<D, Line@881, 1, 0<, 81, 0, 0<<D, Line@881, 0, 2<, 81, 1, 2<<D, Line@881, 0, 2<, 80, 0, 2<<D, Line@881, 0, 2<, 81, 0, 0<<D, Line@880, 1, 2<, 80, 0, 2<<D, Line@880, 1, 2<, 81, 1, 2<<D, Line@880, 1, 2<, 80, 1, 0<<D, Line@880.5, 0.5, 3<, 81, 0, 2<<D, Line@880.5, 0.5, 3<, 80, 0, 2<<D, Line@880.5, 0.5, 3<, 80, 1, 2<<D, Line@880.5, 0.5, 3<, 81, 1, 2<<D, Line@881, 0.25, 0<, 81, 0.25, 0.75<, 81, 0.75, 0.75<, 81, 0.75, 0<<D, Line@880, 1, 1<, 80, 3, 1<, 80, 3, 0<, 80, 1, 0<<D, Line@880.75, 1, 1<, 80.75, 3, 1<, 80.75, 3, 0<, 80.75, 1, 0<, 80.75, 1, 1<<D, Line@880.75, 3, 1<, 80, 3, 1<<D, Line@880.75, 3, 0<, 80, 3, 0<<D, Line@880.355, 2.5, 1.5<, 80, 3, 1<<D, Line@880.355, 2.5, 1.5<, 80.75, 3, 1<<D, Line@ 880.355, 2.5, 1.5<, 80.355, 1, 1.5<, 80.75, 1, 1<, 80, 1, 1<, 80.355, 1, 1.5<<D<; Show@ perspective@graphics3d@maisond, 850, 60 Degree, 30 Degree<, 1DD; Show@perspective@Graphics3D@Drop@Maison, 2D, DefaultColor Ø RGBColor@1, 0, 0D, Frame Ø True, PlotLabel Ø "Maison"D, 850, 60 Degree, 30 Degree<, 1DD; 0.04 Maison 0.02 0-0.02-0.01 0 0.01 0.02 0.03 Ces trois exemples représentent ce que nous pouvons faire avec notre programme. On peut s'apercevoir que l'on obtient une perspective à trois points de fuite si le centre de projection est près de l'objet. Perspectives Ù La représentation réalisée, de type «fil de fer», est claire mais il est difficile d'observer la profondeur : on ne sait pas ce qui est devant ou derrière. Il faudrait donc travailler plutôt avec les faces pour faire apparaître les faces visibles et supprimer les faces cachées. Cela pourrait être réalisable en mode «fil de fer» mais pour un objet unique, car en présence d'une superposition d'objets, cette représentation ne sera plus valide ou beaucoup plus complexe à réaliser. Ù Il faudrait également modifier l'opération d'enregistrement des coordonnées des points qui est fastidieuse et assez répétitive pour éviter de répéter plusieurs fois un même point. Ù Il faudrait également développer la partie des projections parallèles car ainsi on aurait toutes les projections 3D et l'utilisateur pourrait choisir la représentation souhaitée ; cependant, elle peut être reconstituée avec notre programme puisque si l'on place le centre de projection a l'infini (ou très loin) on observe une projection parallèle.
2001.Perspectives.nb 5 Ù Il faudrait également développer la partie des projections parallèles car ainsi on aurait toutes les projections 3D et l'utilisateur pourrait choisir la représentation souhaitée ; cependant, elle peut être reconstituée avec notre programme puisque si l'on place le centre de projection a l'infini (ou très loin) on observe une projection parallèle. Conclusion Comme pour tous les programmes, il faut développer une collection de «sous-fonctions» que le programme pourra appeler au moment opportun. Plus il existera de fonctions complémentaires, plus il y aura de possibilités d'exécution pour le programme. Le programme doit être fonctionnel, surtout la fonction d'appel qui est invoquée par l'utilisateur. En revanche les fonctions internes sont fabriquées à l'insu de l'utilisateur mais sont comprises entre les programmeurs. La projection qui est basée sur un problème mathématique relativement simple est en revanche plus difficile pour la partie programmation. Bien heureusement la programmation à l'aide de Mathematica est relativement aisée. Le fait d'avoir une perspective à 3 points de fuite pourrait déranger certaines personnes qui n'ont pas l'habitude de voir ce genre de représentation. Comme tout programme, le notre pourra être amélioré pour avoir une meilleure flexibilité d'utilisation. Bibliographie [1] DONY R. Graphisme dans le plan et l'espace avec Turbo Pascal. Masson, 1991, 271-284 [2] ROGERS D.F. et ADAMS J.A. Mathematical Elements for Computer Graphics. McGraw-Hill Inc, 1990 [3] SCHWEIZER P. Infographie II. Presses Polytechniques Romandes, 1987 [4] WOLFRAM S. Mathematica : le livre. International Thomson Publishing Company, France, 1997 [5] BARRERE R. Mathematica, calcul formel et programmation symbolique pour l'informatique scientifique. Polycopié ensmm, 2000 Annexe Les directives à insérer dans la liste de primitives sont : GrayLevel@iD Niveau de gris entre 0 HnoirL et 1 HblancL RGBColor@r, v, bd Couleur rouge, verte, bleu, chacune entre 0 et 1 Dashing@8w1, w2 <D Affiche les lignes en trait interrompu de paramètres w1, w2 Thickness@wD Epaisseur de la ligne Hue@h, s, bd Couleur avec teinte, saturation, luminosité entre 0 et 1 Les options à donner dans la commande d'exécution sont : Background Ø color DefaultColor Ø color Axes Ø True Axes Ø 8True, False< AxesLabel Ø 8x, y< PlotLabel Ø!text" GridLines Ø Automatic Frame Ø True Définit la couleur de l ' arrière plan Définit la couleur par défaut Affiche des axes Affiche l ' axe des x mais pas l' axe y Affiche le nom de l' axe x et de l' axe y Affiche le nom du graphe Dessine un quadrillage sur le tracé Ajoute des axes sur un cadre autour du tracé