Code_TYMPAN  4.4.0
Industrial site acoustic simulation
Diffraction.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 
17 #include "Geometry/Cylindre.h"
18 #include "Tools/UnitConverter.h"
19 #include "Diffraction.h"
20 
21 // Filter diffraction rays that are not in the shadow zone (i.e area not hit by direct rays)
22 bool responseAngleLimiter(const vec3& from, const vec3& N1, const vec3& N2, vec3& T)
23 {
24  decimal FT = from * T;
25 
26  // Return true if FROM and TO are colinear and point in the same direction
27  if ((1. - FT) < EPSILON_4)
28  {
29  return true;
30  }
31 
32  // Return false if FROM and TO point in opposite directions
33  if (FT < 0.)
34  {
35  return false;
36  }
37 
38  decimal F1 = from * N1;
39  decimal F2 = from * N2;
40 
41  // Return false if the ray's incoming direction is such that there is no shadow zone
42  if ((F1 * F2) > 0.)
43  {
44  return false;
45  }
46 
47  decimal T1 = T * N1;
48  decimal T2 = T * N2;
49 
50  // Return false if TO is not in the shadow zone of the obstacle
51  if ((F1 <= 0.) && ((T1 > EPSILON_4) || ((ABS(T2) - ABS(F2)) > EPSILON_4)))
52  {
53  return false;
54  }
55 
56  if ((F2 <= 0.) && ((T2 > EPSILON_4) || ((ABS(T1) - ABS(F1)) > EPSILON_4)))
57  {
58  return false;
59  }
60 
61  return true;
62 }
63 
64 bool responseAlwaysYes(const vec3& from, const vec3& N1, const vec3& N2, vec3& T)
65 {
66  return true;
67 }
68 
69 void getThetaRandom(const decimal& angleOuverture, const decimal& delta_theta, const decimal& nbResponseLeft,
70  decimal& theta)
71 {
72  theta = ((decimal)(rand())) * angleOuverture / ((decimal)RAND_MAX);
73 
74  if (theta > angleOuverture / 2.)
75  {
76  theta += ((decimal)(2 * M_PI) - angleOuverture);
77  }
78 }
79 
80 void getThetaRegular(const decimal& angleOuverture, const decimal& delta_theta, const decimal& nbResponseLeft,
81  decimal& theta)
82 {
83  // compute next angle around the cone of Keller
84  theta = (nbResponseLeft * delta_theta) - (angleOuverture / decimal(2.));
85 }
86 
87 Diffraction::Diffraction(const vec3& position, const vec3& incomingDirection, Cylindre* c)
88  : Event(position, incomingDirection, (Shape*)(c))
89 {
90  name = "unknown diffraction";
92  type = DIFFRACTION;
93 
94  // Skip instructions dependant on the Cylindre if c==NULL
95  if (c)
96  {
97  buildRepere();
98  computeAngle();
99  computeDTheta();
100 
101  N1 = dynamic_cast<Cylindre*>(shape)->getFirstShape()->getNormal();
102  N2 = dynamic_cast<Cylindre*>(shape)->getSecondShape()->getNormal();
103  }
104 
106  {
108  }
109  else
110  {
112  }
113 
115  ->DiffractionUseRandomSampler) // Tir des rayons alĂ©atoires sur le cone de Keller
116  {
118  }
119  else
120  {
122  }
123 }
124 
126 {
127  type = DIFFRACTION;
128  buildRepere();
129  computeAngle();
130  computeDTheta();
131 
132  N1 = other.N1;
133  N2 = other.N2;
134 
136 }
137 
138 bool Diffraction::getResponse(vec3& r, bool force)
139 {
140  bool bRep = false;
141  do
142  {
143  decimal theta = 0.;
144  // get the angle of the next response around Keller's cone
145  // (avoids returning an angle that would result in a response pointing inside the obstacle)
146  (*getTheta)(angleOuverture, delta_theta, (decimal)nbResponseLeft, theta);
147 
148 #ifdef _ALLOW_TARGETING_
149  if (!force)
150  {
151  nbResponseLeft--;
152  if (nbResponseLeft < 0)
153  {
154  return false;
155  }
156  }
157 
158  if (!targets.empty())
159  {
160  r = vec3(targets.back());
161  targets.pop_back();
162  return true;
163  }
164 #else
165  // force is true only when targeting is allowed
166  nbResponseLeft--;
167  if (nbResponseLeft < 0)
168  {
169  return false;
170  }
171 #endif
172 
173  vec3 localResponse;
174  // convert from polar coordinates to carthesian ones
175  Tools::fromRadianToCarthesien2(angleArrive, theta, localResponse);
176 
177  // transpose the local response into global coordinates
178  r = localRepere.vectorFromLocalToGlobal(localResponse);
179 
180  // validate response
181  bRep = (*responseValidator)(from, N1, N2, r);
182 
183  } while (!bRep);
184 
185  return true;
186 }
187 
189 {
190  Cylindre* c = (Cylindre*)(shape);
191  vec3 O = pos;
192  vec3 v1 = c->getVertices()->at(c->getLocalVertices()->at(0));
193  vec3 v2 = c->getVertices()->at(c->getLocalVertices()->at(1));
194 
195  // Z axis is along the diffraction edge
196  vec3 Z = v1 - O;
197  if (Z.dot(from) < 0)
198  {
199  Z = v2 - O;
200  }
201  Z.normalize();
202 
203  // X axis is the mean of the two normals
204  vec3 X = c->getFirstShape()->getNormal() + c->getSecondShape()->getNormal();
205  X.normalize();
206 
207  // Y axis is the cross product of Z and X
208  vec3 Y;
209  Y.cross(Z, X);
210  Y.normalize();
211 
212  localRepere = Repere(X, Y, Z, O);
213 }
214 
216 {
217  Cylindre* c = (Cylindre*)(shape);
218 
219  // The cone's aperture angle
220  angleOuverture = c->getAngleOuverture();
221 
223 
224  // Angle between the incoming ray and the Z axis
225  decimal cosAngleArrive = localRepere.getW().dot(from);
226 
227  angleArrive = acos(cosAngleArrive);
228 }
229 
230 bool Diffraction::generateTest(std::vector<vec3>& succededTest, std::vector<vec3>& failTest,
231  unsigned int nbResponses)
232 {
233  for (unsigned int i = 0; i < nbResponses; i++)
234  {
235  vec3 newDir = vec3(((decimal)rand() / (decimal)RAND_MAX) * 2.f - 1.f,
236  ((decimal)rand() / (decimal)RAND_MAX) * 2.f - 1.f,
237  ((decimal)rand() / (decimal)RAND_MAX) * 2.f - 1.f);
238  newDir.normalize();
239  if (isAcceptableResponse(newDir))
240  {
241  succededTest.push_back(newDir);
242  }
243  else
244  {
245  failTest.push_back(newDir);
246  }
247  }
248  return true;
249 }
250 
251 #ifdef _ALLOW_TARGETING_
253 {
254 
255  vec3 localResponse = localRepere.vectorFromGlobalToLocal(test);
256 
257  if (localResponse.z < 0.)
258  {
259  return false;
260  }
261 
262  decimal phi = acos(localResponse.z);
263  decimal tetha;
264 
265  if (localResponse.y >= 0.)
266  {
267  tetha = acos(localResponse.x /
268  (sqrt(localResponse.x * localResponse.x + localResponse.y * localResponse.y)));
269  }
270  else
271  {
272  tetha =
273  2. * M_PI - acos(localResponse.x /
274  (sqrt(localResponse.x * localResponse.x + localResponse.y * localResponse.y)));
275  }
276 
277  if (!(tetha < angleOuverture / 2. || tetha > (2. * M_PI - angleOuverture / 2.)))
278  {
279  return false;
280  }
281 
282  decimal deltaPhi = fabs(angleArrive - phi);
283  if (deltaPhi < M_PI / 18.)
284  {
285  return true;
286  }
287  return false;
288 }
289 
290 bool Diffraction::generateResponse(std::vector<vec3>& responses, unsigned int nbResponses)
291 {
292  vec3 newDir;
293  for (unsigned int i = 0; i < nbResponses; i++)
294  {
295  getResponse(newDir, true);
296  responses.push_back(newDir);
297  }
298 
299  return true;
300 }
301 
302 bool Diffraction::appendTarget(vec3 target, bool force)
303 {
304 
305  if (force)
306  {
307  vec3 newDir = target - pos;
308  newDir.normalize();
309  targets.push_back(newDir);
310  return true;
311  }
312 
313  if (targets.size() > static_cast<unsigned int>(nbResponseLeft))
314  {
315  return false;
316  }
317  vec3 newDir = target - pos;
318  newDir.normalize();
319  if (isAcceptableResponse(newDir))
320  {
321  targets.push_back(newDir);
322  return true;
323  }
324  return false;
325 }
326 #endif //_ALLOW_TARGETING_
double ABS(double a)
Return the absolute value.
Definition: 3d.h:67
bool responseAngleLimiter(const vec3 &from, const vec3 &N1, const vec3 &N2, vec3 &T)
Definition: Diffraction.cpp:22
void getThetaRandom(const decimal &angleOuverture, const decimal &delta_theta, const decimal &nbResponseLeft, decimal &theta)
Definition: Diffraction.cpp:69
void getThetaRegular(const decimal &angleOuverture, const decimal &delta_theta, const decimal &nbResponseLeft, decimal &theta)
Definition: Diffraction.cpp:80
bool responseAlwaysYes(const vec3 &from, const vec3 &N1, const vec3 &N2, vec3 &T)
Definition: Diffraction.cpp:64
@ DIFFRACTION
Definition: Event.h:27
NxReal c
Definition: NxVec3.cpp:317
bool DiffractionFilterRayAtCreation
Flag to filter the created rays during diffraction.
bool DiffractionUseRandomSampler
Flag to enable random (and not regular) sampling for diffraction.
static AcousticRaytracerConfiguration * get()
Get access to the configuration.
std::string name
Each instantiated object may be named.
Definition: Base.h:52
Cylinder class.
Definition: Cylindre.h:27
Diffraction class Event.
Definition: Diffraction.h:31
vec3 N2
Face 2 normal.
Definition: Diffraction.h:137
void computeDTheta()
Compute the angle step between two responses in function of the aperture angle and the number of resp...
Definition: Diffraction.h:123
Repere localRepere
Local frame.
Definition: Diffraction.h:129
virtual bool getResponse(vec3 &r, bool force=false)
Computes the next response of the event in function of the number of responses left.
vec3 N1
Face 1 normal.
Definition: Diffraction.h:136
decimal delta_theta
Angle step between two rays to send.
Definition: Diffraction.h:134
decimal angleArrive
Incident ray angle.
Definition: Diffraction.h:132
virtual bool generateTest(std::vector< vec3 > &succededTest, std::vector< vec3 > &failTest, unsigned int nbResponses)
bool(* responseValidator)(const vec3 &, const vec3 &, const vec3 &, vec3 &)
Filter generated response (or not)
Definition: Diffraction.h:56
void computeAngle()
Compute the angle between the incident ray and the diffraction edge.
void buildRepere()
Build local frame.
void(* getTheta)(const decimal &, const decimal &, const decimal &, decimal &)
Definition: Diffraction.h:60
Diffraction(const vec3 &position=vec3(0.0, 0.0, 0.0), const vec3 &incomingDirection=vec3(0.0, 0.0, 0.0), Cylindre *c=NULL)
Constructor.
Definition: Diffraction.cpp:87
decimal angleOuverture
Angle formed by the two faces of the diffraction edge.
Definition: Diffraction.h:131
Class describing an event (reflection, diffraction, ...)
Definition: Event.h:37
int nbResponseLeft
Number of remaining rays to launch.
Definition: Event.h:238
Shape * shape
The impact primitive.
Definition: Event.h:241
vec3 from
Direction vector of the incoming ray.
Definition: Event.h:237
vec3 pos
Location point of the event.
Definition: Event.h:236
int initialNbResponse
Number of rays to launch after event.
Definition: Event.h:239
typeevent type
Event type.
Definition: Event.h:242
virtual bool generateResponse(std::vector< vec3 > &responses, unsigned int nbResponses)
Definition: Event.h:189
virtual bool appendTarget(vec3 target, bool force=false)
Definition: Event.h:194
virtual bool isAcceptableResponse(vec3 &test)
Return true if the ray direction vector in response of the event is acceptable.
Definition: Event.h:178
Frame class.
Definition: Repere.h:26
vec3 vectorFromGlobalToLocal(const vec3 &global)
Get local coordinates of vector expressed in global coordinates.
Definition: Repere.cpp:94
vec3 vectorFromLocalToGlobal(const vec3 &local)
Get global coordinates of vector expressed in local coordinates.
Definition: Repere.cpp:84
vec3 getW() const
Definition: Repere.h:79
base class for shapes (Cylindre, Mesh, Sphere, Triangle,...)
Definition: Shape.h:57
virtual vec3 getNormal(const vec3 pos=vec3())
Get normal.
Definition: Shape.h:145
#define M_PI
Pi.
Definition: color.cpp:25
#define EPSILON_4
Definition: mathlib.h:50
void fromRadianToCarthesien2(decimal tetha, decimal phi, vec3 &result)
Convert spherical coordinates to cartesian coordinates In this function :
float decimal
Definition: mathlib.h:45
base_vec3< decimal > vec3
Definition: mathlib.h:381