\input $FORMAT/myplain.tex %\magnification 1200 \def \listingpath {% /var/www/syracuse/texpng/jpv/guide_jps/} \input \listingpath macros-doc.tex \titre {jps2ps~: version 0.15} \centerline {{\sl par Jean-Paul Vignault}} \centerline {{\sl Groupe des Utilisateurs de Linux Poitevins (GULP)}} \centerline {(|jpv@melusine.eu.org|)} \centerline {\today } \vskip \titreskip %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% debut du manuel %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \input \listingpath macros_compl-doc.tex \pageno -1 \egroup \pageno 1 Ce document présente les différences entre la version $0.15$ et la précédente. \paragraphe {Divers} \syntaxe \longref {$\{f\}$} {currentpathtransform} {$-$} {applique la transformation $f$ au chemin courant, où $f~: \rset ^2\rightarrow \rset ^2$} \longref {$array_1$} {uniqp} {$array_2$} {$array_2$ est le tableau obtenu à partir du tableau de points $array_1$ en suprimant les points identiques consécutifs} \longref {$array_1$ $array_2$} {append} {$array_3$} {$array_3$ est le tableau obtenu en concaténant les tableaux $array_1$ et $array_2$} \longref {$string_1$ $string_2$} {append} {$string_3$} {$string_3$ est la chaîne de caractères obtenue en concaténant les chapines de caractères $string_1$ et $string_2$} \endsyntaxe \paragraphe {Chemins continus paramétrés} Le type $chemin$ de la version $0.14$ est repris plus modestement en type $chemin\ continu$, en attendant une version future plus complète. \bgroup \let \ssparagraphe \sparagraphe \sinput \datapath diff_parampath.tex \egroup \paragraphe {Commandes 3d} On rappelle que la position de la caméra est donnée par le point $CamPos$, et que son orientation est définie par les 2~vecteurs $CamVec$ et $CamUp$ qui déterminent la ligne de visée et le plan de visée. Pour faciliter le positionnement de la caméra, on dispose maintenant de la commande |SetCamView| qui oriente la caméra vers un point fixé et qui recalcule le vecteur $CamUp$ pour avoir une base orthonormale du plan de visée. \exempledble {camview_01} {.4}{.5} \exempledble {camview_02} {.4}{.5} \exempledble {camview_03} {.4}{.5} De plus quelques nouvelles commandes sont venues enrichir la librairie 3d~: \syntaxe \longref {$M$} {SetCamView} {$-$} {Oriente la visée de la caméra vers le point $M (x, y , z)$ et recalcule tous les vecteurs nécessaires} \longref {$xmin$ $xmax$} {setxrange3d} {$-$} {affecte les variables $xmin3d$ et $xmax3d$ définissant l'intervalle de travail sur l'axe $Ox$ en $3d$} \longref {$ymin$ $ymax$} {setyrange3d} {$-$} {affecte les variables $ymin3d$ et $ymax3d$ définissant l'intervalle de travail sur l'axe $Oy$ en $3d$} \longref {$zmin$ $zmax$} {setzrange3d} {$-$} {affecte les variables $zmin3d$ et $zmax3d$ définissant l'intervalle de travail sur l'axe $Oz$ en $3d$} \longref {$-$} {qplanxz} {$-$} {effectue un quadrillage du plan $xOz$} \longref {$-$} {qplanyz} {$-$} {effectue un quadrillage du plan $yOz$} \longref {$[$ $A_0$ $\ldots $ $A_{n}$ $]$ $f$} {papply3d} {$[$ $b_0$ $\ldots $ $b_n$ $]$ ou $-$} {construit un nouveau tableau en répétant, pour $i$ variant de $0$ à $n$, l'opération suivante~: déposer le point $A_i$ puis exécuter $f$. Si à la fin de cette opération le tableau est vide, alors il est enlevé de la pile.} \longref {$[$ $A_0$ $\ldots $ $A_{n}$ $]$} {isobarycentre3d} {$G$} {le point $G$ est le barycentre du système $[(A_0, 1) ; \ldots ; (A_n, 1)]$} \longref {$[$ $A$ $a$ $B$ $b$ $]$} {barycentre3d} {$G$} {le point $G$ est le barycentre du système $[(A, a) ; (B, b)]$} \longref {$M$ $A$ $\alpha $} {hompoint3d} {$M'$} {$M'$ est l'image de $M$ par l'homothétie de centre $A$ et de rapport $\alpha $} \longref {$M$ $A$} {sympoint3d} {$M'$} {$M'$ est l'image de $M$ par la symétrie de centre $A$} \longref {$M$ $u$} {translatepoint3d} {$M'$} {$M'$ est l'image de $M$ par la translation de vecteur $\vec u$} \longref {$x$ $y$ $z$ $k_1$ $k_2$ $k_3$} {scaleOpoint3d} {$k_1x$ $k_2y$ $k_3z$} {opère une \og dilatation\fg \ des coordonnées du point $M (x, y, z)$ sur les axes $Ox$, $Oy$ et $Oz$ suivant les facteurs $k_1$, $k_2$ et $k_3$} \longref {$M$ $\alpha_x$ $\alpha_y$ $\alpha_z$} {rotateOpoint3d} {$M'$} {$M'$ est l'image de $M$ par la rotation de centre $O$ et d'angles respectifs $\alpha_x$ $\alpha_y$ $\alpha_z$ sur les axes $Ox$, $Oy$, $Oz$} \longref {$x$ $y$ $z$} {3dto2d} {$X$ $Y$} {calcule les coordonnées du point projeté sur l'écran pour la représentation 3d. cette commande est synonyme de la commande |CamView|} \endsyntaxe \paragraphe {Solides} Ce paragraphe présente un ensemble de macros dont le but est la manipulation et la représentation de solides convexes. Un effort particulier a été fait pour respecter la philosophie de la programmation \og orientée objet\fg , avec contrôle de typage et messages d'erreurs adéquats. Ce travail est basé sur les travaux de Manuel Luque \footnum {|melusine.eu.org/syracuse/mluque/pst-v3d/|} et de Christophe Poulain \footnum {|melusine.eu.org/syracuse/poulecl/macros/|} ainsi que le cours d'infographie du Prof. Daniel Thalmann dans la section \og \sl Computer Graphics\fg \ du {\sl Virtual Reality Lab\/} \footnum {|vrlab.epfl.ch/teaching/teaching\_index.html|} . \sparagraphe {Le type {\sl solid}} Le type $solid$ est un type à plusieurs composantes. Les deux composantes essentielles sont~: \item {$\bullet $} Un tableau des coordonnées (3d) des sommets du solides. Ce tableau est indexé à partir de l'indice~$0$. \item {$\bullet $} Un tableau des $faces$ du solide. Ce tableau est indexé à partir de l'indice~$0$. Et l'on désigne par $face$ un tableau des indices des sommets de la face considérée, avec la convention importante suivante~: les {\bf sommets sont rangés dans l'ordre trigonométrique} si l'on regarde la face considérée depuis l'extérieur du solide. \sparagraphe {Solides précalculés} Certains solides simples sont précalculés~: le cube, le cylindre, le cône, le tronc de cône, la sphère, le tétraèdre, l'octaèdre, l'icosaèdre, et le dodécaèdre. \def \listingpath {% /var/www/syracuse/texpng/jpv/guide_jps/} $$ \epsillustrate {solide_01.ps} $$ Voici la liste des commandes associées~: \syntaxe \longref {$a$} {newcube} {$solid$} {crée un nouveau cube, de type $solid$, de centre $O$, d'arête $a$} \longref {$z_0$ $r$ $z_1$} {newcylindre} {$solid$} {crée un nouveau cylindre, de type $solid$, d'axe $Oz$, de rayon $r$, allant du plan $z = z_0$ jusqu'au plan $z = z_1$} \longref {$z_0$ $r$ $z_1$} {newcone} {$solid$} {crée un nouveau cône, de type $solid$, d'axe $Oz$, de rayon $r$, allant du plan $z = z_0$ jusqu'au plan $z = z_1$} \longref {$z_0$ $r_0$ $z_1$ $r_1$} {newtronccone} {$solid$} {crée un nouveau tronc de cône, de type $solid$, d'axe $Oz$, de rayon de base $r_0$ (sur le plan $z = z_0$) et de rayon au sommet $r_1$ (sur le plan $z = z_1$)} \endsyntaxe $$ \epsillustrate {solide_02.ps} $$ \syntaxe \longref {$r$ $\{mode\}$} {newsphere} {$solid$} {crée une nouvelle sphère, de type $solid$, de centre $O$, de rayon $r$. Le paramètre $mode \in \{0, 1, 2, 3, 4\}$ est optionnel; il indique le niveau de résolution souhaité ($0 = $ mini, $4$ = maxi)} \longref {$-$} {newtetraedre} {$solid$} {crée un nouveau tétraèdre régulier, de type $solid$} \longref {$-$} {newoctaedre} {$solid$} {crée un nouvel octaèdre régulier, de type $solid$, de centre $O$} \longref {$-$} {newicosaedre} {$solid$} {crée un nouvel isocaèdre régulier, de type $solid$, de centre $O$} \longref {$-$} {newdodecaedre} {$solid$} {crée un nouveau dodécaèdre régulier, de type $solid$, de centre $O$} \endsyntaxe Pour la sphère, plusieurs modes de résolution sont proposés par un argument optionnel. Le mode par défaut est stocké dans la variable $defaultsolidmode$. Ceci permet de préparer son image en basse résolution (mode $0$), et de ne calculer la résolution souhaitée, lourde en temps de calcul, qu'au dernier moment. \` A terme, il est prévu de proposer un tel mode pour le cylindre, le cône et le tronc de cône. \syntaxe \Longref {} {defaultsolidmode} {mode de résolution par défaut pour les solides} {2} \endsyntaxe \sparagraphe {Dessiner un solide} Pour dessiner un solide, on dispose des commandes |drawsolid| et |drawsolid*|, cette dernière réalisant en plus le coloriage des faces visibles. \syntaxe \longref {$solid$} {drawsolid} {$-$} {dessine le solide $solid$} \longref {$solid$} {drawsolid*} {$-$} {dessine le solide $solid$ avec coloriage des faces visibles} \endsyntaxe On dispose de plus d'un booléen permettant d'activer ou non la représentation des arêtes cachées. \syntaxe \Longref {} {aretescachees} {booléen indiquant à la procédure |drawsolid| si l'on doit ou non représenter les arêtes cachées} {$true$} \endsyntaxe Par défaut, et comme à l'habitude, la couleur de coloriage des faces est définie par $fillstyle$. Pour une scène non éclairée (voir plus loin), 2~autres méthodes sont prévues pour spécifier la couleur d'une face donnée~: \item {$\bullet $} on spécifie, face par face, la couleur souhaitée avec la commande |solidputfcolors|. La couleur est spécifiée par une chaîne de caractères. \item {$\bullet $} on spécifie la couleur souhaitée en fonction du nombre de côtés des faces. On utilise pour cela la commande |solidputncolors|. Pour chacune de ces méthodes, on transmet comme argument un tableau comportant des chaînes de caractères désignant la couleur souhaitée. Ce tableau est ensuite stocké comme un constituant du solide. Pour un solide donné, on obtient ces tableaux avec les commandes |solidgetfcolors| et |solidgetncolors|. L'élement d'indice $i$ du tableau $fcolor$ correspond à la face d'indice $i$ du solide, et l'élement d'indice $i$ du tableau $ncolors$ correspond à la couleurs des faces à $3 + i$ côtés. Dans l'exemple ci-dessous, on dessine un cube tronqué, dont on précise que les faces triangulaires (à 3~côtés) doivent êtres colorées en bleu. On définit ensuite un nouveau cube, que l'on stocke dans la variable $moncube$, dont on définit la couleur pour chacune des $6$~faces. On représente ensuite 2~instances de ce cube, l'une ayant subi une rotation de $120°$ autour de l'axe $Oz$. Dans cet exemple, on pourra remarquer un phénomène étonnant au premier abord~: dans la variable $moncube$ est stocké le cube de centre $O$ et d'arête~$2$. On fait ensuite subir à ce solide une rotation de $20°$ autour de l'axe $Oz$, puis une translation de vecteur $\vec k$ (vecteur unitaire dirigeant l'axe $Oz$). La variable $moncube$ désigne alors, non pas le cube d'origine, mais le cube transformé. Ce phénomène s'explique par le fait que pour les objets complexes (les solides, mais aussi les matrices, les tableaux, etc...), ce n'est pas l'objet que postscript dépose sur la pile, mais une référence à l'objet (un {\sl pointeur\/} comme l'on dit en C, en Pascal ou en ADA). Or les transformations effectuées agissent sur l'objet lui-même... Si l'on veut éviter ce phénomène, et si l'on souhaite avoir 2~solides identiques, mais avec des instances séparées, on utilisera la commande |dupsolid| qui construit une nouvelle instance, copie conforme de celle passée en argument. \exempledble {solide_03} {.4}{.5} \syntaxe \longref {$solid$ $array$} {solidputncolors} {$-$} {affecte au solide $solid$ le tableau $array$ en tant que tableau des couleurs des faces à $n$ côtés} \longref {$solid$} {solidgetncolors} {$array$} {le tableau $array$ est le tableau des couleurs des faces à $n$ côtés pour le solide $solid$} \longref {$solid$ $array$} {solidputfcolors} {$-$} {affecte au solide $solid$ le tableau $array$ en tant que tableau des couleurs des faces} \longref {$solid$} {solidgetfcolors} {$array$} {le tableau $array$ est le tableau des couleurs des faces pour le solide $solid$} \endsyntaxe \sparagraphe {Générer un solide} Un solide peut être {\sl monoface}, auquel cas il sera visible du côté de sa normale, et invisible du côté \og arrière\fg . Il peut également être {\sl biface}, autrement dit aplati. Plusieurs méthodes pour générer un solide~: \item {$\bullet $} On crée un tableau des coordonnées des sommets, puis le tableau des faces, qui est lui-même un tableau de tableaux, ces derniers contenant, pour une face donnée, les indices des sommets de la face, rangés par ordre trigonométrique lorsque l'on regarde le solide de l'extérieur. On dépose alors les 2~tableaux (sommets et faces) sur la pile et on invoque la fonction |generesolid|. \exempledble {solide_gen_02} {.3}{.6} \item {$\bullet $} On construit un tableau des coordonnées 2d des sommets d'une face sur le plan $xOy$, puis on invoque l'une des fonctions |generemonoface|, |generebiface|, |genereprismedroit| ou |genereprisme|. \exempledble {solide_gen_01} {.3}{.6} \item {} {\bf Remarque~:} Pour cette dernière méthode, le tableau décrivant la face initiale peut-être obtenue du chemin continu courant en utilisant la commande $currentcpathpointstable$. Par exemple, voici un prisme droit généré à partir de la courbe $y = 2\sin x$~: \exempledble {solide_gen_04} {.3}{.6} En résumé~: \syntaxe \longref {$array_1$ $array_2$} {generesolid} {$solid$} {construit un solide dont le tableaux des sommets est $array_1$ et le tableau des faces est $array_2$} \longref {$array$} {generemonoface} {$solid$} {construit un solide monoface, dans le plan $xOy$, à partir du tableau de points $array$. Les points sont en 2d, et rangés de manière à décrire l'orientation de la face (sens trigonométrique $\Rightarrow $ face de normale $Oz$, dans le sens des $z$ croissants)} \longref {$array$} {generebiface} {$solid$} {construit un solide biface, dans le plan $xOy$, à partir du tableau de points $array$. Les points sont en 2d, et rangés de manière à décrire l'orientation de la face (sens trigonométrique $\Rightarrow $ face de normale $Oz$, dans le sens des $z$ croissants)} \longref {$array$ $z_0$ $z_1$} {genereprismedroit} {$solid$} {construit un prisme droit d'axe $Oz$ à partir du tableau de points $array$. Les points sont en 2d, et rangés de manière à décrire l'orientation de la face (sens trigonométrique $\Rightarrow $ face de normale $Oz$, dans le sens des $z$ croissants). La base du prisme est sur le plan $z = z_0$ et sa face supérieure sur le plan $z = z_1$} \longref {$array$ $z_0$ $z_1$ $\vec u$} {genereprisme} {$solid$} {construit un prisme oblique d'axe $(O, \vec u)$ à partir du tableau de points $array$. Les points sont en 2d, et rangés de manière à décrire l'orientation de la face (sens trigonométrique $\Rightarrow $ face de normale $Oz$, dans le sens des $z$ croissants). La base du prisme est sur le plan $z = z_0$ et sa face supérieure sur le plan $z = z_1$} \endsyntaxe \sparagraphe {Opérations sur les solides} La commande |solidtransform| à qui l'on passe en argument une transformation $\rset ^3 \rightarrow \rset ^3$, applique cette tranformation à chacun des sommets du solide considéré. Ceci permet notamment, par le biais des commandes |translatepoint3d| et |rotate0point3d|, de positionner un solide dans l'espace, mais aussi, par l'intermédiaire de |scaleOpoint3d|, de changer ses dimensions. \syntaxe \longref {$solid$ $\{f\}$} {solidtransform} {$solid$} {applique la transformation $f$ au solide $solid$, $f$ étant une application $\rset ^3 \longrightarrow \rset ^3$} \endsyntaxe Pour les cubes, on dispose de la commande |tronque_cube|, qui permet d'obtenir un nouveau solide en coupant les $8$~coins du cube d'origine suivant une proportion que l'on transmet en argument ($2 \Rightarrow $ on coupe au milieu de l'arête, $3\Rightarrow $ au tiers, $4\Rightarrow $ au quart, etc...) \syntaxe \longref {$solid_1$ $n$} {tronque\_cube} {$solid_2$} {$solid_2$ est le solide obtenu en coupant chaque coin du parallélépipède $solid_1$. $n$ est un réel supérieur à 2 indiquant la proportion à respecter pour la tronquature} \endsyntaxe \sparagraphe {\' Eclairage par une source lumineuse ponctuelle} Il est possible d'éclairer la scène par une source ponctuelle d'une couleur et d'une intensité donnée. Dans ce cas, seule cette dernière est prise en compte pour le coloriage des faces des solides présents. L'intensité de la couleur d'une face dépend de l'inclinaison de la face et de sa distance par rapport à la source lumineuse. \exempledble {solide_light} {.3}{.6} \syntaxe \longref {$array$} {setlight} {$-$} {Affecte la couleur de la source lumineuse ponctuelle dans l'espace RGB ou CYMK, $array$ étant un tableau de 3 ou 4 réels de l'intervalle $[0; 1]$} \longref {$\{f\}$} {setlight} {$-$} {\' Exécute la fonction $f$ dans un |gsave .. grestore|, y récupère la définition de la couleur dans l'espace RGB, puis l'affecte à la couleur de la source lumineuse ponctuelle.} \longref {$i$} {setlightintensity} {$-$} {Affecte l'intensité de la source lumineuse ponctuelle} \longref {$x$ $y$ $z$} {setlightsrc} {$-$} {Affecte la position de la source lumineuse ponctuelle} \Longref {} {lightintensity} {Intensité de la source lumineuse ponctuelle} {$1$} \endsyntaxe \sparagraphe {Boîte à outils} Ci-dessous une liste des autres fonctions et procédures disponibles concernant le type $solid$~: \syntaxe \longref {$-$} {newsolid} {$solid$} {dépose le solide nul sur la pile} \longref {$solid$} {emptysolid} {$bool$} {$bool$ vaut $true$ si le solide est vide, $false$ sinon} \longref {$any$} {issolid} {$bool$} {$bool$ vaut $true$ si $any$ est de type $solid$, $false$ sinon} \longref {$solid$ $i$} {solidgetsommetsface} {$array$} {$array$ est le tableau des sommets de la face d'indice $i$ du solide $solid$} \longref {$solid$ $i$ $j$} {solidgetsommetface} {$S$} {$S$ est le sommet d'indice $i$ de la face d'indice $j$ du solide $solid$} \longref {$solid$ $i$} {solidgetsommet} {$S$} {$S$ est le sommet d'indice $i$ du solide $solid$} \longref {$solid$} {solidgetpointstable} {$array$} {$array$ est le tableau des sommets du solide} \longref {$solid$} {solidgetfaces} {$array$} {$array$ est le tableau des faces du solide} \longref {$solid$ $i$} {solidgetface} {$array$} {$array$ est le tableau décrivant la face $i$ du solide (tableau d'indices de sommets)} \longref {$solid$ $array$} {solidputpointstable} {$solid$} {} \longref {$solid$ $array$} {solidputfaces} {$array$} {} \longref {$solid$ $i$} {solidfacevisible?} {$bool$} {$bool$ vaut $true$ si la face d'indice $i$ du solide $solid$ est visible} \longref {$solid$ $i$} {solidnormaleface} {$\vec u$} {$\vec u$ est un vecteur normal à la face d'indice $i$ du solide $solid$. Le vecteur est orientaté vers l'extérieur du solide} \longref {$solid$ $i$} {solidcentreface} {$G$} {le point $G$ est le centre de la face d'indice $i$ du solide $solid$} \longref {$solid$} {solidnombresommets} {$n$} {nombres de sommets du solide $solid$} \longref {$solid$} {solidnombrefaces} {$n$} {nombres de faces du solide $solid$} \longref {$solid$} {solidnumsommets} {$-$} {affiche en face de chaque sommet du solide $solid$ son indice dans le tableau des sommets} \longref {$solid$} {dupsolid} {$solid$ $solid$} {crée une nouvelle instance du solide déposé sur la pile} \endsyntaxe \bye \longref {} {xplanmappoint} {} {} \longref {} {yplanmappoint} {} {} \longref {} {zplanmappoint} {} {}