• Aucun résultat trouvé

Lancer de rayons ultrasonores

3.3 Propagation en milieu homogène

3.3.2 Calcul d’intersection

On distingue chacun des modes de polarisation en triant les lenteurs dans l’ordre décroissant, de telle sorte que sq L< sqT 1< sqT 2.

〈Tri des lenteurs〉

trier(lenteurs, valeursPropres); Tri des lenteurs,

mêmes permutations appliquées aux valeurs propres. float valeurPropre; valeurPropre = valeursPropres[indiceMode(mode)]; rayon.lenteur = lenteurs[indiceMode(mode)];

La polarisationu est le vecteur propre de Γ associé à la valeur propre λ du mode

considéré. La résolution du système linéaire à trois équations et trois inconnues sui-vant donne donc la polarisation :

⎧ ⎨ ⎩

Γ11u1+ Γ 12u2+ Γ 13u3= λu1

Γ21u1+ Γ 22u2+ Γ 23u3= λu2

Γ31u1+ Γ 32u2+ Γ 33u3= λu3

〈Calcul de polarisation en milieu anisotrope〉

rayon.polarisation = calculVecteurPropre(matriceChristoffel, valeurPropre); Enfin, pour la direction d’énergie, nous reprenons la formule donnée en sec-tion2.2.3aux facteurs constants près puisqu’on normalise le résultat.

〈Calcul de direction d’énergie en milieu anisotrope〉

for(int i, j, k, l 0; 2) {

rayon.directionÉnergie[i] = tenseurConstantesÉlastiques[indicesVoigt(i, j, k, l)] *

rayon.polarisation[j] * rayon.polarisation[l] * rayon.direction[k]; indicesVoigt

79

}

normaliser(rayon.directionÉnergie);

3.3.2 Calcul d’intersection

Une fois les caractéristiques du rayon initialisées, il nous faut calculer le premier impact du rayon avec une primitive de la scène de contrôle. Celle-ci peut être la surface du traducteur ou une limite de matériau, constituant une interface avec un autre matériau. Dans les deux cas, nous déterminons :

— La position de l’intersection du rayon avec la primitive, pour en déduire l’élément du traducteur multiéléments intersecté ou le point de départ des rayons fils générés à une interface,

— La distance de propagation du rayon à l’intersection, qui nous permet de calculer le temps de vol, ou temps mis par l’onde pour atteindre l’intersection, afin d’en déduire la phase de l’onde.

— La normale au point d’intersection, utile aux calculs d’interface et au moment de l’intersection avec le traducteur.

Ces données peuvent être calculées à l’aide des résultats de l’opération d’inter-section d’un rayon avec une scène telle que décrite en d’inter-section3.1.1et fournie par la bibliothèque Embree. Spécifiquement, la méthode d’intersection d’Embree que nous utilisons prend en paramètres :

— Une scène de lancer de rayons construite au préalable et contenant les struc-tures accélératrices (voir section3.1.1),

— Un rayon identifié par une origine, une direction, une distance minimale et une distance maximale d’intersection.

〈Calcul d’intersection〉

void calculIntersection(RayonUS rayon, Vecteur3D & positionIntersection, float & tempsVol) {

Intersection intersection = intersectionEmbree(scène, rayon); positionIntersection = positionIntersection(intersection, scène); tempsVol = tempsVol(intersection, rayon);

tempsVol 84

}

Position de l’intersection

Après le calcul d’intersection, on dispose d’une part d’un identifiant unique cor-respondant à la primitive géométrique intersectée ainsi que des coordonnées bary-centriques u et v spécifiques à cette primitive et d’autre part de la distance d’inter-section notée t. On dispose alors de deux méthodes pour retrouver la position finale

M d’intersection :

— L’utilisation des coordonnées barycentriques u et v et des coordonnées des sommets v0, v1et v2de la primitive, dans le cas d’un triangle :

M= (1 − u − v).v0+ u.v1+ v.v2 — Le calcul vectoriel depuis l’origine :

M= O+ t.d

