Code_TYMPAN  4.4.0
Industrial site acoustic simulation
TYVisibilityCone.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 "TYVisibilityCone.h"
17 
18 VisibilityCone::VisibilityCone(const OPoint3D& pA, const OPoint3D& pB, const OPoint3D& pC)
19 {
20  _pA2D = OPoint3D{pA._x, pA._y, 0.};
21  _pB2D = OPoint3D{pB._x, pB._y, 0.};
22  _pC2D = OPoint3D{pC._x, pC._y, 0.};
26 }
27 
28 bool VisibilityCone::segmentIsVisibleInCone(const OSegment3D& segmentToTest) const
29 {
30  // unpack points
31  const OPoint3D& pM{segmentToTest._ptA};
32  const OPoint3D& pN{segmentToTest._ptB};
33 
34  // project all points on horizontal plane z = 0
35  const OPoint3D pM2D{pM._x, pM._y, 0.};
36  const OPoint3D pN2D{pN._x, pN._y, 0.};
37 
38  return pointIsInCone(pM2D) || pointIsInCone(pN2D) || segmentIntersectsBorderCone(pM2D, pN2D);
39 }
40 
41 bool VisibilityCone::pointIsInCone(const OPoint3D& pM2D) const
42 {
43  const OVector3D vMB = buildVector2D(pM2D, _pB2D);
44  const OVector3D vMC = buildVector2D(pM2D, _pC2D);
45 
46  return vMB.scalar(_nAB) >= 0 && vMC.scalar(_nAC) >= 0;
47 }
48 
50 {
51  const OVector3D vMN = buildVector2D(pM2D, pN2D);
52  const OVector3D vAM = buildVector2D(_pA2D, pM2D);
53  return segmentIntersectsSemiLine2D(_vAB, vMN, vAM) || segmentIntersectsSemiLine2D(_vAC, vMN, vAM);
54 }
55 
57 {
58  const OVector3D ez{0., 0., 1.};
59  const OVector3D vBC{_pB2D, _pC2D};
60 
61  _nAB = _vAB.cross(ez);
62  if (_nAB.scalar(vBC) > 0)
63  {
64  _nAB.invert();
65  }
66 
67  _nAC = _vAC.cross(ez);
68  if (_nAC.scalar(vBC) < 0)
69  {
70  _nAC.invert();
71  }
72 }
73 
74 bool segmentIntersectsSemiLine2D(const OVector3D& vAB, const OVector3D& vMN, const OVector3D& vAM)
75 {
76  // there is intersection in 1 point <=> AB * s - MN * t = AM has a unique solution with t in (0, 1) and s
77  // > 0
78 
79  double s, t;
80 
81  if (solveLin2x2(vAB._x, -vMN._x, vAB._y, -vMN._y, vAM._x, vAM._y, s, t))
82  {
83  if (t >= 0. && t <= 1. && s >= 0.)
84  {
85  return true;
86  }
87  }
88 
89  return false;
90 }
91 
92 bool solveLin2x2(double a11, double a12, double a21, double a22, double b1, double b2, double& x1, double& x2)
93 {
94  const double det{a11 * a22 - a21 * a12};
95 
96  // infinity of solution or no solution case
97  if (std::abs(det) < EPSILON_13)
98  {
99  return false;
100  }
101 
102  // unique solution case
103  const double det_inv{1. / det};
104  x1 = (a22 * b1 - a12 * b2) * det_inv;
105  x2 = (a11 * b2 - a21 * b1) * det_inv;
106 
107  return true;
108 }
#define EPSILON_13
Definition: 3d.h:41
NxReal s
Definition: NxVec3.cpp:317
bool solveLin2x2(double a11, double a12, double a21, double a22, double b1, double b2, double &x1, double &x2)
Solve a 2x2 linear system of equations Ax = b.
bool segmentIntersectsSemiLine2D(const OVector3D &vAB, const OVector3D &vMN, const OVector3D &vAM)
Test if the segment [MN] intersects the semi-line [AB) in 2D (horizontal plane z = 0)
OVector3D buildVector2D(const OPoint3D &pA2D, const OPoint3D &pB2D)
Optimized way to build a vector in 2D (horizontal plane z = 0) from point A to B To use as a replacem...
double _y
y coordinate of OCoord3D
Definition: 3d.h:283
double _x
x coordinate of OCoord3D
Definition: 3d.h:282
The 3D point class.
Definition: 3d.h:487
Class to define a segment.
Definition: 3d.h:1141
OPoint3D _ptA
Point A of the segment.
Definition: 3d.h:1253
OPoint3D _ptB
Point B of the segment.
Definition: 3d.h:1255
The 3D vector class.
Definition: 3d.h:298
void invert()
Inverts this vector.
Definition: 3d.cpp:236
double scalar(const OVector3D &vector) const
Performs the scalar product between this object and another vector.
Definition: 3d.cpp:210
OVector3D cross(const OVector3D &vector) const
Cross product.
Definition: 3d.cpp:196
bool segmentIntersectsBorderCone(const OPoint3D &pM2D, const OPoint3D &pN2D) const
Test if the segment [MN] intersects the borders of the visibility cone.
bool pointIsInCone(const OPoint3D &pM2D) const
Test if the point M lies inside the visibility cone.
bool segmentIsVisibleInCone(const OSegment3D &segmentToTest) const
Test if a segment is visible in the visibility cone.
void setupNormalsOfCone()
Compute exterior normal of the cone.
VisibilityCone(const OPoint3D &pA, const OPoint3D &pB, const OPoint3D &pC)
Builds a visibility cone spanned from point A into points B and C This cone is such that [BC] segment...