Commit 4046bfd9 authored by Armin Erraji's avatar Armin Erraji

Added construction functions for image sources, image edges and image receiver...

Added construction functions for image sources, image edges and image receiver as well as functions for the creation of the propagation lists
parent 9febe15b
#ifndef INCLUDE_WATCHER_DIFFRACTION_APERTURES
#define INCLUDE_WATCHER_DIFFRACTION_APERTURES
namespace ITAPropagationPathSim
{
namespace CombinatedModel
{
using namespace ITAGeo;
using namespace std;
namespace ImageConstruction
{
}
}
}
#endif // INCLUDE_WATCHER_DIFFRACTION_APERTURES
#ifndef INCLUDE_WATCHER_IMAGE_CONSTRUCTOR
#define INCLUDE_WATCHER_IMAGE_CONSTRUCTOR
#include<ITAPropagationPathSim/CombinatedModel/PropagationShapes.h>
// ITA includes
#include <ITAGeo/Base.h>
#include <ITAGeo/Halfedge/MeshModel.h>
#include <ITAGeo/Utils.h>
namespace ITAPropagationPathSim
{
namespace CombinatedModel
{
using namespace ITAGeo;
using namespace std;
namespace ImageConstruction
{
ITA_PROPAGATION_PATH_SIM_API bool ConstructImageSources(shared_ptr<const ITAGeo::CEmitter> pEmitter, vector<CPropagationShapeShared>& vpPropagationTree);
ITA_PROPAGATION_PATH_SIM_API bool ConstructImageReceivers(shared_ptr<const CSensor> pSensor, vector<CPropagationShapeShared>& vpPropagationLists, CShapesMap vpVisibilityMap, const int iMaxReflectionOrder);
ITA_PROPAGATION_PATH_SIM_API bool ConstructImageEdges(shared_ptr<const ITAGeo::CEmitter> pEmitter, vector<CPropagationShapeShared> vpPropagationTree);
}
}
}
#endif // INCLUDE_WATCHER_IMAGE_CONSTRUCTOR
#ifndef INCLUDE_WATCHER_COMBINED_PROPAGATION_ENGINE
#define INCLUDE_WATCHER_COMBINED_PROPAGATION_ENGINE
#include<ITAPropagationPathSim/CombinatedModel/PropagationShapes.h>
// ITA includes
......@@ -16,9 +19,12 @@ namespace ITAPropagationPathSim
public:
//Constructor
CPathEngine(shared_ptr<const ITAGeo::Halfedge::CMeshModelList> pMeshModelList);
CPathEngine(shared_ptr<const Halfedge::CMeshModelList> pMeshModelList);
void ApplyEmitter(shared_ptr<const CEmitter> pEmitter, const int iMaxDiffractions, const int iMaxReflections, const int iMaxCombinedOrder);
void ApplySensor(shared_ptr<const CSensor> pSensor);
void CreatePropagationTree(shared_ptr<const CEmitter> pEmitter, const int iMaxDiffractions = DiffractionOrder::DIFFRACTION_ORDER_2,const int iMaxReflections = ReflectionOrder::SPECULAR_REFLECTION_ORDER_2, const int iMaxCombinedOrder = Order::ORDER_3);
private:
......@@ -27,6 +33,7 @@ namespace ITAPropagationPathSim
shared_ptr<const ITAGeo::Halfedge::CMeshModelList> m_pMeshModelList; //!< Copy of propagation model list
CShapesMap m_mvpShapeVisibilityMap; //!< Map of which shape can illuminate which ones
vector<CPropagationShapeShared> m_vpPropagationTree; //!< Vector of all propagation shapes (as well as its children) visible to the emitter
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<const CEmitter> m_pEmitter; //!< Const pointer to emitter
shared_ptr<const CSensor> m_pSensor; //!< Const pointer to sensor
unique_ptr<const int> m_pMaxReflectionOrder; //!< Const pointer to maximum reflection order
......@@ -39,9 +46,19 @@ namespace ITAPropagationPathSim
void CanFaceIlluminateEdge(bool & bCanFaceIlluminateEdgeOut, CPropagationFaceShared & pPropagationFace, CPropagationEdgeShared & pPropagationEdge);
void CanFaceIlluminateFace(bool & bCanFaceIlluminateFaceOut, CPropagationFaceShared & pPropagationFaceStart, CPropagationFaceShared & pPropagationFaceEnd);
void CanEdgeIlluminateEdge(bool & bCanEdgeIlluminateEdgeOut, CPropagationEdgeShared & pPropagationEdgeStart, CPropagationEdgeShared & pPropagationEdgeEnd);
void GetPropagationShapes();
void ConstructPropagationShapes();
//Create the propagation tree
void CreatePropagationTree();
void RecursiveAddChildrenToTree(const CPropagationShapeShared & pPropagationShapeChildIn, CPropagationShapeShared& vpShapeChildCopyOut, int iReflectionOrder, int iDiffractionOrder, int iCombinedOrder);
//Create the propagation list
void CreatePropagationLists();
void RecursiveAddShapesToPropagationLists(shared_ptr<CPropagationShape>& pPropagationShapeIn);
};
}
}
\ No newline at end of file
}
#endif // INCLUDE_WATCHER_COMBINED_PROPAGATION_ENGINE
\ No newline at end of file
#ifndef INCLUDE_WATCHER_PROPAGATION_SHAPES
#define INCLUDE_WATCHER_PROPAGATION_SHAPES
#include <ITAPropagationPathSim/Definitions.h>
// ITA includes
......@@ -23,11 +27,28 @@ namespace ITAPropagationPathSim
typedef OpenMesh::PolyMesh_ArrayKernelT<> CITAMesh;
typedef map <CPropagationShapeShared, vector<CPropagationShapeShared>> CShapesMap;
typedef string MeshModelHandle;
typedef pair < MeshModelHandle, CITAMesh::FaceHandle> PropagationFaceHandle;
struct ImageReceiverMap : map<PropagationFaceHandle, shared_ptr<ImageReceiverMap>>
{
shared_ptr<VistaVector3D> v3ImageReceiver;
shared_ptr<bool> pHasIlluminableImageReceiver;
};
enum Tristate : uint8_t
{
False = 0,
True = 1,
Undefined = 2
};
class CPropagationShape
{
public:
//Public member variables
//!< Type of shape(e.g. edge or face)
enum EShapeType
{
INVALID = -1, //!< Invalid shape
......@@ -38,6 +59,9 @@ namespace ITAPropagationPathSim
LAST_ELEMENT //!< Last element of EShapeType
} iShapeType; //! Type of Shape
//!< Shows whether shape is illuminable by sensor or not
shared_ptr<Tristate> pIsIlluminableBySensor;
//!< Point of interaction
unique_ptr<VistaVector3D> v3InteractionPoint;
......@@ -61,14 +85,17 @@ namespace ITAPropagationPathSim
{
public:
//Public member variables
CITAMesh::FaceHandle hFace;
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> v3ImageReceiver;
shared_ptr<bool> pHasValidImageSource;
//Public member functions
void CopyFrom(const CPropagationFace& oPropagationFaceIn);
......@@ -84,6 +111,9 @@ namespace ITAPropagationPathSim
CITAMesh::FaceHandle hMainFace;
CITAMesh::FaceHandle hOppositeFace;
shared_ptr<bool> pHasValidImageEdge;
shared_ptr<VistaVector3D> v3FromVertex;//!< Start vertex of corresponding halfedge
shared_ptr<VistaVector3D> v3ToVertex;//!< End vertex of corresponding halfedge
shared_ptr<VistaVector3D> v3MainFaceNormal;//!< Face normal of main face
......@@ -102,4 +132,6 @@ namespace ITAPropagationPathSim
};
}
}
\ No newline at end of file
}
#endif // INCLUDE_WATCHER_PROPAGATION_SHAPES
#include <ITAPropagationPathSim\CombinatedModel\PropagationEngine.h>
#include <ITAPropagationPathSim/CombinatedModel/ImageConstructor.h>
using namespace ITAPropagationPathSim::CombinatedModel;
namespace ITAPropagationPathSim
{
namespace CombinatedModel
{
namespace ImageConstruction
{
//Recursive construct of image sources (only visible locally)
bool RecursiveConstructImageSources(CPropagationFaceShared pPropagationFace)
{
auto v3ParentImageSource = static_pointer_cast<CPropagationFace>(pPropagationFace->pParent)->v3ImageSource;
//If the previous image source lies beyond the plane, a valid path can not be built
if (!ITAGeoUtils::IsPointInFrontOfPlane(*pPropagationFace->pPlane, *v3ParentImageSource))
return false;
//Initialize image source and set it
pPropagationFace->v3ImageSource = make_shared<VistaVector3D>();
ITAGeoUtils::MirrorPointOverPlane(*v3ParentImageSource, *pPropagationFace->pPlane, *pPropagationFace->v3ImageSource);
//Add further images
for (auto& pShapeChild : pPropagationFace->vpChildren)
{
if (pShapeChild->iShapeType == CPropagationShape::FACE)
{
auto pPropagationFaceChild = static_pointer_cast<CPropagationFace>(pShapeChild);
pPropagationFaceChild->pHasValidImageSource = make_shared<bool>(RecursiveConstructImageSources(pPropagationFaceChild));
}
}
return true;
}
bool ConstructImageSources(shared_ptr<const ITAGeo::CEmitter> pEmitter, vector<CPropagationShapeShared>& vpPropagationTree)
{
for (auto& pPropagationShape : vpPropagationTree)
{
if (pPropagationShape->iShapeType == CPropagationShape::FACE)
{
auto pPropagationFace = static_pointer_cast<CPropagationFace>(pPropagationShape);
//Initialize image source and set it
pPropagationFace->v3ImageSource = make_shared<VistaVector3D>();
ITAGeoUtils::MirrorPointOverPlane(pEmitter->v3InteractionPoint, *pPropagationFace->pPlane, *pPropagationFace->v3ImageSource);
//First image source is valid
pPropagationFace->pHasValidImageSource = make_shared<bool>(true);
//Add further images
for (auto& pShapeChild : pPropagationFace->vpChildren)
{
if (pShapeChild->iShapeType == CPropagationShape::FACE)
{
pPropagationFace = static_pointer_cast<CPropagationFace>(pShapeChild);
pPropagationFace->pHasValidImageSource = make_shared<bool>(RecursiveConstructImageSources(pPropagationFace));
}
}
}
}
return true;
}
void RecursivePrepareImageReceivers(ITAPropagationPathSim::CombinatedModel::CShapesMap &vpVisibilityMap, CPropagationShapeShared &vpShapeParent, std::shared_ptr<ImageReceiverMap> &pParentImageReceiverMap, int iOrder, int iMaxOrder)
{
auto vpShapeChildren = vpVisibilityMap[vpShapeParent];
for (auto& pShapeChild : vpShapeChildren)
{
if (pShapeChild->iShapeType == CPropagationShape::FACE)
{
auto pFaceChild = static_pointer_cast<CPropagationFace>(pShapeChild);
PropagationFaceHandle hPropagationFace = make_pair(*pFaceChild->sMeshModelName, pFaceChild->hFace);
(*pParentImageReceiverMap)[hPropagationFace] = make_shared<ImageReceiverMap>();
pParentImageReceiverMap->at(hPropagationFace)->v3ImageReceiver = make_shared<VistaVector3D>();
if (ITAGeoUtils::IsPointInFrontOfPlane(*pFaceChild->pPlane, *pParentImageReceiverMap->v3ImageReceiver))
{
pParentImageReceiverMap->at(hPropagationFace)->pHasIlluminableImageReceiver = make_shared<bool>(true);
ITAGeoUtils::MirrorPointOverPlane(*pParentImageReceiverMap->v3ImageReceiver, *pFaceChild->pPlane, *pParentImageReceiverMap->at(hPropagationFace)->v3ImageReceiver);
if(iOrder < iMaxOrder)
RecursivePrepareImageReceivers(vpVisibilityMap, pShapeChild, pParentImageReceiverMap->at(hPropagationFace), iOrder + 1, iMaxOrder);
}
else
{
pParentImageReceiverMap->at(hPropagationFace)->pHasIlluminableImageReceiver = make_shared<bool>(false);
}
}
}
}
shared_ptr<ImageReceiverMap> PrepareImageReceivers(shared_ptr<const ITAGeo::CSensor> pSensor, CShapesMap vpVisibilityMap, const int iMaximumOrder)
{
shared_ptr<ImageReceiverMap> pImageReceiverMap = make_shared<ImageReceiverMap>();
if (iMaximumOrder == 0)
return nullptr;
//TODO: change to: for (auto&& [pShape,pShapeChildren] : vpVisibilityMap) when c++17 applied
for (auto& pShapeKey : vpVisibilityMap)
{
if (pShapeKey.first->iShapeType == CPropagationShape::FACE)
{
auto pFace = static_pointer_cast<CPropagationFace>(pShapeKey.first);
PropagationFaceHandle hPropagationFace = make_pair(*pFace->sMeshModelName, pFace->hFace);
(*pImageReceiverMap)[hPropagationFace] = make_shared<ImageReceiverMap>();
pImageReceiverMap->at(hPropagationFace)->v3ImageReceiver = make_shared<VistaVector3D>();
if (ITAGeoUtils::IsPointInFrontOfPlane(*pFace->pPlane, pSensor->v3InteractionPoint))
{
pImageReceiverMap->at(hPropagationFace)->pHasIlluminableImageReceiver = make_shared<bool>(true);
ITAGeoUtils::MirrorPointOverPlane(pSensor->v3InteractionPoint, *pFace->pPlane, *pImageReceiverMap->at(hPropagationFace)->v3ImageReceiver);
auto vpShapeParent = pShapeKey.first;
auto pParentImageReceiverMap = pImageReceiverMap->at(hPropagationFace);
if(iMaximumOrder > 1)
RecursivePrepareImageReceivers(vpVisibilityMap, vpShapeParent, pParentImageReceiverMap, 2, iMaximumOrder);
}
else
{
pImageReceiverMap->at(hPropagationFace)->pHasIlluminableImageReceiver = make_shared<bool>(false);
}
}
}
return pImageReceiverMap;
}
bool ConstructImageReceivers(shared_ptr<const ITAGeo::CSensor> pSensor, vector<CPropagationShapeShared>& vpPropagationLists, CShapesMap vpVisibilityMap, const int iMaxReflectionOrder)
{
//Prepare the image receiver map (TODO: Move to propagation engine)
shared_ptr<ImageReceiverMap> pImageReceiverMap = PrepareImageReceivers(pSensor, vpVisibilityMap, iMaxReflectionOrder);
//Set the image receivers
for(int iteration = (int) vpPropagationLists.size()-1; iteration>=0; iteration--)
{
auto pShape = vpPropagationLists[iteration];
//Only set image receivers, if at least one edge occurs
bool bEdgeOccurs = false;
//First, go to the last element
while (pShape->pChild != nullptr)
{
bEdgeOccurs |= pShape->iShapeType == CPropagationShape::EDGE;
pShape = pShape->pChild;
}
//Ignore current list if zero edges occured
if (!bEdgeOccurs)
continue;
//Thereafter set image receivers backwards until a non face shape appears
CPropagationFaceShared pFace;
auto pCurrentImageReceiverMap = pImageReceiverMap;
while (pShape->iShapeType == CPropagationShape::FACE)
{
pFace = static_pointer_cast<CPropagationFace>(pShape);
pCurrentImageReceiverMap = pCurrentImageReceiverMap->at(make_pair(*pFace->sMeshModelName, pFace->hFace));
//delete current list from propagation lists if image receiver is not valid
if (!*pCurrentImageReceiverMap->pHasIlluminableImageReceiver)
{
//vpPropagationLists.erase(vpPropagationLists.begin()+iteration);
vpPropagationLists[iteration] = nullptr;
break;
}
else
{
pFace->v3ImageReceiver = pCurrentImageReceiverMap->v3ImageReceiver;
pShape = pShape->pParent;
}
}
}
return true;
}
bool RecursiveConstructImageEdge(shared_ptr<const CPropagationFace> pParentFace, shared_ptr<CPropagationEdge> pPropagationEdge)
{
//Only one image must be in front of plane
bool bValidImageEdge = ITAGeoUtils::IsPointInFrontOfPlane(*pParentFace->pPlane, *pPropagationEdge->v3FromVertexMirrored);
bValidImageEdge |= ITAGeoUtils::IsPointInFrontOfPlane(*pParentFace->pPlane, *pPropagationEdge->v3FromVertexMirrored);
//If both images are not valid the whole image edge is invalid
if (!bValidImageEdge)
return false;
ITAGeoUtils::MirrorPointOverPlane(*pPropagationEdge->v3FromVertexMirrored, *pParentFace->pPlane, *pPropagationEdge->v3FromVertexMirrored);
ITAGeoUtils::MirrorPointOverPlane(*pPropagationEdge->v3ToVertexMirrored, *pParentFace->pPlane, *pPropagationEdge->v3ToVertexMirrored);
//Recursive construction until no further faces are found
if (pParentFace->pParent != nullptr && pParentFace->pParent->iShapeType == CPropagationShape::FACE)
{
auto pGrandParentFace = static_pointer_cast<CPropagationFace>(pPropagationEdge->pParent);
bValidImageEdge = RecursiveConstructImageEdge(pGrandParentFace, pPropagationEdge);
}
return bValidImageEdge;
}
bool RecursiveConstructImageEdges(CPropagationShapeShared pPropagationShape)
{
//if the type is face, just go one level deeper
if (pPropagationShape->iShapeType == CPropagationShape::EDGE)
{
auto pPropagationEdge = static_pointer_cast<CPropagationEdge>(pPropagationShape);
//Create image vertices only for edges with faces as parents
if (pPropagationEdge->pParent->iShapeType == CPropagationShape::FACE)
{
auto pParentFace = static_pointer_cast<CPropagationFace>(pPropagationEdge->pParent);
pPropagationEdge->v3FromVertexMirrored = make_shared<VistaVector3D>();
pPropagationEdge->v3ToVertexMirrored = make_shared<VistaVector3D>();
ITAGeoUtils::MirrorPointOverPlane(*pPropagationEdge->v3FromVertex, *pParentFace->pPlane, *pPropagationEdge->v3FromVertexMirrored);
ITAGeoUtils::MirrorPointOverPlane(*pPropagationEdge->v3ToVertex, *pParentFace->pPlane, *pPropagationEdge->v3ToVertexMirrored);
//First mirroring is valid
pPropagationEdge->pHasValidImageEdge = make_shared<bool>(true);
//Ff grandparent is also a face, further mirroring of image vertices
if (pParentFace->pParent != nullptr && pParentFace->pParent->iShapeType == CPropagationShape::FACE)
{
pParentFace = static_pointer_cast<CPropagationFace>(pParentFace->pParent);
*pPropagationEdge->pHasValidImageEdge = RecursiveConstructImageEdge(pParentFace, pPropagationEdge);
}
}
}
//Go one level deeper
for (auto& pShapeChild : pPropagationShape->vpChildren)
RecursiveConstructImageEdges(pShapeChild);
return true;
}
bool ConstructImageEdges(shared_ptr<const ITAGeo::CEmitter> pEmitter, vector<CPropagationShapeShared> vpPropagationTree)
{
//First element of tree has never an image edge, so only construct them for its children
for (auto& pShape : vpPropagationTree)
for (auto& pShapeChild : pShape->vpChildren)
RecursiveConstructImageEdges(pShapeChild);
return true;
}
}
}
}
#include <ITAPropagationPathSim\CombinatedModel\PropagationEngine.h>
#include <ITAPropagationPathSim\CombinatedModel\ImageConstructor.h>
//Typedefs
typedef OpenMesh::PolyMesh_ArrayKernelT<> CITAMesh;
......@@ -22,10 +23,15 @@ ITAPropagationPathSim::CombinatedModel::CPathEngine::CPathEngine(shared_ptr<cons
pMesh->request_vertex_normals();
}
//Get all propagation shapes of the mesh model list
ConstructPropagationShapes();
//Create a visibility map
CreateVisibilityMap();
}
void ITAPropagationPathSim::CombinatedModel::CPathEngine::CreatePropagationTree(shared_ptr<const ITAGeo::CEmitter> pEmitter, const int iMaxDiffractions, const int iMaxReflections, const int iMaxCombinedOrder)
void ITAPropagationPathSim::CombinatedModel::CPathEngine::ApplyEmitter(shared_ptr<const ITAGeo::CEmitter> pEmitter, const int iMaxDiffractions, const int iMaxReflections, const int iMaxCombinedOrder)
{
//Set emitter
m_pEmitter = pEmitter;
......@@ -33,14 +39,38 @@ void ITAPropagationPathSim::CombinatedModel::CPathEngine::CreatePropagationTree(
//Set orders
m_pMaxDiffractionOrder = make_unique<const int>(iMaxDiffractions);
m_pMaxReflectionOrder = make_unique<const int>(iMaxReflections);
m_pMaxCombinedOrder = make_unique<const int> (iMaxCombinedOrder);
m_pMaxCombinedOrder = make_unique<const int>(iMaxCombinedOrder);
//Create propagation tree
CreatePropagationTree();
//Construct image sources
ImageConstruction::ConstructImageSources(m_pEmitter, m_vpPropagationTree);
//Construct image edges
ImageConstruction::ConstructImageEdges(m_pEmitter, m_vpPropagationTree);
}
void ITAPropagationPathSim::CombinatedModel::CPathEngine::ApplySensor(shared_ptr<const ITAGeo::CSensor> pSensor)
{
//Set sensor
m_pSensor = pSensor;
//Create propagation lists with each one containing a possible propagation path candidate
CreatePropagationLists();
//Construct image receivers
ImageConstruction::ConstructImageReceivers(m_pSensor, m_vpPropagationLists, m_mvpShapeVisibilityMap, *m_pMaxReflectionOrder);
}
void ITAPropagationPathSim::CombinatedModel::CPathEngine::CreatePropagationTree()
{
//Set initial values for number of diffractions/reflections
for (const auto& pPropagationShape : m_vpPropagationShapes)
{
// If iMaxCombined order is zero, no paths are added
if (iMaxCombinedOrder <= 0)
// If m_pMaxCombinedOrder order is zero, no paths are added
if (*m_pMaxCombinedOrder <= 0)
break;
switch (pPropagationShape->iShapeType)
......@@ -48,7 +78,7 @@ void ITAPropagationPathSim::CombinatedModel::CPathEngine::CreatePropagationTree(
case CPropagationShape::FACE:
{
//Only add reflection paths if iMaxReflections is at least one
if (iMaxReflections >= 1 )
if (*m_pMaxReflectionOrder >= 1 )
{
CPropagationFaceShared pFaceCopy = make_shared<CPropagationFace>();
pFaceCopy->CopyFrom(*static_pointer_cast<CPropagationFace>(pPropagationShape));
......@@ -81,7 +111,7 @@ void ITAPropagationPathSim::CombinatedModel::CPathEngine::CreatePropagationTree(
case CPropagationShape::EDGE:
{
//Only add reflection paths if iMaxDiffractions is at least one
if (iMaxDiffractions >= 1)
if (*m_pMaxCombinedOrder >= 1)
{
CPropagationEdgeShared pEdgeCopy = make_shared<CPropagationEdge>();
pEdgeCopy->CopyFrom(*static_pointer_cast<CPropagationEdge>(pPropagationShape));
......@@ -116,6 +146,129 @@ void ITAPropagationPathSim::CombinatedModel::CPathEngine::CreatePropagationTree(
}
}
void ITAPropagationPathSim::CombinatedModel::CPathEngine::CreatePropagationLists()
{
for (auto& pPropagationShape : m_vpPropagationTree)
{
RecursiveAddShapesToPropagationLists(pPropagationShape);
}
}
void ITAPropagationPathSim::CombinatedModel::CPathEngine::RecursiveAddShapesToPropagationLists(shared_ptr<CPropagationShape>& pPropagationShapeIn)
{
//In this if case, pPropagationShapeIn is eventually tested for illuminability for the sensor
//and its branches are followed up until the first branch(illuminable by the emitter)
if (*pPropagationShapeIn->pIsIlluminableBySensor != Tristate::False)
{
CPropagationShapeShared pShape;
switch (pPropagationShapeIn->iShapeType)
{
case CPropagationShape::FACE:
{
auto pFace = make_shared<CPropagationFace>();
pFace->CopyFrom(*static_pointer_cast<CPropagationFace>(pPropagationShapeIn));
//If the face has no valid image source, do not follow up its branch and return immediately
if (pFace->pHasValidImageSource != nullptr && *pFace->pHasValidImageSource == false)
return;
//If the illuminability is not found out yet, check for illuminability and break switch without setting pShape if shape is not illuminable
if (*pPropagationShapeIn->pIsIlluminableBySensor == Tristate::Undefined)
{
if (CanPointIlluminateFace(m_pSensor->v3InteractionPoint, *pFace->sMeshModelName, pFace->hFace))
{
*pPropagationShapeIn->pIsIlluminableBySensor = Tristate::True;
}
else
{
*pPropagationShapeIn->pIsIlluminableBySensor = Tristate::False;
break;