Code_TYMPAN  4.2.0
Industrial site acoustic simulation
TYAcousticModel.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) <2012-2014> <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 
16 #include <deque>
17 #include <list>
18 #include <cmath>
19 #include <algorithm>
20 #include "Tympan/core/defines.h"
27 #include "TYAcousticModel.h"
28 #include "TYSolver.h"
29 
31  : _useSol(true),
32  _useReflex(false),
33  _propaCond(0),
34  _interference(false),
35  _paramH(10.0),
36  _solver(solver)
37 {
39  _absoNulle.setType(SPECTRE_TYPE_ABSO); // Spectre d'absorption
40 }
41 
43 {
44 
45 }
46 
48 {
50  // Calcul avec sol reel
51  _useSol = config->UseRealGround;
52  // Calcul avec reflexion sur les parois verticales
53  _useReflex = config->UseReflection;
54  // Calcul en conditions favorables
55  _propaCond = config->PropaConditions;
56  // Definit l'atmosphere courante du site
57  double pression = config->AtmosPressure;
58  double temperature = config->AtmosTemperature;
59  double hygrometrie = config->AtmosHygrometry;
60 
61  pSolverAtmos = std::unique_ptr<AtmosphericConditions> ( new AtmosphericConditions(pression, temperature, hygrometrie) );
62  // Calcul avec interference
63  _interference = config->ModSummation;
64  // On calcul tout de suite le spectre de longueur d'onde
66  // Coefficient multiplicateur pour le calcul des reflexions supplementaires en condition favorable
67  _paramH = config->H1parameter;
68 }
69 
70 
71 void TYAcousticModel::compute( const std::deque<TYSIntersection>& tabIntersect, TYTrajet& trajet,
72  TabPoint3D& ptsTop, TabPoint3D& ptsLeft,
73  TabPoint3D& ptsRight )
74 {
75  bool vertical = true, horizontal = false;
76 
77  // Construction du rayon SR
78  OSegment3D rayon;
79  trajet.getPtSetPtRfromOSeg3D(rayon);
80  bool conditionFav = false;
81 
82  // Calcul des conditions de propagation suivant la direction du vent
84  assert(config->DSWindDirection >= 0 && config->DSWindDirection <= 360);
85 
86  double windRadian = DEGTORAD(config->DSWindDirection);
87  OVector3D windDirection = OVector3D(-sin(windRadian), -cos(windRadian), 0);
88  OVector3D propaDirection = rayon.toVector3D();
89  propaDirection._z = 0;
90  double angle = RADTODEG(acos(windDirection.dot(propaDirection)/(windDirection.norme()*propaDirection.norme())));//Angle always between 0-180
91  assert(180 >= angle >= 0);
92  assert(180 >= config->AngleFavorable >= 0);
93 
94  if (angle <= config->AngleFavorable)
95  {
96  conditionFav = true;
97  }
98  else
99  {
100  conditionFav = false;
101  }
102 
103 
104  // Recuperation de la source
105  tympan::AcousticSource& source = trajet.asrc;
106 
107  // Distance de la source au recepteur
108  double distance = trajet.getDistance();
109 
110  TYTabChemin& tabChemins = trajet.getChemins();
111 
112  // Calcul des parcours lateraux
113  // 1. Vertical
114  computeCheminsAvecEcran(rayon, source, ptsTop, vertical, tabChemins, distance, conditionFav);
115 
116  // 2. Horizontal gauche
117  computeCheminsAvecEcran(rayon, source, ptsLeft, horizontal, tabChemins, distance, conditionFav);
118 
119  // 3. Horizontal droite
120  computeCheminsAvecEcran(rayon, source, ptsRight, horizontal, tabChemins, distance, conditionFav);
121 
122  if (tabChemins.size() == 0)
123  {
124  computeCheminSansEcran(rayon, source, tabChemins, distance, conditionFav);
125  }
126 
127  // Calcul des reflexions si necessaire
128  computeCheminReflexion(tabIntersect, rayon, source, tabChemins, distance);
129 
130  // On calcule systematiquement le chemin a plat sans obstacle
131  // pour limiter l'effet d'ecran a basse frequence
132  TYTabChemin& tabCheminsSansEcran = trajet.getCheminsDirect();
133  computeCheminAPlat(rayon, source, tabCheminsSansEcran, distance);
134 
135  // Calcul la pression cumulee de tous les chemins au point de reception du trajet
136  solve(trajet);
137 
138  // Le calcul est fini pour ce trajet, on peut effacer les tableaux des chemins
139  tabChemins.clear();
140  tabCheminsSansEcran.clear();
141 }
142 
143 void TYAcousticModel::computeCheminAPlat(const OSegment3D& rayon, const tympan::AcousticSource& source, TYTabChemin& TabChemins, double distance) const
144 {
145  TYTabEtape tabEtapes;
146 
147  // Calcul de la pente moyenne sur le trajet source-recepteur
148  OSegment3D penteMoyenne;
149  meanSlope(rayon, penteMoyenne);
150 
151  // Etape directe Source-Recepteur
152  TYEtape etape1;
153  TYChemin chemin1;
154 
155  etape1._pt = rayon._ptA;
156  etape1._type = TYSOURCE;
157  etape1._Absorption = (source.directivity->lwAdjustment(OVector3D(rayon._ptA, rayon._ptB), rayon.longueur())).racine();
158 
159  chemin1.setType(CHEMIN_DIRECT);
160 
161  tabEtapes.push_back(etape1); // Ajout de l'etape directe
162  chemin1.setLongueur(distance); // Dans ce cas, la longueur = la distance source/recepteur
163  chemin1.setDistance(distance);
164  chemin1.calcAttenuation(tabEtapes, *pSolverAtmos);
165 
166  TabChemins.push_back(chemin1);
167  tabEtapes.clear(); // Vide le tableau des etapes
168 
169  // Liaison avec reflexion
170  // 1. Calcul du point de reflexion
171 
172  // Ajout du chemin reflechi
173  TYEtape etape2;
174  TYChemin chemin2;
175  chemin2.setType(CHEMIN_SOL);
176 
177  etape2.setPoint(rayon._ptA);
178  etape2._type = TYSOURCE;
179 
180  OPoint3D ptSym;
181  int symOK = 0;
182  if (penteMoyenne.longueur() > 0) // Si la pente moyenne est definie, on prend le point symetrique
183  {
184  symOK = penteMoyenne.symetrieOf(rayon._ptA, ptSym);
185  }
186 
187  if (symOK == 0) // Sinon on prend une simple symetrie par rapport a z
188  {
189  ptSym = rayon._ptA;
190  ptSym._z = 2 * penteMoyenne._ptA._z - ptSym._z;
191  }
192 
193  // Calcul du point de reflexion
194  OPoint3D ptReflex;
195  penteMoyenne.intersects(OSegment3D(ptSym, rayon._ptB), ptReflex, TYSEUILCONFONDUS);
196 
197  // 2. Etape avant la reflexion
198  OSegment3D seg1(rayon._ptA, ptReflex); // On part de la source vers le point de reflexion
199  double rr = seg1.longueur();
200 
201  // Directivite de la source
202  etape2._Absorption = (source.directivity->lwAdjustment(OVector3D(seg1._ptA, seg1._ptB), seg1.longueur())).racine();
203 
204  tabEtapes.push_back(etape2); // Ajout de l'etape avant reflexion
205 
206  // 3. Etape apres la reflexion
207 
208  TYEtape etape3;
209  etape3._pt = ptReflex;
210  etape3._type = TYREFLEXIONSOL;
211 
212  OSegment3D seg2 = OSegment3D(ptReflex, rayon._ptB);// Segment Point de reflexion->Point de reception
213  rr += seg2.longueur(); // Longueur parcourue sur le trajet reflechi
214 
215  if (_useSol)
216  {
217  etape3._Absorption = getReflexionSpectrumAt( seg1, rr, penteMoyenne, source);
218  }
219  else // Sol totalement reflechissant
220  {
221  etape3._Absorption = _absoNulle;
222  }
223 
224  tabEtapes.push_back(etape3); // Ajout de l'etape apres reflexion
225 
226  chemin2.setLongueur(rr);
227  chemin2.setDistance(distance);
228  chemin2.calcAttenuation(tabEtapes, *pSolverAtmos);
229  TabChemins.push_back(chemin2);
230 
231  tabEtapes.clear(); // Vide le tableau des etapes
232 }
233 
234 void TYAcousticModel::computeCheminSansEcran(const OSegment3D& rayon, const tympan::AcousticSource& source, TYTabChemin& TabChemin, double distance, bool conditionFav) const
235 {
236  /*
237  LE CALCUL POUR UN TRAJET SANS OBSTACLE COMPORTE UN CHEMIN DIRECT
238  ET DE UN (CONDITIONS NORMALES) A TROIS (CONDITIONS FAVORABLES) TRAJETS
239  REFLECHIS
240  */
241  OSegment3D seg1, seg2;
242  TYTabEtape tabEtapes;
243  double rr = 0.0; // Longueur du chemin reflechi
244 
245  // Calcul de la pente moyenne sur le trajet source-recepteur
246  OSegment3D penteMoyenne;
247  meanSlope(rayon, penteMoyenne);
248 
249 
250  // 1. Conditions homogenes sans vegetation
251  TYTabEtape Etapes;
252  addEtapesSol(rayon._ptA, rayon._ptB, penteMoyenne, source, true, true, Etapes, rr);
253 
254  // Ajout du chemin direct
255  TYChemin chemin;
256  chemin.setType(CHEMIN_DIRECT);
257  tabEtapes.push_back(Etapes[0]); // Ajout de l'etape directe
258  chemin.setLongueur(distance); // Dans ce cas, la longueur = la distance source/recepteur
259  chemin.setDistance(distance);
260  chemin.calcAttenuation(tabEtapes, *pSolverAtmos);
261  TabChemin.push_back(chemin) ; // (4) Ajout du chemin dans le tableau des chemins de la frequence
262 
263  tabEtapes.clear(); // Vide le tableau des etapes
264 
265  // Ajout du chemin reflechi
266  chemin.setType(CHEMIN_SOL);
267  tabEtapes.push_back(Etapes[1]); // Ajout de l'etape avant reflexion
268  tabEtapes.push_back(Etapes[2]); // Ajout de l'etape apres reflexion
269  chemin.setLongueur(rr);
270  chemin.setDistance(distance);
271  chemin.calcAttenuation(tabEtapes, *pSolverAtmos);
272  TabChemin.push_back(chemin);
273 
274  tabEtapes.clear(); // Vide le tableau des etapes
275 
276  // 2. Conditions faborables
277  // on s'assure que les reflexions n'iront pas se faire au dela de la source et
278  // du recepteur
279 
280  if ((_propaCond==1) || (_propaCond == 2 && conditionFav))
281  {
282  OPoint3D ptProj;
283  int res;
284  double hauteurA = 0.0, hauteurB = 0.0;
285  if (penteMoyenne.longueur() > 0)
286  {
287  res = penteMoyenne.projection(rayon._ptA, ptProj, TYSEUILCONFONDUS);
288  if (res == 0) {ptProj = penteMoyenne._ptA;}
289  hauteurA = rayon._ptA._z - ptProj._z;
290  res = penteMoyenne.projection(rayon._ptB, ptProj, TYSEUILCONFONDUS);
291  if (res == 0) {ptProj = penteMoyenne._ptB;}
292  hauteurB = rayon._ptB._z - ptProj._z;
293  }
294  else
295  {
296  ptProj = rayon._ptA;
297  ptProj._z = penteMoyenne._ptA._z;
298  hauteurA = rayon._ptA._z - ptProj._z;
299  ptProj = rayon._ptB;
300  ptProj._z = penteMoyenne._ptB._z;
301  hauteurB = rayon._ptB._z - ptProj._z;
302  }
303 
304  // On s'assure que le calcul en conditions favorable ne va pas provoquer
305  //des reflexions au dela de la source et du recepteur
306  if (rayon.longueur() > (10 * (hauteurA + hauteurB)))
307  {
308  // 2.1 Conditions favorables
309 
310  // En conditions favorables, le chemin possede deux points de reflexion supplementaires
311  // Le premier a n fois la hauteur du point de reception (n = 10 en general) a proximite
312  // de la source, le second est aussi a n fois la hauteur du point de reception; cote recepteur
313 
314 
315  // 2.1.1 Premier chemin
316  chemin.setType(CHEMIN_SOL);
317 
318  // Premiere etape
319  TYEtape etape; // Etape 1.1
320  etape._pt = rayon._ptA;
321  etape._type = TYSOURCE;
322 
323  // Calcul du point de reflexion
324  OPoint3D projA, projB;
325 
326  double distRef = _paramH * hauteurA; //distance =H1*hauteur de la source
327 
328  if (penteMoyenne.longueur() > 0)
329  {
330  res = penteMoyenne.projection(rayon._ptA, projA, TYSEUILCONFONDUS);
331  if (res == 0) {projA = penteMoyenne._ptA;}
332  }
333  else
334  {
335  projA = rayon._ptA;
336  projA._z = penteMoyenne._ptA._z;
337  }
338 
339  OVector3D vect(projA, penteMoyenne._ptB);
340  vect.normalize();
341  OPoint3D ptReflex(OVector3D(projA) + vect * distRef);
342 
343  seg1 = OSegment3D(rayon._ptA, ptReflex);
344 
345  rr = seg1.longueur(); // Longueur du chemin reflechi
346 
347  etape._Absorption = (source.directivity->lwAdjustment(OVector3D(rayon._ptA, rayon._ptB), rayon.longueur())).racine();
348 
349  tabEtapes.push_back(etape);
350 
351  // Deuxieme etape
352  etape._pt = ptReflex;
353  etape._type = TYREFLEXIONSOL;
354 
355  seg2 = OSegment3D(ptReflex, rayon._ptB);
356  rr = rr + seg2.longueur(); // Longueur totale du chemin reflechi
357 
358  // Prise en compte du terrain au point de reflexion
359  // 3 cas :
360  if (_useSol)
361  {
362  etape._Absorption = getReflexionSpectrumAt( seg1, rr, penteMoyenne, source );
363  }
364  else // Calcul sol reflechissant
365  {
366  etape._Absorption = _absoNulle;
367  }
368 
369  tabEtapes.push_back(etape);
370 
371  // Ajout du premier chemin au trajet
372  chemin.setLongueur(rr);
373  chemin.setDistance(distance);
374  chemin.calcAttenuation(tabEtapes, *pSolverAtmos);
375  TabChemin.push_back(chemin) ; // (2) Ajout du chemin dans le tableau des chemins de la frequence
376 
377  tabEtapes.clear(); // On s'assure que le tableau des etapes est vide
378 
379  // 2.1.2. Deuxieme chemin
380  chemin.setType(CHEMIN_SOL);
381 
382  // Premiere etape
383  etape._pt = rayon._ptA;
384  etape._type = TYSOURCE;
385 
386  // Calcul du point de reflexion
387  if (penteMoyenne.longueur() > 0)
388  {
389  res = penteMoyenne.projection(rayon._ptB, projB, TYSEUILCONFONDUS);
390  if (res == 0) {projB = penteMoyenne._ptB;}
391  }
392  else
393  {
394  projB = rayon._ptB;
395  projB._z = penteMoyenne._ptB._z;
396  }
397 
398  distRef = _paramH * hauteurB;
399  ptReflex = OPoint3D(OVector3D(projB) - vect * distRef);
400 
401  seg1 = OSegment3D(rayon._ptA, ptReflex);
402  rr = seg1.longueur(); // Longueur du chemin reflechi
403 
404  etape._Absorption = (source.directivity->lwAdjustment(OVector3D(rayon._ptA, rayon._ptB), rayon.longueur())).racine();
405 
406  tabEtapes.push_back(etape);
407 
408  // Deuxieme etape
409  etape._pt = ptReflex;
410  etape._type = TYREFLEXIONSOL;
411 
412  seg2 = OSegment3D(ptReflex, rayon._ptB);
413  rr = rr + seg2.longueur(); // Longueur totale du chemin reflechi
414 
415  // Prise en compte du terrain au point de reflexion
416 
417  // 3 cas :
418  if (_useSol)
419  {
420  etape._Absorption = getReflexionSpectrumAt( seg1, rr, penteMoyenne, source );
421  }
422  else // Calcul sol reflechissant
423  {
424  etape._Absorption = _absoNulle;
425  }
426 
427 
428  tabEtapes.push_back(etape);
429 
430  // Ajout du deuxieme chemin
431  chemin.setDistance(distance);
432  chemin.setLongueur(rr);
433  chemin.calcAttenuation(tabEtapes, *pSolverAtmos);
434  TabChemin.push_back(chemin) ; // (3) Ajout du chemin dans le tableau des chemins de la frequence
435  tabEtapes.clear();
436  Etapes.clear();
437 
438  }
439  }
440 }
441 
442 
443 bool TYAcousticModel::computeCheminsAvecEcran(const OSegment3D& rayon, const tympan::AcousticSource& source, const TabPoint3D& pts, const bool vertical, TYTabChemin& TabChemins, double distance, bool conditionFav) const
444 {
445  /* ============================================================================================================
446  07/03/2005 : Suppression du calcul ddes pentes moyennes avant et apres l'obstacle.
447  On utilise uniquement la pente moyenne totale qui est prise comme la projection au sol de la
448  source et du recepteur.
449  ==============================================================================================================*/
450  if (pts.size() <= 1) { return false; }
451 
452  double rr = 0.0; // Longueur parcourue lors de la reflexion sur le sol
453 
454  OSegment3D penteMoyenneTotale;//, penteMoyenneAvant, penteMoyenneApres;
455  OPoint3D firstPt(pts[1]);
456  OPoint3D lastPt(pts[pts.size() - 1]);
457 
458  TYTabEtape tabTwoReflex;
459  double longTwoReflex = 0.0 ;
460 
461  TYTabEtape tabOneReflexBefore;
462  double longOneReflexBefore = 0.0;
463 
464  TYTabEtape tabOneReflexAfter;
465  double longOneReflexAfter = 0.0;
466 
467  TYTabEtape tabNoReflex;
468  double longNoReflex = 0.0;
469 
471  meanSlope(rayon, penteMoyenneTotale);
472 
473  // /*--- AVANT L'OBSTACLE ---*/
474 
475  TYTabEtape Etapes;
476  OSegment3D segCourant(rayon._ptA, firstPt);
477  double tempLong = segCourant.longueur();
478 
479  bool bCheminOk = addEtapesSol(rayon._ptA, firstPt, penteMoyenneTotale, source, true, false, Etapes, rr); // Calcul des etapes avant l'obstacle
480 
481  // Si le parcours du rayon rencontre le sol (hors des reflexions), on ne continue pas la creation du chemin
482  if (!bCheminOk) { return true; }
483 
484  tabNoReflex.push_back(Etapes[0]); // Ajoute le trajet direct au chemin sans reflexion
485  longNoReflex += tempLong;
486 
487  tabOneReflexAfter.push_back(Etapes[0]); // Ajoute le trajet direct au chemin une reflexion apres
488  longOneReflexAfter += tempLong;
489 
490  tabOneReflexBefore.push_back(Etapes[1]); // Ajoute les trajets reflechis
491  tabOneReflexBefore.push_back(Etapes[2]);
492  longOneReflexBefore += rr;
493 
494  tabTwoReflex.push_back(Etapes[1]); // Ajoute les trajets reflechis
495  tabTwoReflex.push_back(Etapes[2]);
496  longTwoReflex += rr;
497 
498  Etapes.clear(); // Efface le contenu de Etapes
499 
500  /*--- CONTOURNEMENT DE L'OBSTACLE ---*/
501 
502  double epaisseur = 0.0;
503  TYEtape Etape;
504 
505  for (unsigned int i = 1; i < pts.size() - 1; i++)
506  {
507  epaisseur += (OSegment3D(pts[i], pts[i + 1])).longueur();
508 
509  Etape._pt = pts[i];
510  Etape._type = TYDIFFRACTION;
511  Etape._Absorption = _absoNulle;
512 
513  tabTwoReflex.push_back(Etape);
514  tabOneReflexBefore.push_back(Etape);
515  tabOneReflexAfter.push_back(Etape);
516  tabNoReflex.push_back(Etape);
517  }
518 
519  longNoReflex += epaisseur;
520  longOneReflexAfter += epaisseur;
521  longOneReflexBefore += epaisseur;
522  longTwoReflex += epaisseur;
523 
524  /*--- APRES L'OBSTACLE ---*/
525  segCourant = OSegment3D(lastPt, rayon._ptB);
526  tempLong = segCourant.longueur();
527 
528  addEtapesSol(lastPt, rayon._ptB, penteMoyenneTotale, source, false, true, Etapes, rr);
529 
530  tabNoReflex.push_back(Etapes[0]);
531  longNoReflex += tempLong;
532 
533  tabOneReflexBefore.push_back(Etapes[0]);
534  longOneReflexBefore += tempLong;
535 
536  tabOneReflexAfter.push_back(Etapes[1]);
537  tabOneReflexAfter.push_back(Etapes[2]);
538  longOneReflexAfter += rr;
539 
540  tabTwoReflex.push_back(Etapes[1]);
541  tabTwoReflex.push_back(Etapes[2]);
542  longTwoReflex += rr;
543 
544  Etapes.clear();
545 
546  /*--- PRISE EN COMPTE DE L'EFFET DE DIFFRACTION APPORTE PAR L'ECRAN SUR CHAQUE CHEMIN ---*/
547 
548  OSpectre Diff;
549  bool bDiffOk = true; // Sera mis a false si la difference de marche devient <=0
550 
551  Etape._pt = rayon._ptB;
552  Etape._Absorption = _absoNulle;
553 
554  // 4.1. Chemin sans reflexion
555  Diff = calculAttDiffraction(rayon, penteMoyenneTotale, false, longNoReflex, epaisseur, vertical, false, bDiffOk, conditionFav);
556  Etape._Attenuation = Diff;
557  tabNoReflex.push_back(Etape);
558 
559  // 4.2. Chemin 2 reflexions
560  Diff = calculAttDiffraction(rayon, penteMoyenneTotale, false, longTwoReflex, epaisseur, vertical, false, bDiffOk, conditionFav);
561  Etape._Attenuation = Diff;
562  tabTwoReflex.push_back(Etape);
563 
564  // 4.3. Chemin une reflexion avant
565  Diff = calculAttDiffraction(rayon, penteMoyenneTotale, true, longOneReflexBefore, epaisseur, vertical, false, bDiffOk, conditionFav);
566  Etape._Attenuation = Diff;
567  tabOneReflexBefore.push_back(Etape);
568 
569  // 4.4. Chemin une reflexion apres
570  Diff = calculAttDiffraction(rayon, penteMoyenneTotale, true, longOneReflexAfter, epaisseur, vertical, true, bDiffOk,conditionFav);
571  Etape._Attenuation = Diff;
572  tabOneReflexAfter.push_back(Etape);
573 
574  /*--- AJOUT DES CHEMINS AU au tableau des chemins ---*/
575 
576  TYChemin chemin;
577  chemin.setType(CHEMIN_ECRAN);
578  chemin.setDistance(distance);
579 
580  // Chemin reflexion au sol avant et apres l'obstacle
581  chemin.setLongueur(longTwoReflex);
582  chemin.calcAttenuation(tabTwoReflex, *pSolverAtmos);
583  TabChemins.push_back(chemin);
584 
585  // Chemin avec une reflexion avant
586  chemin.setLongueur(longOneReflexBefore);
587  chemin.calcAttenuation(tabOneReflexBefore, *pSolverAtmos);
588  TabChemins.push_back(chemin);
589 
590  // Chemin avec une reflexion apres
591  chemin.setLongueur(longOneReflexAfter);
592  chemin.calcAttenuation(tabOneReflexAfter, *pSolverAtmos);
593  TabChemins.push_back(chemin);
594 
595  //Chemin sans reflexion sur le sol
596  chemin.setLongueur(longNoReflex);
597  chemin.calcAttenuation(tabNoReflex, *pSolverAtmos);
598  TabChemins.push_back(chemin);
599 
600  tabTwoReflex.clear();
601  tabOneReflexBefore.clear();
602  tabOneReflexAfter.clear();
603  tabNoReflex.clear();
604  Etapes.clear();
605 
606 
607  return true;
608 }
609 
610 bool TYAcousticModel::addEtapesSol(const OPoint3D& ptDebut, const OPoint3D& ptFin, const OSegment3D& penteMoyenne, const tympan::AcousticSource& source, const bool& fromSource, const bool& toRecepteur, TYTabEtape& Etapes, double& rr) const
611 {
612  /* =========================================================================================
613  0001 : 10/03/2005 : Modification du calcul des points symetriques
614  ========================================================================================= */
615  bool res = true;
616 
617  OSegment3D segDirect(ptDebut, ptFin);
618  OPoint3D ptSym, ptReflex, pt3;
619 
620  TYEtape EtapeCourante;
621 
622  // === CONSTRUCTION DU TRAJET DIRECT ptDebut-ptFin
623  EtapeCourante._pt = ptDebut;
624 
625  if (fromSource) // Si on part d'une source, on tient compte de la directivite de celle-ci
626  {
627  EtapeCourante._type = TYSOURCE;
628  EtapeCourante._Absorption = (source.directivity->lwAdjustment(OVector3D(ptDebut, ptFin), ptDebut.distFrom(ptFin))).racine();
629  }
630  else
631  {
632  EtapeCourante._type = TYDIFFRACTION;
633  EtapeCourante._Absorption = _absoNulle;
634  }
635 
636  Etapes.push_back(EtapeCourante);
637 
638  // === CONSTRUCTION DU TRAJET REFLECHI
639 
640  // Construction du plan correspondant a la pente moyenne.
641  OPoint3D pt1(penteMoyenne._ptA);
642  OPoint3D pt2(penteMoyenne._ptB);
643  pt3._z = pt1._z;
644 
645  if (pt2._x != pt1._x)
646  {
647  pt3._y = pt1._y + 1;
648  pt3._x = (pt1._y - pt2._y) * (pt3._y - pt1._y) / (pt2._x - pt1._x) + (pt1._x);
649  }
650  else
651  {
652  if (pt1._y != pt2._y)
653  {
654  pt3._x = pt1._x + 1;
655  pt3._y = (pt2._x - pt1._x) * (pt3._x - pt1._x) / (pt1._y - pt2._y) + (pt1._y);
656  }
657  else // pt1 et pt2 sont confondus on decale pt2 (on construit un plan horizontal)
658  {
659  pt2._x = pt1._x + 1;
660  pt2._y = pt1._y - 1;
661  pt3._y = pt1._y + 1;
662  pt3._x = (pt1._y - pt2._y) * (pt3._y - pt1._y) / (pt2._x - pt1._x) + (pt1._x);
663  }
664  }
665 
666  OPlan planPenteMoyenne(pt1, pt2, pt3);
667 
668  // On construit le segment correspondant a la projection des points sur le plan
669  OPoint3D ptDebutProj; // PtDebut projete sur le plan
670  planPenteMoyenne.intersectsSegment(OPoint3D(ptDebut._x, ptDebut._y, +100000), OPoint3D(ptDebut._x, ptDebut._y, -100000), ptDebutProj);
671 
672  OPoint3D ptFinProj; // PtFin projete sur le plan
673  planPenteMoyenne.intersectsSegment(OPoint3D(ptFin._x, ptFin._y, +100000), OPoint3D(ptFin._x, ptFin._y, -100000), ptFinProj);
674 
675  OSegment3D segPente(ptDebutProj, ptFinProj);
676 
677 
678  // Liaison avec reflexion
679  // Calcul du point de reflexion
680  int symOK = 0;
681 
682  EtapeCourante._pt = ptDebut;
683  if (segPente.longueur() > 0) // Si la pente moyenne est definie, on prend le point symetrique
684  {
685  symOK = segPente.symetrieOf(ptDebut, ptSym);
686  }
687 
688  if ( symOK == 0 ) // Sinon on prend une simple symetrie par rapport a z
689  {
690  ptSym = ptDebut;
691  ptSym._z = 2 * segPente._ptA._z - ptSym._z;
692  }
693 
694  int result = segPente.intersects(OSegment3D(ptSym, ptFin), ptReflex, TYSEUILCONFONDUS);
695 
696  if (result == 0) // Si pas d'intersection trouvee, on passe au plan B
697  {
698  OPoint3D ptSymFin;
699  symOK = 0;
700 
701  if (segPente.longueur() > 0) // Si la pente moyenne est definie, on prend le point symetrique
702  {
703  symOK = segPente.symetrieOf(ptFin, ptSymFin);
704  }
705 
706  if ( symOK == 0 ) // Sinon on prend une simple symetrie par rapport a z
707  {
708  ptSymFin = ptFin;
709  ptSymFin._z = 2 * segPente._ptB._z - ptSymFin._z;
710  }
711 
712  // Calcul du coefficient lie au rapport des hauteurs
713  // Distance de du point symetrique a la droite de pente moyenne
714  double d1 = ptSym.distFrom(segPente._ptA);
715  double d2 = ptSymFin.distFrom(segPente._ptB);
716 
717  double coefH = (d1 + d2) != 0 ? d1 / (d2 + d1) : 0.0;
718 
719  // Calcul des coordommees du point de reflexion
720  ptReflex._x = (ptSymFin._x - ptSym._x) * coefH + ptSym._x;
721  ptReflex._y = (ptSymFin._y - ptSym._y) * coefH + ptSym._y;
722  ptReflex._z = (ptSymFin._z - ptSym._z) * coefH + ptSym._z;
723  }
724 
725 
726  // On traie deux cas :
727  // 1/ le depart et l'arrivee ne sont pas sur le sol
728  // 2/ le depart ou l'arrivee sont sur le sol et sont soit la source, soit le recepteur
729  // 3/ ni 1, ni 2, dans ce cas, les segments ne sont pas produits
730  if ((ptSym.distFrom(ptReflex) > TYSEUILCONFONDUS) && (ptFin.distFrom(ptReflex) > TYSEUILCONFONDUS))
731  {
732  // Etape avant la reflexion
733  OSegment3D seg1(ptDebut, ptReflex);
734 
735  rr = seg1.longueur();
736 
737  if (fromSource) // Si on part d'une source, on tient compte de la directivite de celle-ci
738  {
739  EtapeCourante._type = TYSOURCE;
740  EtapeCourante._Absorption = (source.directivity->lwAdjustment(OVector3D(ptDebut, ptReflex), ptDebut.distFrom(ptReflex))).racine();
741  }
742  else
743  {
744  EtapeCourante._type = TYDIFFRACTION;
745  EtapeCourante._Absorption = _absoNulle;
746  }
747 
748  Etapes.push_back(EtapeCourante);
749 
750  // Etape Apres reflexion
751  EtapeCourante._pt = ptReflex;
752  EtapeCourante._type = TYREFLEXIONSOL;
753 
754  OSegment3D seg2 = OSegment3D(ptReflex, ptFin);// Segment Point de reflexion->Point de reception
755  rr = rr + seg2.longueur(); // Longueur parcourue sur le trajet reflechi
756 
757  // 3 cas :
758  if (_useSol)
759  {
760  EtapeCourante._Absorption = getReflexionSpectrumAt( seg1, rr , segPente, source);
761  }
762  else // Sol totalement reflechissant
763  {
764  EtapeCourante._Absorption = _absoNulle;
765  }
766 
767  Etapes.push_back(EtapeCourante);
768  }
769  else if (fromSource || toRecepteur)
770  {
771  // Etape avant la reflexion
772  OSegment3D seg1(ptDebut, ptReflex);
773  rr = seg1.longueur();
774 
775  EtapeCourante._Absorption = _absoNulle;
776 
777  Etapes.push_back(EtapeCourante);
778 
779  // Etape Apres reflexion
780  EtapeCourante._pt = ptReflex;
781  EtapeCourante._type = TYREFLEXIONSOL;
782 
783  OSegment3D seg2 = OSegment3D(ptReflex, ptFin);// Segment Point de reflexion->Point de reception
784  rr = rr + seg2.longueur(); // Longueur parcourue sur le trajet reflechi
785 
786  // 3 cas :
787  if (_useSol)
788  {
789  EtapeCourante._Absorption = getReflexionSpectrumAt( seg1, rr, segPente, source );
790  }
791  else // Sol totalement reflechissant
792  {
793  EtapeCourante._Absorption = _absoNulle;
794  }
795 
796  Etapes.push_back(EtapeCourante);
797  }
798  else
799  {
800  Etapes.clear();
801  res = false;
802  }
803 
804  return res;
805 }
806 
807 void TYAcousticModel::computeCheminReflexion( const std::deque<TYSIntersection>& tabIntersect, const OSegment3D& rayon,
808  const tympan::AcousticSource& source, TYTabChemin& TabChemins,
809  double distance ) const
810 {
811  if (!_useReflex) { return; }
812 
813  OSegment3D segInter;
814  OSegment3D rayonTmp;
815  OPoint3D ptSym;
816  OSpectre SpectreAbso;
817 
818  OSegment3D seg; // Segment source image->recepteur
819  OSegment3D segMontant; // Segment source-> point de reflexion
820  OSegment3D segDescendant; // Segment point de reflexion->recepteur
821 
822  OPoint3D pt; // Point d'intersection
823 
824  size_t nbFaces = tabIntersect.size();
825 
826  // Pour chaque face test de la reflexion
827  for (unsigned int i = 0; i < nbFaces; i++)
828  {
829  TYSIntersection inter = tabIntersect[i];
830 
831  // Si la face ne peut interagir on passe a la suivante
832  if ( (!inter.isInfra) || !(inter.bIntersect[1]) ) { continue; }
833 
834  segInter = inter.segInter[1];
835 
836  // Calcul du symetrique de A par rapport au segment
837  segInter.symetrieOf(rayon._ptA, ptSym); // On ne s'occupe pas de la valeur de retour de cette fonction
838  seg._ptA = ptSym;
839  seg._ptB = rayon._ptB; // Segment source image->recepteur
840 
841  if (segInter.intersects(seg, pt, TYSEUILCONFONDUS))
842  {
843  // Construction du segment source->pt de reflexion
844  segMontant._ptA = rayon._ptA;
845  segMontant._ptB = pt;
846  // Construction du segment pt de reflexion-> recepteur
847  segDescendant._ptA = segMontant._ptB;
848  segDescendant._ptB = rayon._ptB;
849 
850  bool intersect = false;
851  size_t j = 0;
852 
853  // Si on traverse un autre ecran, qui peut etre de la topo, le chemin de reflexion n'est pas pris en compte
854  while ((j < nbFaces) && (!intersect))
855  {
856  if (j == i)
857  {
858  j++;
859  continue; // Si la face ne peut interagir on passe a la suivante
860  }
861 
862  segInter = tabIntersect[j].segInter[1];
863 
864  // On teste si segInter intersecte le segment montant ou
865  // le segment descendant dans le plan global).
866  // point bidon seul vaut l'intersection ou non
867  if ((segInter.intersects(segMontant, pt, TYSEUILCONFONDUS)) ||
868  (segInter.intersects(segDescendant, pt, TYSEUILCONFONDUS)))
869  {
870  //intersection trouvee, la boucle peut etre interrompue;
871  intersect = true;
872  break;
873  }
874 
875  j++;
876  }
877 
878  // Si le chemin reflechi n'est pas coupe, on peut calculer la reflexion
879  if (!intersect)
880  {
881  SpectreAbso = dynamic_cast<tympan::AcousticBuildingMaterial*>(inter.material)->asEyring();
882  SpectreAbso = SpectreAbso.mult(-1.0).sum(1.0);
883 
887  //TYAcousticCylinder* pCyl = NULL;
888  //if (pSurfaceGeoNode) { pCyl = dynamic_cast<TYAcousticCylinder*>(pSurfaceGeoNode->getParent()); }
889  //rayonTmp = rayon * SI.matInv;
890  //if (pCyl)
891  //{
892  // OPoint3D centre(pCyl->getCenter());
893  // OVector3D SC(rayonTmp._ptA, centre);
894  // OVector3D CR(centre, rayonTmp._ptB);
895  // double diametre = pCyl->getDiameter();
896  // double dSC = SC.norme(); // Norme du vecteur
897  // double phi = SC.angle(CR);
898 
899  // SpectreAbso = SpectreAbso.mult(diametre * sin(phi / 2) / (2 * dSC));
900  //}
901 
902  // Premiere etape : du debut du rayon au point de reflexion sur la face
903  TYTabEtape tabEtapes;
904 
905  double rr = segMontant.longueur() + segDescendant.longueur();
906 
907  TYEtape Etape;
908  Etape._pt = rayon._ptA;
909  Etape._type = TYSOURCE;
910  Etape._Absorption = (source.directivity->lwAdjustment(OVector3D(segMontant._ptA, segMontant._ptB), segMontant.longueur())).racine();
911 
912  tabEtapes.push_back(Etape);
913 
914  // Deuxieme etape : du point de reflexion a la fin du rayon
915  Etape._pt = segDescendant._ptA;
916  Etape._type = TYREFLEXION;
917  Etape._Absorption = SpectreAbso;
918 
919  tabEtapes.push_back(Etape);
920 
921  TYChemin Chemin;
922  Chemin.setType(CHEMIN_REFLEX);
923  Chemin.setLongueur(rr);
924  Chemin.setDistance(distance);
925  Chemin.calcAttenuation(tabEtapes, *pSolverAtmos);
926 
927  TabChemins.push_back(Chemin); // Mise en place du chemin dans la table des chemins
928  tabEtapes.clear();
929  }
930  }
931  }
932 }
933 
934 
935 
936 OSpectre TYAcousticModel::calculC(const double& epaisseur) const
937 {
938  // C = (1 + (5*lambda/epaisseur)i¿½) / (1/3 + (5*lambda/epaisseur)i¿½)
939 
941  OSpectre opLambda;
942 
943  if (epaisseur < 1.0E-2)
944  {
945  C .setDefaultValue(1.0);
946  }
947  else
948  {
949  const double unTiers = 1.0 / 3.0;
950 
951  opLambda = _lambda.mult(5.0 / epaisseur); // (5*lambda/e)
952  opLambda = opLambda.mult(opLambda); // (5*lambda/e)i¿½
953 
954  C = opLambda.sum(1.0); // 1 + (5*lambda/e)i¿½
955  C = C.div(opLambda.sum(unTiers)); // (1 + (5*lambda/e)i¿½) / (1/3 + (5*lambda/epaisseur)i¿½)
956  }
957 
958  C.setType(SPECTRE_TYPE_AUTRE); // Ni Attenuation, ni Absorption
959 
960  return C;
961 }
962 
963 OSpectre TYAcousticModel::calculAttDiffraction(const OSegment3D& rayon, const OSegment3D& penteMoyenne, const bool& miroir, const double& re, const double& epaisseur, const bool& vertical, const bool& avantApres, bool& bDiffOk, bool conditionFav) const
964 {
965  double rd;
966 
967  OSpectre s;
968 
969  OSpectre C = calculC(epaisseur); // Facteur correctif lie a l'epaisseur de l'ecran
970 
971  // Si le chemin comporte une reflexion sur le sol (et une seule), on prend le trajet source image recepteur
972  if (miroir)
973  {
974  OPoint3D ptSym;
975  if (!avantApres) // On est avant l'obstacle, on calcul le symetrique du point A
976  {
977  if (penteMoyenne.longueur() > 0) // On peut calculer la symetrie
978  {
979  penteMoyenne.symetrieOf(rayon._ptA, ptSym);
980  }
981  else // On se contente de prendre le symetrique par rapport a z
982  {
983  ptSym = rayon._ptA;
984  ptSym._z = 2 * penteMoyenne._ptA._z - ptSym._z;
985  }
986 
987  OSegment3D segReflex(ptSym, rayon._ptB);
988  rd = segReflex.longueur();
989  }
990  else // On est apres l'obstacle, on calcule le symetrique du point B
991  {
992  if (penteMoyenne.longueur() > 0) // On peut calculer la symetrie
993  {
994  penteMoyenne.symetrieOf(rayon._ptB, ptSym);
995  }
996  else // On se contente de prendre le symetrique par rapport a z
997  {
998  ptSym = rayon._ptB;
999  ptSym._z = 2 * penteMoyenne._ptB._z - ptSym._z;
1000  }
1001 
1002  OSegment3D segReflex(rayon._ptA, ptSym);
1003  rd = segReflex.longueur();
1004  }
1005  }
1006  else
1007  {
1008  rd = rayon.longueur();
1009  }
1010 
1011  // Dans le cas du calcul en conditions favorables on considere un trajet direct courbe
1012  if ((((_propaCond==1) || (_propaCond == 2 && conditionFav))) && (vertical))
1013  {
1014  double gamma = rd * 8.0;
1015  gamma = (gamma > 1000 ? gamma : 1000.0);// Rayon minimum 1000 metres
1016 
1017  double alpha = 2 * asin(rd / (2 * gamma));
1018 
1019  rd = gamma * alpha; // Longueur de l'arc de rayon gamma passant par les points extreme du segment de longueur rd
1020  }
1021 
1022  double delta = re - rd ; // difference de marche
1023  delta = delta <= 0 ? 0.0 : delta;
1024 
1025  // Attenuation apportee par la diffraction = sqrt(3 + (40 * C * delta)/lambda)
1026 
1027  s = _lambda.invMult(40 * delta); // =40*delta/lambda
1028  s = s.mult(C); // 40*delta*C/lambda
1029  s = s.sum(3.0);
1030 
1031  // Si la diffraction a lieu dans le plan vertical (arete horizontale),
1032  // les attenuations minimales et maximales sont limitees respectivement
1033  // a 0 dB et 20 ou 25 dB (selon que l'on est en ecran mince ou epais).
1034  if (vertical)
1035  {
1036  s = limAttDiffraction(s, C);
1037  }
1038 
1040 
1041  return s.racine();
1042 }
1043 
1045 {
1048 
1049  double lim20dB = pow(10.0, (20.0 / 10.0));
1050  double lim25dB = pow(10.0, (25.0 / 10.0));
1051  double lim0dB = pow(10.0, (0.0 / 10.0));
1052 
1053  double valeur;
1054 
1055  for (unsigned int i = 0 ; i < sNC.getNbValues() ; i++)
1056  {
1057  valeur = sNC.getTabValReel()[i];
1058 
1059  valeur = valeur < lim0dB ? lim0dB : valeur ; // L'attenuation ne peut etre inferieure a 1
1060 
1061  if ((C.getTabValReel()[i] - 1) <= 1e-2) // Comportement ecran mince
1062  {
1063  valeur = valeur > lim20dB ? lim20dB : valeur;
1064  }
1065  else // Comportement ecran epais ou multiple
1066  {
1067  valeur = valeur > lim25dB ? lim25dB : valeur;
1068  }
1069 
1070  s.getTabValReel()[i] = valeur;
1071 
1072  }
1073 
1074  return s;
1075 }
1076 
1078 {
1079  const double PIM4 = 4.0 * M_PI;
1080 
1081  double rD2 = trajet.getDistance();
1082 
1083  rD2 = rD2 * rD2 ;
1084 
1085  double divGeom = pSolverAtmos->compute_z() / (PIM4 * rD2);
1086 
1087  OSpectre& SLp = trajet.getSpectre();
1088 
1089  // W.rho.c / (4pi*rdi¿½)
1090  SLp = trajet.asrc.spectrum.mult(divGeom);
1091 
1092  // (W.rho.c/4.pi.Rdi¿½)*Attenuations du trajet
1093  if (_interference)
1094  {
1095  SLp = SLp.mult(trajet.getPInterference(*pSolverAtmos));
1096  }
1097  else
1098  {
1099  SLp = SLp.mult(trajet.getPEnergetique(*pSolverAtmos));
1100  }
1101  SLp.setType(SPECTRE_TYPE_LP); //Le spectre au point est bien un spectre de pression !
1102 
1103  return true;
1104 }
1105 
1106 OSpectreComplex TYAcousticModel::getReflexionSpectrumAt(const OSegment3D& incident, double length, const OSegment3D& segPente, const tympan::AcousticSource& source) const
1107 {
1108  OSpectreComplex spectre;
1109 
1110  // Search for material at reflexion point
1111  // Set position of ray at the same high as the source
1112  vec3 start = OPoint3Dtovec3(incident._ptB);
1113  start.z = (decimal)incident._ptA._z;
1114  Ray ray1( start, vec3(0., 0., -1.) );
1115  ray1.setMaxt ( 20000 );
1116 
1117  std::list<Intersection> LI;
1118 
1119  static_cast<double>( _solver.getScene()->getAccelerator()->traverse( &ray1, LI ) );
1120 
1121  if(LI.empty())
1122  {
1123  start.z = (decimal)(incident._ptB._z + 1000);
1124  Ray ray1( start, vec3(0., 0., -1.) );
1125  ray1.setMaxt ( 20000 );
1126  static_cast<double>( _solver.getScene()->getAccelerator()->traverse(&ray1, LI));
1127  }
1128 
1129  assert(!LI.empty());
1130  unsigned int indexFace = LI.begin()->p->getPrimitiveId();
1131  tympan::AcousticMaterialBase *mat = _solver.getTabPolygon()[indexFace].material;
1132 
1133  // Avoid cases where the reflexion point is below a "floating" volumic source
1134  while(_solver.getTabPolygon()[indexFace].is_infra() && source.volume_id == _solver.getTabPolygon()[indexFace].volume_id )
1135  {
1136  start.z = (decimal)min(min(_solver.getTabPolygon()[indexFace].tabPoint[0]._z, _solver.getTabPolygon()[indexFace].tabPoint[1]._z),
1137  _solver.getTabPolygon()[indexFace].tabPoint[2]._z) ;
1138  Ray ray(start, vec3(0,0,-1));
1139  ray.setMaxt ( 20000 );
1140  std::list<Intersection> LI2;
1141  static_cast<double>( _solver.getScene()->getAccelerator()->traverse( &ray, LI2 ) );
1142  // assert( !LI2.empty() );
1143  if (LI2.empty())
1144  break;
1145  indexFace = LI2.begin()->p->getPrimitiveId();
1146  mat = _solver.getTabPolygon()[indexFace].material;
1147  }
1148 
1149  // Angle estimation
1150  OVector3D direction(incident._ptA, incident._ptB);
1151  direction.normalize();
1152 
1153  // This is kept commented for the time being, even though it's the best solution
1154  //double angle = ( direction * -1 ).angle( _solver.getTabPolygon()[indexFace].normal );
1155  //angle = ABS(M_PI/2. - angle);
1156  double angle = (direction*-1).angle(OVector3D(incident._ptB, segPente._ptA));
1157  // Compute reflexion spectrum
1158  spectre = mat->get_absorption(angle, length);
1159 
1160  return spectre;
1161 }
1162 
1163 void TYAcousticModel::meanSlope(const OSegment3D& director, OSegment3D& slope) const
1164 {
1165  // Search for primitives under the two segment extremities
1166 
1167  // To begin : initialize slope
1168  slope = director;
1169 
1170  // first one
1171  OPoint3D pt = director._ptA;
1172  pt._z += 1000.;
1173  vec3 start = OPoint3Dtovec3(pt);
1174  Ray ray1( start, vec3(0., 0., -1.) );
1175 
1176  std::list<Intersection> LI;
1177 
1178  double distance1 = static_cast<double>( _solver.getScene()->getAccelerator()->traverse( &ray1, LI ) );
1179  assert( distance1 > 0. );
1180  assert(!LI.empty());
1181 
1182  unsigned int indexFace = LI.begin()->p->getPrimitiveId();
1183 
1184  // Avoid cases where the extremities are above infrastructure elements
1185  while(_solver.getTabPolygon()[indexFace].is_infra()){
1186  start.z = (decimal)min(min(_solver.getTabPolygon()[indexFace].tabPoint[0]._z, _solver.getTabPolygon()[indexFace].tabPoint[1]._z),
1187  _solver.getTabPolygon()[indexFace].tabPoint[2]._z) ;
1188  Ray ray(start, vec3(0,0,-1));
1189  ray.setMaxt ( 20000 );
1190  std::list<Intersection> LI2;
1191  double distance = static_cast<double>( _solver.getScene()->getAccelerator()->traverse( &ray, LI2 ) );
1192  // assert(distance > 0.);
1193  if (LI2.empty() || distance < 0.)
1194  break;
1195  distance1 += distance;
1196  indexFace = LI2.begin()->p->getPrimitiveId();
1197  }
1198 
1199  // Second one
1200  LI.clear();
1201  pt = director._ptB;
1202  pt._z += 1000.;
1203  start = OPoint3Dtovec3(pt);
1204  Ray ray2( start, vec3(0., 0., -1.) );
1205 
1206  double distance2 = static_cast<double>( _solver.getScene()->getAccelerator()->traverse( &ray2, LI ) );
1207  // An error can occur if some elements are outside of the grip (emprise)
1208  assert( distance2 > 0. );
1209  assert(!LI.empty());
1210 
1211  indexFace = LI.begin()->p->getPrimitiveId();
1212 
1213  // Avoid cases where the extremities are above infrastructure elements
1214  while(_solver.getTabPolygon()[indexFace].is_infra()){
1215  start.z = (decimal)min(min(_solver.getTabPolygon()[indexFace].tabPoint[0]._z, _solver.getTabPolygon()[indexFace].tabPoint[1]._z),
1216  _solver.getTabPolygon()[indexFace].tabPoint[2]._z) ;
1217  Ray ray(start, vec3(0,0,-1));
1218  ray.setMaxt ( 20000 );
1219  std::list<Intersection> LI2;
1220  double distance = static_cast<double>( _solver.getScene()->getAccelerator()->traverse( &ray, LI2 ) );
1221  // assert(distance > 0.);
1222  if (LI2.empty() || distance < 0.)
1223  break;
1224  distance2 += distance;
1225  indexFace = LI2.begin()->p->getPrimitiveId();
1226  }
1227 
1228  // Compute projection on the ground of segment points suppose sol is under the points ...
1229  slope._ptA._z = director._ptA._z - (distance1-1000.);
1230  slope._ptB._z = director._ptB._z - (distance2-1000.);
1231 }
1232 
OSpectre _Attenuation
attenuation Spectrum
Definition: TYEtape.h:144
void setType(const int &type)
Change the path type.
Definition: TYChemin.h:114
static OSpectre getLambda(const double &c)
Definition: spectre.cpp:726
Describes building material.
Definition: entities.hpp:43
void init()
Initialize the acoustic model.
The 3D vector class.
Definition: 3d.h:296
const std::vector< TYStructSurfIntersect > & getTabPolygon() const
Get the array of polygons.
Definition: TYSolver.h:55
Accelerator * getAccelerator() const
Get the accelerator.
Definition: Scene.h:74
Representation of one of the most optimal path between source and receptor: S—>R. The class TYChemin represents a path between a Source and a receptor (Recepteur class). It&#39;s constituted of a collection of steps (TYEtape class).
Definition: TYChemin.h:38
The TYEtape class is used to describe a part (a step) of a path (TYChemin) for the computation of tra...
Definition: TYEtape.h:47
static OSpectre getEmptyLinSpectre(const double &valInit=1.0E-20)
Create a physical quantity spectrum.
Definition: spectre.cpp:637
virtual OSpectre sum(const OSpectre &spectre) const
Arithmetic sum of two spectrums in one-third Octave.
Definition: spectre.cpp:314
virtual ComplexSpectrum get_absorption(double incidence_angle, double length)
Virtual method to return material absorption at reflection point.
Definition: entities.hpp:29
void normalize()
Normalizes this vector.
Definition: 3d.cpp:247
void computeCheminReflexion(const std::deque< TYSIntersection > &tabIntersect, const OSegment3D &rayon, const tympan::AcousticSource &source, TYTabChemin &TabChemins, double distance) const
Compute the list of path generated by reflection on the vertical walls.
OSpectre getPInterference(const AtmosphericConditions &atmos)
Compute the quadratic pressure on the journey.
Definition: TYTrajet.cpp:181
virtual int symetrieOf(const OPoint3D &pt, OPoint3D &ptSym) const
Return the symmetrical of a point.
Definition: 3d.cpp:1212
OPoint3D _ptB
Point B of the segment.
Definition: 3d.h:1199
OPoint3D _ptA
Point A of the segment.
Definition: 3d.h:1197
double distFrom(const OPoint3D &pt) const
Computes the distance from this point to another.
Definition: 3d.cpp:409
This file provides class for solver configuration.
Default solver.
Definition: TYSolver.h:38
base_vec3< decimal > vec3
Definition: mathlib.h:269
std::vector< OPoint3D > TabPoint3D
Definition: 3d.h:481
NxReal s
Definition: NxVec3.cpp:345
virtual double longueur() const
Return the segment length.
Definition: 3d.cpp:1207
void setPoint(const OPoint3D &pt)
Definition: TYEtape.h:108
OSpectre limAttDiffraction(const OSpectre &sNC, const OSpectre &C) const
Limit the screen attenuation value with a frequency dependent criteria.
OSpectreComplex getReflexionSpectrumAt(const OSegment3D &incident, double length, const OSegment3D &segPente, const tympan::AcousticSource &source) const
Find Reflexion spectrum at point defined by the end of an incident segment.
std::deque< TYChemin > TYTabChemin
TYChemin collection.
Definition: TYChemin.h:149
std::complex< double > TYComplex
Definition: macros.h:26
OSpectre getPEnergetique(const AtmosphericConditions &atmos)
Compute the acoustic pressure (phase modulation) on the journey.
Definition: TYTrajet.cpp:111
double norme() const
Computes the length of this vector.
Definition: 3d.cpp:237
double getDistance()
Get/Set the distance between source and receptor.
Definition: TYTrajet.h:78
virtual OSpectre invMult(const double &coefficient=1.0) const
Division of a double constant by this spectrum.
Definition: spectre.cpp:446
bool bIntersect[2]
Flag to indicate the face cuts vertical plane ([0]) or horizontal plane ([1])
virtual OSpectre div(const OSpectre &spectre) const
Division of two spectrums.
Definition: spectre.cpp:407
virtual decimal traverse(Ray *r, std::list< Intersection > &result) const
Run this accelerator.
Definition: Accelerator.h:55
OSpectre & getSpectre()
Get/Set the spectrum at the receptor point.
Definition: TYTrajet.h:155
virtual unsigned int getNbValues() const
Number of values in the spectrum.
Definition: spectre.cpp:789
virtual void setType(TYSpectreType type)
Set the spectrum type.
Definition: spectre.h:101
TYTabChemin & getCheminsDirect()
Return an array of the direct paths.
Definition: TYTrajet.h:102
OPoint3D _pt
The starting point of this step.
Definition: TYEtape.h:142
3D vector Vector defined with 3 float numbers
Definition: mathlib.h:107
virtual void compute(const std::deque< TYSIntersection > &tabIntersect, TYTrajet &trajet, TabPoint3D &ptsTop, TabPoint3D &ptsLeft, TabPoint3D &ptsRight)
void getPtSetPtRfromOSeg3D(OSegment3D &seg) const
Definition: TYTrajet.h:143
TYTabChemin & getChemins()
Return the collection of paths of *this.
Definition: TYTrajet.h:95
virtual ~TYAcousticModel()
This class TYTrajet (journey) links a couple Source-Receptor and a collection of paths, in addition to the direct path.
Definition: TYTrajet.h:35
double _y
y coordinate of OCoord3D
Definition: 3d.h:281
double _x
x coordinate of OCoord3D
Definition: 3d.h:280
Plan defined by its equation : ax+by+cz+d=0.
Definition: plan.h:30
double DEGTORAD(double a)
Converts an angle from degrees to radians.
Definition: 3d.h:129
virtual Spectrum lwAdjustment(Vector direction, double distance)=0
< Pure virtual method to return directivity of the Source
const Scene * getScene() const
Get the Scene.
Definition: TYSolver.h:62
#define TYSEUILCONFONDUS
Definition: 3d.h:49
virtual bool computeCheminsAvecEcran(const OSegment3D &rayon, const tympan::AcousticSource &source, const TabPoint3D &pts, const bool vertical, TYTabChemin &TabChemins, double distance, bool conditionFav=false) const
Compute the segment path from the list of the points of the TYTrajet journey. It takes in account the...
: Describes a ray by a pair of unsigned int. The first one gives the source number (in the range 0-40...
Definition: Ray.h:38
OSpectreComplex _absoNulle
bool isInfra
Flag to define if is a infrastructure face.
void calcAttenuation(const TYTabEtape &tabEtapes, const AtmosphericConditions &atmos)
Compute the global attenuation on the path.
Definition: TYChemin.cpp:72
float decimal
Definition: mathlib.h:46
void setMaxt(decimal _maxt)
set the maxt
Definition: Ray.h:351
TYAcousticModel(TYSolver &solver)
OSpectre calculAttDiffraction(const OSegment3D &rayon, const OSegment3D &penteMoyenne, const bool &miroir, const double &re, const double &epaisseur, const bool &vertical, const bool &avantApres, bool &bDiffOk, bool conditionFav=false) const
Compute the attenuation from the diffraction on the screen.
vec3 OPoint3Dtovec3(const OPoint3D &_p)
Converts a OPoint3D to vec3.
Definition: mathlib.h:313
tympan::AcousticMaterialBase * material
Pointer to a material.
OSpectre calculC(const double &epaisseur) const
Compute the spectrum of the C factor used in the diffraction calculation.
Spectrum spectrum
Associated spectrum.
Definition: entities.hpp:328
Data structure for intersections.
Math library.
TYSolver & _solver
Reference to the solver.
void meanSlope(const OSegment3D &director, OSegment3D &slope) const
Create a segment corresponding to the projection of "director" segment on the ground.
Class to define a segment.
Definition: 3d.h:1087
double RADTODEG(double a)
Converts an angle from radians to degrees.
Definition: 3d.h:140
int intersectsSegment(const OPoint3D &pt1, const OPoint3D &pt2, OPoint3D &ptIntersec) const
Calculate the intersection of this plane with a segment defined by two points.
Definition: plan.cpp:141
void setDistance(const double &distance)
Definition: TYChemin.h:108
boost::shared_ptr< SolverConfiguration > LPSolverConfiguration
Definition: interfaces.h:24
std::deque< TYEtape > TYTabEtape
TYEtape collection.
Definition: TYEtape.h:149
Base class for material.
Definition: entities.hpp:22
void setLongueur(const double &longueur)
Definition: TYChemin.h:95
virtual double * getTabValReel()
Definition: spectre.h:112
SourceDirectivityInterface * directivity
Pointer to the source directivity.
Definition: entities.hpp:329
virtual int projection(const OPoint3D &pt, OPoint3D &ptProj, double seuilConfondus) const
Return the projection of a point.
Definition: 3d.cpp:1227
std::unique_ptr< AtmosphericConditions > pSolverAtmos
ACOUSTIC_EVENT_TYPES _type
Acoustic event type.
Definition: TYEtape.h:141
Describes an acoustic source.
Definition: entities.hpp:315
bool addEtapesSol(const OPoint3D &ptDebut, const OPoint3D &ptFin, const OSegment3D &penteMoyenne, const tympan::AcousticSource &source, const bool &fromSource, const bool &toRecepteur, TYTabEtape &Etapes, double &longueur) const
Compute the different steps from a point to another via a reflection and a direct view...
virtual OVector3D toVector3D() const
Build a OVector3D from a segment used for the direction of the sources.
Definition: 3d.h:1187
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.
OSegment3D segInter[2]
Intersection segment between face and vertical plane ([0]) and horizontal plane ([1]) ...
bool solve(TYTrajet &trajet)
Compute the source contribution to the point.
double _z
z coordinate of OCoord3D
Definition: 3d.h:282
virtual OSpectre racine() const
Compute the root square of this spectrum.
Definition: spectre.cpp:518
void computeCheminSansEcran(const OSegment3D &rayon, const tympan::AcousticSource &source, TYTabChemin &TabChemins, double distance, bool conditionFav=false) const
Compute the list of paths generated by reflection on the ground if there is no screen.
Store acoustic power values for different frequencies.
Definition: spectre.h:49
OSpectreComplex _Absorption
absorption Spectrum
Definition: TYEtape.h:143
#define M_PI
Pi.
Definition: color.cpp:24
string volume_id
Volume id.
Definition: entities.hpp:330
void computeCheminAPlat(const OSegment3D &rayon, const tympan::AcousticSource &source, TYTabChemin &TabChemins, double distance) const
Compute the list of paths for a perfectly flat and reflective ground.
virtual int intersects(const OSegment3D &seg, OPoint3D &pt, double seuilConfondus) const
Return the intersection point with another segment.
Definition: 3d.cpp:1236
virtual void setDefaultValue(const double &valeur=TY_SPECTRE_DEFAULT_VALUE)
Definition: spectre.cpp:192
double dot(const OVector3D &v)
dot product (assuming an orthonormal reference frame)
Definition: 3d.h:361
static LPSolverConfiguration get()
Get the configuration.
Definition: config.cpp:99
tympan::AcousticSource & asrc
Business source.
Definition: TYTrajet.h:182