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