Triangulation de surfaces implicites algébriques Programmation

publicité
Triangulation de surfaces implicites algébriques Programmation Ocaml
Haider Sadjaad ­ Sarrasin Nicolas
2008 – 2009
Énoncé du problème : Programmer la triangulation de la frontière d'objets en 3D, décrits par une inéquation algébrique, en utilisant les bases de Bernstein. C'est une extension de la méthode programmée en TP pour calculer des couvertures de courbes implicites algébriques f(x,y)=0. En 3D chaque cube sera pavé par 5 (ou 6) tétraèdres, et l'intersection entre la surface et un tétraèdre sera approchée par un triangle ou un quadrilatère : soient Si les sommets du tétraèdres, i= 0,1,2,3. Calculer la valeur de la fonction f aux sommets Si. Il existe une seule fonction affine F(x, y, z) = Ax + By + Cz + D qui prend ces valeurs aux sommets. Elle s'annule sur un plan, dont l'intersection avec le tétraèdre est la facette cherchée.
Références : chercher Marching Cubes, Marching Tetrahedra.
Sommaire
1. Marching Tetrahedra : Principe de l'algorithme ● Un mot sur l'algorithme du Marching Cube ● Marching Tetrahedra
2. Notions de bases
● Présence d'une intersection entre un cube/tétraèdre et une surface ● Intersection entre une arête et une surface
● Intersection d'un tétraèdre et une surface
1. 3. Détails de la programmation
● Les types
● Les principales fonctions
● L'algorithme
4. Quelques exemples
● Comparaison de rendu : sphère unité
● Exemples divers
5. Conclusion
6. Sources
4
4
4
5
5
5
5
6
6
6
7
7
7
9
10
11
1. Marching Tetrahedra : Principe de l'algorithme.
Un mot sur l'algorithme Marching Cubes
L'algorithme Marching Cubes est une méthode permettant de générer un objet polygonal à partir d'un maillage structuré et uniforme. Le champs scalaire est divisé en cubes de taille identique et est parcouru, cubes par cubes, pour déterminer les éventuelles intersections de chaque cube avec la surface. Différentes configurations sont possibles et dépendent de la répartition des intersections de la surface avec les arêtes des cubes.
Marching Tetrahedra
L’algorithme du Marching Tetrahedra dérive de l’algorithme du Marching Cubes. Le principe est de diviser le cube élémentaire en tétraèdres. Ainsi, pour chaque cube, on peut extraire 6 tétraèdres sur lesquels vont se calculer les intersections.
Pour l'implémentation de l'algorithme, la convention suivante fut choisit :
Tétraèdre n°0
Tétraèdre n°1
Tétraèdre n°2
Tétraèdre n°3
Tétraèdre n°4
Tétraèdre n°5
A (resp. G) étant le point le plus bas (reps. haut) du cube ayant les plus petites (resp. grandes) coordonnées. Il y a par conséquent, plus de faces générées qu'avec l'algorithme du Marching Cubes.
Pour chacun des cubes et des tétraèdres, on évalue la valeurs des sommets avec l'isovaleur de la fonction. Ensuite, pour chaque arête intersectée, on calcule l'intersection par interpolation linéaire ce qui nous donne les sommets de la facette recherchée sur chaque tétraèdres.
2. Notions de base
Pour implémenter l'algorithme du Marching Tetrahedra, nous avons utilisé plusieurs notions.
Présence d'intersection entre un cube/tétraèdre et une surface implicite : Soient Si, i=1,..,n les sommets d'un tel polyèdre. On évalue les valeurs de chaque sommets avec la fonction définissant la surface. Trois cas sont à distinguer :
● si toutes les valeurs sont positives : le polyèdre est à l'extérieur de la surface
● si toutes les valeurs sont négatives : le polyèdre est à l'intérieur de la surface
● s'il existe au moins deux valeurs de signe différents : le polyèdre intersecte la surface.
Intersection entre une arête et une surface implicite :
On utilise une interpolation linéaire avec la méthode de dichotomie.
Considérons A (évalué négativement) et B (évalué positivement) les deux extrémités de l'arête, la méthode se présente sous cette forme :
●
●
si le produits de deux valeurs des extrémités est positif, on s'arrête il n'y a pas d'intersection.
Sinon, ○ si ∣∣A−B∣∣ alors on s'arrête. ○ sinon, on calcule le milieu M du segment [AB] et on évalue ce point avec la fonction
■ si le produit de la valeur de A avec celle de M est négatif alors l'intersection est sur [AM], et on effectue la dichotomie sur le segment [AM]
■ sinon, l'intersection est sur le segment [MB], et on effectue la dichotomie sur [MB].
Intersection d'un tétraèdre avec une surface implicite
Lorsqu'on a déterminé la présence d'intersections entre la surface et le tétraèdre, on calcule ces points via la méthode de dichotomie, au niveau de chaque arête du tétraèdre. Il y a deux cas possibles : soit la facette obtenue est un triangle soit un quadrilatère.
Il ne reste plus qu'à orienté la face correctement.
3. Détails de la programmation Pour les méthodes d'affichage, on reprend la librairie ugly.cma utilisée en cours.
Les fonctions utilisées pour réaliser l'algorithme se trouvent dans la librairie marching_tetrahedron.cma, quelques unes (non énoncées ici) ont déjà été vues en cours.
les types :
­ type point3d={ x:float;y:float;z:float;} définit un point de l'espace
i
j
k
­ type monome = {coeff:float; degres:int array;} définit un élément d'un polynôme a x y z .
­ type polynome = monome list définit un polynôme. C'est le type utilisé pour définir les surfaces implicites.
­ type surf_imp = Surf of polynome | Union of surf_imp*surf_imp | Intersection of surf_imp*surf_imp | Intersection_Op of surf_imp*surf_imp définit le type de la surface. Celle­ci peut être un simple polynôme, une union de deux surfaces ou une intersection de deux surfaces ou encore une différence de deux surfaces.
les principales fonctions :
– évaluer la valeur d'un point3d avec un polynôme : evalf polynome point3d
– évaluer la valeur d'un point avec une surface : evalfunc surf_imp point3d
Cette fonction utilise la fonction evalf, la valeur d'une union de surface correspond au minimum des valeurs du point3d en chaque surface, l'intersection correspond au maximum enfin l'intersection opposée détermine le maximum entre la première surface et l'opposé de la deuxième.
– définition d'un cube : cube point3d long.
On définit un cube par un tuple (longueur d'une arête, [liste des sommets]) en prenant en paramètre le point le plus bas du cube et la longueur d'une arête.
– définition d'un tétraèdres : tetras point3d long
Prend un paramètre le point le plus bas du cube et sa longueur et retourne une liste des sommets de chaque tétraèdres composants ce cube.
– position d'un cube (resp. tétraèdre) par rapport à une surface :
cube_cmp_surf (resp. tetra_cmp_surf) surf_imp cube (resp. tetraèdre)
Évalue la valeur de la surface en chaque sommets du polyèdre et retourne un booléen pour signaler une intersection ou non. – intersection d'un tétraèdre avec une surface implicite : inter_tetra_surf surf_imp tétraèdre epsilon
Détermine la facette résultant de l'intersection entre un tétraèdre et une surface implicite.
Suivant le nombre de valeurs positives et négatives des sommets, on retourne un triangle ou un quadrilatère orienté correctement.
L'algorithme :
let rec marching_tetrahedron nivrec surface_imp liste_cubes eps = if nivrec = 0 then let good_tetras = L.map( function i ­> tetras_cut_surf surf_imp i) liste_cubes in L.map( function i ­> inter_tetra_surf surf_imp i eps) (break_list good_tetras) else let good_cubes = L.filter(function i­> true = cube_cmp_surf surf_imp i) liste_cubes in let new_liste_cubes = L.map( function i ­> divide_cube i) good_cubes in let final_liste_cubes = break_list new_liste_cubes in marching_tetrahedron (nivrec­1) surf_imp final_liste_cubes eps;;
Si le niveau de récursion est nul alors on calcule l'intersection entre les tétraèdres de chaque cubes qui intersectent la surface et la surface.
Sinon, on détermine quels sont les cubes qui intersectent la surface, puis on les divise en huit cubes de même taille et on appel la fonction sur la nouvelle liste de cube.
4.Quelques exemples.
Comparaison de rendu : sphère unité
Les trois exemples ci­dessous résultent de l'exécution du programme pour afficher la sphère unité.
Le cube de départ est [−1,5 ; 1,5]3 que l'on divise ensuite en 8 cubes identiques de longueur 1,5.
Epsilon = 1e­5
•Rendu n°1 : niveau de récursion : 0, temps d'exécution : 0.04 sec , nombre de faces : 24
•Rendu n°2 : niveau de récursion : 2, temps d'exécution : 0.41sec, nombre de faces : 588.
•Rendu n°3 : niveau de récursion : 5, temps d'exécution :, 50.07 sec, nombre de faces : 39228.
Exemples divers
En incorporant les opérations booléennes à notre programmation (union, intersection et différence), nous avons pu générer, à partir de forme simple, des résultats plus complexe qui n'ont pas d'équation propre.
•Différence d'un plan et de l'union de deux sphères
•Intersection entre trois sphères
5. Conclusion
L'algorithme du Marching Tetrahedra est un algorithme simple à mettre en oeuvre. Il est néanmoins plus gourmand en ressource que l'algorithme du Marching Cubes dont il découle puisqu'il génère un nombre plus important de faces.
Il a été choisit au départ de ne pas considérer les différents cas possibles de configuration des valeurs des sommets pour évaluer les intersections au niveau des tétraèdres.
Ceci a permit d'allèger le code en évitant les accumulations de conditions mais il implique de tester pour chaque face si elle est bien orientée ou pas, ce qui fut l'une des difficultés principale de l'implementation. Il serait interessant de tester l'autre approche puis de comparer les performances.
L'algorithme est aussi relativement performant puisqu'on arrive à des rendus ineteressants pour des niveaux de recursions peu important (à partir de 2~3).
6. Sources
Description de l'algorithme du Marching Cubes :
http://fr.wikipedia.org/wiki/Marching_cubes
http://en.wikipedia.org/wiki/Marching_cubes
Description de l'algorithme du Marching Tetrahedra :
http://fr.wikipedia.org/wiki/Marching_tetrahedra
http://en.wikipedia.org/wiki/Marching_tetrahedrons
Implémentation du Marching Tetrahedra en langage C :
http://www.mougel.org/informatique/IUP/IUP3/VisuSc/tetra.htm
Téléchargement