La méthode basée sur les coordonnées barycentriques offre une meilleure préci-sion, en particulier pour de fortes valeurs de t. En effet, l’ensemble des calculs est effectué sur des nombres à virgule flottante en simple précision (32 bits, normeIEEE 754). Les nombres sont représentés sont la forme d’approximations à la puissance de 2 la plus proche avec une précision limitée (voir en annexeB). Pour de fortes valeurs de t, l’arrondi choisi par l’unité de calcul flottant tend à causer des erreurs pouvant situer l’intersection en amont de la primitive intersectée, engendrant ainsi des auto-intersections, comme schématisé en figure3.13.

Ces problèmes de précision sont réduits par l’approche barycentrique puisque les coordonnées barycentriques servent à localiser le point d’intersection dans une étendue spatiale délimitée par les sommets de la primitive triangulaire intersectée.

×

× ×

Figure 3.13 – Schématisation de l’erreur de précision en lancer de rayons Par ailleurs, puisque le calcul est directement effectué en fonction des sommets du triangle, le point d’intersection est inclus dans le plan formé par ces trois plans avec plus de précision.

〈positionIntersection〉

Vecteur3D positionIntersection(Intersection intersection, Scène scène) { float u = donnéesIntersection.u;

float v = donnéesIntersection.v;

Triangle triIntersecté = scène.triangles[donnéesIntersection.idPrimitive];

Vecteur3D posIntersection = (1 - u - v) * triIntersecté.v0 + Vecteur3D 21

u * triIntersecté.v1 + v * triIntersecté.v2; return positionIntersection;

}

Temps de vol

Pour obtenir le temps de vol, ou temps mis par une onde pour aller de son origine à son intersection, dans un milieu isotrope, il suffit de considérer le rapport entre la distance d parcourue et la vitesse de propagation. On obtient, avec v la vitesse de propagation et s la lenteur :

tvol= d

v = d.s

Cette relation est valable dans les milieux isotropes puisque la direction d’énergie et la direction de phase sont confondues. Or, en milieux anisotropes, ce n’est pas le cas. Lorsque nous lançons un rayon ultrasonore, la direction du rayon est celle de l’énergie de la perturbation mécanique. Elle se déplace selon la direction d’énergie (définie en section2.2.1) avec une vitesse Vedite vitesse d’énergie.

Cette vitesse est différente de la vitesse de phase Vϕ qui correspond à la vitesse de propagation du front d’onde. En effet, comme le montre le schéma en figure3.14, en considérant l’onde portée par le rayon de manière isolée sous la forme d’une onde plane, l’énergie parcourt en une période une distance supérieure à celle parcourue par la phase.

Ainsi, la vitesse d’énergie est supérieure à la vitesse de phase. Sa projection sur la direction de phase est égale à la vitesse de phase. On a donc :

 Ve 

α

Figure 3.14 – Différence entre les distances parcourues par la phase (ligne pleine) et l’énergie(ligne pointillée)

Avec n la direction de phase normalisée.

Par conséquent, le temps de vol d’une onde en milieu anisotrope s’écrit :

tvol = d

Ve = d.cos(α)

Vϕ = d.s.〈Ve· n〉

〈tempsVol〉

float tempsVol(Intersection intersection, RayonUS rayon) { return intersection.distance * rayon.lenteur *

produitScalaire(rayon.directionÉnergie, rayon.directionPhase); }

Normale au point d’intersection

Le calcul de la normale au point d’intersection est calculé de la même manière que la position d’intersection. En effet, à la construction de la géométrie de la pièce, utilisée par l’outil d’intersection, chaque point du maillage se voit attribuer une nor-male. La normale au point d’intersection est construite par interpolation linéaire des normales de chaque sommet du triangle, à l’aide des coordonnées barycentriques du point d’intersection dans le triangle. Ce vecteur interpolé est ensuite normalisé. 〈normale〉

Vecteur3D normale(Intersection intersection, RayonUS rayon) { float u = donnéesIntersection.u;

float v = donnéesIntersection.v;

Triangle triIntersecté = scène.triangles[donnéesIntersection.idPrimitive]; Vecteur3D normale = (1 - u - v) * triIntersecté.n0 +

Vecteur3D 21 u * triIntersecté.n1 + v * triIntersecté.n2; normaliser(normale); return normale; }

Ce choix de construction de normale n’étant pas anodin, les raisons le justifiant sont détaillées en section3.5.3.