Code_TYMPAN  4.4.0
Industrial site acoustic simulation
PostTreatment.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) <2012-2024> <EDF-DTG> <FRANCE>
3  * This file is part of Code_TYMPAN (R).
4  * Code_TYMPAN (R) is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * Code_TYMPAN (R) is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  * See the GNU General Public License for more details.
12  * You should have received a copy of the GNU General Public License along
13  * with Code_TYMPAN (R). If not, see <https://www.gnu.org/licenses/>.
14  */
15 
16 #include <set>
17 #include <vector>
18 #include <map>
19 
21 #include "Geometry/Triangle.h"
22 #include "Geometry/Cylindre.h"
23 #include "PostTreatment.h"
24 
25 #include <math.h>
26 
27 typedef std::pair<unsigned int, unsigned int> segment;
28 typedef std::map<segment, std::vector<Shape*>> mapSegmentShapes;
29 
31 {
32 
33  Triangle* triangle = dynamic_cast<Triangle*>(shape);
34  if (!shape)
35  {
36  return;
37  }
38 
39  std::vector<unsigned int>* vertices = triangle->getLocalVertices();
40  for (unsigned int i = 0; i < vertices->size(); i++)
41  {
42  segment seg1 = std::pair<unsigned int, unsigned int>(vertices->at(i),
43  vertices->at((i + 1) % (vertices->size())));
44  mapSegmentShapes::iterator it = currentMap.find(seg1);
45 
46  if (it == currentMap.end())
47  {
48  std::vector<Shape*> newList;
49  newList.push_back(shape);
50  currentMap.insert(std::pair<segment, std::vector<Shape*>>(seg1, newList));
51  }
52  else
53  {
54  it->second.push_back(shape);
55  }
56 
57  segment seg2 = std::pair<unsigned int, unsigned int>(vertices->at((i + 1) % (vertices->size())),
58  vertices->at(i));
59  it = currentMap.find(seg2);
60 
61  if (it == currentMap.end())
62  {
63  std::vector<Shape*> newList;
64  newList.push_back(shape);
65  currentMap.insert(std::pair<segment, std::vector<Shape*>>(seg2, newList));
66  }
67  else
68  {
69  it->second.push_back(shape);
70  }
71  }
72 }
73 
74 bool isAcceptableEdge(const segment& seg, Shape* p1, Shape* p2, decimal& angleOuverture,
75  std::vector<bool>& isGround)
76 {
77 
78  // First we test is the current segment does not belong to both a construct and the ground
79  if (!p1->isSol() && !p2->isSol() && isGround[seg.first] && isGround[seg.second])
80  {
81  return false;
82  }
83 
84  /*
85  we test if p1 vs p2 angle is greater than PI/2+angleMax
86  else they are considered as colinear and no diffraction cylinder is built
87  seg
88  |
89  p1 |p2/
90  | /
91  __________|/
92  comp \
93  \ normal
94  \
95 
96  */
97 
98  // Minimal angle (other PI) between two face to allow building of a diffraction cylinder
99  float angleMax = (decimal)(AcousticRaytracerConfiguration::get()->AngleDiffMin * M_PI / 180);
100 
101  // Compute "mean" normal between the two faces
102  vec3 normal = p1->getNormal() + p2->getNormal();
103  normal.normalize();
104 
105  // Search for a vertex of the first shape not belonging to seg
106  std::vector<unsigned int>* vertices = p1->getLocalVertices();
107  vec3 otherVertex;
108  for (unsigned int i = 0; i < vertices->size(); i++)
109  {
110  if (vertices->at(i) != seg.first && vertices->at(i) != seg.second)
111  {
112  otherVertex = p1->getVertices()->at(vertices->at(i));
113  break;
114  }
115  }
116 
117  // Find a vector othogonal to seg and lying in the first shape
118  vec3 proj =
119  otherVertex.closestPointOnLine(p1->getVertices()->at(seg.first), p1->getVertices()->at(seg.second));
120  vec3 comp = otherVertex - proj;
121  comp.normalize();
122 
123  // Compute the angle betwwen comp and the "mean" normal
124  decimal cos_angle = comp.dot(normal);
125  angleOuverture = 2.f * acos(cos_angle);
126 
127  if (cos_angle < cos(M_PI / 2. + angleMax / 2.))
128  {
129  return true;
130  }
131 
132  return false;
133 }
134 
136 {
137  // define diffraction cylinder diameter
138  float cylinderThick = (float)AcousticRaytracerConfiguration::get()->CylindreThick;
139 
140  // Create a list of segments common to two faces
141  mapSegmentShapes segmentList;
142  std::vector<Shape*>* shapes = scene->getShapes();
143  std::vector<bool> isGround(scene->getVertices()->size(), false);
144 
145  for (unsigned int i = 0; i < shapes->size(); i++)
146  {
147  Shape* shape = shapes->at(i);
148  registerSegmentsFromShapes(shape, segmentList);
149 
150  if (shape->isSol())
151  {
152  for (unsigned int j = 0; j < shape->getLocalVertices()->size(); j++)
153  {
154  isGround[shape->getLocalVertices()->at(j)] = true;
155  }
156  }
157  }
158 
159  std::set<segment> validSegment;
160 
161  for (mapSegmentShapes::iterator it = segmentList.begin(); it != segmentList.end(); it++)
162  {
163  // If segment is owned by 2 shapes, we test angle between them
164  if (it->second.size() == 2)
165  {
166  std::set<segment>::iterator itset1 = validSegment.find(it->first);
167  std::set<segment>::iterator itset2 =
168  validSegment.find(std::pair<unsigned int, unsigned int>(it->first.second, it->first.first));
169  decimal angleOuverture = NAN;
170  if (itset1 == validSegment.end() && itset2 == validSegment.end() &&
171  isAcceptableEdge(it->first, it->second.at(0), it->second.at(1), angleOuverture, isGround))
172  {
173  validSegment.insert(it->first);
174  Cylindre* cylindre = new Cylindre(it->second.at(0), it->second.at(1), scene->getVertices(),
175  it->first.first, it->first.second, cylinderThick);
176  cylindre->setAngleOuverture(angleOuverture);
177  scene->addShape(cylindre);
178  }
179  }
180  }
181 
182  return true;
183 }
184 
185 #ifdef _ALLOW_TARGETING_
186 bool PostTreatment::findTargetsForNMPB(Scene* scene, std::vector<Recepteur>& recepteurs,
187  TargetManager& targetManager, decimal density)
188 {
189 
190  std::vector<Shape*>* shapes = scene->getShapes();
191  for (unsigned int i = 0; i < shapes->size(); i++)
192  {
193  if (dynamic_cast<Triangle*>(shapes->at(i)))
194  {
195  /*Triangle* t = dynamic_cast<Triangle*>(shapes->at(i));
196  if(!(t->getMaterial()->isNatural)){
197  vec3 normale = t->getNormal();
198  vec2 normale2D = vec2(sqrt(normale.x * normale.x + normale.y * normale.y),normale.z);
199  normale2D.normalize();
200  //Si l'angle de la normale par rapport a l'horizontale est plus faible que 15 degres pour etre
201  coherent avec la definition de surface verticale de la NMPB if(acos(normale2D.dot(vec2(1.,0.))) <
202  M_PI / 12.){ std::vector<vec3> samples; t->sample(density,samples);
203  targetManager.registerTargets(samples);
204  }
205  }*/
206  }
207  else if (dynamic_cast<Cylindre*>(shapes->at(i)))
208  {
209  Cylindre* c = dynamic_cast<Cylindre*>(shapes->at(i));
210  std::vector<vec3> samples;
211  c->sample(density, samples);
212  targetManager.registerTargets(samples);
213  }
214  }
215 
216  for (unsigned int i = 0; i < recepteurs.size(); i++)
217  {
218  targetManager.registerTarget(recepteurs.at(i).getPosition());
219  }
220 
221  return true;
222 }
223 
224 void PostTreatment::appendDirectionToSources(TargetManager* targets, std::vector<Source>& sources)
225 {
226  /*for(unsigned int i = 0; i < sources.size(); i++){
227  vec3 pos = sources.at(i).getPosition();
228  for(unsigned int j = 0; j < targets.size(); j++){
229  vec3 newDir = targets.at(j) - pos;
230  newDir.normalize();
231  sources.at(i).addDirection(newDir);
232  }
233  sources.at(i).setInitialRayCount(targets.size());
234  }*/
235  for (unsigned int i = 0; i < sources.size(); i++)
236  {
237  sources.at(i).setTargetManager(targets);
238  sources.at(i).setInitialTargetCount(sources.at(i).getInitialRayCount());
239  }
240 }
241 #endif
NxReal c
Definition: NxVec3.cpp:317
std::pair< unsigned int, unsigned int > segment
bool isAcceptableEdge(const segment &seg, Shape *p1, Shape *p2, decimal &angleOuverture, std::vector< bool > &isGround)
void registerSegmentsFromShapes(Shape *shape, mapSegmentShapes &currentMap)
std::map< segment, std::vector< Shape * > > mapSegmentShapes
double CylindreThick
Diffraction cylinder diameter.
static AcousticRaytracerConfiguration * get()
Get access to the configuration.
Cylinder class.
Definition: Cylindre.h:27
void setAngleOuverture(decimal angle)
Definition: Cylindre.h:43
This class mainly define a mesh (list of Shape) used by the Simulation object.
Definition: Scene.h:51
std::vector< Shape * > * getShapes()
Return all the shapes.
Definition: Scene.h:88
void addShape(Shape *shape)
Add a shape to the list.
Definition: Scene.h:68
std::vector< vec3 > * getVertices()
Return all the vertices.
Definition: Scene.h:97
base class for shapes (Cylindre, Mesh, Sphere, Triangle,...)
Definition: Shape.h:57
std::vector< unsigned int > * getLocalVertices()
Get local vertices.
Definition: Shape.h:133
std::vector< vec3 > * getVertices()
Definition: Shape.h:127
bool isSol() const
Get/Set the flag _isSol (ground or not)
Definition: Shape.h:194
virtual vec3 getNormal(const vec3 pos=vec3())
Get normal.
Definition: Shape.h:145
Class to manage targets.
Definition: TargetManager.h:27
bool registerTargets(std::vector< vec3 > &newTargets)
Register a vector of targets.
bool registerTarget(const vec3 newTarget)
Register a new target.
Triangle class.
Definition: Triangle.h:25
#define M_PI
Pi.
Definition: color.cpp:25
bool constructEdge(Scene *scene)
Build the edges list of a scene.
float decimal
Definition: mathlib.h:45
base_vec3< decimal > vec3
Definition: mathlib.h:387