BRGM L'ENTREPRISE A U SERVICE DE LA TERRE APPROXIMATION VOLUMIQUE ET OCTREES R 31333 ISA-SGN 90 Août 1990 LACOUR Ph. - SGN/ISA BRGM établissement public à caractère industriel et commercial Sidge : Tour Mirabeau, 39-43, quai André-Citroën - 75739 Paris cedex 15, France Tél.: (33) 1 40.58.89.00 - Télex : B R G M 780258 F - Télécopieur : (33) 1 40.58.89.33 R.C. 58 B 5614 Paris - SIRET : 58205614900419 Centre scientifique et technique : Avenue de Concyr, Orléans-La Source (Loiret) - B.P. 6009 - 45060 Orléans cedex 2, France Tél.: (33) 38.64.34.34 - Télex : B R G M 780258 F - Télécopieur : (33) 38.64.35.18 Reme M*~ M1" Le? H1- rciements A s Yve» Martinez J e a n F*±er-ï-e V e y r i e r service SGN/ISA R é g i s Bacl i er- SOMMAIRE INTRODUCTION 1 PRESENTATION GENERALE 3 Orientation Objet 3 Problème posé 3 Structure de données 3 ALGORITHMES 5 1 - Repérage et Codage 5 la - Repérage des octants fils d'un cube 5 1b - Repérage des direction de recherche des adjacents 6 S - Définitions, Propositions 7 Définition 1 <Frère) 7 Proposition S (Adjacent Frère) 7 Proposition 3 (adjacent) / 9 Définition 4 (cube frontière d'un octree 1) 10 Définition 5 (cube frontière d'un octree S) 10 3 - Algorithmes 10 3a - Algorithme de subdivision 10 3b - Algorithme d'Intersection et de réunion 11 3c - Algorithme de recherche d'adjacent 13 3d - Algorithme de recherche de la filiation 15 3e - Algorithme de recherche de la parenté 16 3f - Algorithme de création de 1'Octree frontière 17 CONCLUSION 18 BIBLIOGRAPHIE 19 ANNEXE la Structure "pointeurs" i Descriptif des objets HyperCube et Octree. i 1 - Organisation de l'objet HyperCube i la - Descriptif des champs de l'objet HyperCube ii lb - Descriptif des méthodes de l'objet HyperCube ii i 2 - Organisation de l'objet Octree iv Sa - Descriptif des champs de l'objet Octree vi Sb - Descriptif des méthodes de l'objet Octree vii Annexe lb Structure "tableau" ix Descriptif des objets Octree et OctreeSurf. ix 1 - Organisation de l'objet Octree ix la - Descriptif des champs de l'objet Octree xii lb - Descriptif des méthodes de l'objet Octree xiii S - Organisation de l'objet OctreeSurf xv Sa - Descriptif des champs de l'objet OctreeSurf xvi Sb - Descriptif des méthodes de l'objet OctreeSurf xvi i Annexe S Résultat des fonctions xvii i 1 - Tableau de résultat de la fonction NouvDir xviii S - Tableau de résultat de la fonction EstFrere xix 3 - Tableau de résultat de la fonction OpposeSurAxe xx - 1 - INTRODUCTION En informatique, le volume d'un solide peut être décrit de deux manières : - Un arbre C.S.G ("Constructive Solid Geometry") - Un arbre Octal (ou Octree) La première méthode consiste à approcher le volume par des primitives volumiques le composant, le problème étant la détermination desdites primitives. En effet celles-ci sont à priori inconnues dans un volume quelconque (cas qui nous intéresse i c i ) , il en est autrement si le volume est luimême défini par des primitives volumiques connues. <Cf Annexe la) • La seconde méthode 1CMEA 81D(celle choisie dans cette étude) consiste à englober le volume dans un cube appelé "Univers", puis a subdiviser celui-ci en huit cubes égaux, les "Octants fils", chacun reçoit alors un attribut de couleur : - Blanc s'il n'appartient pas au volume - Noir s'il appartient au volume - Gris s'il intersecte le volume La subdivision est opérée récursivement sur chacun des fils. Ce pose alors le problème de l'arrêt de la subdivision. On se donne une taille minimale de subdivision en fonction de la finesse de définition du volume. Les octants noirs et blancs sont considérés comme terminaux (ils ne seront pas subdivisés), alors que les octants gris seront eux subdivisés jusqu'à obtention d'octants noirs blancs ou de taille minimale. (Cf Annexe lb) Il existe toutefois deux types d'Octree : - Les Octrees dits "complets" - Les Octrees dits "polygonaux" ou "exacts" Pour les Octrees "complets" on réalise la subdivision spatiale telle que décrite précédemment. Pour les Octrees "polygonaux" on introduit des attributs supplémentaires pour les octants gris : - Face si l'octant est traversé uniquement par une facette du solide. - Arête si l'octant est traversé par une arête et par les deux facettes qui s'y rattache. - Sommet si l'octant contient un seul sommet et si les facettes qui le traversent se rencontrent en ce point. - aLes Octrees "polygonaux" ne peuvent être utilisés que lorsqu'il s'agit, de décrire un volume polygonal, ou pouvant être considéré comme tel. Aussi ne traiterons nous ici que de l'utilisation des octrees "complets". La description du volume d'un solide a pour but la réalisation d'opérations sur des solides, opérations telles que intersection ou réunion entre deux solides, représentation de solide, coupe dans un solide. Toutes ces opérations nécessitent des notions d'adjacence entre les octants composant l'arbre, des notions de frontière de 1'octree. Ces notions seront abordées ultérieurement. Figura 1 x Objet et 1'Octree correspondant PRESENTATION GENERALE Orientation Objet Pour développer les algorithmes nous avons utilisé un langage de programmation orienté objet le C++ glockenspiel. L'avantage de ce concept de programmation réside dans la structure de nos données qui ne sont plus tributaires des procédures qui les utilisent mais qui possèdent leurs procédures à travers lesquelles nous accédons aux données. 2CWILE 883 En fait le C++ est un langage de classes, c'est à dire que chaque objet est structuré en ses données et ses procédures, tout cela formant un type évolué appelé classe. Cela réalise une encapsulation 3CWILE 883donnéesprocédures qui fait qu'une modification de l'organisation des données en interne influe le moins possible sur l'utilisation de ses données. Un autre concept de la programmation en C++ est la notion d'héritage^CWILE 883, en effet si une classe doit posséder la même structure de données qu'une autre classe, dite classe mère, on ne récrit que les données supplémentaires de la nouvelle classe et on la fait hériter de la classe mère. Ainsi toute modification de la classe mère se répercutera automatiquement sur les classes filles qui ont héritées d'elle. Problème posé Le problème posé par le BRGM est d'analyser un volume pour en tirer le maximum de renseignements et pouvoir réaliser les opérations décrites en introduction. Tout cela bien sûr le plus rapidement possible et sur des modèles relativement importants <le mai liage moyen est de l'ordre de 80000 points). Les volumes sont donnés sous forme de mai liages tridimensionnels, chaque point possédant un attribut, nous nous limiterons à un attribut noir (1) ou blanc (0). Avec ces volumes nous devons créer l'octree correspondant, être capable de le stocker sur disque et enfin de pouvoir réaliser des opérations sur ces octrees. Structure de données La première approche envisagée fut celle d'une structure pointeur avec deux objets, l'hypercube et l'octree. Cette structure est relativement naturelle et simple a appréhender. En effet l'objet élémentaire qu'est l'hypercube est la base de l'octree, chaque hypercube devant posséder le nom de son père et celui de ses fils s'il en a <Cf Annexe S ) . Mais cette structure est trop gourmande en mémoire, la seule chose intéressante à - 4 conserver étant la couleur (on ne peut pas la retrouver par calcul) le reste est donc stocké inutilement. Cette solution fût donc abandonnée. La seconde structure dérive de la structure d'arbre binaire sous forme tableau (Cf cours L0*f ) . Mais cette structure oblige à réserver la place pour la filiation des octants noirs et blancs, ce qui est très coûteux en mémoire, donc incompatible avec les exigences du BRGM. La structure définitive est donc une structure tableau où l'on ne conserve que la filiation des octants gris. Pour cela on sépare en deux tableaux les octants gris et les octants noirs et blancs. C'est à dire que dans chaque tableau un octant est représenté par un bit. Dans le tableau codant les gris le bit est à 1 si l'octant est gris et à 0 dans le cas contraire. De mfme dans le tableau codant les noirs, le bit est à 1 si l'octant est noir et à 0 autrement. Ainsi il est possible de retrouver rapidement la couleur d'un octant et de reconnaître les octants gris dans un niveau de subdivision. Cette dernière possibilité est primordiale car il faut être capable de déterminer le nombre de gris avant une position précise pour connaître la filiation d'un octant gris. De même il faut pouvoir déterminer le n * ^ m e gris dans un niveau pour connaître la parenté. - 5 ALGORITHMES Les Algorithmes mis en oeuvre sont valables dans la mesure où l'on définit le repère associé à l'univers. 1 - Repérage et Codage Tout d'abord, le repère est un repère direct, l'axe des côtes étant dirigé vers le haut. L'origine du repère se trouve en bas à gauche et au fond du cube univers. 1* - Repérage des octants fils d'un cube Les vecteurs d'origine le centre de l'univers et d'extrémités le centre d'un des octants fils, ont pour coordonnées respectivement et dans l'ordre croissant des côtes, ordonnées, abscisses : (-1, - 1 , -1 ) (-1 »-l> + 1 ) (-1, + 1» -1 ) (-1 > + l >+1) (+1, - 1 , -1 ) ( + 1,-!> + 1 ) ( + 1,+1» -1 ) ( + 1, + l» +1) Remplaçons les -1 par des 0. Cela devient : - < 0, 0, 0) ( 0, 0,+l) < 0,+l, 0) ( 0,+l,+l) (+1, 0, 0) <+l, 0,+l) (+1,+1, 0) (+1,+1,+1> Si l'on considère que ce sont les trois premiers bits d'un octet, le codage des octants fils devient : 0 1 2 3 h 5 é> 7 pour pour pour pour pour pour pour pour 1 'octant 1 'octant 1 'octant 1 'octant 1 'octant 1 'octant 1 'octant 1 'octant Nord-Ouest-Nadir Nord-Ouest-Zéni th Nord-Est-Nadir Nord-Est-Zénith Sud-Ouest-Nad i r Sud-Ouest-Zéni th Sud-Est-Nadir Sud-Est-Zénith Les octants fils ne seront désormais désigné que par leur code ainsi l'octant fils ¿f désignera l'octant Sud-Ouest-Nad ir. - 6 lb - Repérage des direction de recherche des adjacents Les directions utilisées seront les directions cardinales composées simples des directions élémentaires Nord-Sud,Ouest-Est et Zénith-Nadir. Cela nous amène à considérer vingt six directions possibles. Ces directions sont repérées par les vecteurs suivants : (-1 ,-1 >-l> pour (-1 »-!) 0) pour (-1 ,-1 ,+1 ) pour (-1 > 0 9 -1 ) pour <-l > 0 , 0) pour (-1 > 0 ; + 1 ) pour (-1 » + l »-D pour (-1 . + !> 0) pour (-1 j + 1 , + 1) pour < , - 1 , -1 ) pour < ,-1 , 0) pour » - l 5 + 1) pour ( , 0> - l > pour ( > 0 ,+ 1 ) pour < »+l .-1 > pour ( . + 1» 0) pour ( .+1 , + D pour ( + 1f - 1 J -1 ) pour ( + 1,-1 i 0 ) pour ( + 1, - 1 , + 1 ) pour ( + 1; 0 f - D pour ( + 1> 0» 0) pour ( + 1, 0 , + 1 )pour (+1 » + l > -1) pour ( + 1»+l , 0) pour < + l j + l J + 1) pour la la la la la la la la la la la la la la la la la la la la la la la la la la direction direction d irect ion direction direction direction direction direct ion direction direction direction direction direction direction direction direction direction direction direction direction direction direction direction direct ion direction direction Nord-Ouest-Nadir Nord-Ouest Nord-Ouest-Zéni th Nord-Nadir Nord Nord-Zénith Nord-Est-Nad ir Nord-Est Nord-Est-Zénith Ouest-Nadir Ouest Ouest-Zénith Nadir Zénith Est-Nadir Est Est-Zénith Sud-Ouest-Nadir Sud-Ouest Sud-Ouest-Zéni th Sud-Nadir Sud Sud-Zénith Sud-Est-Nadir Sud-Est Sud-Est-Zénith Séparons ce vecteur en deux composantes. Une première composante appelée direction spécidiée qui contiendra 1 si le nombre correspondant est un 1 et 0 dans la cas contraire. Une seconde composante appellee direction indéterminée qui contiendra 1 si le nombre correspondant est un 0 et 0 dans le cas contraire. Par exemple la direction Sud-Nadir sera codée de la façon suivante : - direction spécifiée - direction indéterminée <+l, 0, 0) < 0,+l, 0) De plus l'utilisateur devant passer la direction en paramètre, pour que cela soit plus explicite, nous utiliserons une variable contenant l'octet représentant la direction spécifiée accolé à l'octet représentant la direction indéterminée. - 7 Les formules de changement de représentation sont : - Passage de représentation vectorielle à représentation cardinale : - DirCard = DirSp * 8 + Dirlnd - Passage de représentation cardinale à représentation vectorielle : - DirSp = (DirCard &. 00111000) / 8 - Dirlnd = (DirCard & 00000111) S - Définitions, Proposition Définition 1 (Frère) Dans un octree, un octant est dit frère d'un autre si il appartient au même octant père que celui-ci. Proposition S (Adjacent Frère) Dans un octree, un octant O g ( 0ai»^22»^23^ adjacent d'un octant O j (0 j j,0 ig,013) dans la direction d (d¿,dg,d3), est Frère de celui-ci si et seulement si : i) ii ) iii) O 0 0 1 1 S i e i * d 1 + O l s * d g + O = O u si d j s 0 = - 0 - ü si dj <> 0 1 3 * d 3 < = 0 Démonstration 5Cqaco 90D Soient CO J J les coordonnées du centre de 0 1 , C P O ^ les coordonnées du centre du père de 0|, a la longueur de l'artte de Oj . La portion d'espace englobée par le père de 0^ est définie par : ( C P 0 H - 2a <= x i <= C P 0 U + 2a) i - 0,1,2 Ol est la portion d'espace définie par ( C 0 i i + 0 i i * a ~ a < = X i < = C 0 1 : j + 0 i i * a + a > Le voisin de O j dans la direction d est le translaté de O j par la translation de vecteur 2a * d, soit la portion d'espace définie par : ( C O ^ + Oí i * a + 2a * d^ - a <= x^ <= COj ¿ + 0^ ¿ * a + 2a * di + a ) ( 1 ) - sLe fils de type OQ dut père de Qj (CPOjj + Cgj * a - vérifie a <= x¿ <= CPOj j : + Ogj * a + a) (2) Identifions (1) et <2) : alors quel que soit i = 1,2,3 Ojj + 2 * dj = 0ai.(3> l°cas : dj = 0, alors 0j¿ = Cgj (d'après (3)) et °li * dl i <= 02°cas : dj = - 1 , alors 0 ^ = Ogj + 2 (d'après (3)> donc Ojj = +1 (car Ojj = -1,0,1) et 0 t i * dj¿ <* 0. 3°cas : dj = +1, alors 0 ¿ i = Ogj - 2 (d'après (3>) donc Oij = -1 (car Oji = -1,0,1) et 0,^ * d 1 4 <= 0. d'où le résultat. - 9 Proposition 3 (adjacent) On dit qu'un octant O j est adjacent à un autre octant Og dans une direction d, si l'une des conditions est vérifiée : i) O j est le frère de O g dans la direction d ii> 0 j est l'adjacent de l'octant père de O g dans une direction d' et 0 ^ n'a pas de filiation. iii) O j est un fils de l'adjacent A de l'octant père de O g dans une direction d'. Soit OA le fils de A qui est de même type que Og. O j est alors l'adjacent Frère de OA. Avec d' vérifiant : - d'i « 0 si dj = 0 ou si dj = - Ogi . - d ' j - d j si dj *= Ogj . Démonstration 6Cqaco 903 i) a déjà été traité dans la proposition S, ii) est similaire à iii) et peut être traité comme lui, à condition de raisonner comme si on subdivisait tous les octants. On considère simplement les octants non subdivisés comme étant leurs propres fils. Soient a la longueur de l*ar?te de Og , COgj les coordonnées du centre de Og, CPOgj les coordonnées du centre du père POg de Og , CAPOgj les coordonnées du centre de l'adjacent de POg dans la direction d', COjJ les coordonnées du centre de O j , CPOjj les coordonnées du centre du père de 0\ . Il faut et il suffit que les coordonnées de CAPOg et de CPOj coïncident, soit les expressions de ces coordonnées : CAPO g i = C P O e i + 4 * di' # a CPO ! j, = CPOgj + 0 S i * a + 3 * d ¿ # a - Oji * a D'où la relation suivante : ¿ t * d j ' +OJJ = 0 g i +2*dj Trois cas se présentent alors : i) d ¿ = - 1 , la relation devient ^ d ^ ' + O i j = Ogj-2 a- 0 e i = -1 alors 0 ^ = 1, d i' = 1 b - 0 2 i = +1 alors O J Î = - 1 , d j ' = 0 ii) d ¿ = 0 , la relation devient A d ^ ' + O j i = O g j a - O g ! = -1 alors 0 ^ = - 1 , d j ' = 0 b - 0 2 i = 0 alors 0 ^ = 0 , d f = 0 c - 0 e i = +1 alors On = + 1 , d ¿' = 0 iii) d ¿ = + 1 , la relation devient 4dj'+0j¿ = ®Eï + 2 a- 0 2 i = -1 alors 0 ^ = 1, d j ' = 0 b - 0 2 i = +1 alors O - ^ = - 1 , d ^ = 1 - 10 - En regroupant les résultats, on obtient : - d ' j = 0 si d j = 0 ou si d i = - O p j . - d ' i = d j si d j = Ogisoit là condition sur d ' . De plus on obtient - Q^i = O U si d¿ = 0 : - Cfei = -Ojj si di O 0 soit la relation qui donne l'opposé sur l'axe de direction, obtenue dans la proposition S. Définition h (cube frontière d'un octree 1) On dira qu'un cube est frontière d'un octree si parmi ses adjacents, il en existe au moins un qui soit blanc. Définition 5 (cube frontière d'un octree 2 ) On dira qu'un cube est frontière d'un octree s'il existe un chemin d'adjacents blancs qui conduise au frontière de l'univers. 3 - Algorithmes 3a - Algorithme de subdivision Subdivise (Niveau, NbGrisPere) /* niveau du géniteur */ /* Nb de groupes a creer */ tantque (i < NbGrisPere) < QuidAdresse (j,NGroupe,Nom> Coul <- QuidCouleur (Niveau,j) Si (Coul = GRIS) C QuidPosition (Abscisse,Ordonnée,Cote,Niveau,j) NbFilsGris <- NbFilsGris + CreerFils (Abscisse, Ordonnée, Cote, Niveau + 1) i <- i + 1 >; j <- j + i > NbGFils CNiveau + 1] <- NbGrisPere Si (NbFilsGris <> 0) Subdivise (Niveau +• 1 ,NbFi lsGr is ) - 11 - 3b - Algorithms d'Intersection et de réunion Intersecte (Octl, Octe, Niveau, Posl, Pose, Pos) /* /# /* /* /* octree a intersecter " " niveau d'intersection position des peres du feuillage a intersecter */ */ #/ */ */ **#*•****•**#***#*#**#•**#*#* * * * * # * # * * # # * * * # * * * * * # * * * * * * * Table * * * Cubel Cubée Résultat * * * * * 0 NOIR BLANC NOIR # # 1 NOIR GRIS NOIR # * S NOIR NOIR NOIR * * 3 BLANC BLANC BLANC # * ^ BLANC GRIS GRIS * * 5 GRIS GRIS Indt *##**#*#**##**#*#*#•***#*#* d'intersection * * # * # * * * * * * Table * Cubel CubeS 0 1 2 3 ¿v 5 NOIR NOIR NOIR BLANC BLANC GRIS BLANC GRIS NOIR BLANC GRIS GRIS Résultat # # BLANC * GRIS * NOIR • BLANC * BLANC * Indt * *#***#***#***##**#•#***#*#*# < QuidAdresse de réunion * (Pos,NGroupe,Nom) Coull <- Octl -> QuidCouleur CoulH <- OctS -> QuidCouleur Coul <- (Coull OR CoulS) // Coul <- (Coull AND CoulH) // (Niveau,Posl) (Niveau,PosH) pour la réunion pour l'intersection Si (Coul = GRIS) UniversGris CNiveauD CNGroupeD UniversGris [Niveau] CNGroupeD OR PB CNom] Si (Coull = CoulS) < NbGFils CNiveau + 13 <- NbGFils CNiveau + 1 3 + 1 Octl -> QuidFils (Niveau,Posl,0,NivFilsl,PosFilsl) Octe -> QuidFils (Niveau,Pose,0,NivFilse,PosFilse) Qu i dF i 1s (N i veau,Pos,0,N i vF i 1s,PosF ils) //pour l'intersection pour j allant de 0 à 7 Intersecte (Oct 1,Octe,NivFils,PosFilsl + j , PosFilse + j, PosFils + j ) ; > QuidAdresse (PosFils,NGroupeFils,NomFils); -IS - — Si ((Uni versGris [Niveau + 13CNGroupeFils3 = 0) et (UniversNoir CNiveau + 13CNGroupeFils3 = 0>) < NbGFils CNiveau + 13 <- NbGFils CNiveau + 1 3 - 1 UniversGris CNiveau3CNGroupe3 <UniversGris CNiveau3CNGroupe3 AND (NOT P2 CNom3) UniversNoir CNiveau3CNGroupe3 <UniversNoir CNiveau3CNGroupe3 OR (PS CNom3) > > //pour la réunion pour j allant de 0 à 7 i Réuni (Octl,OctS,NivFils,PosFilsl + j , PosFilsS + j , PosFils + j ) ; > QuidAdresse (PosFils,NGroupeFils,NomFils); Si ((UniversGris CNiveau + 13CNGroupeFils3 = 0) et (UniversNoir CNiveau + 13CNGroupeFils3 = S55)) C NbGFils CNiveau + 13 <- NbGFils CNiveau + 1 3 - 1 UniversGris CNiveau3CNGroupe3 <UniversGris CNiveau3CNGroupe3 AND (NOT PE CNom3) > > Sinon Si (Coull = GRIS) { Rattache (Posl,Pos,Oct 1,Niveau) > Sinon C Rattache (PosS,Pos,0ct2,Niveau) } > Sinon i Si (Coul = NOIR) UniversNoir CNiveau3 CNGroupe3 <UniversNoir CNiveau3 CNGroupe3 OR > P2 CNom3 - 13 3c - Algorithme de recherche d'adjacent Adjacent (DirCard, NiveauCube, Pos i t ionCube, NiveauAdjacent, PositionAdjacent) /* /* /* /* /* direction de recherche niveau du cube position du cube niveau de l'adjacent position de l'adjacent */ */ */ */ */ - lit - — i Si ((NiveauCube = 0) et <PositionCube = 0)) C NiveauAdjacent <- 255 PositionAdjacent <- 0 > Sinon < Dir <- QuidDir (DirCard) QuidAdresse (Posit ionCube,NGroupe, Nom) FilsAPrendre <- OpposeSurAxe (Nom,Dir) Si (Frère (Nom,Dir)) < QuidPere (NiveauCube, PositionCube, NiveauPere, PositionPere) QuidFils (NiveauPere, PositionPere, FiIsAPrendre, NiveauAdjacent, PositionAdjacent) > Sinon < NDir <- NouvDir (Nom,Dir); DirVoisin <- QuidDirCard (NDir) QuidPere (NiveauCube, Posi tionCube, NiveauPere, PositionPere) Adjacent (DirVoisin, NiveauPere, Posi tionPere, N i veauVo i s i nDuPere, Posit ionVoisinDuPere) Si (NiveauVoisinDuPere <> 255) QuidFils (NiveauVoisinDuPere, Posi tionVoisinDuPere, FiIsAPrendre, NiveauAd jacent, Posi t ionAd jacent) Sinon Í NiveauAdjacent <- 255 PositionAdjacent <- 0 > - 15 - _ 3d - Algorithme de recherche de la filiation Qu idFi Is (NiveauPere, Posi t ionPere > NomFils, NiveauFils, PositionFils ) Í Si (EstFeuille (NiveauPere,Positio nPere) = FAUX) CompteGris (PositionFils,Posit i onPere,N iveauPer e) PositionFils <- PositionFils * 8 PositionFils <- PositionFils + NomFils NiveauFils <- NiveauPere + 1 • > S i nij n < PositionFils <- Posi tionPere NiveauFils <- NiveauPere } > CompteGris (PositionFi ls, PositionPere, NiveauPere) <. pour i allant de 0 à NGroupe - 1 PositionGrise < - PositionGrise + NGris CUniversG ris CNiveau3 C i33 y Pos itionGrise <- Pos itionGrise + NG ris C(UniversGris CNiveauD AND Masque CNom3>3 y CNGroupe3 - 16 - — 3e - Algorithme de recherche de la parenté Qu idPere (NiveauFils, Posit ionFils, NiveauPere, Posi t ionPere) C Si (NiveauFils = 0) < NiveauPere PositionPere <- 0 <- 0 } Sinon < QuidAdresse (Posi tionFils,N6roupe,Nom) NiveauPere <- NiveauFils - 1 PositionPere <- RechGris (NiveauPere,NGroupe) > > RechGris (NiveauPere, Posi tionPere) < NFils = NbGFils [NiveauPere3 * 8 tantque (NbGrisTrouve <= PositionPere) C NbGrisTrouve = NbGrisTrouve + NGris CUniversGr is CNiveauPere3 LUI i = i + 1 > i = i - 1 NbGrisTrouve -= NbGrisTrouve NGris CUniversGris [NiveauPere] CiD3 i = i * 8 tantque ((NbGrisTrouve <= PositionPere) et (i < NFils)) { Si (QuidCouleur (NiveauPere,i) = GRIS) NbGrisTrouve = NbGrisTrouve + 1 i = i + 1 } i = i - 1 return (i) > NGris est un tableau contenant le nombre de bits à un dans un octet en fonction de sa valeur. Cela permet de traiter huit fils à la fois. - 17 - 3f - Algorithme de création de 1'Octree frontière La création d'un Octree frontière avait pour but de diminuer la taille occupée en mémoire par la structure de données, en éliminant l'intérieur du volume. Cela nous donnait une surface codée dans un octree. Cette structure tenant moins de place elle permettait de rajouter le stockage de la filiation et de la parenté. L'accès aux données en étant alors accéléré, problème crucial de la représentation graphique. Mais la première notion d'octree frontière (définition A) n'élimine pas l'intérieur de 1'octree, en effet tous les gris restent gris, seuls quelques noirs deviennent blancs. Quant à la seconde notion d'octree frontière, elle n'a pas été implémentée car l'algorithme est trop gourmand en niveau de récursivité. - 18 - CONCLUSION Cette étude a permis de démontrer que les algorithmes applicables aux Octrees sont parfaitement adaptables aux besoins du BRGM en matière d'approximation volumique. La structure de données proposée est compacte et rapide, les tests effectués sur un BULL BM60 <640K,BMhz) ont permis de creer deux Octrees et de les intersecter (resp. réunir) en moins de 5 minutes pour des volumes de l'ordre de 80000 points. Il s'agit tout de m?me d'une ébauche qui demande à être approfondie, tout particulièrement dans le domaine de la visualisation, de la coupe des volumes et de la modification des volumes après création de 1'octree. De plus la structure de données du BRGM étant en FORTRAN, il est nécessaire de réaliser 1'interfaçage FORTRAN-C++, car pour l'instant les routines fonctionnent tout à fait en dehors de tout environnement. Il est donc nécessaire d'envisager, a plus ou moins long terme, la création d'une interface utilisateurs, aussi bien pour l'utilisation des routines dans un programme FORTRAN, que pour l'utilisateur du logiciel ainsi créé. 1 - 19 - BIBLIOGRAPHIE 1CMEA 813 D. fEASHER Geometric Modeling Using Octree Encoding COMPUTER GRAPHICS AND IMAGE PROCESSING 19, 1S9-147 P.134-135. Date de publication 198S, date d'écriture 1981, ECWILE 883 R. W IEflER et J.F. LEHIS An Introduction to ObjectOriented Programming and C++ Chpt 1 et 2. 3CWILE 883 R. WIENER et J.F. LEHIS An Introduction to ObjectOriented Programming and C++ Chpt 4 4CWILE 883 R. WIENER et J.F. LEHIS An Introduction to ObjectOriented Programming and C++ Chpt 5 5Cgaco 903G. GARCIA et J.F. LEC0RRE Recherche d'adjacents dans un espace multidimensionnel représenté par un arbre AFCET Vo1. 9,N°1 1990 P.38-39. 6Cgaco 903G. GARCIA et J.F. LECORRE Recherche d'adjacents dans un espace multidimensionnel représenté par un arbre AFCET Vo1. 9,N«1 1990 P.39-40. Erratum GARCIA et J.F. LECORRE Recherche d'adjacent» dans un espace multidimensionnel représenté par un arbre AFCET Vo1. 9,N°1 1990 P.41, paragraphe 4.2, Il faut lire s (d XOR r.specif) OR r.Indif « 11.. 1 pour le mot «indif» (d AND r.specif) pour le mot «specif». On constate que le mot «indif» est donné par la même formule que «tous-les-produits-négatifs», ce qui permet de ne faire li calcul qu'une fois. 1 - ANNEXE la Structure "pointeurs" Cette structure inclue deux objets : + L'hypercube + L'octree L'octree étant en fait un arbre d'HyperCubes situé dans 1'espace. Descriptif des objets HyperCube et Octree. 1 - Organisation de l'objet HyperCube private : HyperCube * HyperCubePere; HyperCube * * HyperCubesFils; unsigned char Taille; short * Coord; unsigned char Couleur; unsigned char TypeFils; HyperCube unsigned char HyperCube * HyperCube * long unsigned char short * unsigned char QuidNom QuidPere QuidFils QuidTaille QuidCouleur QuidPosition ""HyperCube EstFeuille (short, unsigned char, unsigned char, unsigned char, short *, HyperCube * = 0, unsigned char = 0 ) ; (); <); (unsigned c h a r ) ; (); (); (); ( ) ; <); - i l - la - Descriptif des champs de l'objet HyperCube - HyperCubePere ; Pointeur sur l'adresse du père de 1'HyperCube considéré. Ce champ sert à remonter dans l'arborescence, il est fort utile pour la recherche d'adjacents. - HyperCubesFils : Pointeur sur la structure des fils de 1'HyperCube. Ce pointeur est en fait un tableau de pointeurs sur chacun des fils de 1'HyperCube. - Taille i Contient la taille de 1'HyperCube considéré. Cette taille est en fait stockée sous la forme du niveau de subdivision auquel appartient 1'HyperCube. La taille de 1'HyperCube est la taille de l'univers divisée par la puissance de deux du niveau. - Coord ; Contient les coordonnées du centre de 1'HyperCube dans le repère de l'univers. Ces coordonnées sont exprimées en demi-maille. - Couleur : Contient la couleur de 1'HyperCube Gris = 1, Blanc = 0. : Noir = 3, - TypeFils ; Contient le nom de 1'HyperCube parmi ses frères. - I l l - lb - Descriptif des méthodes de l'objet HyperCube - HyperCube : Constructeur de l'objet HyperCube. Cette procédure permet l'initialisation des champs de l'objet. - QuidNom : Retourne le nom de 1'HyperCube parmi ses frères. Par défaut, le nom de la racine est zéro. 11 s'agit de lire le champ TypeFils. — QuidPere : Retourne l'adresse du père de l'HyperCube. Par défaut, le père de la racine est la racine elle-mîme. Il s'agit de lire le champ HyperCubePere. - QuidFils : Retourne l'adresse du fils de l'HyperCube. Le fils d'un noeud terminal est le noeud lui-même. Il s'agit de lire le champ HyperCubeFils. - QuidTaille : Retourne la taille de l'HyperCube. Par défaut, la taille de la racine est la taille de l'univers. Il s'agit de lire le champ Taille. - QuidCouleur ; Retourne la couleur de l'HyperCube. Il s'agit de lire le champ Couleur. - QuidPosition : Retourne la position de l'HyperCube dans l'univers. Il s'agit de lire le champ Coord. - ""HyperCube ; Destructeur de l'objet HyperCube. Cette procédure désalloue les pointeurs affectés par le constructeur. - EstFeui1 le : Détermine si un HyperCube est noeud terminal ou non. IV 2 - Organisation de l'objet Octree private : HyperCube short long float float unsigned ch ar * # # * Direction short short Directioni unsigned ch ar unsigned ch ar unsigned ch ar void # short vo id void vo id vo id void Racine; VolumeV; NbrePts; MinAxe; LMaille; Minimal ; QuidDir QuidDirCard Frere (short); (Direction); (unsigned char, Direction); (unsigned char, NouvDir Direction); (unsigned char, OpposeSurAxe Direction); (short, CVol short, short); ValCouleur (ParamCube); Subdivise (HyperCube * ) ; Posi t ionFiIs (unsigned char, ParamCube); (HyperCube *); Li tOctree EffaceBranche (HyperCube *>; (HyperCube *, Rattache HyperCube * ) ; (HyperCube *, Intersecte HyperCube *, HyperCube * ) ; (HyperCube *, Réuni HyperCube *, HyperCube * ) ; pub lie Octree Octree (unsigned char, short *, float *, float *>; (short, short *, float *, float *, short * ) ; — v HyperCube vo id void vo id HyperCube Octree Octree void * * # * Ad jacent Translat ion Homothetie Rotation QuidRacine Intersection Reunion ^Octree Affiche (short, HyperCube * ) ; <float * ) ; (float * ) ; (float * ) ; <>; (Octree *) ; (Octree * ) ; <>; <>; - v i - Sa — Descriptif des champs de l'objet Octree - Racine : contient l'adresse de l'HyperCube racine de 1'Octree. - VolumeV : Indicatrice définissant le volume. - NbrePts : Nombre de points définissant le volume. - MinAxe : Position de l'univers dans le repère absolu. - LMaille : Largeur des mailles sur chaque axe. - Minimal : Taille minimum de subdivision de l'espace. - vi i - Sb - Descriptif des méthodes de l'objet Octree - QuidDir : Renvoie la direction vectorielle correspondant à la direction cardinale passée en paramètre. - QuidDirCard : Réalise l'opération inverse de la fonction ci-dessus. -Frère : Détermine si le cube de nom passé en paramètre possède un frère comme adjacent dans la direction spécifiée. - NouvDir : Détermine la direction dans laquelle il faut rechercher l'adjacent au père du noeud. - OpposeSurAxe : Détermine l'opposé de l'HyperCube sur l'axe de direction de recherche de l'adjacent. - CVol : Retourne la couleur du point du volume. - ValCouleur : Détermine la couleur de l'HyperCube. - Subdivise : Réalise la subdivision spatiale. — PositionFils : Retourne les coordonnées du fils de l'HyperCube. - LitOctree : Lit l'Octree. - EffaceBranche : Efface 1'octree récursivement. - Rattache : Rattache une branche d'un Octree à un autre Octree. - Intersecte : Intersecte deux Octrees. - vi 11 - - Réuni : Réunit deux Octrees. - Octree ; Constructeurs de 1'Octree. L'un des deux est utilisé pour la construction á partir d'un volume, l'autre pour l'intersection ou la réunion de deux Octrees. - Adjacent : Recherche l'adjacent au cube dans la direction de recherche spécifiée. - Translation : - Homothetie : - Rotation ; - QuidRacine i Retourne la racine de 1'Octree. - Intersection : Fonction appelée par l'utilisateur pour intersecter deux Octrees. - Reunion : Fonction appelée par l'utilisateur pour réunir deux Octrees. - ^Octree : Destructeur de 1'Octree. - Affiche : Affichage de 1'Octree. - ix - -— Annexe lb Structure "tableau" Cette structure inclut deux objets : + L'octree volumique (Octree) + L'octree surfacique (OctreeSurf) Dans cette structure les pointeurs sur la parenté sont obtenus par un calcul. La lenteur du parcours de cette structure nécessite la création d'une structure intermédiaire, l'octree surfacique, dont les pointeurs sur la parenté sont contenus dans des variables, mais n'étant plus des adresses absolues, le stockage est plus économique. Nous avons donc deux objets : un octree volumique et un octree surfacique qui hérite du premier. L'Octree surfacique étant destiné à être utilisé lors de la représentation graphique. Descriptif des objets Octree et OctreeSurf. 1 - Organisation de l'objet Octree fr iend Octree * operator + (OctreeSc, OctreeSc) ; fr iend Octree * operator * De treeü,, (Octrees,, Octree&c) ; * VolumeV; NbrePts; private: unsigned char huge long protected : unsigned unsigned unsigned unsigned float float unsigned unsigned char char long long char char FILE Direction short unsigned char * * UniversGris; * * UniversNoir; * ÑbBFils; * * * * TUnivers; MinAxe; LMaille; NMaille; Minimal ; Fichier ; QuidDir QuidDirCard Frere (short); (Direction) (unsigned char, Direc t ion); — x — Direction NouvDir unsigned char OpposeSurAxe vo id LitOctree vo id Rattache vo id Intersecte void Réuni virtual void unsigned char unsigned char virtual vo id Compactage QuidGr is QuidNo ir QuidPere virtual void QuidFiIs unsigned long vo id QuidTai1 le QuidPosi tion unsigned long RechGris vo id QuidAdresse unsigned char unsigned char QuidNom EstFeuilie (unsigned char, Direct ion); (unsigned char, Direct ion); (unsigned char, long); (unsigned long, unsigned long, Octree *, unsigned char); (Octree *, Octree *, unsigned char, unsigned long, unsigned long, unsigned long); (Octree *, Octree *, unsigned char, unsigned long, unsigned long, unsigned long); <); (unsigned unsigned (unsigned unsigned char , long); char, long); (unsigned unsigned unsigned unsigned char , long, char&, long&); (unsigned unsigned unsigned unsigned unsigned (unsigned ( shorts., shortSt, shor t&c, unsigned long); (unsigned unsigned (uns igned unsigned unsigned (unsigned (unsigned unsigned char , long, char, char&, long&<) ; char ) char , char , long); long , long&c, char&c) ; long ) char, long); - xi - private: unsigned char CVo1 unsigned char ValCouleur void Subdivise void PositionFils unsigned char void CreerFils CompteGris (short, short, short); (short, short, short, unsigned (unsigned long); <short&, short&, short&c, unsigned unsigned (short, short, short, unsigned unsigned (unsigned unsigned unsigned long); char, long, char); long, char); long&, long, char); public: Octree Octree Octree unsigned char QuidCou leur unsigned unsigned unsigned float float unsigned void NbGris QuidTUn i ver s QuidMinimal QuidMinAxe QuidLMaille QuidNMaille Adjacent void void void vo id long long char char Translation Homothetie Rotation ^Octree Affiche (Octree *) (Octree *, Octree *) ; (short, short*, float*, float*, unsigned char huge *) ; (unsigned char, unsigned long); (unsigned char ) <>S • <); (unsigned char); (unsigned c h a r ) ; (unsigned char) (unsigned char, unsigned char, unsigned long, unsigned chari, unsigned long&); (float *>; (float * ) ; (float * ) ; (); <); - x 11 - la - Descriptif des champs de l'objet Octree Nous ne décrirons que les champs qui diffèrent de la version "pointeurs". - UniversGris : Tableau codant les cubes gris, chaque élément du tableau est un octet qui correspond à un groupe de huit fils. Chaque bit correspond à un fils, si le bit est à un alors le fils est gris, sinon il est soit noir soit blanc. - UniversNoir ; Ce tableau est de même structure que J.e précédent, seule différence il code la couleur noire. Si le bit est à un alors le fils est noir sinon il est soit blanc soit gris. - NbGFils : Contient le nombre de groupes de huit fils de chaque niveau. - NMaille : Contient le nombre de mailles sur chaque axe. - Fichier : Sert à sortir les résultats sur fichier. Cela évite des déclarations "extern" au sein du programme puisque le fichier fait partie intégrante de l'objet. - x i11 - lb - Descriptif des méthodes de l'objet Octree - Compactage ; Sert à compacter 1'octree résultant d'une intersection ou d'une réunion, en effet la place réservée par le constructeur est plus importante que nécessaire. - QuidGris : Retourne le masque des gris du groupe de fils considéré. - QuidNoir ; Retourne le masque des noirs du groupe de fils considéré. - RechGri s : Recherche le rang du cube parmi les gris du niveau. Utilisée par QuidPère. - Quidftdresse : Retourne le numéro de groupe et le nom du cube de position passée en paramètre. - CreerFils ; Crée les huits fils d'un HyperCube. - CompteGris : Compte les gris d'un niveau qui sont placés avant la position spécifiée. Utilisée par QuidFils. - Octree : Constructeurs de 1'Octree. Un des trois sert à la réalisation de la subdivision spatiale, un autre réserve la place pour Intersection et Reunion, le dernier réserve la place pour la création de 1'Octree surfac ique. - NbGris : Retourne le nombre de gris du niveau. Il s'agit en fait du nombre de groupe de fils du niveau suivant. - QuidTUnivers : Retourne la taille de la racine. - QuidMinAxe : Retourne le minimum sur chaque axe, c'est à dire la position de 1'Octree dans le repère absolu. - x i v - - QuidLMaille : Retourne la largeur des mailles sur chaque axes. - QuidNMailie : Retourne le nombre de maille sur chaque axes. - Les opérateurs surchargés + et * servent à l'utilisateur en tant qu'opérateurs de réunion et d'intersection. - xv - S - Organisation de l'objet OctreeSurf private: unsigned long unsigned long * huge * PtrPere; * huge * PtrFils; void QuidFiIs vo id QuidPere vo id Direct ion unsigned char Compactage DirOpp EstFrontiert unsigned char FrereBlanc vo id Evider (unsigned unsigned unsigned unsigned unsigned (unsigned unsigned unsigned unsigned char, long, char, char&, long&); char, long, chari, long&>; •O; (Direction) ; (Octree*, unsigned char, unsigned long); (Octree *, Direction, unsigned char, unsigned long); (Octree*, unsigned char, unsigned long, uns i g ned 1o n g ) ; pub lie: OctreeSurf (Octree LancerDeRayon ( ) ; ~OctreeSurf (); *); - XVI Sa - Descriptif des champs de l'objet OctreeSurf - PtrPere : Contient le déplacement dans le niveau du père, ceci permet d'accéder à la parenté. - PtrFils : Contient le déplacement dans le niveau du fils, ceci permet d'accéder à la filiation. — xvii — 2b — Descriptif des méthodes de l'objet OctreeSurf - QuidFils : Lit le champ correspondant dans le tableau PtrFils. Diffère en cela de l'objet Octree où ceci était fait par calcul - QuidPere : Lit le champ correspondant dans le tableau PtrPere. Diffère en cela de l'objet Octree où ceci était fait par calcul - Compactage : Même fonction que dans l'objet Octree. - DirQpp : Retourne la direction opposé à la direction paramètre. - EstFrontiere : Determine si un cube est frontière. - FrereBlanc : Détermine si dans la filiation de l'adjacent gris, il existe un blanc accolé au cube considéré. - Evider : Supprime l'intérieur de 1'Octree volumique. - OctreeSurf : Constructeur de 1'octree surfacique, fait appel au constructeur de 1'octree volumique qui réserve la place pour 1'octree à partir d'un octree, puis appelle Evider. - LancerDeRayon : réalise un lancer de rayon. - ^OctreeSurf : Détruit l'objet OctreeSurf, désalloue la place occupée par les pointeurs. - xvLii Annexe S Résultat des fonctions 1 - Tableau de résultat de la fonction NouvOir DCard 000 001 010 011 100 101 110 111 NaNO NO NaN NaNO NO NaN NO NO N NaN N NaN N N N NaO 0 Na 0 0 FRERE Na FRERE Na FRERE FRERE FRERE N NaO 0 N NaO 0 N 0 0 N Na FRERE N FRERE FRERE FRERE NaO 0 FRERE 0 0 FRERE Na FRERE FRERE FRERE FRERE Na ZNO ZN Na NO N FRERE ZNO 2N Na N N FRERE ZN ZN Na 0 FRERE FRERE ZO Z Na FRERE FRERE FRERE Z Z ZO Z NaNE 0 FRERE NaN ZO Z N FRERE FRERE NaNE Z Z NE 0 FRERE Na ZO FRERE FRERE NaE Z Z E NE NaE E N Na FRERE N FRERE FRERE NE NaE E NE E E FRERE Na FRERE FRERE FRERE FRERE E NaE E E E E ZNE ZE NaSO N FRERE NaO ZN Z 0 NE E Na ZNE ZE FRERE FRERE FRERE NaSO Z Z SO E E NaS ZE ZE S SO NaS S 0 Na FRERE 0 FRERE FRERE FRERE Na FRERE FRERE FRERE FRERE SO NaS S S NaS S S S S ZSO ZS NaSE 0 FRERE Na ZO Z FRERE FRERE FRERE NaE Z Z E SO S NaS S S NaSE ZS SE ZSE FRERE FRERE FRERE Z E E E ZE S S SE SE SE ZSE z FRERE so s s zso zs s s zs .. . zs SE - XÏ*X - 2 — Tableau de résultat de la fonction EstFrere DCard 000 001 010 011 100 101 110 111 NaNO NO NaN FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX V FAUX V FAUX V V N NaO 0 FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX V FAUX V V V FAUX FAUX V FAUX FAUX V FAUX V V V V Na ZNO ZN FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX V FAUX FAUX FAUX FAUX V V FAUX FAUX FAUX V V FAUX FAUX ZO Z NaNE FAUX V FAUX FAUX FAUX FAUX V V FAUX FAUX FAUX FAUX FAUX V FAUX FAUX FAUX V FAUX FAUX FAUX FAUX NE NaE E FAUX FAUX V FAUX V V FAUX FAUX FAUX FAUX FAUX FAUX V FAUX V V V FAUX FAUX FAUX FAUX FAUX FAUX ZNE ZE NaSO FAUX V FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX V V V FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX SO NaS S FAUX FAUX V FAUX V V V FAUX V V V FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX ZSO ZS NaSE FAUX V FAUX FAUX FAUX V V V FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX SE ZSE V V V FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX FAUX - XTT - 3 — Tableau de résultat de la fonction OpposeSurAxe DCard 000 001 010 011 100 101 110 111 NaNO NO NaN 111 110 101 110 111 100 101 100 111 100 101 110 011 010 001 010 011 000 001 000 011 000 001 010 N NaO 0 100 011 010 101 010 011 110 001 000 111 000 001 000 111 110 001 110 111 010 101 100 011 100 101 Na ZNO ZN 001 111 101 000 110 100 011 101 111 010 100 110 101 011 001 100 010 000 111 001 011 110 000 010 ZO Z NaNE 011 001 111 010 000 110 001 011 101 000 010 100 111 101 011 110 100 010 101 111 001 100 110 000 NE NaE E 110 011 010 111 010 011 100 001 000 101 000 001 010 111 110 011 110 111 000 101 100 001 100 101 ZNE ZE NaSO 111 011 111 1 10 010 110 101 001 101 100 000 100 011 111 011 010 110 010 001 101 001 000 100 000 SO NaS S 110 101 100 111 100 101 100 111 110 101 110 111 010 001 000 011 000 001 000 011 010 001 010 011 ZSO ZS NaSE 111 101 111 110 100 110 101 111 101 100 110 100 011 001 011 010 000 010 001 011 001 000 010 000 SE ZSE 110 111 111 1 10 100 101 101 100 010 011 011 010 000 001 001 000