Code_TYMPAN  4.4.0
Industrial site acoustic simulation
TYTrajet.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 
16 #include "TYTrajet.h"
18 
20  : asrc(asrc_), arcpt(arcpt_), _distance(0.0)
21 {
22  _ptS = asrc.position;
23  _ptR = arcpt.position;
24  _distance = _ptS.distFrom(_ptR);
25  // build_tab_rays();
26 }
27 
28 TYTrajet::TYTrajet(const TYTrajet& other) : asrc(other.asrc), arcpt(other.arcpt)
29 {
30  *this = other;
31  if (tympan::SolverConfiguration::get()->KeepRays == false)
32  {
33  for (unsigned int i = 0; i < _tabRays.size(); i++)
34  {
35  delete _tabRays.at(i);
36  _tabRays.at(i) = nullptr;
37  }
38  _tabRays.clear();
39  }
40 }
41 
43 {
44  reset();
45 }
46 
47 void TYTrajet::reset()
48 {
49  _chemins.clear();
50  _cheminsDirect.clear();
51 }
52 
54 {
55  if (this != &other)
56  {
57  _chemins = other._chemins;
58  _ptS = other._ptS;
59  _ptR = other._ptR;
60  _distance = other._distance;
61  _sLP = other._sLP;
62  asrc = other.asrc;
63  arcpt = other.arcpt;
64  asrc_idx = other.asrc_idx;
65  arcpt_idx = other.arcpt_idx;
66  }
67  return *this;
68 }
69 
70 bool TYTrajet::operator==(const TYTrajet& other) const
71 {
72  if (this != &other)
73  {
74  if (_chemins != other._chemins)
75  {
76  return false;
77  }
78  if (_ptS != other._ptS)
79  {
80  return false;
81  }
82  if (_ptR != other._ptR)
83  {
84  return false;
85  }
86  if (_distance != other._distance)
87  {
88  return false;
89  }
90  if (_sLP != other._sLP)
91  {
92  return false;
93  };
94  // if (asrc != other.asrc) { return false; };
95  // if (arcpt != other.arcpt) ;
96  if (asrc_idx != other.asrc_idx)
97  {
98  return false;
99  };
100  if (arcpt_idx != other.arcpt_idx)
101  {
102  return false;
103  };
104  }
105 
106  return true;
107 }
108 
109 bool TYTrajet::operator!=(const TYTrajet& other) const
110 {
111  return !operator==(other);
112 }
113 
114 void TYTrajet::addChemin(const TYChemin& chemin)
115 {
116  _chemins.push_back(chemin);
117 }
118 
119 void TYTrajet::addCheminDirect(const TYChemin& chemin)
120 {
121  _cheminsDirect.push_back(chemin);
122 }
123 
125 {
126  return _chemins[0].getAttenuation();
127 }
128 
130 {
132  OSpectreComplex sTemp;
133  int firstReflex = -1;
134  unsigned int indiceDebutEffetEcran = 0;
135  unsigned int i = 0;
136 
137  // On calcule l'attenuation sur le trajet direct (sauf chemins reflechis).
138  for (i = 0; i < this->_chemins.size(); i++)
139  {
140  // Si un ecran est present, on ne traite pas les reflexions (dans un premier temp ...)
141  if ((_chemins[0].getType() == CHEMIN_ECRAN) && (_chemins[i].getType() == CHEMIN_REFLEX))
142  {
143  firstReflex = i;
144  break;
145  }
146  sTemp = _chemins[i].getAttenuation();
147  s = s.sum(sTemp.mult(sTemp)); // somme des carres des modules
148  }
149 
150  // Dans le cas d'un ecran, on compare l'attenuation obtenue a celle du trajet direct
151  // pour eviter les effets d'amplification (plus de bruit avec l'ecran que sans ecran ...)
152  if (_chemins[0].getType() == CHEMIN_ECRAN)
153  {
155 
156  for (i = 0; i < _cheminsDirect.size(); i++)
157  {
158  sTemp = _cheminsDirect[i].getAttenuation();
159  attDirect = attDirect.sum(sTemp.mult(sTemp));
160  }
161 
162  // On regarde l'attenuation globale obtenue pour chaque frequence,
163  // on la compare a celle obtenue sur le trajet sans ecran,
164  // si elle est superieure a 1 alors on prend la valeur obtenue pour le trajet sans ecran
165  for (i = 0; i < s.getNbValues(); i++)
166  {
167  if (s.getTabValReel()[i] < attDirect.getTabValReel()[i])
168  {
169  indiceDebutEffetEcran = i; // On prend note de l'indice
170  break; // Si l'ecran commence a attenuer plus que le trajet direct, il faut sortir de la
171  // boucle
172  }
173  } //*/
174 
175  if (firstReflex != -1) // S'il y a une reflexion sur un ecran
176  {
177  // On rajoute la contribution des chemins reflechis
178  // 1. Aux chemins normaux et aux chemins directs
179  for (i = firstReflex; i < _chemins.size(); i++)
180  {
181  sTemp = _chemins[i].getAttenuation().mult(_chemins[i].getAttenuation());
182  s = s.sum(sTemp);
183  attDirect = attDirect.sum(sTemp);
184  }
185 
186  // On remplace la contribution du trajet direct pour toutes les frequences ou cela est necessaire
187  for (i = 0; i < indiceDebutEffetEcran; i++)
188  {
189  s.getTabValReel()[i] = attDirect.getTabValReel()[i];
190  }
191  }
192  }
193  build_tab_rays();
194  _chemins.clear(); // On efface le tableau des chemins pour (essayer de) gagner de la place en memoire
195  _cheminsDirect.clear();
196  return s;
197 }
198 
200 {
201  unsigned int i = 0, j = 0;
202  int firstReflex = -1;
203  unsigned int indiceDebutEffetEcran = 0;
204  bool ecranFound = false;
205 
206  if (_chemins.size())
207  {
208  ecranFound = (_chemins[0].getType() == CHEMIN_ECRAN);
209  }
210 
211  // On recupere prealablement l'ensemble des attenuations et les longueurs des chemins
212  std::vector<OSpectreComplex> tabSpectreAtt;
213  std::vector<OSpectreComplex> tabSpectreAttDirect;
214  std::vector<double> tabLongueur;
215  std::vector<double> tabLongueurDirect;
216 
217  for (i = 0; i < _chemins.size(); i++)
218  {
219  tabSpectreAtt.push_back(_chemins[i].getAttenuation());
220  tabLongueur.push_back(_chemins[i].getLongueur());
221  }
222 
223  // On calcule la somme des carres des modules et la somme des produits croises
224 
225  OSpectre sCarreModule = OSpectre::getEmptyLinSpectre();
226  OSpectre sProduitCroise = OSpectre::getEmptyLinSpectre();
227  OSpectre sTemp;
228 
229  for (i = 0; i < _chemins.size(); i++)
230  {
231 
232  // Si un ecran est present, on ne traite pas les reflexions (dans un premier temp ...)
233  if (ecranFound && (_chemins[i].getType() == CHEMIN_REFLEX))
234  {
235  firstReflex = i;
236  break;
237  }
238  // on fait la somme du carre des modules
239  sCarreModule = sCarreModule.sum(tabSpectreAtt[i].mult(tabSpectreAtt[i]));
240 
241  // on calcule les produits croises avec les autres chemins
242  for (j = i + 1; j < _chemins.size(); j++)
243  {
244  // On procedera aux produits croise avec les chemins reflechis plus loin ...
245  if (ecranFound && (_chemins[j].getType() == CHEMIN_REFLEX))
246  {
247  continue;
248  }
249 
250  sTemp = tabSpectreAtt[i].mult(tabSpectreAtt[j].mult(2.0));
251  sTemp = sTemp.mult(
252  correctTiers(tabSpectreAtt[i], tabSpectreAtt[j], atmos, tabLongueur[i], tabLongueur[j]));
253  sProduitCroise = sProduitCroise.sum(sTemp);
254  }
255  }
256 
257  OSpectre s = sCarreModule.sum(sProduitCroise); //.abs() ;
258 
259  // Dans le cas d'un ecran, on compare l'attenuation obtenue a celle du trajet direct
260  // pour eviter les effets d'amplification (plus de bruit avec l'ecran que sans ecran ...)
261 
262  if (ecranFound) // On comparera au carre des modules des trajets directs
263  {
264  // On calcule l'attenuation sur le trajet direct
265  OSpectre sCarreModuleDirect = OSpectre::getEmptyLinSpectre();
266  OSpectre sProduitCroiseDirect = OSpectre::getEmptyLinSpectre();
267 
268  for (i = 0; i < _cheminsDirect.size(); i++)
269  {
270  tabSpectreAttDirect.push_back(_cheminsDirect[i].getAttenuation());
271  tabLongueurDirect.push_back(_cheminsDirect[i].getLongueur());
272  }
273 
274  for (i = 0; i < _cheminsDirect.size(); i++)
275  {
276  // on fait la somme du carre des modules
277  sCarreModuleDirect = sCarreModuleDirect.sum(tabSpectreAttDirect[i].mult(tabSpectreAttDirect[i]));
278 
279  // on calcule les produits croises avec les autres chemins
280  for (j = i + 1; j < _cheminsDirect.size(); j++)
281  {
282  sTemp = tabSpectreAttDirect[i].mult(tabSpectreAttDirect[j].mult(2.0));
283  sTemp = sTemp.mult(correctTiers(tabSpectreAttDirect[i], tabSpectreAttDirect[j], atmos,
284  tabLongueurDirect[i], tabLongueurDirect[j]));
285  sProduitCroiseDirect = sProduitCroiseDirect.sum(sTemp);
286  }
287  }
288 
289  OSpectre attDirect = sCarreModuleDirect.sum(sProduitCroiseDirect); //.abs() ;
290 
291  // On compare l'attenuation sur le trajet "normal" en energetique a
292  // l'attenuation sur le trajet direct en energetique.
293  // Si elle est superieure, alors on prend l'attenuation sur le trajet direct
294 
295  for (j = 0; j < s.getNbValues(); j++)
296  {
297  if (s.getTabValReel()[j] < attDirect.getTabValReel()[j])
298  {
299  indiceDebutEffetEcran = j; // On prend note de l'indice
300  break; // Si l'ecran commence a attenuer plus que le trajet direct, il faut sortir de la
301  // boucle
302  }
303  }
304 
305  if (firstReflex != -1) // S'il y a une reflexion sur un ecran
306  {
307  // On rajoute la contribution des chemins reflechis:
308  // 1. aux chemins "normaux"
309  for (i = firstReflex; i < _chemins.size(); i++)
310  {
311  sCarreModule = sCarreModule.sum(tabSpectreAtt[i].mult(tabSpectreAtt[i]));
312 
313  // on calcule les produits croises avec les autres chemins
314  for (j = 0; j < _chemins.size(); j++)
315  {
316  if (j == i)
317  {
318  continue;
319  } // pas avec lui meme
320 
321  sTemp = tabSpectreAtt[i].mult(tabSpectreAtt[j].mult(2.0));
322  sTemp = sTemp.mult(correctTiers(tabSpectreAtt[i], tabSpectreAtt[j], atmos, tabLongueur[i],
323  tabLongueur[j]));
324  sProduitCroise = sProduitCroise.sum(sTemp);
325  }
326  }
327 
328  s = sCarreModule.sum(sProduitCroise);
329 
330  // // 2. au chemins "direct"
331  for (i = firstReflex; i < _chemins.size(); i++)
332  {
333  sCarreModuleDirect = sCarreModuleDirect.sum(tabSpectreAtt[i].mult(tabSpectreAtt[i]));
334 
335  // Produit croise avec les chemins directs
336  for (j = 0; j < _cheminsDirect.size(); j++)
337  {
338  sTemp = tabSpectreAtt[i].mult(tabSpectreAttDirect[j].mult(2.0));
339  sTemp = sTemp.mult(correctTiers(tabSpectreAtt[i], tabSpectreAttDirect[j], atmos,
340  tabLongueur[i], tabLongueurDirect[j]));
341  sProduitCroiseDirect = sProduitCroiseDirect.sum(sTemp);
342  }
343  // Produit croise avec les autres chemins reflechis
344  for (j = i + 1; j < _chemins.size(); j++)
345  {
346  sTemp = tabSpectreAtt[i].mult(tabSpectreAtt[j].mult(2.0));
347  sTemp = sTemp.mult(correctTiers(tabSpectreAtt[i], tabSpectreAtt[j], atmos, tabLongueur[i],
348  tabLongueur[j]));
349  sProduitCroiseDirect = sProduitCroiseDirect.sum(sTemp);
350  }
351  }
352 
353  attDirect = sCarreModuleDirect.sum(sProduitCroiseDirect); //.abs();
354  }
355 
356  // On remplace la contribution du trajet direct pour toutes les frequences ou cela est necessaire
357  for (i = 0; i < indiceDebutEffetEcran; i++)
358  {
359  s.getTabValReel()[i] = attDirect.getTabValReel()[i];
360  }
361  }
362  build_tab_rays();
363  _chemins.clear(); // On efface le tableau des chemins pour (essayer de) gagner de la place en memoire
364  _cheminsDirect.clear();
365 
366  return s;
367 }
368 
370  const AtmosphericConditions& atmos, const double& ri, const double& rj) const
371 {
372  const double dp6 = pow(2, (1.0 / 6.0));
373  const double invdp6 = 1.0 / dp6;
374  const double dfSur2f = (dp6 - invdp6) / 2.0; // df/2f
375  OSpectre cosTemp;
376  OSpectre s;
377 
378  OSpectre sTemp = atmos.get_k().mult(ri - rj); // k(ri-rj)
379 
380  if (ri == rj)
381  {
382  s = (si.getPhase().subst(sj.getPhase()).subst(sTemp)).cos(); // cos(EPS_i - EPS_j)
383  }
384  else
385  {
386 
387  s = si.getPhase().subst(sj.getPhase()); // thetaI - thetaJ
388 
389  double df = sqrt(1 + dfSur2f * dfSur2f);
390  cosTemp = sTemp.mult(df); // k(ri-rj) * sqrt(1 + (df/2f)²)
391  cosTemp = cosTemp.sum(s); // k(ri-rj) * sqrt(1 + (df/2f)²) + (thetaI - thetaJ)
392  cosTemp = cosTemp.subst(sTemp); // k(ri-rj)*sqrt(1 + (df/2f)²) + EPS_i - EPS_j
393  cosTemp = cosTemp.cos(); // cos(k(ri-rj)*sqrt(1 + (df/2f)²) + EPS_i - EPS_j)
394 
395  sTemp = sTemp.mult(dfSur2f); // k(ri-rj)*df/2f
396 
397  s = sTemp.sin(); // sin(k(ri-rj)*df/2f)
398  s = s.div(sTemp); // sin(k(ri-rj)*df/2f) / (k(ri-rj)*df/2f)
399  s = s.mult(cosTemp); // sin(k(ri-rj)*df/2f) / (k(ri-rj)*df/2f) * cos(k(ri-rj)*sqrt(1 + (df/2f)²) +
400  // EPS_i - EPS_j)
401  }
402 
403  return s;
404 }
405 
407 {
408  _tabRays.clear();
409  for (size_t i = 0; i < _chemins.size(); i++)
410  {
411  _tabRays.push_back(_chemins[i].get_ray(_ptR));
412  }
413 }
414 
415 std::vector<acoustic_path*>& TYTrajet::get_tab_rays()
416 {
417  return _tabRays;
418 }
NxReal s
Definition: NxVec3.cpp:317
Class for the definition of atmospheric conditions.
const OSpectre & get_k() const
Get the wave number spectrum.
OSpectreAbstract & sum(const OSpectreAbstract &spectre) const
Arithmetic sum of two spectrums in one-third Octave.
Definition: spectre.cpp:219
OSpectreAbstract & subst(const OSpectreAbstract &spectre) const
Arithmetic subtraction of two spectrums in one-third Octave.
Definition: spectre.cpp:316
OSpectreAbstract & sin() const
Compute the sin of this spectrum.
Definition: spectre.cpp:464
OSpectreAbstract & cos() const
Compute the cos of this spectrum.
Definition: spectre.cpp:478
OSpectreAbstract & mult(const OSpectreAbstract &spectre) const
Multiplication of two spectrums.
Definition: spectre.cpp:243
OSpectre getPhase() const
Definition: spectre.cpp:1365
static OSpectre getEmptyLinSpectre(const double &valInit=1.0E-20)
Create a physical quantity spectrum.
Definition: spectre.cpp:1115
double * getTabValReel() override
Definition: spectre.h:356
Representation of one of the most optimal path between source and receptor: S—>R. The class TYChemin ...
Definition: TYChemin.h:71
This class TYTrajet (journey) links a couple Source-Receptor and a collection of paths,...
Definition: TYTrajet.h:35
tympan::AcousticReceptor & arcpt
Business receptor.
Definition: TYTrajet.h:229
OPoint3D _ptS
Source point definition in the site frame.
Definition: TYTrajet.h:235
OSpectreOctave getPEnergetique(const AtmosphericConditions &atmos)
Compute the acoustic pressure in octave bands on the journey.
Definition: TYTrajet.cpp:129
OPoint3D _ptR
Receptor point definition in the site frame.
Definition: TYTrajet.h:238
void build_tab_rays()
Definition: TYTrajet.cpp:198
TYTabChemin _chemins
Paths collection.
Definition: TYTrajet.h:241
void addCheminDirect(const TYChemin &chemin)
Add a new path to the array of direct paths.
Definition: TYTrajet.cpp:119
TYTrajet & operator=(const TYTrajet &other)
Operator =.
Definition: TYTrajet.cpp:53
OSpectreOctave getPNoOp()
Return the attenuation without computation (computed by an external function)
Definition: TYTrajet.cpp:124
void addChemin(const TYChemin &chemin)
Add a new path.
Definition: TYTrajet.cpp:114
OSpectre correctTiers(const OSpectreComplex &si, const OSpectreComplex &sj, const AtmosphericConditions &atmos, const double &ri, const double &rj) const
Definition: TYTrajet.cpp:369
std::vector< acoustic_path * > _tabRays
Vector of rays equivalent to chemin.
Definition: TYTrajet.h:254
bool operator!=(const TYTrajet &other) const
Operator !=.
Definition: TYTrajet.cpp:109
tympan::source_idx asrc_idx
Definition: TYTrajet.h:226
OSpectreOctave _sLP
Definition: TYTrajet.h:251
TYTabChemin _cheminsDirect
Direct paths collection (without obstacles)
Definition: TYTrajet.h:244
virtual ~TYTrajet()
Destructor.
Definition: TYTrajet.cpp:42
tympan::receptor_idx arcpt_idx
Definition: TYTrajet.h:230
void reset()
Reset method.
Definition: TYTrajet.cpp:47
tympan::AcousticSource & asrc
Business source.
Definition: TYTrajet.h:225
std::vector< acoustic_path * > & get_tab_rays()
Definition: TYTrajet.cpp:207
double _distance
Distance between source and receptor.
Definition: TYTrajet.h:247
bool operator==(const TYTrajet &other) const
Operator ==.
Definition: TYTrajet.cpp:70
TYTrajet(tympan::AcousticSource &asrc_, tympan::AcousticReceptor &arcpt_)
Constructor.
Definition: TYTrajet.cpp:19
OSpectre getPInterference(const AtmosphericConditions &atmos)
Compute the quadratic pressure on the journey.
Definition: TYTrajet.cpp:199
Describes an acoustic receptor.
Definition: entities.hpp:388
Describes an acoustic source.
Definition: entities.hpp:366
static LPSolverConfiguration get()
Get the configuration.
Definition: config.cpp:93
This file provides class for solver configuration.