Code_TYMPAN  4.4.0
Industrial site acoustic simulation
ValidRay.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 "Geometry/Sphere.h"
19 #include "ValidRay.h"
20 #include "SpecularReflexion.h"
21 #include "Diffraction.h"
22 #include "DoNothing.h"
23 
25 {
26  vec3 impact = r->getPosition() + r->getDirection() * inter->t;
27  DoNothing* newEvent = new DoNothing(impact, r->getDirection(), inter->p);
28  boost::shared_ptr<Event> SPEv(newEvent);
29 
30  vec3 newDir;
31  // Check if the event can provide a response (should always be true in the case of a newly created
32  // DoNothing event)
33  if (newEvent->getResponse(newDir))
34  {
35  // update position of the ray and add the event to the list of events
36  r->setPosition(impact);
37  newDir.normalize();
38  r->setDirection(newDir); // ray's direction = event's response
39  r->addEvent(SPEv);
40  return true;
41  }
42 
43  return false;
44 }
45 
47 {
48  vec3 impact = r->getPosition() + r->getDirection() * inter->t;
49  vec3 normal = inter->p->getNormal(impact);
50 
51  // intersection is not valid if the ray goes in the same direction as the normal of the intersected shape
52  if (normal.dot(r->getDirection()) > 0.)
53  {
54  return false;
55  }
56 
57  if (AcousticRaytracerConfiguration::get()->UsePathDifValidation &&
59  {
60  return false;
61  }
62 
63  SpecularReflexion* newEvent = new SpecularReflexion(impact, r->getDirection(), inter->p);
64  boost::shared_ptr<Event> SPEv(newEvent);
65 
66  vec3 newDir;
67 
68  // if the newly created event can provide a response
69  if (newEvent->getResponse(newDir))
70  {
71  // update the ray's position, direction and add the new event to the ray's list of events
72  r->setPosition(r->getPosition() + r->getDirection() * inter->t);
73  newDir.normalize();
74  r->setDirection(newDir); // ray's direction = event's response
75  r->addEvent(SPEv);
76  r->setNbReflexion(r->getReflex() + 1);
77  return true;
78  }
79 
80  // no response could be provided by the new event => intersection is not valid
81  return false;
82 }
83 
84 // Computes distance between impact and last event/source and adds it to the cumulDistance
85 void ValidRay::computeCumulDistance(Ray* r, const vec3& impact)
86 {
87  vec3 previousPos;
88  if (r->getEvents()->size())
89  {
90  previousPos = r->getEvents()->back()->getPosition();
91  }
92  else
93  {
94  previousPos = r->getSource()->getPosition();
95  }
96 
97  r->setCumulDistance(r->getCumulDistance() + previousPos.distance(impact));
98 }
99 
101 {
103  computeCumulDistance(r, impact);
104 
105  // Compute the difference between :
106  // - the cumulative length since the last valid reflection
107  // and
108  // - the euclidian distance between impact and the last reflection
109  decimal delta = r->getCumulDistance() - impact.distance(lastReflexionPos);
110 
111  // Add the difference to the cumulative delta
112  r->setCumulDelta(r->getCumulDelta() + delta);
113 
114  // Reset cumulDistance
115  r->setCumulDistance(0.);
116 
117  // If the path difference is below the MaxPathDifference threshold, return true, else return false
119 }
120 
122 {
124  computeCumulDistance(r, impact);
125 
126  // Compute the difference between :
127  // - the cumulative length since the last valid reflection
128  // and
129  // - the euclidian distance between impact and the last reflection
130  decimal delta = r->getCumulDistance() - impact.distance(lastReflexionPos);
131 
132  // Sum of cumulDelta and delta (Note: cumulDelta is not modified)
133  decimal currentCumulDelta = r->getCumulDelta() + delta;
134 
135  // If the path difference is below the MaxPathDifference threshold, return true, else return false
136  return (currentCumulDelta <= AcousticRaytracerConfiguration::get()->MaxPathDifference);
137 }
138 
139 bool ValidRay::computeRealImpact(Ray* r, Intersection* inter, Cylindre* cylindre, vec3& impact)
140 {
141  // First segment: 2 times the ray's incoming direction
142  vec3 p1 = r->getPosition();
143  vec3 p2 = r->getPosition() + r->getDirection() * inter->t * 2.;
144 
145  // Second segment: diffraction edge
146  vec3 p3 = cylindre->getVertices()->at(cylindre->getLocalVertices()->at(0));
147  vec3 p4 = cylindre->getVertices()->at(cylindre->getLocalVertices()->at(1));
148 
149  // Find the shortest segment S between the ray and the diffraction edge
150  vec3* pa = new vec3(); // extremity of S on the ray
151  vec3* pb = new vec3(); // extremity of S on the diffraction edge
152 
153  decimal* mua = new decimal(); // position of a along the ray
154  decimal* mub = new decimal(); // position of b along the diffraction edge
155 
156  bool res = LineLineIntersect(p1, p2, p3, p4, pa, pb, mua, mub);
157 
158  impact = *pb; // pb corrsponds to the impact of the ray on the diffraction edge
159 
160  delete pa;
161  delete pb;
162  delete mua;
163  delete mub;
164 
165  return res;
166 }
167 
168 bool ValidRay::isRayPassesNearRidge(Ray* r, const vec3& impact, const vec3& realImpact)
169 {
170  vec3 closestPoint;
171  // compute length from last reflection to the closest point on the ray from realImpact
172  decimal length = r->computePertinentLength(realImpact, impact, closestPoint);
173 
174  // compute the thickness of the diffracted ray
175  decimal thick = r->getThickness(length, true);
176 
177  // compute the distance between the realImpact and the closestPoint
178  decimal closestDistance = realImpact.distance(closestPoint);
179 
180  // return true if the closest point on the ray from realImpact is within the thickness of the ray
181  return (closestDistance <= (thick / 2.));
182 }
183 
185 {
186  Cylindre* cylindre = (Cylindre*)(inter->p);
187 
188  vec3 impact = r->getPosition() + r->getDirection() * inter->t;
189 
191  // Test if creating a new diffraction is allowed (depends on path length difference)
192  if (config->UsePathDifValidation && !pathDiffValidationForDiffraction(r, impact))
193  {
194  return false;
195  }
196 
197  // Compute the real impact of the ray on the ridge
198  // Define first segment
199  vec3 realImpact;
200  if (!computeRealImpact(r, inter, cylindre, realImpact))
201  {
202  return false;
203  }
204 
205  // Validate the creation of event using distance from the ridge (if needed)
206  if (config->DiffractionUseDistanceAsFilter && !isRayPassesNearRidge(r, impact, realImpact))
207  {
208  return ValidRay::validRayWithDoNothingEvent(r, inter);
209  }
210 
211  // Create a diffraction event
212  vec3 from = realImpact - r->getPosition();
213  from.normalize();
214  Diffraction* newEvent = new Diffraction(realImpact, from, (Cylindre*)(inter->p));
215  boost::shared_ptr<Event> SPEv(newEvent);
216 
217  // Define the number of rays to throw
218  unsigned int diff_nb_rays = 0;
219  if (config->NbRayWithDiffraction > 0)
220  {
221  diff_nb_rays = config->NbRayWithDiffraction;
222  }
223  else
224  {
225  diff_nb_rays = (unsigned int)(r->getSource()->getSampler()->computeDiffractionNbr(
226  (decimal)(M_PIDIV2 - newEvent->getAngle())));
227  }
228 
229  // Reduce (if needed) number of rays thrown depending on the diffraction order
230  if (config->DiffractionDropDownNbRays)
231  {
232  diff_nb_rays =
233  (unsigned int)(diff_nb_rays / pow(static_cast<float>(2), static_cast<int>(r->getDiff())));
234  }
235 
236  diff_nb_rays += 1; // DO NOT MOVE/CONCATENATE THIS OPERATION ON UPPER LINES !!!
237  newEvent->setNbResponseLeft(diff_nb_rays); // Set the number of rays to throw
238 
239  // Add the event to the list
240  r->addEvent(SPEv);
241  r->setNbDiffraction(r->getDiff() + 1);
242  vec3 newDir;
243  if (newEvent->getResponse(newDir))
244  {
245  r->setPosition(realImpact);
246  r->setDirection(newDir);
247 
248  return true;
249  }
250 
251  return true;
252 }
253 #ifdef _ALLOW_TARGETING_
254 void ValidRay::appendDirectionToEvent(boost::shared_ptr<Event> e, TargetManager& targets)
255 {
256  std::vector<vec3>& ponctualTargets = targets.getTargets();
257 
258  std::vector<vec3> acceptableTargets;
259  for (unsigned int i = 0; i < ponctualTargets.size(); i++)
260  {
261  vec3 response = ponctualTargets.at(i) - e->getPosition();
262  response.normalize();
263  if (e->isAcceptableResponse(response))
264  {
265  acceptableTargets.push_back(response);
266  }
267  }
268 
269  if (acceptableTargets.size() < static_cast<unsigned int>(e->getNbResponseLeft()))
270  {
271  for (unsigned int i = 0; i < acceptableTargets.size(); i++)
272  {
273  e->appendTarget(acceptableTargets.at(i), true);
274  }
275  }
276  else
277  {
278  for (unsigned int i = 0; i < static_cast<unsigned int>(e->getNbResponseLeft()); i++)
279  {
280  int index = rand() % e->getNbResponseLeft();
281  e->appendTarget(acceptableTargets.at(index), true);
282  }
283  }
284 }
285 #endif // _ALLOW_TARGETING_
@ SPECULARREFLEXION
Definition: Event.h:26
Class defining the configuration of the acoustic ray tracer.
bool UsePathDifValidation
Flag to activate path validations during diffraction.
unsigned int NbRayWithDiffraction
Number of rays to throw during diffraction.
static AcousticRaytracerConfiguration * get()
Get access to the configuration.
double MaxPathDifference
Parameter (by default 24) for path validations during diffraction.
Cylinder class.
Definition: Cylindre.h:27
Diffraction class Event.
Definition: Diffraction.h:31
virtual void setNbResponseLeft(int _nbResponseLeft)
Set the number of remaining rays to launch.
Definition: Diffraction.h:41
virtual bool getResponse(vec3 &r, bool force=false)
Computes the next response of the event in function of the number of responses left.
virtual double getAngle()
Get the angle between the incident ray and the diffraction edge.
Definition: Diffraction.h:90
Event that is only a point in a ray path with no direction change.
Definition: DoNothing.h:25
virtual bool getResponse(vec3 &r, bool force=false)
Return a direction vector for the impact. Ray direction vector in response of the event.
Definition: DoNothing.h:45
: 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
void setDirection(vec3 _direction)
set the direction if the ray
Definition: Ray.h:376
unsigned int getReflex() const
Return the reflections number encountered by the ray.
Definition: Ray.h:176
void setPosition(vec3 _position)
set the starting point ray
Definition: Ray.h:366
void setNbDiffraction(unsigned int _nbDiffraction)
set the diffractions number for the ray
Definition: Ray.h:466
Source * getSource()
Return the ray source.
Definition: Ray.h:227
void setCumulDistance(decimal _cumulDistance)
set the cumulative distance by the ray computed at each step
Definition: Ray.h:476
void setNbReflexion(unsigned int _nbReflexion)
set the reflections number for the ray
Definition: Ray.h:456
decimal getThickness(const decimal &distance, bool diffraction)
Compute the thickness of the ray after having traveled a certain distance depending on the type of so...
Definition: Ray.cpp:266
vec3 getPosition() const
Return starting point ray.
Definition: Ray.h:356
Base * getLastPertinentEventOrSource(typeevent evType=DIFFRACTION)
Return a pointer to the last event of type evType or source if none.
Definition: Ray.cpp:225
vec3 getDirection() const
Return direction of the ray.
Definition: Ray.h:346
decimal getCumulDelta() const
Return the cumulative difference between the rays length and its length when ignoring diffractions an...
Definition: Ray.h:286
decimal computePertinentLength(const vec3 &ref, const vec3 &lastPos, vec3 &closestPoint)
Compute ray length from last pertinent event (i.e. source or last diffraction) to the nearest point o...
Definition: Ray.cpp:149
void setCumulDelta(decimal _cumulDelta)
set the cumulative walking step difference by the ray computed at each step
Definition: Ray.h:486
unsigned int getDiff() const
Return the diffractions number encountered by the ray.
Definition: Ray.h:166
vec3 computeLocalOrigin(Base *ev)
Return position of ev which might be a source or an event.
Definition: Ray.h:137
void addEvent(boost::shared_ptr< Event > _event)
Definition: Ray.h:496
decimal getCumulDistance() const
Return the cumulative length since the last reflection event.
Definition: Ray.h:296
std::vector< boost::shared_ptr< Event > > * getEvents()
Return the events array encountered by the ray.
Definition: Ray.h:195
virtual unsigned int computeDiffractionNbr(const decimal &theta)
Return the number of rays to launch after a diffraction event.
Definition: Sampler.h:110
vector< vec3 > * getVertices()
Definition: Shape.h:127
vector< unsigned int > * getLocalVertices()
Get local vertices.
Definition: Shape.h:133
virtual vec3 getNormal(const vec3 pos=vec3())
Get normal.
Definition: Shape.h:145
vec3 getPosition()
Get the position of the Source.
Definition: Source.h:105
Sampler * getSampler()
Get the Sampler of this Source.
Definition: Source.h:151
Specular reflection class Event.
virtual bool getResponse(vec3 &r, bool force=false)
Return a direction vector for the impact. Ray direction vector in response of the event.
Class to manage targets.
Definition: TargetManager.h:27
std::vector< vec3 > & getTargets()
Return the targets.
Definition: TargetManager.h:42
#define M_PIDIV2
Definition: mathlib.h:68
bool isRayPassesNearRidge(Ray *r, const vec3 &impact, const vec3 &realImpact)
Return True if ray passes near enough the ridge for it be in the thickness of the ray.
Definition: ValidRay.cpp:168
bool validRayWithDoNothingEvent(Ray *r, Intersection *inter)
Definition: ValidRay.cpp:24
void computeCumulDistance(Ray *r, const vec3 &impact)
adds the distance between impact and the last REFLECTION/SOURCE of the ray to the cumulDistance of th...
Definition: ValidRay.cpp:85
bool pathDiffValidationForReflection(Ray *r, const vec3 &impact)
Tests if the addition of a reflection event at position impact does not cause the pathDifference to e...
Definition: ValidRay.cpp:100
bool validTriangleWithSpecularReflexion(Ray *r, Intersection *inter)
Definition: ValidRay.cpp:46
bool computeRealImpact(Ray *r, Intersection *inter, Cylindre *cylindre, vec3 &impact)
Try to compute the intersection of the ray and the ridge.
Definition: ValidRay.cpp:139
bool pathDiffValidationForDiffraction(Ray *r, const vec3 &impact)
Tests if the addition of a diffraction event at position impact does not cause the pathDifference to ...
Definition: ValidRay.cpp:121
bool validCylindreWithDiffraction(Ray *r, Intersection *inter)
Definition: ValidRay.cpp:184
bool LineLineIntersect(const vec3 &p1, const vec3 &p2, const vec3 &p3, const vec3 &p4, vec3 *pa, vec3 *pb, decimal *mua, decimal *mub)
Calculate the segment between the lines (p1,p2) and (p3,p4)
Definition: mathlib.h:1460
float decimal
Definition: mathlib.h:45
base_vec3< decimal > vec3
Definition: mathlib.h:381
Intersection struct.
Definition: Shape.h:46
decimal t
Definition: Shape.h:48
Shape * p
Definition: Shape.h:49