Commit 88c308a4 authored by Armin Erraji's avatar Armin Erraji

Bugfix Calculation of aperture points

parent 1fd95bb8
......@@ -38,9 +38,11 @@ namespace ITAPropagationPathSim
void ApplySensor(shared_ptr<CSensor> pSensor);
void ConstructPropagationPathsWithStopWatch(CPropagationPathList& oPaths);
void ConstructPropagationPaths(CPropagationPathList& oPaths);
size_t GetNumberPropagationPathCandidates();
private:
......@@ -48,7 +50,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
vector<CPropagationShapeShared> m_vpPropagationCandidates; //!< 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
......
......@@ -97,6 +97,8 @@ namespace ITAPropagationPathSim
//!<Copy shape
void CopyFrom(const CPropagationShape& oPropagationShapeIn);
void GetBoundingBoxAxesAligned(VistaVector3D& v3Min, VistaVector3D& v3Max) const;
//!< Set barycenter and radius of the boundary sphere of the shape
bool SetBoundarySphere();
......
#ifndef INCLUDE_WATCHER_PROPAGATION_RTREE
#define INCLUDE_WATCHER_PROPAGATION_RTREE
// ITAGeo
#include <ITAGeo/Definitions.h>
#include <ITAGeo/Utils.h>
#include <ITAGeo/Base.h>
#include <ITAGeo/ModelBase.h>
#include <ITAGeo/Halfedge/MeshModel.h>
#include<ITAPropagationPathSim/CombinedModel/PropagationShapes.h>
using namespace std;
namespace ITAPropagationPathSim
{
namespace CombinedModel
{
// Typedefs
typedef OpenMesh::PolyMesh_ArrayKernelT<> CITAMesh;
//! Buildings RTree class
/**
* @todo
*
*/
class ITA_GEO_API CShapesTree
{
public:
//---Constructor and Destructor---------------------------------------------
CShapesTree();
~CShapesTree();
//---Public member functions------------------------------------------------
void Create(const vector<CPropagationShapeShared>& vpShapesIn);
//TODO
bool IsLineSegmentIntersected(const VistaVector3D& oLineStart, const VistaVector3D& oLineEnd) const;
//TODO
//void GetNonIntersectedFaces(vector<CPropagationShapeShared>& vpFacesOut, const VistaVector3D& oLineStart, const VistaVector3D& oLineStart);
/*TODO: For faster illumination tests
void GetIlluminableShapes(vector<CPropagationShapeShared>& vpShapesOut, const VistaPlane& oPlaneIn);
void GetIlluminableShapes(vector<CPropagationShapeShared>& vpShapesOut, const CPropagationFaceShared& pFace);
void GetIlluminableShapes(vector<CPropagationShapeShared>& vpShapesOut, const CPropagationEdgeShared& pEdge);
*/
//---Public member variables------------------------------------------------
private:
//---Private member functions-----------------------------------------------
void SetVertices();
void CreateBranches();
//---Private member variables-----------------------------------------------
//Minimum and maximum of bounding box as well as vertices of box
VistaVector3D m_v3TreeMin;
VistaVector3D m_v3TreeMax;
//Vector of shapes within bounding box
vector<CPropagationShapeShared> m_vpShapes;
//Branches
vector<shared_ptr<CShapesTree>> m_vpBranches;
};
}
}
#endif // INCLUDE_WATCHER_PROPAGATION_RTREE
\ No newline at end of file
......@@ -9,6 +9,7 @@ set( DirFiles
ImageConstructor.h
PropagationEngine.h
PropagationShapes.h
RTree.h
ReflectionLocator.h
)
......
......@@ -178,7 +178,7 @@ namespace ITAPropagationPathSim
map <UrbanEdgeHandle, map <UrbanEdgeHandle, double>> m_mdApertureStartDifferenceMap;
//RTree of building meshes
shared_ptr<ITAGeo::Urban::RTree::CBuildings> m_pBuildingsTree;
shared_ptr<ITAGeo::Urban::RTree::CShapesTree> m_pBuildingsTree;
//Matrix of illumination of diffraction edges
map<UrbanEdgeHandle, set<shared_ptr<DiffractionEdge>>> m_mDiffractionMatrix;
......
......@@ -175,7 +175,7 @@ namespace ITAPropagationPathSim
}
//The last direction vector(between the last edge and the (imaged) receiver) does not contain a correction vector for the receiver
vfDirectionVectorLength.push_back((*vpStartVertexDiff.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]
......@@ -201,34 +201,35 @@ namespace ITAPropagationPathSim
//To get vfRelativeApexPosition, the Gaussian-elimination is used to delete
//the term b[i-1] * vfRelativeApexPosition[i-1] in each row, so that
//in the last row, only one variable is left over.
//Thereafter the searched vfRelativeApexPosition can be calculated.
//d[i] replaces a[i] and e[i] replaces c[i]
//┌ ┐ ┌ ┐ ┌ ┐
//| d[0] b[0] 0 0 ... 0 0 0 | | vfRelativeApexPosition[0] | | e[0] |
//| 0 d[1] b[1] 0 ... 0 0 0 | | vfRelativeApexPosition[1] | | e[1] |
//| 1 e[0] 0 0 ... 0 0 0 | | vfRelativeApexPosition[0] | | d[0] |
//| 0 1 e[1] 0 ... 0 0 0 | | vfRelativeApexPosition[1] | | d[1] |
//| ... ... ... ... ... ... ... |*| ... |=| ... |
//| 0 0 0 0 ... 0 d[n-2] b[n-2]| | vfRelativeApexPosition[n-2]| | e[n-2]|
//| 0 0 0 0 ... 0 0 d[n-1]| | vfRelativeApexPosition[n-1]| | e[n-1]|
//| 0 0 0 0 ... 0 1 e[n-2]| | vfRelativeApexPosition[n-2]| | d[n-2]|
//| 0 0 0 0 ... 0 0 1 | | vfRelativeApexPosition[n-1]| | d[n-1]|
//└ ┘ └ ┘ └ ┘
vector<float> d, e;
//The first row remains the same
d.push_back(a.front());
e.push_back(c.front());
d.push_back(c.front()/a.front());
if(a.size()>1)
e.push_back(b.front()/a.front());
//
for (int i = 1; i < a.size()-1; i++)
{
e.push_back(b[i] / (a[i] - b[i - 1] * e[i - 1]));
}
for (int i = 1; i < a.size(); i++)
{
d.push_back(a[i] - b[i - 1] * b[i - 1] / d[i - 1]);
e.push_back(c[i] - b[i - 1] * c[i - 1] / d[i - 1]);
d.push_back((c[i] - b[i - 1] * d[i - 1]) / (a[i] - b[i-1]*e[i - 1]));
}
//Solve the equation system beginning at the last row
vfRelativeApexPosition.back() = e.back() / d.back();
vfRelativeApexPosition.back() = d.back();
for (int i = vfRelativeApexPosition.size() - 2; i >= 0; i--)
{
vfRelativeApexPosition[i] = (e[i] - b[i] * vfRelativeApexPosition[i + 1]) / d[i];
vfRelativeApexPosition[i] = (d[i] - e[i] * vfRelativeApexPosition[i + 1]);
}
}
......@@ -251,6 +252,73 @@ namespace ITAPropagationPathSim
//v3InteractionPoint = from_vertex + vfRelativeApexPosition * (to_vertex - from_vertex)
VistaVector3D v3InteractionPoint = (1 - vfRelativeApexPosition.back()) * (*pEdge->v3StartVertex) + vfRelativeApexPosition.back()*(*pEdge->v3EndVertex);
//Interaction point must lie in valid range of parent and child of edge
if (!pEdge->pParent.expired())
{
if (pEdge->pParent.lock()->iShapeType == CPropagationShape::FACE)
{
auto pParentFace = static_pointer_cast<CPropagationFace>(pEdge->pParent.lock());
bValidAperturePoints = ITAGeoUtils::IsPointInFrontOfPlane(*pParentFace->pPlane, v3InteractionPoint);
}
else
{
auto pParentEdge = static_pointer_cast<CPropagationEdge>(pEdge->pParent.lock());
//Illumination test at from vertex position
VistaPlane oMainPlane, oOppositePlane;
oMainPlane.SetOrigin(*pParentEdge->v3StartVertex);
oOppositePlane.SetOrigin(*pParentEdge->v3StartVertex);
oMainPlane.SetNormVector(*pParentEdge->v3MainFaceNormal);
oOppositePlane.SetNormVector(*pParentEdge->v3OppositeFaceNormal);
bool bMainFaceIlluminated = ITAGeoUtils::IsPointInFrontOfPlane(oMainPlane, v3InteractionPoint);
bool bOppositeFaceIlluminated = ITAGeoUtils::IsPointInFrontOfPlane(oOppositePlane, v3InteractionPoint);
//Check whether wedge angle is >pi or <pi; TODO: export in own function
bool bIsOuterAngle = pParentEdge->v3MainFaceNormal->Cross(*pParentEdge->v3OppositeFaceNormal).Dot(*pParentEdge->v3EndVertex - *pParentEdge->v3StartVertex) > 0;
if (bIsOuterAngle)
bValidAperturePoints = bMainFaceIlluminated || bOppositeFaceIlluminated;
else
bValidAperturePoints = bMainFaceIlluminated && bOppositeFaceIlluminated;
}
}
if (pEdge->pChild != nullptr)
{
if (pEdge->pChild->iShapeType == CPropagationShape::FACE)
{
auto pChildFace = static_pointer_cast<CPropagationFace>(pEdge->pChild);
bValidAperturePoints = ITAGeoUtils::IsPointInFrontOfPlane(*pChildFace->pPlane, v3InteractionPoint);
}
else
{
auto pChildEdge = static_pointer_cast<CPropagationEdge>(pEdge->pChild);
//Illumination test at from vertex position
VistaPlane oMainPlane, oOppositePlane;
oMainPlane.SetOrigin(*pChildEdge->v3StartVertex);
oOppositePlane.SetOrigin(*pChildEdge->v3StartVertex);
oMainPlane.SetNormVector(*pChildEdge->v3MainFaceNormal);
oOppositePlane.SetNormVector(*pChildEdge->v3OppositeFaceNormal);
bool bMainFaceIlluminated = ITAGeoUtils::IsPointInFrontOfPlane(oMainPlane, v3InteractionPoint);
bool bOppositeFaceIlluminated = ITAGeoUtils::IsPointInFrontOfPlane(oOppositePlane, v3InteractionPoint);
//Check whether wedge angle is >pi or <pi; TODO: export in own function
bool bIsOuterAngle = pChildEdge->v3MainFaceNormal->Cross(*pChildEdge->v3OppositeFaceNormal).Dot(*pChildEdge->v3EndVertex - *pChildEdge->v3StartVertex) > 0;
if (bIsOuterAngle)
bValidAperturePoints = bMainFaceIlluminated || bOppositeFaceIlluminated;
else
bValidAperturePoints = bMainFaceIlluminated && bOppositeFaceIlluminated;
}
}
//Set the interaction point
pEdge->v3InteractionPoint = make_unique <VistaVector3D>(v3InteractionPoint);
......
......@@ -112,6 +112,36 @@ void ITAPropagationPathSim::CombinedModel::CPathEngine::ApplyEmitter(shared_ptr<
//}
}
size_t ITAPropagationPathSim::CombinedModel::CPathEngine::GetNumberPropagationPathCandidates()
{
if(m_vpPropagationCandidates.size() > 0)
return m_vpPropagationCandidates.size();
else
{
size_t iNumber = 0;
vector<CPropagationShapeShared> pCandidates;
pCandidates.insert(pCandidates.end(), m_vpPropagationTree.begin(), m_vpPropagationTree.end());
for (int i = 0; i<pCandidates.size(); i++)
{
auto pCandidate = pCandidates[i];
if (pCandidate == nullptr)
continue;
iNumber++;
pCandidates.insert(pCandidates.end(), pCandidate->vpChildren.begin(), pCandidate->vpChildren.end());
}
return iNumber;
}
}
void ITAPropagationPathSim::CombinedModel::CPathEngine::ApplySensor(shared_ptr<ITAGeo::CSensor> pSensor)
{
//Set sensor
......@@ -122,34 +152,34 @@ void ITAPropagationPathSim::CombinedModel::CPathEngine::ApplySensor(shared_ptr<I
}
void ITAPropagationPathSim::CombinedModel::CPathEngine::ConstructPropagationPaths(ITAGeo::CPropagationPathList& oPaths)
void ITAPropagationPathSim::CombinedModel::CPathEngine::ConstructPropagationPathsWithStopWatch(ITAGeo::CPropagationPathList& oPaths)
{
ITAStopWatch sw; sw.start();
ITAStopWatch sw, sw2; sw.start(); sw2.start();
std::cout << m_vpPropagationLists.size() << " path candidates at start. Calculation time for counting: " << timeToString(sw.stop()) <<endl;
std::cout << m_vpPropagationCandidates.size() << " path candidates at start. Calculation time for counting: " << timeToString(sw.stop()) <<endl;
sw.start();
//First, construct the aperture points
Diffraction::ConstructAperturePoints(m_pEmitter, m_pSensor, (int)*m_pNumberIterationApexCalc, m_vpPropagationLists, m_vpPropagationLists);
std::cout << m_vpPropagationLists.size() << " path candidates after aperture points calculated. Calculation time: " << timeToString(sw.stop()) << endl;
Diffraction::ConstructAperturePoints(m_pEmitter, m_pSensor, (int)*m_pNumberIterationApexCalc, m_vpPropagationCandidates, m_vpPropagationCandidates);
std::cout << m_vpPropagationCandidates.size() << " path candidates after aperture points calculated. Calculation time: " << timeToString(sw.stop()) << endl;
sw.start();
//Thereafter, with the constructed aperture points, construct the image apertures as secondary image sources
//for the faces after each edge
ImageConstruction::ConstructImageApertures(m_vpPropagationLists, m_vpPropagationLists);
std::cout << m_vpPropagationLists.size() << " path candidates after image aperture calculated. Calculation time: " << timeToString(sw.stop()) << endl;
ImageConstruction::ConstructImageApertures(m_vpPropagationCandidates, m_vpPropagationCandidates);
std::cout << m_vpPropagationCandidates.size() << " path candidates after image aperture calculated. Calculation time: " << timeToString(sw.stop()) << endl;
sw.start();
//Construct the intersection points of the reflections
Reflection::ConstructPointsOfReflection(m_pSensor, m_vpPropagationLists, m_vpPropagationLists);
std::cout << m_vpPropagationLists.size() << " path candidates after points of reflection calculated. Calculation time: " << timeToString(sw.stop()) << endl;
Reflection::ConstructPointsOfReflection(m_pSensor, m_vpPropagationCandidates, m_vpPropagationCandidates);
std::cout << m_vpPropagationCandidates.size() << " path candidates after points of reflection calculated. Calculation time: " << timeToString(sw.stop()) << endl;
//Calculate perceptional culling
if (*m_pMaxLevelReduction > 0.0f)
{
sw.start();
PerceptionalCulling(m_vpPropagationLists, m_vpPropagationLists);
std::cout << m_vpPropagationLists.size() << " path candidates after perceptional culling. Calculation time: " << timeToString(sw.stop()) << endl;
PerceptionalCulling(m_vpPropagationCandidates, m_vpPropagationCandidates);
std::cout << m_vpPropagationCandidates.size() << " path candidates after perceptional culling. Calculation time: " << timeToString(sw.stop()) << endl;
}
......@@ -157,14 +187,14 @@ void ITAPropagationPathSim::CombinedModel::CPathEngine::ConstructPropagationPath
if (*m_pAccumulatedAngleThreshold > 0)
{
sw.start();
Diffraction::AccumulatedAngleCulling(*m_pAccumulatedAngleThreshold, m_pEmitter,m_pSensor, m_vpPropagationLists, m_vpPropagationLists);
std::cout << m_vpPropagationLists.size() << " path candidates after angle culling. Calculation time: " << timeToString(sw.stop()) << endl;
Diffraction::AccumulatedAngleCulling(*m_pAccumulatedAngleThreshold, m_pEmitter,m_pSensor, m_vpPropagationCandidates, m_vpPropagationCandidates);
std::cout << m_vpPropagationCandidates.size() << " path candidates after angle culling. Calculation time: " << timeToString(sw.stop()) << endl;
}
sw.start();
if (*m_pFilterIntersectedPaths)
{
FilterVisiblePaths(m_vpPropagationLists, m_vpPropagationLists);
FilterVisiblePaths(m_vpPropagationCandidates, m_vpPropagationCandidates);
cout << "Calculation time for filter of non-intersected and therefore visible paths: " << timeToString(sw.stop()) << endl;
......@@ -175,6 +205,44 @@ void ITAPropagationPathSim::CombinedModel::CPathEngine::ConstructPropagationPath
ConvertShapeListsToPropagationPaths(oPaths);
std::cout << "Calculation time converting to CPropagationPathList object : " << timeToString(sw.stop()) << endl;
std::cout << "Calculation time propagation paths in total: " << timeToString(sw2.stop()) << endl;
}
void ITAPropagationPathSim::CombinedModel::CPathEngine::ConstructPropagationPaths(ITAGeo::CPropagationPathList& oPaths)
{
//First, construct the aperture points
Diffraction::ConstructAperturePoints(m_pEmitter, m_pSensor, (int)*m_pNumberIterationApexCalc, m_vpPropagationCandidates, m_vpPropagationCandidates);
//Thereafter, with the constructed aperture points, construct the image apertures as secondary image sources
//for the faces after each edge
ImageConstruction::ConstructImageApertures(m_vpPropagationCandidates, m_vpPropagationCandidates);
//Construct the intersection points of the reflections
Reflection::ConstructPointsOfReflection(m_pSensor, m_vpPropagationCandidates, m_vpPropagationCandidates);
//Calculate perceptional culling
if (*m_pMaxLevelReduction > 0.0f)
{
PerceptionalCulling(m_vpPropagationCandidates, m_vpPropagationCandidates);
}
//Calculate accumulated angle and filter lists
if (*m_pAccumulatedAngleThreshold > 0)
{
Diffraction::AccumulatedAngleCulling(*m_pAccumulatedAngleThreshold, m_pEmitter, m_pSensor, m_vpPropagationCandidates, m_vpPropagationCandidates);
}
if (*m_pFilterIntersectedPaths)
{
FilterVisiblePaths(m_vpPropagationCandidates, m_vpPropagationCandidates);
}
//Convert pPropagationShapes to pPropagationAnchors
ConvertShapeListsToPropagationPaths(oPaths);
}
void ITAPropagationPathSim::CombinedModel::CPathEngine::PerceptionalCulling(const vector<CPropagationShapeShared> vpAllPathsIn, vector<CPropagationShapeShared>& vpAudiblePathsOut)
......@@ -333,7 +401,7 @@ void ITAPropagationPathSim::CombinedModel::CPathEngine::ConvertShapeListsToPropa
}
for (auto& pShapeStart : m_vpPropagationLists)
for (auto& pShapeStart : m_vpPropagationCandidates)
{
if (pShapeStart == nullptr)
continue;
......@@ -473,7 +541,7 @@ void ITAPropagationPathSim::CombinedModel::CPathEngine::CreatePropagationTree()
fAccumulatedPenalty += *m_pDiffractionPenalty;
//Only add reflection paths if iMaxDiffractions is at least one
if (*m_pMaxCombinedOrder >= 1)
if (*m_pMaxDiffractionOrder >= 1)
{
CPropagationEdgeShared pEdgeCopy = make_shared<CPropagationEdge>();
pEdgeCopy->CopyFrom(*static_pointer_cast<CPropagationEdge>(pPropagationShape));
......@@ -734,7 +802,7 @@ void ITAPropagationPathSim::CombinedModel::CPathEngine::RecursiveAddShapesToProp
}
//Add shape to list
m_vpPropagationLists.push_back(pShape);
m_vpPropagationCandidates.push_back(pShape);
}
}
......@@ -1004,10 +1072,20 @@ void ITAPropagationPathSim::CombinedModel::CPathEngine::CanFaceIlluminateEdge(bo
bMainFaceIlluminated = ITAGeoUtils::CanFaceBeIlluminated(*pEdgeMesh, pPropagationEdge->hMainFace, *pVertex);
bOppositeFaceIlluminated = ITAGeoUtils::CanFaceBeIlluminated(*pEdgeMesh, pPropagationEdge->hOppositeFace, *pVertex);
//Check whether wedge angle is >pi or <pi; TODO: export in own function
bool bIsOuterAngle = pPropagationEdge->v3MainFaceNormal->Cross(*pPropagationEdge->v3OppositeFaceNormal).Dot(*pPropagationEdge->v3EndVertex - *pPropagationEdge->v3StartVertex) > 0;
if (*m_pFilterIlluminatedRegionDiffraction)
bCanFaceIlluminateEdgeOut = bMainFaceIlluminated != bOppositeFaceIlluminated; // A XOR B, only valid, if at least one point can lie in the shadow region
if (bIsOuterAngle)
bCanFaceIlluminateEdgeOut = bMainFaceIlluminated != bOppositeFaceIlluminated; // A XOR B, only valid, if at least one point can lie in the shadow region
else
bCanFaceIlluminateEdgeOut = false; //Never illuminable
else
bCanFaceIlluminateEdgeOut = bMainFaceIlluminated || bOppositeFaceIlluminated; // A OR B, also valid, if face can only lie in the illuminated region
if (bIsOuterAngle)
bCanFaceIlluminateEdgeOut = bMainFaceIlluminated || bOppositeFaceIlluminated; // A OR B, also valid, if face can only lie in the illuminated region
else
bCanFaceIlluminateEdgeOut = bMainFaceIlluminated && bOppositeFaceIlluminated; // A AND B, only valid if face lie comnplete in the illuminated region
if (bCanFaceIlluminateEdgeOut)
return;
......@@ -1040,10 +1118,21 @@ void ITAPropagationPathSim::CombinedModel::CPathEngine::CanEdgeIlluminateEdge(bo
bMainFaceIlluminated = ITAGeoUtils::CanFaceBeIlluminated(*pEdgeEndMesh, pPropagationEdgeEnd->hMainFace, (1 - eps)*(*pPropagationEdgeStart->v3StartVertex) + (eps)*(*pPropagationEdgeStart->v3EndVertex));
bOppositeFaceIlluminated = ITAGeoUtils::CanFaceBeIlluminated(*pEdgeEndMesh, pPropagationEdgeEnd->hOppositeFace, (1 - eps)*(*pPropagationEdgeStart->v3StartVertex) + (eps)*(*pPropagationEdgeStart->v3EndVertex));
//Check whether wedge angle is >pi or <pi; TODO: export in own function
bool bIsOuterAngle = pPropagationEdgeEnd->v3MainFaceNormal->Cross(*pPropagationEdgeEnd->v3OppositeFaceNormal).Dot(*pPropagationEdgeEnd->v3EndVertex - *pPropagationEdgeEnd->v3StartVertex) > 0;
if (*m_pFilterIlluminatedRegionDiffraction)
bCanEdgeIlluminateEdgeOut = bMainFaceIlluminated != bOppositeFaceIlluminated; // A XOR B, only valid, if at least one point can lie in the shadow region
if (bIsOuterAngle)
bCanEdgeIlluminateEdgeOut = bMainFaceIlluminated != bOppositeFaceIlluminated; // A XOR B, only valid, if at least one point can lie in the shadow region
else
bCanEdgeIlluminateEdgeOut = false; //Never illuminable
else
bCanEdgeIlluminateEdgeOut = bMainFaceIlluminated || bOppositeFaceIlluminated; // A OR B, also valid, if face can only lie in the illuminated region
if (bIsOuterAngle)
bCanEdgeIlluminateEdgeOut = bMainFaceIlluminated || bOppositeFaceIlluminated; // A OR B, also valid, if face can only lie in the illuminated region
else
bCanEdgeIlluminateEdgeOut = bMainFaceIlluminated && bOppositeFaceIlluminated; // A AND B, only valid if face lie comnplete in the illuminated region
if (bCanEdgeIlluminateEdgeOut)
return;
......
......@@ -23,6 +23,18 @@ void CPropagationShape::CopyFrom(const CPropagationShape & oPropagationShapeIn)
pIsIlluminableBySensor = oPropagationShapeIn.pIsIlluminableBySensor;
}
void CPropagationShape::GetBoundingBoxAxesAligned(VistaVector3D& v3Min, VistaVector3D& v3Max) const
{
v3Min = *vv3Vertices[0];
v3Max = v3Min;
for (auto& v3Vertex : vv3Vertices)
{
v3Min.SetValues(fminf(v3Min[0], (*v3Vertex)[0]), fminf(v3Min[1], (*v3Vertex)[1]), fminf(v3Min[2], (*v3Vertex)[2]));
v3Max.SetValues(fmaxf(v3Max[0], (*v3Vertex)[0]), fmaxf(v3Max[1], (*v3Vertex)[1]), fmaxf(v3Max[2], (*v3Vertex)[2]));
}
}
bool CPropagationShape::SetBoundarySphere()
{
//the shape must have at least one vertex
......@@ -183,6 +195,8 @@ void CPropagationEdge::CopyFrom(const CPropagationEdge & oPropagationEdgeIn)
pHasValidImageEdge = oPropagationEdgeIn.pHasValidImageEdge;
}
bool CPropagationEdge::SetMinimumDistance(const CPropagationShape & oPropagationShape)
{
if (v3Barycenter == nullptr || oPropagationShape.v3Barycenter == nullptr)
......
#include <ITAPropagationPathSim/CombinedModel/RTree.h>
using namespace ITAGeo;
using namespace ITAPropagationPathSim::CombinedModel;
//===RTree::CBuildings class=======================================================================================
// ---Constructor & Destructor-------------------------------------------------------------------------------------
CShapesTree::CShapesTree()
{
}
CShapesTree::~CShapesTree()
{
}
// ---Create functions----------------------------------------------------------------------------------------------
void CShapesTree::Create(const vector<CPropagationShapeShared>& vpShapesIn)
{
//Set buildings vector
m_vpShapes = vpShapesIn;
//Set vertex VistaVectors
SetVertices();
//Create branches if number of shapes is more than one
if (m_vpShapes.size() > 1)
CreateBranches();
}
void CShapesTree::CreateBranches()
{
//Create 8 vectors of shape-vectors (for each region one vector)
vector<vector<CPropagationShapeShared>> vvpBranchShapes;
vvpBranchShapes.resize(8);
//Points, where branches are sub-divided into. Mid points between max and min.
float fSubDivideX = m_v3TreeMin[Vista::X] + m_v3TreeMax[Vista::X] / 2.0f;
float fSubDivideY = m_v3TreeMin[Vista::Y] + m_v3TreeMax[Vista::Y] / 2.0f;
float fSubDivideZ = m_v3TreeMin[Vista::Z] + m_v3TreeMax[Vista::Z] / 2.0f;
//Add building to branchbuildings vector according to its location
for (auto &pShape : m_vpShapes)
{
VistaVector3D v3Min, v3Max;
pShape->GetBoundingBoxAxesAligned(v3Min, v3Max);
if (v3Min[2] < fSubDivideZ)
{
if (v3Min[1] < fSubDivideY)
{
if (v3Min[0] < fSubDivideX)
{
vvpBranchShapes[0].push_back(pShape);
}
else
{
vvpBranchShapes[1].push_back(pShape);
}
}
else
{
if (v3Min[0] < fSubDivideX)