• Aucun résultat trouvé

B.1 Projection d'une bo^ te orthogonalement a la diagonale principale

3.4 Operations booleennes



ERATIONS BOOL



EENNES 53

3.3.2 Transformation des normales

Ce traitement est encore une fois tres simple, et peut ^etre precise par le resultat suivant: Soit ~n la normale sortante au point d'intersection entre le rayon R0 et l'objet A. Alors la normale exterieure au point d'intersection entre le rayon R et l'objet T(A) esttT;1(~n).

Remarque 1

Les resultats que nous venons d'enoncer peuvent bien s^ur s'appliquer aux matrices globales, qui representent des transformations anes compactees.

Remarque 2

Les resultats enonces ci-dessus expliquent pourquoi on conserve dans les n!uds de type transformation ane la matrice inverse de la transformation: c'est celle-ci qui est utile, aussi bien pour la transformation du rayon que pour la transformation des normales.

3.4 Operations booleennes

La gestion des operations booleennes est relativement simple dans son principe: pour realiser une intersection entre un rayon et un objet de type operation booleenne, on realise l'intersection entre le rayon et chacun des operandes, puis on combine les listes d'intervalles d'intersection trouvees.

Il y a cependant deux parametres importants dont il faut tenir compte: la notion d'homogeneite et la notion de priorite horizontale.

Pour tous les types d'operations, l'algorithme de combinaison parcourt les deux listes d'intervalles d'intersection, et calcule la liste resultante. On peut d'ailleurs noter que l'algorithme utilise la liste d'intervalles de l'operande gauche pour stocker le resultat. La liste droite est liberee en n d'algorithme et il faut donc prendre garde a ce que cette liste ne partage pas de donnees avec la liste resultat.

D'un point de vue pratique, les listes d'intervalles d'intersection sont stockees sous forme de listes ch^ainees, et on utilise un pointeur courant pour chacune des listes. A chaque etape de l'algorithme, on determine l'intervalle resultant de la combinaison des deux intervalles pointes par les pointeurs courants. Puis on incremente l'un ou l'autre des pointeurs, voire m^eme les deux selon les positions relatives.

3.4.1 Positions relatives de deux intervalles

Pour chaque couple d'intervalles d'intersection (un avec l'operande gauche et un avec l'operande droit), il est important de determiner la position relative de l'un par rapport a l'autre. On peut en fait trouver 11 positions relatives dierentes, que nous allons detailler maintenant.

On note Ginet Goutles abscisses d'entree et de sortie de l'intervalle gauche et Dinet Doutles abscisses d'entree et de sortie de l'intervalle droit. Les dierentes positions sont les suivantes:

