24 std::ifstream file(filePath);
30 const std::string key =
"REFLECTION_ORDER=";
33 while (std::getline(file, line))
35 if (line.compare(0, key.size(), key) == 0)
39 return static_cast<size_t>(std::stoul(line.substr(key.size())));
52 double seuilConfondus)
59 const double ux = B.
_x - A.
_x;
60 const double uy = B.
_y - A.
_y;
61 const double uz = B.
_z - A.
_z;
63 const double vx = D.
_x - C.
_x;
64 const double vy = D.
_y - C.
_y;
65 const double vz = D.
_z - C.
_z;
68 const double nx = uy * vz - uz * vy;
69 const double ny = uz * vx - ux * vz;
70 const double nz = ux * vy - uy * vx;
72 const double anx = std::abs(nx);
73 const double any = std::abs(ny);
74 const double anz = std::abs(nz);
83 double a1, a2, u1, u2, c1, c2, v1, v2;
85 if ((anx >= any) && (anx >= anz))
97 else if ((any >= anx) && (any >= anz))
122 const double w1 = c1 - a1;
123 const double w2 = c2 - a2;
125 const double det = u1 * v2 - u2 * v1;
133 const double t = (w1 * v2 - w2 * v1) / det;
134 const double s = (w1 * u2 - w2 * u1) / det;
136 const double lenU = std::sqrt(ux * ux + uy * uy + uz * uz);
137 const double lenV = std::sqrt(vx * vx + vy * vy + vz * vz);
138 const double paramTol = seuilConfondus / std::max(1.0, std::max(lenU, lenV));
140 if ((t < -paramTol) || (t > 1.0 + paramTol) || (
s < -paramTol) || (
s > 1.0 + paramTol))
145 pt.
_x = A.
_x + t * ux;
146 pt.
_y = A.
_y + t * uy;
147 pt.
_z = A.
_z + t * uz;
162 zmin = zmin.
div(C3 * C2);
167 const double d_SR,
const double d,
const double z,
187 const double dMax = std::max(d_SS, d_SR);
188 const double dMin =
std::min(d_SS, d_SR);
189 const double numerator = (dMax + e) * dMin * d;
191 for (std::size_t i = 0; i < TY_SPECTRE_OCT_NB_ELMT; ++i)
195 kMeteo[i] = std::exp(-(1.0 / 2000.0) * std::sqrt(numerator / (2.0 * (z - zMin[i]))));
217 for (std::size_t i = 0; i < TY_SPECTRE_OCT_NB_ELMT; ++i)
221 const double term = 2.0 + (C2 / lambda[i]) * c3[i] * z;
222 dz[i] = 10.0 * std::log10(1.0 + term * kmeteo[i]);
233 double distance)
const
237 const std::string solverConfigPath =
"C:\\projects\\tympan_tools\\17534-3\\solver_conf.txt";
238 const size_t defaultReflectionOrder = 1;
239 const size_t multipleReflectionOrder =
242 if (multipleReflectionOrder == 0)
247 std::vector<ReflectingSegmentCache> reflectingSegments;
248 reflectingSegments.reserve(tabIntersect.size());
252 for (
const auto& inter : tabIntersect)
254 if (inter.isInfra && inter.bIntersect[1])
260 if (reflectingSegments.empty())
265 std::vector<const TYSIntersection*> currentCombination;
266 currentCombination.reserve(multipleReflectionOrder);
268 std::deque<OPoint3D> currentImageSources;
269 currentImageSources.push_back(ray.
_ptA);
275 currentImageSources, tabIntersect, ray, source, TabChemins, distance);
279 const std::deque<std::deque<TYSIntersection>>& tabIntersectSegments,
280 const std::deque<OPoint3D>& pathPoints2D,
double hs,
double hr,
double& Gs,
double& Gm,
double& Gr)
const
305 const std::deque<std::deque<TYSIntersection>>& tabIntersectSegments,
306 const std::deque<OPoint3D>& pathPoints2D,
double hs,
double& Gs)
const
308 double heightRatio = 30.0;
311 if (pathPoints2D.size() < 2)
316 if (tabIntersectSegments.size() != pathPoints2D.size() - 1)
321 const double srcZoneLength = heightRatio * hs;
330 double traversedLength = 0.0;
331 double coveredLength = 0.0;
332 double weightedGroundSum = 0.0;
334 for (
size_t i = 0; i + 1 < pathPoints2D.size(); ++i)
336 const OPoint3D& ptA = pathPoints2D[i];
337 const OPoint3D& ptB = pathPoints2D[i + 1];
340 const double currentSegmentLength = currentSegment.
longueur();
347 const double remainingLength = srcZoneLength - traversedLength;
357 if (remainingLength < currentSegmentLength)
359 const double alpha = remainingLength / currentSegmentLength;
361 ptEndZone.
_x = ptA.
_x + alpha * (ptB.
_x - ptA.
_x);
362 ptEndZone.
_y = ptA.
_y + alpha * (ptB.
_y - ptA.
_y);
363 ptEndZone.
_z = ptA.
_z + alpha * (ptB.
_z - ptA.
_z);
365 double GCurSeg = 0.0;
366 double dpCurSeg = 0.0;
367 computeGZone(ptA, ptEndZone, GCurSeg, dpCurSeg, tabIntersectSegments[i]);
369 weightedGroundSum += GCurSeg;
370 coveredLength += dpCurSeg;
371 traversedLength = srcZoneLength;
377 double GCurSeg = 0.0;
378 double dpCurSeg = 0.0;
379 computeGZone(ptA, ptB, GCurSeg, dpCurSeg, tabIntersectSegments[i]);
381 weightedGroundSum += GCurSeg;
382 coveredLength += dpCurSeg;
383 traversedLength += currentSegmentLength;
388 Gs = weightedGroundSum / coveredLength;
399 const std::deque<std::deque<TYSIntersection>>& tabIntersectSegments,
400 const std::deque<OPoint3D>& pathPoints2D,
double hr,
double& Gr)
const
402 double heightRatio = 30.0;
405 if (pathPoints2D.size() < 2)
410 if (tabIntersectSegments.size() != pathPoints2D.size() - 1)
415 const double rcpZoneLength = heightRatio * hr;
424 double traversedLength = 0.0;
425 double coveredLength = 0.0;
426 double weightedGroundSum = 0.0;
428 for (
size_t i = pathPoints2D.size() - 1; i > 0; --i)
430 const OPoint3D& ptA = pathPoints2D[i - 1];
431 const OPoint3D& ptB = pathPoints2D[i];
434 const double currentSegmentLength = currentSegment.
longueur();
441 const double remainingLength = rcpZoneLength - traversedLength;
449 if (remainingLength < currentSegmentLength)
451 const double alpha = remainingLength / currentSegmentLength;
456 ptStartZone.
_x = ptB.
_x + alpha * (ptA.
_x - ptB.
_x);
457 ptStartZone.
_y = ptB.
_y + alpha * (ptA.
_y - ptB.
_y);
458 ptStartZone.
_z = ptB.
_z + alpha * (ptA.
_z - ptB.
_z);
460 double GCurSeg = 0.0;
461 double dpCurSeg = 0.0;
462 computeGZone(ptStartZone, ptB, GCurSeg, dpCurSeg, tabIntersectSegments[i - 1]);
464 weightedGroundSum += GCurSeg;
465 coveredLength += dpCurSeg;
466 traversedLength = rcpZoneLength;
472 double GCurSeg = 0.0;
473 double dpCurSeg = 0.0;
474 computeGZone(ptA, ptB, GCurSeg, dpCurSeg, tabIntersectSegments[i - 1]);
476 weightedGroundSum += GCurSeg;
477 coveredLength += dpCurSeg;
478 traversedLength += currentSegmentLength;
483 Gr = weightedGroundSum / coveredLength;
494 const std::deque<std::deque<TYSIntersection>>& tabIntersectSegments,
495 const std::deque<OPoint3D>& pathPoints2D,
double hs,
double hr,
double& Gm)
const
497 double heightRatio = 30.0;
500 if (pathPoints2D.size() < 2)
505 if (tabIntersectSegments.size() != pathPoints2D.size() - 1)
510 const double srcZoneLength = heightRatio * hs;
511 const double rcpZoneLength = heightRatio * hr;
515 for (
size_t i = 0; i + 1 < pathPoints2D.size(); ++i)
527 const double middleZoneBegin = srcZoneLength;
528 const double middleZoneEnd = dp - rcpZoneLength;
530 double traversedLength = 0.0;
531 double coveredLength = 0.0;
532 double weightedGroundSum = 0.0;
534 for (
size_t i = 0; i + 1 < pathPoints2D.size(); ++i)
536 const OPoint3D& ptA = pathPoints2D[i];
537 const OPoint3D& ptB = pathPoints2D[i + 1];
540 const double currentSegmentLength = currentSegment.
longueur();
547 const double segmentBegin = traversedLength;
548 const double segmentEnd = traversedLength + currentSegmentLength;
551 const double overlapBegin = std::max(segmentBegin, middleZoneBegin);
552 const double overlapEnd =
std::min(segmentEnd, middleZoneEnd);
556 const double alphaBegin = (overlapBegin - segmentBegin) / currentSegmentLength;
557 const double alphaEnd = (overlapEnd - segmentBegin) / currentSegmentLength;
560 ptZoneBegin.
_x = ptA.
_x + alphaBegin * (ptB.
_x - ptA.
_x);
561 ptZoneBegin.
_y = ptA.
_y + alphaBegin * (ptB.
_y - ptA.
_y);
562 ptZoneBegin.
_z = ptA.
_z + alphaBegin * (ptB.
_z - ptA.
_z);
565 ptZoneEnd.
_x = ptA.
_x + alphaEnd * (ptB.
_x - ptA.
_x);
566 ptZoneEnd._y = ptA.
_y + alphaEnd * (ptB.
_y - ptA.
_y);
567 ptZoneEnd._z = ptA.
_z + alphaEnd * (ptB.
_z - ptA.
_z);
569 double GCurSeg = 0.0;
570 double dpCurSeg = 0.0;
571 computeGZone(ptZoneBegin, ptZoneEnd, GCurSeg, dpCurSeg, tabIntersectSegments[i]);
573 weightedGroundSum += GCurSeg;
574 coveredLength += dpCurSeg;
577 traversedLength = segmentEnd;
582 Gm = weightedGroundSum / coveredLength;
598 const bool sameOrder = (seg1.
_ptA == seg2.
_ptA) && (seg1.
_ptB == seg2.
_ptB);
600 const bool reverseOrder = (seg1.
_ptA == seg2.
_ptB) && (seg1.
_ptB == seg2.
_ptA);
602 return sameOrder || reverseOrder;
606 const std::vector<const TYSIntersection*>& currentCombination,
607 const std::deque<OPoint3D>& imageSourcesList,
const OPoint3D& receptorPoint,
608 std::deque<OPoint3D>& reflectionPointsList)
const
610 reflectionPointsList.clear();
612 if (currentCombination.empty())
620 if (imageSourcesList.size() != currentCombination.size() + 1)
630 for (
int i =
static_cast<int>(currentCombination.size()) - 1; i >= 0; --i)
632 const OPoint3D& currentImageSource = imageSourcesList[i + 1];
633 const OSegment3D& currentBarrier = currentCombination[i]->segInter[1];
641 reflectionPointsList.clear();
645 reflectionPointsList.push_front(currentReflectionPoint);
646 nextPoint = currentReflectionPoint;
653 const std::vector<const TYSIntersection*>& barrierCombination,
654 const std::deque<OPoint3D>& reflectionPointsList,
const std::deque<TYSIntersection>& tabIntersect,
657 const size_t reflectionOrder = barrierCombination.size();
659 if (reflectionPointsList.size() != reflectionOrder)
664 std::deque<OPoint3D> pathPoints;
665 pathPoints.push_back(sourcePoint);
666 for (
const auto& point : reflectionPointsList)
668 pathPoints.push_back(point);
670 pathPoints.push_back(receptorPoint);
674 for (
size_t i = 0; i <= reflectionOrder; ++i)
676 const OSegment3D pathSegment(pathPoints[i], pathPoints[i + 1]);
678 for (
const auto& sceneBarrier : tabIntersect)
691 if (sceneBarrier.segInter[1].intersects(pathSegment, intersectionPoint,
TYSEUILCONFONDUS))
702 const std::vector<const TYSIntersection*>& barrierCombination,
703 const std::deque<OPoint3D>& imageSourcesList,
const std::deque<OPoint3D>& reflectionPointsList,
705 double distance)
const
707 const size_t reflectionOrder = barrierCombination.size();
709 if (reflectionOrder == 0)
714 if (imageSourcesList.size() != reflectionOrder + 1)
719 if (reflectionPointsList.size() != reflectionOrder)
728 std::deque<OPoint3D> pathPoints;
729 std::deque<OPoint3D> pathPoints2D;
730 pathPoints.push_back(directRay.
_ptA);
732 for (
const auto& point : reflectionPointsList)
734 pathPoints.push_back(point);
737 pathPoints.push_back(directRay.
_ptB);
740 double pathLength = 0.0;
745 for (
size_t i = 0; i + 1 < pathPoints.size(); ++i)
748 pathLength +=
segment.longueur();
755 pathPoints2D.push_back(A2D);
757 pathPoints2D.push_back(B2D);
761 etape.
_pt = pathPoints[0];
764 const OSegment3D firstLeg(pathPoints[0], pathPoints[1]);
768 tabEtapes.push_back(etape);
771 for (
size_t i = 0; i < reflectionOrder; ++i)
776 if (material ==
nullptr)
781 if (!barrierCombination[i]->pFaceGeomData)
787 etape.
_pt = reflectionPointsList[i];
791 tabEtapes.push_back(etape);
797 double hs{0.0}, hr{0.0};
800 double Gs{0.0}, Gm{0.0}, Gr{0.0};
804 std::deque<std::deque<TYSIntersection>> tabIntersectSegments;
806 tabIntersectSegments.resize(reflectionOrder + 1);
807 for (
size_t i = 0; i < reflectionOrder + 1; ++i)
809 seg =
OSegment3D{pathPoints[i], pathPoints[i + 1]};
815 std::unique_ptr<TYChemin9613Solver> chemin =
createChemin();
817 chemin->setLongueur(pathLength);
818 chemin->setDistance(distance);
819 chemin->calcAttenuation(tabEtapes, *
_pSolverAtmos, dp, hs, hr, Gs, Gm, Gr);
823 for (
size_t i = 0; i < reflectionOrder; ++i)
826 const OPoint3D& O = pathPoints[i + 1];
827 const OPoint3D& R = pathPoints[i + 2];
829 const double a = barrierCombination[i]->pFaceGeomData->a;
830 const double h = barrierCombination[i]->pFaceGeomData->h;
831 const OVector3D& normal = barrierCombination[i]->pFaceGeomData->n;
833 chemin->calcMinimalExtensionCondition(S, O, R, a, h, normal);
836 TabChemins.push_back(*chemin);
859 const double norm2 = cache.
ux * cache.
ux + cache.
uy * cache.
uy + cache.
uz * cache.
uz;
886 const double apx = inputPoint.
_x - cache.
ax;
887 const double apy = inputPoint.
_y - cache.
ay;
888 const double apz = inputPoint.
_z - cache.
az;
890 const double t = (apx * cache.
ux + apy * cache.
uy + apz * cache.
uz) * cache.
invNorm2;
892 const double hx = cache.
ax + t * cache.
ux;
893 const double hy = cache.
ay + t * cache.
uy;
894 const double hz = cache.
az + t * cache.
uz;
897 reflectedPoint.
_x = 2.0 * hx - inputPoint.
_x;
898 reflectedPoint.
_y = 2.0 * hy - inputPoint.
_y;
899 reflectedPoint.
_z = 2.0 * hz - inputPoint.
_z;
903 size_t reflectionOrder,
const std::vector<ReflectingSegmentCache>& reflectingSegments,
904 std::vector<const TYSIntersection*>& currentCombination, std::deque<OPoint3D>& currentImageSources,
905 const std::deque<TYSIntersection>& tabIntersect,
const OSegment3D& ray,
908 if (currentCombination.size() == reflectionOrder)
913 for (
const auto&
segment : reflectingSegments)
916 if (!currentCombination.empty() && currentCombination.back() ==
segment.barrier)
921 const OPoint3D& previousImageSource = currentImageSources.back();
926 currentCombination.push_back(
segment.barrier);
927 currentImageSources.push_back(nextImageSource);
932 TabChemins, distance);
935 currentImageSources, tabIntersect, ray, source, TabChemins, distance);
937 currentImageSources.pop_back();
938 currentCombination.pop_back();
943 const std::vector<const TYSIntersection*>& currentCombination,
944 const std::deque<OPoint3D>& imageSourcesList,
const std::deque<TYSIntersection>& tabIntersect,
946 double distance)
const
948 std::deque<OPoint3D> reflectionPointsList;
965 return buildReflectionPath(currentCombination, imageSourcesList, reflectionPointsList, ray, source,
966 TabChemins, distance);
#define INTERS_NULLE
No intersection.
std::pair< unsigned int, unsigned int > segment
std::deque< TYChemin9613Solver > TYTabChemin9613Solver
TYChemin collection.
std::deque< TYEtape9613Solver > TYTabEtape9613Solver
TYEtape collection.
double _y
y coordinate of OCoord3D
double _z
z coordinate of OCoord3D
double _x
x coordinate of OCoord3D
Class to define a segment.
virtual double longueur() const
Return the segment length.
virtual int symetrieOf(const OPoint3D &pt, OPoint3D &ptSym) const
Return the symmetrical of a point.
OPoint3D _ptA
Point A of the segment.
virtual int intersects(const OSegment3D &seg, OPoint3D &pt, double seuilConfondus) const
Return the intersection point with another segment.
OPoint3D _ptB
Point B of the segment.
OSpectreAbstract & div(const OSpectreAbstract &spectre) const
Division of two spectrums.
double * getTabValReel() override
Get an array of the real values of the spectrum.
TYAcousticModel9613Solver2024(TYSolver9613Solver2024 &solver)
bool validateReflectionCandidate(const std::vector< const TYSIntersection * > &barrierCombination, const std::deque< OPoint3D > &reflectionPointsList, const std::deque< TYSIntersection > &tabIntersect, const OPoint3D &sourcePoint, const OPoint3D &receptorPoint) const
Validate a reflection candidate against the reflecting segments of the scene. A reflection candidate ...
bool computeGroundFactorMiddleZone(const std::deque< std::deque< TYSIntersection >> &tabIntersectSegments, const std::deque< OPoint3D > &pathPoints2D, double hs, double hr, double &Gm) const
Compute the ground factor of the middle zone for a reflected path.
std::unique_ptr< TYChemin9613Solver > createChemin() const override
bool sameReflectingSegment(const TYSIntersection &lhs, const TYSIntersection &rhs) const
Check whether two reflecting segments are identical in plane EL.
ReflectingSegmentCache makeReflectingSegmentCache(const TYSIntersection &inter) const
Build the geometric cache associated with one reflecting segment.
void buildReflectionPathsStreaming(size_t reflectionOrder, const std::vector< ReflectingSegmentCache > &reflectingSegments, std::vector< const TYSIntersection * > ¤tCombination, std::deque< OPoint3D > ¤tImageSources, const std::deque< TYSIntersection > &tabIntersect, const OSegment3D &ray, const tympan::AcousticSource &source, TYTabChemin9613Solver &TabChemins, double distance) const
Recursively build and validate reflection paths in streaming mode.
OSpectreOctave calculZMin(const double C2, const OSpectreOctave &C3) const override
Compute zmin, the min value of z for which the barrier attenuation Dz is null. This minimum distance ...
void computeCheminReflexion(const std::deque< TYSIntersection > &tabIntersect, const OSegment3D &ray, const tympan::AcousticSource &source, TYTabChemin9613Solver &TabChemins, double distance) const override
Compute the list of path generated by reflection on the vertical walls.
void reflectPointAboutCachedLine(const ReflectingSegmentCache &cache, const OPoint3D &inputPoint, OPoint3D &reflectedPoint) const
Reflect a point about the support line stored in a reflecting segment cache.
bool getGroundfactors(const std::deque< std::deque< TYSIntersection >> &tabIntersectSegments, const std::deque< OPoint3D > &pathPoints2D, double hs, double hr, double &Gs, double &Gm, double &Gr) const
Get ground factors for source, middle and receptor zones for a reflected path.
bool computeGroundFactorReceiverZone(const std::deque< std::deque< TYSIntersection >> &tabIntersectSegments, const std::deque< OPoint3D > &pathPoints2D, double hr, double &Gr) const
Compute the ground factor of the receptor zone for a reflected path.
bool computeGroundFactorSourceZone(const std::deque< std::deque< TYSIntersection >> &tabIntersectSegments, const std::deque< OPoint3D > &pathPoints2D, double hs, double &Gs) const
Compute the ground factor of the source zone for a reflected path.
bool buildReflectionPathForCombination(const std::vector< const TYSIntersection * > ¤tCombination, const std::deque< OPoint3D > &imageSourcesList, const std::deque< TYSIntersection > &tabIntersect, const OSegment3D &ray, const tympan::AcousticSource &source, TYTabChemin9613Solver &TabChemins, double distance) const
Build a reflection path from the current reflecting segment combination.
OSpectreOctave calculDz(const double z, const double C2, const OSpectreOctave &C3, const OSpectreOctave &Kmeteo, const OSpectreOctave &zmin) const override
Compute Dz, the barrier attenuation for each octave band in dB.
bool buildReflectionPath(const std::vector< const TYSIntersection * > &barrierCombination, const std::deque< OPoint3D > &imageSourcesList, const std::deque< OPoint3D > &reflectionPointsList, const OSegment3D &directRay, const tympan::AcousticSource &source, TYTabChemin9613Solver &TabChemins, double distance) const
Build a reflection path from a valid reflecting segment combination.
bool buildReflectionPoints(const std::vector< const TYSIntersection * > ¤tCombination, const std::deque< OPoint3D > &imageSourcesList, const OPoint3D &receptorPoint, std::deque< OPoint3D > &reflectionPointsList) const
Build the list of reflection points associated with a reflecting segment combination.
OSpectreOctave calculKmeteo(const bool vertical, const double d_SS, const double d_SR, const double d, const double z, const double e, const OSpectreOctave &z_min) const override
Compute Kmeteo, the correction factor for meteorological effects.
Acoustic model for the 9613Solver.
TYSolver9613Solver & _solver
Reference to the solver.
bool computeGZone(const OPoint3D &ptDebut, const OPoint3D &ptFin, double &GZone, double &dpZone, const std::deque< TYSIntersection > &tabIntersect) const
Compute GZone and dpZone for the segment between ptDebut and ptFin.
bool computeSegmentEdgesHeights(double &hauteurA, double &hauteurB, const OSegment3D &meanSlope, const OSegment3D &ray) const
Compute heights relative to real ground, of the edges of a segment.
std::unique_ptr< AtmosphericConditions > _pSolverAtmos
void meanSlope(const OSegment3D &director, OSegment3D &slope) const
Create a segment corresponding to the projection of "director" segment on the ground.
OSpectreOctave _Absorption
absorption Spectrum
OPoint3D _pt
The starting point of this step.
ACOUSTIC_EVENT_TYPES _type
Acoustic event type.
void selectFaces(std::deque< TYSIntersection > &tabIntersect, const OSegment3D &rayon, const string &sourceVolumeId)
Delegate to _faceSelector the build of the array of intersections.
Describes building material.
ComplexSpectrum spectrum
Spectrum to store acoustic values at different frequencies.
Describes an acoustic source.
string volume_id
Volume id.
SourceDirectivityInterface * directivity
Pointer to the source directivity.
virtual Spectrum lwAdjustment(Vector direction, double distance)=0
< Pure virtual method to return directivity of the Source
bool intersectSegmentsFastInTheirPlane(const OSegment3D &segA, const OSegment3D &segB, OPoint3D &pt, double seuilConfondus)
size_t readReflectionOrderFromConfig(const std::string &filePath, size_t defaultValue)
Cache geometry associated with one reflecting segment.
const TYSIntersection * barrier
Data structure for intersections.