Code_TYMPAN  4.2.0
Industrial site acoustic simulation
TYANIME3DAcousticModel.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) <2012> <EDF-R&D> <FRANCE>
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10  * See the GNU General Public License for more details.
11  * You should have received a copy of the GNU General Public License along
12  * with this program; if not, write to the Free Software Foundation, Inc.,
13  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14 */
15 
21 #include "TYANIME3DAcousticModel.h"
22 
23 
25  TYStructSurfIntersect* tabStruct,
26  const tympan::AcousticProblemModel& aproblem,
27  AtmosphericConditions& atmos) :
28  _tabTYRays(tabRayons),
29  _tabSurfIntersect(tabStruct),
30  _aproblem(aproblem),
31  _atmos(atmos)
32 {
33  _nbRays = _tabTYRays.size();
34 
37 
42 
43  _c = _atmos.compute_c();
44  _K = _atmos.get_k();
46 
48 }
49 
51 {
52 
53 }
54 
55 
57 {
58  for (int i = 0; i < _nbRays; i++)
59  {
61  }
62 }
63 
65 {
66  double angle = 0.0, rd = 0.0, rr = 0.0; // incidence angle of acoustic wave, lenght for events computation
67  int reflIndice = 0;
68 
69  acoustic_path* ray = NULL;
70 
71  OPoint3D Prefl, Pprec, Psuiv; //pt de reflexion, pt precedent et suivant
72 
73  OTabDouble tabPondFresnel; // tableau des ponderations de Fresnel
74  TabPoint3D triangleCentre; // Contains all triangles centres
75 
76  OSpectreComplex spectreAbs;
79  OSpectreComplex prod;
80  OSpectreComplex sum;
81  OSpectreComplex prod1;
82  OSpectreComplex sum1;
83  OSpectreComplex pond;
84 
85  for (int i = 0; i < _nbRays; i++) // boucle sur les rayons
86  {
87  ray = _tabTYRays[i];
88  std::vector<int> tabRefl = ray->getIndexOfEvents(TYREFLEXION | TYREFLEXIONSOL);
89 
90  // Initialisation des spectres
91  prod = one;
92  sum = zero;
93  sum1 = zero;
94  pond = zero;
95 
96  for (size_t j = 0; j < tabRefl.size(); j++)
97  {
98  reflIndice = tabRefl[j];
99 
100  Prefl = ray->getEvents().at(reflIndice)->pos;
101  Pprec = ray->getEvents().at(reflIndice)->previous->pos;
102  Psuiv = ray->getEvents().at(reflIndice)->next->pos;
103  angle = ray->getEvents().at(reflIndice)->angle;
104 
105  // Longueur du trajet reflechi
106  rd = ray->getEvents().at(reflIndice)->distPrevNext;
107  // Longueur du trajet direct
108  rr = Pprec.distFrom(Prefl) + Prefl.distFrom(Psuiv);
109 
110  std::cout << "Position de la reflexion : X = " << Prefl._x << " Y = " << Prefl._y << " Z = " << Prefl._z << std::endl;
111  std::cout << "Angle d'incidence du rayon = " << angle << std::endl;
112  std::cout << "Longueur du rayon direct = " << rd << std::endl;
113  std::cout << "Longueur du rayon reflechi = " << rr << std::endl;
114 
115  // Initialisation des spectres
116  spectreAbs = OSpectreComplex(OSpectre(0.0));
117 
118 
119  if (_useFresnelArea) // Avec ponderation de Fresnel
120  {
121  //if (ray->getEvents().at(reflIndice)->type == TYREFLEXIONSOL)
122  //{
123  // std::cout << "We start using Fresnel Area on the ground" << std::endl;
124 
125  // triangleCentre.clear();
126  // tabPondFresnel.clear();
127  // tabPondFresnel = ComputeFresnelWeighting(angle, Pprec, Prefl, Psuiv, rayNbr, reflIndice, triangleCentre); // calcul des ponderations de Frenel
128  // nbFacesFresnel = tabPondFresnel.size(); // nbr de triangles dans le zone de Fresnel
129 
130  // std::cout << "il y a N ponderations : " << nbFacesFresnel << std::endl;
131 
132  // sum = zero;
133 
134  // for (int k = 0; k < nbFacesFresnel; k++)
135  // {
136  // // boucle sur les faces = intersection plan de l'objet intersecte / ellipsoide de Fresnel
137  // pSol = _topo->terrainAt(triangleCentre[k])->getSol();
138  // pSol->calculNombreDOnde(_atmos);
139 
140  // std::cout << "sol n : " << k << "resistivite = " << pSol->getResistivite() << std::endl;
141 
142  // spectreAbs = pSol->abso(angle, rr, _atmos);
143  // // TO DO : S'assurer que la somme des pondrations de Fresnel gale 1
144  // pond = spectreAbs * tabPondFresnel[k];
145  // sum = sum + pond; // calcul du coeff de reflexion moy en ponderant avec les materiaux
146  // }
147 
148  // prod = prod * sum * (rd / rr);
149  //}
150  //else // Reflexion sur une construction
151  //{
152  // std::cout << "We start using Fresnel Area on a building" << std::endl;
153 
154  // triangleCentre.clear();
155  // tabPondFresnel = ComputeFresnelWeighting(angle, Pprec, Prefl, Psuiv, rayNbr, reflIndice, triangleCentre); // calcul des ponderations de Frenel
156  // nbFacesFresnel = tabPondFresnel.size(); // nbr de triangles dans le zone de Fresnel
157 
158  // std::cout << "il y a N ponderations : " << nbFacesFresnel << std::endl;
159 
160  // sum = zero;
161 
162  // for (int k = 0; k < nbFacesFresnel; k++)
163  // {
164  // // boucle sur les faces = intersection plan de l'objet intersecte / ellipsoide de Fresnel
165  // pond = spectreAbs * tabPondFresnel[k];
166  // sum = sum + pond; // calcul du coeff de reflexion moy en ponderant avec les materiaux
167  // }
168  // prod = prod * sum;
169  //}
170 
171  //std::cout << "End of Fresnel Area" << std::endl;
172  }
173  else // not use Fresnel Area
174  {
175  // Cas particulier d'une reflexion sur le sol
176  std::cout << "We are not using Fresnel Area on the ground" << std::endl;
177  if (ray->getEvents().at(reflIndice)->type == TYREFLEXIONSOL)
178  {
179  unsigned int index_face = ray->getEvents().at(reflIndice)->idFace1;
181  assert(material);
182 
183  spectreAbs = material->get_absorption(angle, rr);
184  }
185  else
186  {
187  unsigned int index_face = ray->getEvents().at(reflIndice)->idFace1;
189  assert(material);
190 
191  spectreAbs = material->get_absorption(angle, rr);
192  }
193  // ATTENTION ! : Il semble qu'on ne tienne compte que d'une seule reflexion : La derniere.
194  prod = spectreAbs;
195  }
196  }
197 
198  _absRefl[i] = prod;
199  }
200 }
201 
203 {
204  // Delta = diffrence de marche
205  // precDiff = distance entre l'evenement precedent et la diffraction
206  // diffEnd = distance entre la diffraction et l'evenement pertinent suivant
207  // precEnd = distance entre l'evenement precedent et l'evenement pertinent suivant
208  // nbF = spectre du nbr de Fresnel de chq diffration
209  // absArrete = spectre complexe d'absorption sur chaque arrete
210  // prod = spectre produit des absorptions sur chaque arrete
211  // kDelta = spectre intermediaire de calcul
212  // mod = spectre module du nombre complexe absArrete
213  // signe = signe de la diffraction
214  // diffIdx = index de l'evenement diffraction courant
215  // vDiffPrec = vecteur diffraction / evenement precedent
216  // vDiffSuiv = vecteur diffraction evenement suivant
217  // n1 = normale la premire face du diedre diffractant
218  // n2 = normale la seconde face du diedre diffractant
219  // normal = n1 + n2
220 
221 
222 
223  double delta = 0.0, precDiff = 0.0, diffEnd = 0.0, precEnd = 0.0;
224  OSpectre nbF; // nbr de Fresnel de chq diffration
225  OSpectreComplex absArrete; // absorption sur chaque arrete
226  OSpectreComplex prod = OSpectreComplex(OSpectre(1.0)); // produit des absorptions sur chaque arrete
227  OSpectre kDelta; // intermediaire de calcul
228  OSpectre mod; // module du nombre complexe absArrete
229  int signe = 1, diffIdx = 0;
230 
231  OVector3D vDiffPrec, vDiffSuiv, n1, n2, normal;
232 
233  acoustic_path* currentRay = NULL;
234 
235  for (int i = 0; i < _nbRays; i++) // boucle sur les rayons
236  {
237  currentRay = _tabTYRays[i];
238 
239  prod = OSpectreComplex(OSpectre(1.0));
240 
241  std::vector<int> tabDiff = currentRay->getIndexOfEvents(TYDIFFRACTION); // gets a vector where diff occur
242 
243  for (size_t j = 0; j < tabDiff.size(); j++)
244  {
245  diffIdx = tabDiff[j]; // Index de l'evenement diffraction courant
246  acoustic_event* currentEv = currentRay->getEvents().at(diffIdx); // Evenement courant
247 
248  precDiff = currentEv->previous->distNextEvent; // Distance de l'venement prcedent la diffraction
249  diffEnd = currentEv->distEndEvent; // de la diffraction l'vnement pertinent suivant (recepteur ou reflexion)
250  precEnd = currentEv->previous->distEndEvent; // Chemin sans diffraction
251 
252  vDiffPrec = OVector3D(currentEv->pos, currentEv->previous->pos);
253  vDiffSuiv = OVector3D(currentEv->pos, currentEv->next->pos);
254  n1 = _tabSurfIntersect[ currentEv->idFace1 ].normal; // normale de la 1ere face
255  n2 = _tabSurfIntersect[ currentEv->idFace2 ].normal; // normale de la 2e face
256  normal = n1 + n2; // somme des normales
257 
258  // Because we only deal with diffraction in shadow zone, "signe" is set to 1
259  signe = 1;
260 
261  delta = signe * (precDiff + diffEnd - precEnd);
262  kDelta = _K * delta;
263  nbF = _lambda.invMult(2.0 * delta); // 2 * delta / lambda
264 
265  if (true) // DTn 20131220 pour forcer l'operation( delta > ( _lambda.div(20) ).valMax() )
266  {
267  mod = (((nbF * 20.0 + 3.0)).sqrt()).inv(); // 1 / sqrt(20 * nbF + 3)
268  }
269  else
270  {
271  mod = 1;
272  }
273 
274  absArrete = OSpectreComplex(mod, kDelta);// (1 / sqrt(20 * nbF + 3)) exp(j * k * delta)
275  prod = prod * absArrete;
276  }
277 
278  _absDiff[i] = prod;
279  }
280 }
281 
282 /*
283 // calcul de la zone de Fresnel pour une diffraction donnee - Approximation : zone = boite englobante de l'ellipsoide de Fresnel
284 OBox2 TYANIME3DAcousticModel::ComputeFresnelArea(double angle, OPoint3D Pprec, OPoint3D Prefl, OPoint3D Psuiv, int rayNbr, int reflIndice)
285 {
286  OBox2 fresnelArea; // boundingBox de l'ellispsoide de Fresnel
287 
288  // TO DO : Why don't we pass directly the current ray instead of accessing it by its indice in the ray vector ?
289  Prefl = _tabTYRays[rayNbr]->getEvents().at(reflIndice)->pos;
290  Pprec = _tabTYRays[rayNbr]->getEvents().at(reflIndice)->previous->pos;
291  Psuiv = _tabTYRays[rayNbr]->getEvents().at(reflIndice)->next->pos;
292 
293  std::cout << "Coordonnees du point de reflexion " << std::endl;
294  std::cout << Prefl._x << " " << Prefl._y << " " << Prefl._z << std::endl;
295 
296  double distPrefPsuiv = _tabTYRays[rayNbr]->getEvents().at(reflIndice)->distNextEvent;
297  double dr = _tabTYRays[rayNbr]->getEvents().at(reflIndice)->previous->distNextEvent + distPrefPsuiv;
298  double dd = _tabTYRays[rayNbr]->getEvents().at(reflIndice)->distPrevNext;
299 
300  // Calcul de Fc ne prenant en compte que la diffrence de marche
301  OSpectre f = OSpectre::getOSpectreFreqExact(); //frequence
302  OSpectre fc = computeFc(dd, dr);
303 
304  //
305  //MIS EN COMMENTAIRE POUR VALIDATION ULTERIEURE
306 
307  // // Calcul de F lambda officiel (equations 10 15 de H-T63-2010-01193-FR)
308  // // parametre de l'ellipsoide de Fresnel F_{\lambda} via la formule definie dans la publie de D. van Maercke et J. Defrance (CSTB-2007)
309  // // Version initiale du calcul de fc prenant en compte le sol rel
310 
311  // // Le spectre Q sert rcuprer la phase du trajet rflechi
312 
313  // OSpectre f = OSpectre::getOSpectreFreqExact(); //frequence
314  // std::cout << "f = " << f.valMax() << std::endl;
315  // OSpectreComplex Q = _topo.terrainAt(Prefl)->getSol()->calculQ(angle, distPrefPsuiv, _atmos) ; // coeff de reflexion du sol au pt de reflexion
316  // const double c1 = 0.5 * _c /(dr - dd); // cste de calcul
317  // OSpectre phaseQdivPI = Q.getPhase().div(M_PI);
318  // OSpectre fmin = (OSpectre(0.5) - phaseQdivPI)*c1;
319  // OSpectre fmax = (OSpectre(1.0) - phaseQdivPI)*c1;
320  // OSpectre fc = (fmin * fmax).sqrt(); // frequence de transition
321 
322  // std::cout << "fmin = " << fmin.valMax() << std::endl;
323  // std::cout << "fmax = " << fmax.valMax() << std::endl;
324  // std::cout << "fc = " << fc.valMax() << std::endl;
325 
326  // const OSpectre F = (OSpectre(1.0)-((f*f).div(fc*fc)).exp(1.0))*32.0;
327 
328  // OSpectre A = (fc*fc)*-1;
329  // OSpectre B = f*f;
330  // OSpectre C = B.div(A);
331  // const OSpectre F = (OSpectre(1.0)-(C.exp()))*32;
332  //
333 
334  // F fixe a 1 pour eviter une boite trop grande a basse freq
335  const OSpectre F = OSpectre(1.0);
336 
337  // lF fixe a lambda/2
338  OSpectre lF = _lambda.div(2.0) * F;
339 
340  // 1/ boite dans le repere (Ox,Oy,Oz)
341  // Construction de la bb de l'ellipsoide de Fresnel
342 
343  // S' depends on the point where the reflection occurs
344  int reflFace = _tabTYRays[rayNbr]->getEvents().at(reflIndice)->idFace1;
345 #ifdef _DEBUG
346  TYElement* pElm = _tabSurfIntersect[reflFace].pSurfGeoNode->getElement();
347 #endif
348  TYAcousticSurface* face = TYAcousticSurface::safeDownCast(_tabSurfIntersect[reflFace].pSurfGeoNode->getElement());
349  OPlan P = face->getPlan();
350  OPoint3D SIm = P.symPtPlan(Pprec); // Point image du point prcedent la reflexion
351  double dSImR = SIm.distFrom(Psuiv); // Distance de la source image au point suivant la reflexion
352 
353  std::cout << "Coordonnees de la source image " << std::endl;
354  std::cout << SIm._x << " " << SIm._y << " " << SIm._z << std::endl;
355 
356 
357  // On fixe une frequence de travail
358  // TO DO : mettre freq en paramtre utilisateur
359  float freq = 500.0f;
360  double L = 2 * lF.getValueReal(freq) + dSImR;
361  double l = sqrt(lF.getValueReal(freq) * (lF.getValueReal(freq) + 2.*dSImR));
362  double h = l; // hauteur = largeur (ajout pour la lisibilit du code)
363 
364 
365  std::cout << "L = " << L << " l = " << l << std::endl;
366 
367  // Boite de Fresnel placee a l'origine du repere
368  // OBox box = OBox( OCoord3D( 0, 0, 0 ), OCoord3D( L, l, h ) );
369  fresnelArea = OBox2(L, l, h); // DTn uses new constructor of a box centered on 0, 0, 0
370 
371  // Definition de la nouvelle position du centre de la boite // Translation au pt O milieu du segment [SIm R]
372  OPoint3D O(0.5 * (SIm._x + Psuiv._x), 0.5 * (SIm._y + Psuiv._y), 0.5 * (SIm._z + Psuiv._z));
373 
374  // DTn : define a new vector to change box orientation
375  OVector3D vecO(O, Psuiv);
376 
377  // DTn : Move and rotate box
378  fresnelArea.moveAndRotate(O, vecO);
379 
380  return fresnelArea;
381 
382  //
383  // DTn commented to use new OBox manipulator I defined (20131218)
384  // // Deplace le centre de la boite au centre du segment S'P (P = point suivant la rflexion)
385  // const OVector3D vt( ( O._x - (0.5*L) ), ( O._y - ( 0.5*l ) ), ( O._z - ( 0.5*h ) ) );
386  // fresnelArea.Translate( vt );
387 
389  // return fresnelArea.boxRotation( O, Psuiv ); // Voir la dfinition de boxRotation : devrai tre fersnelArea.boxRotation(...)
390  //
391 }
392 */
393 
394 // TO DO : Vrifier que c'est la mthode mise en commentaire dans computeFresnelArea
395 OSpectre TYANIME3DAcousticModel::computeFc(const double& dd, const double& dr)
396 {
397  OSpectre FMin, FMax, fc;
398  OSpectre PhiN = _atmos.get_k() * (dr - dd);
399  OSpectre Phi0Min(M_PI / 2);
400  OSpectre Phi0Max(M_PI);
402 
403  for (unsigned int i = 0; i < TY_SPECTRE_DEFAULT_NB_ELMT - 1; i++)
404  {
405  double fn = freq.getTabValReel()[i];
406  double fnp1 = freq.getTabValReel()[i + 1];
407  double phin = PhiN.getTabValReel()[i];
408  double phinp1 = PhiN.getTabValReel()[i + 1];
409  double phi0 = Phi0Min.getTabValReel()[i];
410  FMin.getTabValReel()[i] = fn + ((phi0 - phin) / (phinp1 - phin)) * (fnp1 - fn);
411  phi0 = Phi0Max.getTabValReel()[i];
412  FMax.getTabValReel()[i] = fn + ((phi0 - phin) / (phinp1 - phin)) * (fnp1 - fn);
413  }
414 
415  fc = (FMin * FMax).sqrt();
416 
417  // Last value is the same as the previous one
418  fc.getTabValReel()[TY_SPECTRE_DEFAULT_NB_ELMT - 1] = fc.getTabValReel()[TY_SPECTRE_DEFAULT_NB_ELMT - 2];
419 
420  return fc;
421 }
422 
423 /*
424 OTabDouble TYANIME3DAcousticModel::ComputeFresnelWeighting(double angle, OPoint3D Pprec, OPoint3D Prefl, OPoint3D Psuiv, int rayNbr, int reflIndice, TYTabPoint3D& triangleCentre)
425 {
426  OTabDouble tabPond; // tableau des ponderation de Fresnel
427  OTabDouble tabSurface; // tableau des surfaces des triangles de la zone de Fresnel
428  double surfaceTot = 0.0; // somme des surfaces des triangles de la zone de Fresnel
429  const double delaunay = 1e-6; // Parameter needed to compute triangulation
430 
431  std::cout << "Dans ComputeFresnelWeighting :" << std::endl;
432  // And bb was born
433  OBox2 fresnelArea = ComputeFresnelArea(angle, Pprec, Prefl, Psuiv, rayNbr, reflIndice);
434 
435  std::cout << "Coordonnees de l'origine de la boite " << std::endl;
436  std::cout << "Center = " << fresnelArea._center._x << " " << fresnelArea._center._y << " " << fresnelArea._center._z << std::endl;
437 
438  // XXX Altimetry refactoring impacts here.
439 
440 
441 
442  std::cout << "Coordonnees des 8 sommets de la boite " << std::endl;
443  std::cout << "A = " << fresnelArea._A._x << " " << fresnelArea._A._y << " " << fresnelArea._A._z << std::endl;
444  std::cout << "B = " << fresnelArea._B._x << " " << fresnelArea._B._y << " " << fresnelArea._B._z << std::endl;
445  std::cout << "C = " << fresnelArea._C._x << " " << fresnelArea._C._y << " " << fresnelArea._C._z << std::endl;
446  std::cout << "D = " << fresnelArea._D._x << " " << fresnelArea._D._y << " " << fresnelArea._D._z << std::endl;
447 
448 
449  std::cout << "E = " << fresnelArea._E._x << " " << fresnelArea._E._y << " " << fresnelArea._E._z << std::endl;
450  std::cout << "F = " << fresnelArea._F._x << " " << fresnelArea._F._y << " " << fresnelArea._F._z << std::endl;
451  std::cout << "G = " << fresnelArea._G._x << " " << fresnelArea._G._y << " " << fresnelArea._G._z << std::endl;
452  std::cout << "H = " << fresnelArea._H._x << " " << fresnelArea._H._y << " " << fresnelArea._H._z << std::endl;
453 
454 
455  // Remplacer par l'intersection des segments FG, EH, AB, CD
456  // avec le plan de la face sur laquelle se trouve le point de rflexion.
457  OSegment3D AB(fresnelArea._A, fresnelArea._B);
458  OSegment3D CD(fresnelArea._C, fresnelArea._D);
459  OSegment3D FG(fresnelArea._F, fresnelArea._G);
460  OSegment3D EH(fresnelArea._E, fresnelArea._H);
461 
462  LPTYPolygon faceRefl = (*_topo->getAltimetrie()).getFaceUnder(Prefl);
463 
464  // Calcul de l'intersection des segments avec le plan de la face de reflexion
465  OPlan refPlan(faceRefl->getPoint(0), faceRefl->getPoint(1), faceRefl->getPoint(2)); //->getPlan();
466 
467  OPoint3D eProj, fProj, gProj, hProj;
468  refPlan.intersectsSegment(AB._ptA, AB._ptB, eProj);
469  refPlan.intersectsSegment(CD._ptA, CD._ptB, fProj);
470  refPlan.intersectsSegment(EH._ptA, EH._ptB, gProj);
471  refPlan.intersectsSegment(FG._ptA, FG._ptB, hProj);
472 
473 
474  // ANCIENNE VERSION (PROJECTION DES POINT DU "HAUT" DE LA BOITE
475  // fE/fF/fG/fH are the faces under the box corners E/F/G/H
476  //LPTYPolygon fE = (*_topo.getAltimetrie()).getFaceUnder(fresnelArea._E);
477  //LPTYPolygon fF = (*_topo.getAltimetrie()).getFaceUnder(fresnelArea._F);
478  //LPTYPolygon fG = (*_topo.getAltimetrie()).getFaceUnder(fresnelArea._G);
479  //LPTYPolygon fH = (*_topo.getAltimetrie()).getFaceUnder(fresnelArea._H);
480 
481  // Defines 4 planes from the 4 surfaces
482  //OPlan ePlane = fE->plan();
483  //OPlan fPlane = fF->plan();
484  //OPlan gPlane = fG->plan();
485  //OPlan hPlane = fH->plan();
486 
487  // These are the four projections onto the planes defined previously
488  // This is a way of taking into account the ground altitude
489  //OPoint3D eProj = ePlane.projPtPlan(fresnelArea._E);
490  //OPoint3D fProj = fPlane.projPtPlan(fresnelArea._F);
491  //OPoint3D gProj = gPlane.projPtPlan(fresnelArea._G);
492  //OPoint3D hProj = hPlane.projPtPlan(fresnelArea._H);
493  // FIN ANCIENNE VERSION
494 
495  std::cout << "Coordonnees des 4 projetes des sommets hauts de la boite " << std::endl;
496  std::cout << "eProj = " << eProj._x << " " << eProj._y << " " << eProj._z << std::endl;
497  std::cout << "fProj = " << fProj._x << " " << fProj._y << " " << fProj._z << std::endl;
498  std::cout << "gProj = " << gProj._x << " " << gProj._y << " " << gProj._z << std::endl;
499  std::cout << "hProj = " << hProj._x << " " << hProj._y << " " << hProj._z << std::endl;
500 
501  // We get back the points inside the zone
502  TYTabPoint pointsInside;
503  _alti->getPointsInBox(eProj, fProj, gProj, hProj, pointsInside);
504 
505  // We create a tabPoint containing all the points : pointsInside the zone + projection
506  TYTabPoint ptsTriangulation = pointsInside;
507  ptsTriangulation.push_back(eProj);
508  ptsTriangulation.push_back(fProj);
509  ptsTriangulation.push_back(gProj);
510  ptsTriangulation.push_back(hProj);
511 
512  // We triangulate the zone defined by the four projections
513  // i.e. the one between eProj, fProj, gProj, hProj
514  // and with the points which are inside this zone
515  // We compute the triangulation inside the zone of interest
516  _oTriangles = ComputeTriangulation(ptsTriangulation, delaunay);
517 
518  // We wanna get each triangle centre in order to know the ground type under the centre
519  // Then we get the triangle surface and compute fresnel weighting
520  unsigned long nbTriangles = _oTriangles.size();
521  tabPond.reserve(nbTriangles);
522  tabSurface.reserve(nbTriangles);
523 
524  // For each triangle, we get the centre and the surface
525  for (int k = 0; k < nbTriangles; k++)
526  {
527  OTriangle triangleK = _oTriangles.at(k);
528  tabSurface.push_back(triangleK.getSurface());
529  surfaceTot += tabSurface.at(k);
530  triangleCentre.push_back(triangleK.getCentre());
531  }
532  std::cout << "Surface totale = " << surfaceTot << std::endl;
533 
534  // This part computes a ponderation depending on the triangle surface
535  for (int k = 0; k < nbTriangles; k++)
536  {
537  tabPond.push_back(tabSurface.at(k) / surfaceTot);
538  }
539 
540  std::cout << "End of ComputeFresnelWeighting " << std::endl;
541 
542  return tabPond;
543 }
544 */
545 
546 /*
547 std::vector<OTriangle> TYANIME3DAcousticModel::ComputeTriangulation(const TYTabPoint& points, const double& delaunay)
548 {
549 
550  // This function returns a vector of triangles created within the bounding box
551  unsigned int i = 0; // Indices needed
552  ODelaunayMaker oDelaunayMaker(delaunay);
553 
554  // Set des vertex
555  unsigned int nbOfPts = static_cast<uint32>(points.size());
556  for (i = 0; i < nbOfPts; i++)
557  {
558  oDelaunayMaker.addVertex(points[i]);
559  }
560 
561  // Generate
562  oDelaunayMaker.compute();
563 
564  // Get mesh : A triangle is a combination of a face with vertices
565  QList<OTriangle> triangles = oDelaunayMaker.getFaces();
566  QList<OPoint3D> vertexes = oDelaunayMaker.getVertex();
567 
568  unsigned long nbTriangles = triangles.count();
569  // This is the returned vector of triangles
570  std::vector<OTriangle> listeTriangle;
571 
572  // This step associates the corners with their coordinates
573  // Each face has 3 corners named _p1/_p2/_p3 that need to be
574  // linked with the OPoint3D _A/_B/_C
575  for (int m = 0; m < nbTriangles; m++)
576  {
577  listeTriangle.push_back(triangles[m]); // We get the triangle
578  listeTriangle.at(m)._A._x = vertexes[listeTriangle[m]._p1]._x;
579  listeTriangle.at(m)._A._y = vertexes[listeTriangle[m]._p1]._y;
580  listeTriangle.at(m)._A._z = vertexes[listeTriangle[m]._p1]._z;
581  listeTriangle.at(m)._B._x = vertexes[listeTriangle[m]._p2]._x;
582  listeTriangle.at(m)._B._y = vertexes[listeTriangle[m]._p2]._y;
583  listeTriangle.at(m)._B._z = vertexes[listeTriangle[m]._p2]._z;
584  listeTriangle.at(m)._C._x = vertexes[listeTriangle[m]._p3]._x;
585  listeTriangle.at(m)._C._y = vertexes[listeTriangle[m]._p3]._y;
586  listeTriangle.at(m)._C._z = vertexes[listeTriangle[m]._p3]._z;
587  }
588 
589  return listeTriangle;
590 }
591 */
592 
594 {
595  OSpectre phase; // phase du nombre complexe _pressAcoustEff[i] pour chq i
596  OSpectre mod; // module du nombre complexe _pressAcoustEff[i] pour chq i
597  const double rhoc = _atmos.Z_ref; //400.0; // kg/m^2/s
598  double c1; // constante du calcul
599  OPoint3D S, P0; // pt de la source et pt du 1er evenement
600  OSegment3D seg; // premier segment du rayon
601  OSpectre directivite, wSource; // fonction de directivite et spectre de puissance de la source
602 
603  //TYSourcePonctuelle* source = NULL; // source
604 
605  OSpectreComplex prodAbs; // produit des differentes absorptions
606  double totalRayLength; // Computes the total ray length including reflections only (diffractions are not included)
607 
608  for (int i = 0; i < _nbRays; i++) // boucle sur les rayons
609  {
610  totalRayLength = 0.0; // Computes the total ray length including reflections only (diffractions are not included)
611 
612  const tympan::AcousticSource& source = _aproblem.source( _tabTYRays[i]->getSource_idx() );
613 
614  //--------------------------------------
615 
616  totalRayLength = _tabTYRays[i]->getLength();
617 
618  c1 = 4.0 * M_PI * totalRayLength * totalRayLength;
619 
620  S = _tabTYRays[i]->getEvents().at(0)->pos;
621  P0 = _tabTYRays[i]->getEvents().at(1)->pos;
622  seg = OSegment3D(S, P0);
623 
624  OVector3D vec(S, P0);
625  double length = S.distFrom(P0);
626 
627  directivite = source.directivity->lwAdjustment(vec, length);
628  wSource = source.spectrum.toGPhy();
629 
630  prodAbs = _absAtm[i] * _absRefl[i] * _absDiff[i];
631 
632  // module = dir * W * rhoC / (4 * PI * R) * produit (reflex, diffraction, atmos)
633  mod = ((directivite * wSource * rhoc) * (1. / c1)).sqrt() * prodAbs.getModule();
634  // phase = exp(j K *L)
635  phase = _K.mult(_tabTYRays[i]->getLength()) + prodAbs.getPhase();
636 
637  _pressAcoustEff[i] = OSpectreComplex(mod, phase);
638  }
639 }
640 
642 {
643  OSpectre C; // facteur de coherence et son carre
644  OSpectre un = OSpectre(1.0);
645  OSpectreComplex zero = OSpectreComplex(0.0, 0.0);
646  OSpectreComplex sum1; //somme partielle
647  OSpectreComplex sum3;
648  OSpectre sum2; //somme partielle
649  OSpectre mod; // module et module au carre
650  const OSpectre K2 = _K * _K; // nombre d'onde au carre
651 
653  float incerRel = config->Anime3DSigma; // incertitude relative sur la taille du rayon au carree
654 
655  // constante pour la definition du facteur de coherence
656  double cst = (pow(2., 1. / 6.) - pow(2., -1. / 6.)) * (pow(2., 1. / 6.) - pow(2., -1. / 6.)) / 3.0 + incerRel * incerRel;
657  double totalRayLength;
658 
659  const int nbSources = _aproblem.nsources(); // nbr de sources de la scene
660  const int nbRecepteurs = _aproblem.nreceptors(); // nbr de recepteurs de la scene
661 
662  OTab2DSpectreComplex tabPressionAcoust(nbSources);
663 
664  for (int i = 0; i < nbSources; i++)
665  {
666  tabPressionAcoust[i].resize(nbRecepteurs);
667  }
668 
669  for (int i = 0; i < nbSources; i++) // boucle sur les sources
670  {
671  for (int j = 0; j < nbRecepteurs; j++) // boucle sur les recepteurs
672  {
673  sum1 = zero;
674  sum2 = zero;
675  sum3 = zero;
676 
677  for (int k = 0; k < _nbRays; k++) // boucle sur les rayons allant de la source au recepteur
678  {
679  const unsigned int source_id = _tabTYRays[k]->getSource_idx();
680  const unsigned int receptor_id = _tabTYRays[k]->getRecepteur_idx();
681 
682  if ( (source_id == i ) && (receptor_id == j) )
683  {
684  totalRayLength = _tabTYRays[k]->getLength();
685  mod = (_pressAcoustEff[k]).getModule();
686 
687  switch(config->Anime3DForceC)
688  {
689  case 0 :
690  C = 0.; // as energetic in defaultSolver
691  break;
692  case 1 :
693  C = 1.; // as "interference in defaultSolver
694  break;
695  default:
696  C = (K2 * totalRayLength * totalRayLength * (-1) * cst).exp();
697  }
698 
699  sum3 = _pressAcoustEff[k] * C;
700  sum1 = sum1 + sum3;
701  sum2 = sum2 + mod * mod * (un - C * C);
702  }
703  }
704 
705  // Be carefull sum of p!= p of sum
706  sum1 = sum1.getModule() * sum1.getModule();
707  tabPressionAcoust[i][j] = sum1 + sum2;
708  }
709  }
710 
711  return tabPressionAcoust;
712 }
713 
715 {
716 
717  ComputeAbsAtm();// Absorption atmosphrique pour tous les rayons
718 
719  ComputeAbsRefl(); // Absorption par reflexion pour tous les rayons
720 
721  ComputeAbsDiff(); // Attnuation par diffraction pour tous les rayons
722 
723  ComputePressionAcoustEff(); // Pression acoustique efficace pour tous les rayons
724 
725  return ComputePressionAcoustTotalLevel(); // Pression acoustique totale pour tous les couples source-recepteur
726 }
double distEndEvent
Distance between this event and the next event needed for calculating (for example, reflection after a diffraction)
Definition: acoustic_path.h:55
OSpectre computeFc(const double &dd, const double &dr)
static OSpectre getLambda(const double &c)
Definition: spectre.cpp:726
Describes building material.
Definition: entities.hpp:43
This class store data and provide functions to manipulate event in the acoustic context.
Definition: acoustic_path.h:39
The 3D vector class.
Definition: 3d.h:296
This file provides the top-level declaration for the acoustic problem model.
size_t nreceptors() const
Return the total number of receptors.
virtual ~TYANIME3DAcousticModel()
Destructor.
acoustic_event * next
Pointer to the next event in TYRay&#39;s list of events.
Definition: acoustic_path.h:63
std::vector< double > OTabDouble
Type for array of double.
const OSpectre & get_k() const
Get the wave number spectrum.
double compute_c() const
compute sound speed
double distFrom(const OPoint3D &pt) const
Computes the distance from this point to another.
Definition: 3d.cpp:409
tab_acoustic_path & _tabTYRays
Array of all TYMPAN rays.
This file provides class for solver configuration.
double distNextEvent
Distance between this event and the next one in TYRay&#39;s list of events.
Definition: acoustic_path.h:54
std::vector< OPoint3D > TabPoint3D
Definition: 3d.h:481
virtual OSpectre invMult(const double &coefficient=1.0) const
Division of a double constant by this spectrum.
Definition: spectre.cpp:446
void ComputeAbsAtm()
Calculation of the atmospheric absorption.
tympan::AcousticMaterialBase * material
Triangle material.
virtual std::vector< int > getIndexOfEvents(const int &eventType) const
return a tab of indexes of events of the same type in a ray you can merge two types of events (exampl...
OSpectre _K
Wave number.
int idFace2
Face id on which the event happens (diffraction only)
Definition: acoustic_path.h:61
int idFace1
Face id on which the event happens (reflection & diffraction)
Definition: acoustic_path.h:60
OTabSpectreComplex _absRefl
Array of absorptions by reflection per ray.
AtmosphericConditions & _atmos
Atmospheric conditions.
AcousticSource & source(source_idx idx)
Return a source by its id.
OTabSpectreComplex _absDiff
Array of absorptions by diffraction per ray.
std::vector< OSpectreComplex > OTabSpectreComplex
OTabSpectreComplex vector.
Definition: spectre.h:443
double _y
y coordinate of OCoord3D
Definition: 3d.h:281
double _x
x coordinate of OCoord3D
Definition: 3d.h:280
virtual Spectrum lwAdjustment(Vector direction, double distance)=0
< Pure virtual method to return directivity of the Source
OVector3D normal
Surface normal vector.
TYANIME3DAcousticModel(tab_acoustic_path &tabRayons, TYStructSurfIntersect *tabStruct, const tympan::AcousticProblemModel &aproblem, AtmosphericConditions &atmos)
Constructor.
virtual OSpectre toGPhy() const
Converts to physical quantity.
Definition: spectre.cpp:279
static const double Z_ref
reference impedance
Class to describe the acoustic problem.
const tympan::AcousticProblemModel & _aproblem
Problem data.
Spectrum spectrum
Associated spectrum.
Definition: entities.hpp:328
void ComputeAbsRefl()
Calculation of the absorption by reflection.
void ComputePressionAcoustEff()
Calculation of the effective acoustic pressure per ray and per frequency.
Class to define a segment.
Definition: 3d.h:1087
static OSpectre getOSpectreFreqExact()
Return the spectrum of the exact frequencies.
Definition: spectre.cpp:654
Describe surface intersections.
OPoint3D pos
Event position.
Definition: acoustic_path.h:53
boost::shared_ptr< SolverConfiguration > LPSolverConfiguration
Definition: interfaces.h:24
virtual double * getTabValReel()
Definition: spectre.h:112
size_t nsources() const
Return the total number of sources.
OSpectre getPhase() const
Definition: spectre.cpp:1129
SourceDirectivityInterface * directivity
Pointer to the source directivity.
Definition: entities.hpp:329
void ComputeAbsDiff()
Calculation of absorption by diffraction.
virtual ComplexSpectrum get_absorption(double incidence_angle, double length)
Destructor.
Definition: entities.hpp:55
acoustic_event * previous
Pointer to the previous event in TYRay&#39;s list of events.
Definition: acoustic_path.h:62
OSpectre compute_length_absorption(double length) const
Describes an acoustic source.
Definition: entities.hpp:315
The 3D point class.
Definition: 3d.h:484
virtual OSpectre mult(const OSpectre &spectre) const
Multiplication of two spectrums.
Definition: spectre.cpp:383
Class for the definition of atmospheric conditions.
virtual tab_acoustic_events & getEvents()
Get the events list of the ray.
virtual OSpectre exp(const double coef=1.0)
Compute e^(coef * spectre) of this spectrum.
Definition: spectre.cpp:537
double _z
z coordinate of OCoord3D
Definition: 3d.h:282
TYStructSurfIntersect * _tabSurfIntersect
Array containing all the informations relative to a site geometry and associated material to each fac...
Acoustic path.
Definition: acoustic_path.h:75
Store acoustic power values for different frequencies.
Definition: spectre.h:49
bool _useFresnelArea
Flag to take into account or not the Fresnel area.
#define M_PI
Pi.
Definition: color.cpp:24
std::vector< acoustic_path * > tab_acoustic_path
virtual ComplexSpectrum get_absorption(double incidence_angle, double length)
Destructor.
Definition: entities.cpp:50
Describes the ground material, a specific AcousticBuildingMaterial.
Definition: entities.hpp:68
OSpectre _lambda
Wavelength.
OTab2DSpectreComplex ComputeAcousticModel()
Complete calculation of the acoustic model ANIME3D.
OSpectre getModule() const
Definition: spectre.cpp:1139
OTabSpectreComplex _absAtm
Array of atmospheric absorptions per ray.
OTab2DSpectreComplex ComputePressionAcoustTotalLevel()
Calculation of the total quadratic pressure for a source/receptor - calculation with partial coherenc...
OTabSpectreComplex _pressAcoustEff
Array of effective acoustic pressure per ray.
static LPSolverConfiguration get()
Get the configuration.
Definition: config.cpp:99
std::vector< std::vector< OSpectreComplex > > OTab2DSpectreComplex
OTabSpectreComplex 2D array.
Definition: spectre.h:444