{ G ET D DISJOINTS: ceci equivaut a Gout Din. { D ET G DISJOINTS: ceci equivaut a Dout Gin. { G AVANT D: ceci equivaut a Gin< Din< Gout< Dout. { D AVANT G: ceci equivaut a Din< Gin< Dout< Gout. { G CONTIENT D: ceci equivaut a Gin< Din Dout< Gout. { D CONTIENT G: ceci equivaut a Din< Gin Gout< Dout. { G G CONTIENT D: ceci equivaut a Gin= Din< Dout< Gout.

{ G D CONTIENT G: ceci equivaut a Gin= Din< Gout< Dout. { G CONTIENT D D: ceci equivaut a Gin< Din< Dout= Gout. { D CONTIENT G D: ceci equivaut a Din< Gin< Dout= Gout. { G EGAL D: ceci equivaut a Din= Gin Dout= Gout.

La fonction qui determine les positions relatives est employee tres frequemment, elle a donc tout inter^et a ^etre la plus ecace possible. La position relative peut en fait se calculer par 4 tests seulement, comme l'indique la fonction suivante.

#define G_ET_D_DISJOINTS 15 #define D_ET_G_DISJOINTS 0 #define G_AVANT_D 14 #define D_AVANT_G 4 #define G_CONTIENT_D 6 #define D_CONTIENT_G 12 #define G_G_CONTIENT_D 5 #define G_D_CONTIENT_G 13 #define G_CONTIENT_D_D 10 #define D_CONTIENT_G_D 8 #define G_EGAL_D 9

unsigned int position_relative (gauche,droit) {

unsigned int res=0

if (droit->absc_in > gauche->absc_in) if (droit->absc_in >= gauche->absc_out) return(G_ET_D_DISJOINTS) else res+=2 else if (droit->absc_in==gauche->absc_in) res+=1 else res+=0 if (droit->absc_out >= gauche->absc_out) if (droit->absc_out==gauche->absc_out) res+=8 else res+=12 else if (droit->absc_out <= gauche->absc_in) return(D_ET_G_DISJOINTS) else res+=4 return(res) }

3.4. OP 

ERATIONS BOOL



EENNES 55

La numerotation peut sembler bizarre mais elle correspond en fait a la chose suivante:

{ la position de Dinpar rapport aux abscisses de l'intervalle gauche peut prendre 4 valeurs. { 0 si Din< Gin

{ 1 si Din= Gin

{ 2 si Gin< Din< Gout

{ 3 si DinGout

{ la position de Doutpar rapport aux abscisses de l'intervalle gauche peut aussi prendre 4 valeurs. { 0 si Dout Gin

{ 4 si Gin< Dout< Gout

{ 8 si Dout= Gout

{ 12 si Dout> Gout

{ la position relative des deux intervalles se calcule alors en ajoutant les deux valeurs precedentes5. Pour calculer la position d'une abscisse par rapport aux deux autres, il sut alors d'au plus 2 tests, soit en tout un maximum de 4 tests.

3.4.2 Gestion de la priorite horizontale

C'est en eet lors de la combinaison des listes d'intervalles d'intersections que l'on tient compte de cette priorite horizontale.

La priorite est stockee sur chaque n!ud de type intersection ou reunion (elle n'a pas de sens pour une dierence) sous forme de deux variables (une pour chaque type d'objet) pouvant prendre 4 valeurs:

{ GAUCHEsi l'objet gauche est prioritaire. { DROITsi l'objet droit est prioritaire.

{ FUSIONsi l'operation booleenne a ete declaree comme etant homogene. { MELANGE si l'operation booleenne melange les proprietes des objets neutres.

Les valeurs par defaut de ces priorites sontGAUCHEen ce qui concerne les objets actifs et MELANGEen ce qui concerne les objets neutres. Ces valeurs peuvent bien s^ur ^etre redenies.

Lors de l'algorithme de combinaison des intervalles, pour chaque couple d'intervalles, on calcule une priorite \locale" de la facon suivante: si les objets sont de m^eme type, la priorite locale prend la valeur de la priorite pour ce type d'objet, si les objets sont de type dierents, c'est l'objet de type actif qui est prioritaire.

3.4.3 Dierence

Ce cas est peut-^etre le plus simple a traiter. En eet, la notion de priorite horizontale n'y intervient que par le fait que ls objets actifs sont prioritaires par rapport aux neutres. Ainsi, un objet neutre ne peut trouer un objet actif. En toute rigueur, un objet neutre peut trouer un autre neutre : cependant, un message signale un tel evenement car il semble en eet peu logique et sans grande signication physique. De plus, seule la liste gauche est modiee lors d'une dierence. En eet, aucun intervalle resultat ne correspond a une intersection avec l'objet que l'on retranche !

Enn, ces modications concernent soit la disparition complete d'un intervalle (lorsque l'intervalle droit contient le gauche) soit la modication des points d'entree ou de sortie. Le contenu d'un intervalle n'est quant a lui jamais modie.

Pour eectuer ces modications, il sut simplement de modier les valeurs des abscisses d'entree ou de sortie, ainsi que les cellules-point correspondantes. Il sut d'inverser la normale de la cellule-point de l'objet retranche et on peut alors simplement echanger les cellules-point. En eet, un intervalle d'inter-section avec l'objet retranche n'intervient au plus que sur un intervalle de l'objet a qui l'on retranche. On est donc certains de ne jamais perdre d'informations.

3.4.4 Intersection

Ce cas est un peu plus compliquepuisqu'il faut ici tenir compte de facon plus importante de la priorite horizontale.

Une premiere remarque que l'on peut faire est le fait que deux intervalles d'intersection ne vont generer un resultat que si les deux objets intersectes sont de m^eme type et que si les deux intervalles ont une intersection.

Ensuite, pour economiser le temps d'execution, on choisit de conserver le plus petit des deux intervalles (ou le premier des deux si aucun ne contient l'autre). Il faut bien s^ur tenir compte de la priorite horizontale et aecter correctement le contenu de l'intervalle resultat (ou les contenus en cas d'objets neutres).

Enn, dans le cas ou aucun intervalle ne contient l'autre, il faut tronquer l'intervalle resultat et ne pas oublier d'aecter les bonnes cellules-point.

3.4.5 Union

C'est l'operation booleenne la plus compliquee. En eet, il faut tenir compte de la priorite horizontale et de la fusion.

La fusion peut se realiser assez simplement puisque dans le cas ou les deux intervalles n'ont pas d'intersection, il sut d'incrementer le pointeur courant du premier intervalle. S'il y a intersection, il faut combiner les deux intervalles: on remplace le premier des deux intervalles par la combinaison des deux. Il sut donc de modier l'abscisse de sortie ainsi que l'eventuelle cellule-point de sortie.

Dans le cas d'une union a priorite entre deux objets actifs, ceci equivaut a retrancher le plus prioritaire du moins prioritaire, et a eectuer ensuite la reunion entre ces deux intervalles disjoints: dans le cas ou le moins prioritaire est entierement contenu dans le plus prioritaire, le premier dispara^ t.