Commit 7fc0faab authored by Armin Erraji's avatar Armin Erraji

Included perceptional culling in tree structure.

parent 07702f17
......@@ -24,18 +24,17 @@ namespace ITAPropagationPathSim
CPathEngine();
void Configure(const bool bFilterNotNeighbouredEdges = false, const bool bFilterIlluminatedRegionDiffraction = false,
const bool bFilterEdgeToEdgeIntersectedPaths = false,
const bool bFilterEmitterToEdgeIntersectedPaths = false,
const bool bFilterSensorToEdgeIntersectedPaths = false,
const bool bFilterIntersectedPaths = false,
const int iNumberIterationApexCalculation = 5,
const float fIntersectionTestResolution = 0.001f,
const float fAccumulatedAngleThreshold = -1.0f);
const bool bFilterEdgeToEdgeIntersectedPaths = false, const bool bFilterEmitterToEdgeIntersectedPaths = false,
const bool bFilterSensorToEdgeIntersectedPaths = false, const bool bFilterIntersectedPaths = false,
const int iNumberIterationApexCalculation = 5, const float fIntersectionTestResolution = 0.001f);
void SetAbortionCriteria(const int iMaxDiffractions, const int iMaxReflections, const int iMaxCombinedOrder,
const float fMaxLevelReduction=-1.f, const float fReflectionPenalty=0.f, const float fDiffractionPenalty=0.f,
const float fAccumulatedAngleThreshold = -1.0f);
void InitializePathEnvironment(shared_ptr<const Halfedge::CMeshModelList> pMeshModelList);
void ApplyEmitter(shared_ptr<CEmitter> pEmitter, const int iMaxDiffractions, const int iMaxReflections, const int iMaxCombinedOrder);
void ApplyEmitter(shared_ptr<CEmitter> pEmitter);
void ApplySensor(shared_ptr<CSensor> pSensor);
......@@ -52,10 +51,17 @@ namespace ITAPropagationPathSim
vector<CPropagationShapeShared> m_vpPropagationLists; //!< Vector of all propagation shape visible to the emitter with each one pointing to up to one child with the last one visible to the sensor
shared_ptr<CEmitter> m_pEmitter; //!< Const pointer to emitter
shared_ptr<CSensor> m_pSensor; //!< Const pointer to sensor
//Abortion criteria
unique_ptr<const int> m_pMaxReflectionOrder; //!< Const pointer to maximum reflection order
unique_ptr<const int> m_pMaxDiffractionOrder; //!< Const pointer to maximum diffraction order
unique_ptr<const int> m_pMaxCombinedOrder; //!< Const pointer to maximum order of combined diffractions and reflections
unique_ptr<const float> m_pMaxLevelReduction; //!< Const pointer to maximum level reduction
unique_ptr<const float> m_pMaxPropagationRange; //!< Const pointer to maximum propagation range [m]
unique_ptr<const float> m_pReflectionPenalty; //!< Const pointer to reflection penalty
unique_ptr<const float> m_pDiffractionPenalty; //!< Const pointer to angle independent diffraction penalty
unique_ptr <const float> m_pAccumulatedAngleThreshold; //!< Threshold for the accumulated diffraction angle
//Filter member variables
unique_ptr<const bool> m_pFilterNotNeighbouredEdges; //!< Filter not neighboured edges for faster filter calculation
unique_ptr<const bool> m_pFilterIlluminatedRegionDiffraction; //!< Boolean pointer whether to ignore diffractions that can only diffract in illuminated regions(and have therefore a low impact to the whole IR)
......@@ -64,7 +70,6 @@ namespace ITAPropagationPathSim
unique_ptr<const bool> m_pFilterSensorToEdgeIntersectedPaths; //!< Boolean pointer for filtering paths, where always an intersection between the sensor and an edge occurs
unique_ptr<const bool> m_pFilterIntersectedPaths; //!< Boolean pointer for for filtering paths if intersection occurs
unique_ptr<const float> m_pIntersectionTestResolution; //!< Resolution for intersection test
unique_ptr <const float> m_pAccumulatedAngleThreshold; //!< Threshold for the accumulated diffraction angle
unique_ptr <const size_t> m_pNumberIterationApexCalc; //!< Number of iterations for the calculation of the aperture points
......@@ -80,7 +85,7 @@ namespace ITAPropagationPathSim
//Create the propagation tree
void CreatePropagationTree();
void RecursiveAddChildrenToTree(const CPropagationShapeShared & pPropagationShapeChildIn, CPropagationShapeShared& vpShapeChildCopyOut, int iReflectionOrder, int iDiffractionOrder, int iCombinedOrder);
void RecursiveAddChildrenToTree(const CPropagationShapeShared & pPropagationShapeChildIn, CPropagationShapeShared& vpShapeChildCopyOut, int iReflectionOrder, int iDiffractionOrder, int iCombinedOrder, float fAccumulatedPenalty, float fFirstDistance, float fSecondDistance, float fLevelDropAtFirstEdge);
//Create the propagation list
void CreatePropagationLists();
......
......@@ -25,11 +25,12 @@ namespace ITAPropagationPathSim
typedef shared_ptr<CPropagationFace> CPropagationFaceShared;
typedef shared_ptr<CPropagationEdge> CPropagationEdgeShared;
typedef OpenMesh::PolyMesh_ArrayKernelT<> CITAMesh;
typedef map <CPropagationShapeShared, vector<CPropagationShapeShared>> CShapesMap;
typedef map <size_t, vector<CPropagationShapeShared>> CShapesMap;
typedef string MeshModelHandle;
typedef pair < MeshModelHandle, CITAMesh::FaceHandle> PropagationFaceHandle;
//Old implementation[TODO: remove]
//struct ImageReceiverMap : map<PropagationFaceHandle, shared_ptr<ImageReceiverMap>>
/* {
shared_ptr<VistaVector3D> v3ImageReceiver;
......@@ -46,7 +47,7 @@ namespace ITAPropagationPathSim
class CPropagationShape
{
public:
//Public member variables
//---Public member variables-----------------------------------------------------------------------
//!< Type of shape(e.g. edge or face)
enum EShapeType
......@@ -65,6 +66,12 @@ namespace ITAPropagationPathSim
//!< Point of interaction
unique_ptr<VistaVector3D> v3InteractionPoint;
//!< Shape handle
OpenMesh::BaseHandle hShape;
//!< Vertices of shape
vector<shared_ptr<VistaVector3D>> vv3Vertices;
//!< Parent shape(previous shape)
weak_ptr<CPropagationShape> pParent;
......@@ -74,24 +81,50 @@ namespace ITAPropagationPathSim
shared_ptr<string> sMeshModelName;
//Public member functions
//!< Barycenter of shape (used for boundary sphere)
shared_ptr<VistaVector3D> v3Barycenter;
//!< Radius of boundary sphere (longest distance from barycenter to vertex)
float fRadius;
//!< Minimum distance to previous shape
float fMinimumDistance = 0.0f;
//!< Distance level drop
float fDistanceLevelDrop = 0.0f;
//---Public member functions--------------------------------------------------------------------
//!<Copy shape
void CopyFrom(const CPropagationShape& oPropagationShapeIn);
private:
//!< Set barycenter and radius of the boundary sphere of the shape
bool SetBoundarySphere();
bool SetMinimumDistance(const CPropagationShape& oPropagationShape);
//!< Set fMinimumDistance to point (e.g. emitter)
bool SetMinimumDistance(const VistaVector3D& v3Point);
//!< Calculate minimum distance to point (e.g. emitter) and return value
float CalculateMinimumDistance(const VistaVector3D& v3Point);
//!< Calculate the level drop due to the propagation of the sound
float CalculateLevelDrop(float& fFirstDistance, float& fSecondDistance, float& fLevelDropAtFirstEdge);
size_t GetIdentifier() const;
};
class CPropagationFace : public CPropagationShape
{
public:
//Public member variables
//---Public member variables--------------------------------------------------------------------
CITAMesh::FaceHandle hFace; //Face handle corresponding to propagation face
shared_ptr<VistaPlane> pPlane; //Plane built up by face
vector<shared_ptr<VistaVector3D>> vv3Vertices;
shared_ptr<VistaVector3D> v3ImageSource;
shared_ptr<VistaVector3D> v3ImageEdgeSourceStart;
......@@ -99,15 +132,26 @@ namespace ITAPropagationPathSim
shared_ptr<bool> pHasValidImageSource;
//Public member functions
//---Public member functions----------------------------------------------------------------------
//!< Copy face
void CopyFrom(const CPropagationFace& oPropagationFaceIn);
// Set minimum distance to shape
bool SetMinimumDistance(const CPropagationShape& oPropagationShape);
// Set fMinimumDistance to point (e.g. emitter)
bool SetMinimumDistance(const VistaVector3D& v3Point);
// Calculate minimum distance to point (e.g. emitter) and return value
float CalculateMinimumDistance(const VistaVector3D& v3Point);
};
class CPropagationEdge : public CPropagationShape
{
public:
//Public member variables
//---Public member variables-------------------------------------------------------------------------
CITAMesh::HalfedgeHandle hHalfedge;
CITAMesh::EdgeHandle hEdge;
CITAMesh::FaceHandle hMainFace;
......@@ -129,9 +173,22 @@ namespace ITAPropagationPathSim
//!< If the relative position lies between 0.0(at v3FromVertex) and 1.0(at v3ToVertex), the interaction point is on the edge
unique_ptr<float> pRelativeInteractionPoint;
//Public member functions
//---Public member functions-----------------------------------------------------------------------
//!< Copy edge
void CopyFrom(const CPropagationEdge& oPropagationEdgeIn);
// Set minimum distance to shape
bool SetMinimumDistance(const CPropagationShape& oPropagationShape);
// Set fMinimumDistance to point (e.g. emitter)
bool SetMinimumDistance(const VistaVector3D& v3Point);
// Calculate minimum distance to point (e.g. emitter) and return value
float CalculateMinimumDistance(const VistaVector3D& v3Point);
//!< Calculate the level drop due to the propagation of the sound
float CalculateLevelDrop(float& fFirstDistance, float& fSecondDistance, float& fLevelDropAtFirstEdge);
};
}
}
......
......@@ -28,14 +28,14 @@ namespace ITAPropagationPathSim
//Because of possibly occuring reflections during the paths, E_in can contain mirrored versions of the direction edge directions.
//VertexDiff contains the vista vectors of the difference between the FromVertices of two edges
vector<shared_ptr<VistaVector3D>> vpE_in, vpE_out;
vector<unique_ptr<VistaVector3D>> vpVertexDiff;
vector<unique_ptr<VistaVector3D>> vpStartVertexDiff;
//RelativeApexPosition contains the aperture position relative to the edge from- and to-vertices.
//vfE_square contains the squared length of the edge
vector<float> vfRelativeApexPosition, vfE_square;
//The propagation paths always starts at the position of the emitter
shared_ptr<VistaVector3D> v3LastFromVertex = make_shared<VistaVector3D>(pEmitter->v3InteractionPoint);
shared_ptr<VistaVector3D> v3LastStartVertex = make_shared<VistaVector3D>(pEmitter->v3InteractionPoint);
//The propagation paths always ends at the location of the sensor
//Because of possible faces after the last edge, a local copy of the location is needed and will eventually mirrored in a later step
......@@ -58,6 +58,18 @@ namespace ITAPropagationPathSim
}
else //pShape is an edge
{
//If pEdge is the first edge and the parent face contains no valid image source, the whole path is not able to be valid
if (pEdge == nullptr)
{
if (!pShape->pParent.expired() && pShape->pParent.lock()->iShapeType == CPropagationShape::FACE)
{
auto pFace = static_pointer_cast<CPropagationFace>(pShape->pParent.lock());
if (pFace->pHasValidImageSource == false)
continue;
}
}
pEdge = static_pointer_cast<CPropagationEdge>(pShape);
//The start value for the aperture position is located on the mid of the edge
......@@ -74,19 +86,19 @@ namespace ITAPropagationPathSim
{
vpE_in.push_back(make_shared<VistaVector3D>(*pEdge->v3ImageEdgeReceiverEnd - *pEdge->v3ImageEdgeReceiverStart));
vpVertexDiff.push_back(make_unique<VistaVector3D>(*v3LastFromVertex - *pEdge->v3ImageEdgeReceiverStart));
vpStartVertexDiff.push_back(make_unique<VistaVector3D>(*v3LastStartVertex - *pEdge->v3ImageEdgeReceiverStart));
}
else
{
//The input edge direction does not have to be mirrored and is therefore the same direction as the output edge direction
vpE_in.push_back(vpE_out.back());
vpVertexDiff.push_back(make_unique<VistaVector3D>(*v3LastFromVertex - *pEdge->v3StartVertex));
vpStartVertexDiff.push_back(make_unique<VistaVector3D>(*v3LastStartVertex - *pEdge->v3StartVertex));
}
//Set the current from vertex as the next "last" one
v3LastFromVertex = pEdge->v3StartVertex;
v3LastStartVertex = pEdge->v3StartVertex;
//Set the next shape to the child of the current shape
pShape = pShape->pChild;
......@@ -94,30 +106,32 @@ namespace ITAPropagationPathSim
}
}
//Old implementation(image edge source used instead of image receiver):
//If the last shape is not an edge, the image receiver is needed for the calculation of the aperture points
while (pShape != nullptr && pShape->iShapeType == CPropagationShape::FACE)
{
auto pPlane = static_pointer_cast<CPropagationFace>(pShape)->pPlane;
//while (pShape != nullptr && pShape->iShapeType == CPropagationShape::FACE)
//{
// auto pPlane = static_pointer_cast<CPropagationFace>(pShape)->pPlane;
// // Check for a possible visibility
// if (ITAGeoUtils::IsPointInFrontOfPlane(*pPlane, v3SensorPosition))
// {
// //Mirror the (imaged) sensor until an edge is reached
// ITAGeoUtils::MirrorPointOverPlane(v3SensorPosition, *static_pointer_cast<CPropagationFace>(pShape)->pPlane, v3SensorPosition);
// pShape = pShape->pParent.lock();
// }
// else //If the (imaged) sensor is not visible, the whole path is invalid
// {
// bValidAperturePoints = false;
// break;
// }
//}
//
////In the last step, the path candidate could be declared as invalid.
////If it is invalid, go to the next path candidate
//if (bValidAperturePoints == false)
// continue;
// Check for a possible visibility
if (ITAGeoUtils::IsPointInFrontOfPlane(*pPlane, v3SensorPosition))
{
//Mirror the (imaged) sensor until an edge is reached
ITAGeoUtils::MirrorPointOverPlane(v3SensorPosition, *static_pointer_cast<CPropagationFace>(pShape)->pPlane, v3SensorPosition);
pShape = pShape->pParent.lock();
}
else //If the (imaged) sensor is not visible, the whole path is invalid
{
bValidAperturePoints = false;
break;
}
}
//In the last step, the path candidate could be declared as invalid.
//If it is invalid, go to the next path candidate
if (bValidAperturePoints == false)
continue;
//Add path candidate to list and go to the next path candidate, if no edge was found
if (pEdge == nullptr)
......@@ -126,8 +140,22 @@ namespace ITAPropagationPathSim
continue;
}
//Add the (maybe imaged) receiver to the differences vector
vpVertexDiff.push_back(make_unique<VistaVector3D>(*v3LastFromVertex - v3SensorPosition));
//If the last shape is not an edge, the image edge source of the last edge is needed for the calculation of the aperture points
if (pShape != nullptr && pShape->iShapeType == CPropagationShape::FACE)
{
auto pFace = static_pointer_cast<CPropagationFace>(pShape);
//If the image edge source is empty, there is no valid image edge and thus, the path is invalid
if (pFace->v3ImageEdgeSourceStart == nullptr)
continue;
v3LastStartVertex = pFace->v3ImageEdgeSourceStart;
vpE_out.back() = make_shared<VistaVector3D>(*pFace->v3ImageEdgeSourceEnd - *pFace->v3ImageEdgeSourceStart);
}
//Add the receiver to the differences vector
vpStartVertexDiff.push_back(make_unique<VistaVector3D>(*v3LastStartVertex - v3SensorPosition));
for (size_t iCurrentIteration = 0; iCurrentIteration < iNumberIterations; iCurrentIteration++)
......@@ -139,15 +167,15 @@ namespace ITAPropagationPathSim
//The length is determined by the relative aperture position of the last iteration
//The first direction vector(between the source and the first (imaged) edge) does not contain a correction vector for the source
vfDirectionVectorLength.push_back((*vpVertexDiff[0] - vfRelativeApexPosition[0] * *vpE_in[0]).GetLength());
vfDirectionVectorLength.push_back((*vpStartVertexDiff[0] - vfRelativeApexPosition[0] * *vpE_in[0]).GetLength());
for (int i = 1; i < vfRelativeApexPosition.size(); i++)
{
vfDirectionVectorLength.push_back((*vpVertexDiff[i] - (vfRelativeApexPosition[i] * *vpE_in[i]) + (vfRelativeApexPosition[i - 1] * *vpE_out[i - 1])).GetLength());
vfDirectionVectorLength.push_back((*vpStartVertexDiff[i] - (vfRelativeApexPosition[i] * *vpE_in[i]) + (vfRelativeApexPosition[i - 1] * *vpE_out[i - 1])).GetLength());
}
//The last direction vector(between the last edge and the (imaged) receiver) does not contain a correction vector for the receiver
vfDirectionVectorLength.push_back((*vpVertexDiff.back() - vfRelativeApexPosition.back() * *vpE_out.back()).GetLength());
vfDirectionVectorLength.push_back((*vpStartVertexDiff.back() - vfRelativeApexPosition.back() * *vpE_out.back()).GetLength());
// The terms can be written in tridiagonal matrix form as following:
// b[i-1] * vfRelativeApexPosition[i-1] + a[i] * vfRelativeApexPosition[i] + b[i] * vfRelativeApexPosition[i+1] = c[i]
......@@ -164,7 +192,7 @@ namespace ITAPropagationPathSim
for (int i = 0; i < vfE_square.size(); i++)
{
a.push_back(vfE_square[i] * (1 / vfDirectionVectorLength[i] + 1 / vfDirectionVectorLength[i + 1]));
c.push_back(vpVertexDiff[i]->Dot(*vpE_in[i]) / vfDirectionVectorLength[i] - vpVertexDiff[i + 1]->Dot(*vpE_out[i]) / vfDirectionVectorLength[i + 1]);
c.push_back(vpStartVertexDiff[i]->Dot(*vpE_in[i]) / vfDirectionVectorLength[i] - vpStartVertexDiff[i + 1]->Dot(*vpE_out[i]) / vfDirectionVectorLength[i + 1]);
}
for (int i = 0; i < vfE_square.size() - 1; i++)
{
......
......@@ -8,26 +8,164 @@ void CPropagationShape::CopyFrom(const CPropagationShape & oPropagationShapeIn)
{
iShapeType = oPropagationShapeIn.iShapeType;
vv3Vertices = oPropagationShapeIn.vv3Vertices;
pParent = oPropagationShapeIn.pParent;
pChild = oPropagationShapeIn.pChild;
vpChildren = oPropagationShapeIn.vpChildren;
sMeshModelName = oPropagationShapeIn.sMeshModelName;
v3Barycenter = oPropagationShapeIn.v3Barycenter;
fRadius = oPropagationShapeIn.fRadius;
fMinimumDistance = oPropagationShapeIn.fMinimumDistance;
hShape = oPropagationShapeIn.hShape;
pIsIlluminableBySensor = oPropagationShapeIn.pIsIlluminableBySensor;
}
bool CPropagationShape::SetBoundarySphere()
{
//the shape must have at least one vertex
if (vv3Vertices.size() < 1)
return false;
//Set barycenter
v3Barycenter = make_shared<VistaVector3D>(0,0,0,1);
for (auto& v3Vertex : vv3Vertices)
{
*v3Barycenter += *v3Vertex;
}
*v3Barycenter /= vv3Vertices.size();
//Set the radius of the sphere(longest distance between vertex and shape)
fRadius = 0.0f;
for (auto& v3Vertex : vv3Vertices)
{
fRadius = fmaxf(fRadius,(*v3Barycenter- *v3Vertex).GetLength());
}
return true;
}
bool ITAPropagationPathSim::CombinedModel::CPropagationShape::SetMinimumDistance(const CPropagationShape & oPropagationShape)
{
if (v3Barycenter == nullptr || oPropagationShape.v3Barycenter == nullptr)
return false;
//Calculate the distance between two spheres
fMinimumDistance = CalculateMinimumDistance (*oPropagationShape.v3Barycenter) - oPropagationShape.fRadius;
//Negative distances are not possible
fMinimumDistance = fmaxf(fMinimumDistance, 0.0f);
return true;
}
bool CPropagationShape::SetMinimumDistance(const VistaVector3D & v3Point)
{
if (v3Barycenter == nullptr)
return false;
fMinimumDistance = CalculateMinimumDistance(v3Point);
return true;
}
float CPropagationShape::CalculateMinimumDistance(const VistaVector3D & v3Point)
{
//Calculate the distance between two spheres
float fMinimumDistance = (*v3Barycenter - v3Point).GetLength() - fRadius;
//Negative distances are not possible
fMinimumDistance = fmaxf(fMinimumDistance, 0.0f);
return fMinimumDistance;
}
float CPropagationShape::CalculateLevelDrop(float & fFirstDistance, float & fSecondDistance, float & fLevelDropAtFirstEdge)
{
float fLevelDrop = 0;
if (fLevelDropAtFirstEdge < 0.0f)
{
fFirstDistance += fMinimumDistance;
fLevelDrop =fmaxf(0.0f, 20 * log10f(fFirstDistance));
}
else
{
fSecondDistance += fMinimumDistance;
float fAdditionalLevelDrop = 10 * log10f(fSecondDistance*(fSecondDistance + fFirstDistance) / fFirstDistance);
fLevelDrop = fLevelDropAtFirstEdge + fmaxf(0.0f,fAdditionalLevelDrop);
}
return fLevelDrop;
}
size_t CPropagationShape::GetIdentifier() const
{
hash<string> hashString;
hash<EShapeType> hashType;
hash<OpenMesh::BaseHandle> hashShape;
size_t identifier = hashString(*sMeshModelName);
identifier ^= hashType(iShapeType) + 0x9e3779b9 + (identifier << 6) + (identifier >> 2); // Magic number: 2 ^ 32 / ((1 + sqrt(5)) / 2) = 0x9e3779b9
identifier ^= hashShape(hShape) + 0x9e3779b9 + (identifier << 6) + (identifier >> 2);
return identifier;
}
void CPropagationFace::CopyFrom(const CPropagationFace & oPropagationFaceIn)
{
CPropagationShape::CopyFrom(oPropagationFaceIn);
hFace = oPropagationFaceIn.hFace;
pPlane = oPropagationFaceIn.pPlane;
vv3Vertices = oPropagationFaceIn.vv3Vertices;
v3ImageSource = oPropagationFaceIn.v3ImageSource;
v3ImageEdgeSourceStart = oPropagationFaceIn.v3ImageEdgeSourceStart;
v3ImageEdgeSourceEnd = oPropagationFaceIn.v3ImageEdgeSourceEnd;
pHasValidImageSource = oPropagationFaceIn.pHasValidImageSource;
}
bool CPropagationFace::SetMinimumDistance(const CPropagationShape & oPropagationShape)
{
if (v3Barycenter == nullptr || oPropagationShape.v3Barycenter == nullptr)
return false;
//Calculate the distance between two spheres
fMinimumDistance = CalculateMinimumDistance(*oPropagationShape.v3Barycenter) - oPropagationShape.fRadius;
//Negative distances are not possible
fMinimumDistance = fmaxf(fMinimumDistance, 0.0f);
return true;
}
bool CPropagationFace::SetMinimumDistance(const VistaVector3D & v3Point)
{
if (v3Barycenter == nullptr)
return false;
fMinimumDistance = CalculateMinimumDistance(v3Point);
return true;
}
float CPropagationFace::CalculateMinimumDistance(const VistaVector3D & v3Point)
{
//Distance to plane
float fPlaneDistance = fabs(pPlane->CalcDistance(v3Point));
//Distance to sphere
float fSphereDistance = CPropagationShape::CalculateMinimumDistance(v3Point);
//Maximum of both is used
return max(fPlaneDistance, fSphereDistance);
}
void CPropagationEdge::CopyFrom(const CPropagationEdge & oPropagationEdgeIn)
{
CPropagationShape::CopyFrom(oPropagationEdgeIn);
......@@ -44,3 +182,65 @@ void CPropagationEdge::CopyFrom(const CPropagationEdge & oPropagationEdgeIn)
v3ImageEdgeReceiverEnd = oPropagationEdgeIn.v3ImageEdgeReceiverEnd;
pHasValidImageEdge = oPropagationEdgeIn.pHasValidImageEdge;
}
bool CPropagationEdge::SetMinimumDistance(const CPropagationShape & oPropagationShape)
{
if (v3Barycenter == nullptr || oPropagationShape.v3Barycenter == nullptr)
return false;
//Calculate the distance between two spheres
fMinimumDistance = CalculateMinimumDistance(*oPropagationShape.v3Barycenter) - oPropagationShape.fRadius;
//Negative distances are not possible
fMinimumDistance = fmaxf(fMinimumDistance, 0.0f);
return true;
}
bool CPropagationEdge::SetMinimumDistance(const VistaVector3D & v3Point)
{
if (v3Barycenter == nullptr)
return false;
fMinimumDistance = CalculateMinimumDistance(v3Point);
return true;
}
float CPropagationEdge::CalculateMinimumDistance(const VistaVector3D & v3Point)
{
//Distance to projection on line defined by edge
VistaPlane plane1, plane2;
plane1.SetOrigin(*v3StartVertex);
plane2.SetOrigin(*v3StartVertex);
plane1.SetNormVector(*v3MainFaceNormal);
plane2.SetNormVector(*v3OppositeFaceNormal);
//Project point on first plane. Thereafter, project projected point on second plane
VistaVector3D v3Projection = plane1.CalcNearestPointOnPlane(v3Point);
v3Projection = plane2.CalcNearestPointOnPlane(v3Projection);
float fLineDistance = (v3Point - v3Projection).GetLength();
//Distance to sphere
float fSphereDistance = CPropagationShape::CalculateMinimumDistance(v3Point);
//Maximum of both is used
return max(fLineDistance, fSphereDistance);
}
float CPropagationEdge::CalculateLevelDrop(float & fFirstDistance, float & fSecondDistance, float & fLevelDropAtFirstEdge)
{
float fLevelDrop = 0;
fLevelDrop = CPropagationShape::CalculateLevelDrop(fFirstDistance, fSecondDistance, fLevelDropAtFirstEdge);
//This is the first edge
if (fLevelDropAtFirstEdge < 0.0f)
{
fLevelDropAtFirstEdge = fLevelDrop;
}
return fLevelDrop;
}
......@@ -84,7 +84,7 @@ int main( int iNumInArgs, char* pcInArgs[] )
const bool bOnlyNeighbouredEdgeDiffraction = false;
const bool bDiffractionOnlyIntoShadowRegion = true;
const bool bFilterNotVisiblePathsBetweenEdges = false; //Intersection test between edges(expensive)
const bool bFilterNotVisiblePointToEdge = false; //Intersection test between emitter/sensor and edges
const bool bFilterNotVisiblePointToEdge = true; //Intersection test between emitter/sensor and edges
const bool bFilterNotVisiblePaths = true; //Intersection test of calculated sub paths
const float fIntersectionTestResolution = 0.001;
const int iNumIterations = 5;//!< Number of iterations for the calculation of the aperture points
......@@ -94,6 +94,10 @@ int main( int iNumInArgs, char* pcInArgs[] )
const int iMaxReflectionOrder = 3;
const int iMaxCombinedOrder =