diff --git a/CMakeLists.txt b/CMakeLists.txt index d2de630c285c64cb36d391b10ac5487cef92c7a5..3a522382fe6a4619df723af5faee90af3810e2ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,14 +21,14 @@ set( ITAPropagationModelsHeader "include/ITAPropagationModels/DiffractionFilter.h" "include/ITAPropagationModels/FilterEngine.h" "include/ITAPropagationModels/FilterGenerator.h" - "include/ITAPropagationModels/Kirchhoff.h" + "include/ITAPropagationModels/Maekawa.h" "include/ITAPropagationModels/Svensson.h" "include/ITAPropagationModels/UTD.h" ) set( ITAPropagationModelsSources "src/ITAPropagationModels/FilterEngine.cpp" "src/ITAPropagationModels/FilterGenerator.cpp" - "src/ITAPropagationModels/Kirchhoff.cpp" + "src/ITAPropagationModels/Maekawa.cpp" "src/ITAPropagationModels/Svensson.cpp" "src/ITAPropagationModels/UTD.cpp" ) diff --git a/include/ITAPropagationModels/Kirchhoff.h b/include/ITAPropagationModels/Maekawa.h similarity index 100% rename from include/ITAPropagationModels/Kirchhoff.h rename to include/ITAPropagationModels/Maekawa.h diff --git a/src/ITAPropagationModels/Kirchhoff.cpp b/src/ITAPropagationModels/Kirchhoff.cpp deleted file mode 100644 index b8cfd4751b130277f24c68fa7d2f51650f0f5bfd..0000000000000000000000000000000000000000 --- a/src/ITAPropagationModels/Kirchhoff.cpp +++ /dev/null @@ -1,124 +0,0 @@ -#include <ITAPropagationModels/Kirchhoff.h> - -#include <ITAException.h> - -using namespace ITAGeo; -using namespace ITAPropagationModels; - -bool Kirchhoff::IsApplicable( const CPropagationPath& oPropPath ) -{ - if( oPropPath.size() < 3 ) - ITA_EXCEPT1( INVALID_PARAMETER, "Propagation path needs at least 3 anchors for Kirchhoff method" ); - - auto pAnchorDirectLazy( oPropPath[ 0 ] ); - if( pAnchorDirectLazy->iAnchorType == CPropagationAnchor::INVALID ) - ITA_EXCEPT1( INVALID_PARAMETER, "First geo propagation anchor is invalid, please purge first." ); - - auto pAnchorTail( oPropPath[ oPropPath.size() - 1 ] ); - if( pAnchorTail->iAnchorType == CPropagationAnchor::INVALID ) - ITA_EXCEPT1( INVALID_PARAMETER, "Last geo propagation anchor is invalid, please purge first." ); - - // We don't care for first and last anchor's type (except invalid) - - for( size_t i = 1; i < oPropPath.size() - 1; i++ ) - { - auto pAnchorPrev( oPropPath[ i - 1 ] ); - auto pAnchorCur( oPropPath[ i ] ); - auto pAnchorNext( oPropPath[ i + 1 ] ); - - if( pAnchorCur->iAnchorType == CPropagationAnchor::INVALID ) - ITA_EXCEPT1( INVALID_PARAMETER, "Geo propagation path has invalid anchors, please purge first." ); - - if( pAnchorCur->iAnchorType == CPropagationAnchor::DIFFRACTION_APEX ) - { - auto pWedge = std::dynamic_pointer_cast< CITADiffractionWedgeAperture>( pAnchorCur ); - - // Check if prev and next anchors are occluded by wedge - if( !pWedge->IsOccluding( pAnchorPrev, pAnchorNext ) ) - return false; - } - } - - return true; -} - -void Kirchhoff::GetDirectLengthAndDetourLength( const CPropagationPath& oPropPath, double& dPropagationLengthDirect, double& dPropagationLengthDetour ) -{ - if( oPropPath.size() < 3 ) - ITA_EXCEPT1( INVALID_PARAMETER, "Propagation path needs at least 3 anchors for Kirchhoff method" ); - - auto pAnchorDirectLazy( oPropPath[ 0 ] ); - if( pAnchorDirectLazy->iAnchorType == CPropagationAnchor::INVALID ) - ITA_EXCEPT1( INVALID_PARAMETER, "First geo propagation anchor is invalid, please purge." ); - - auto pAnchorTail( oPropPath[ oPropPath.size() - 1 ] ); - if( pAnchorTail->iAnchorType == CPropagationAnchor::INVALID ) - ITA_EXCEPT1( INVALID_PARAMETER, "Last geo propagation anchor is invalid, please purge." ); - - // We don't care for first and last anchor's type (except invalid) - - dPropagationLengthDirect = 0.0f; - dPropagationLengthDetour = 0.0f; - - for( size_t i = 1; i < oPropPath.size(); i++ ) - { - auto pAnchorPrev( oPropPath[ i - 1 ] ); - auto pAnchorCur( oPropPath[ i ] ); - - if( pAnchorCur->iAnchorType == CPropagationAnchor::INVALID ) - ITA_EXCEPT1( INVALID_PARAMETER, "Geo propagation path has invalid anchors, please purge first." ); - - // Detour is everything ... - const VistaVector3D vIntermediateLine = pAnchorCur->v3InteractionPoint - pAnchorPrev->v3InteractionPoint; - const double dIntermediateLength = vIntermediateLine.GetLength(); - dPropagationLengthDetour += dIntermediateLength; - - // ... but direct path skips diffraction anchors - if( pAnchorCur->iAnchorType != CPropagationAnchor::DIFFRACTION_APEX || pAnchorCur == pAnchorTail ) - { - const VistaVector3D vIntermediateDirectLine = pAnchorCur->v3InteractionPoint - pAnchorDirectLazy->v3InteractionPoint; - const double dIntermediateDirectLine = vIntermediateDirectLine.GetLength(); - dPropagationLengthDirect += dIntermediateDirectLine; - pAnchorDirectLazy = pAnchorCur; - } - } - - // Zero-length path would be crude, make assertion here to give user a hint that something is wrong with his input - assert( dPropagationLengthDetour > 0.0f ); - assert( dPropagationLengthDirect > 0.0f ); - - return; -} - -double Kirchhoff::KirchhoffDelta( const double dPropagationLengthDirect, const double dPropagationLengthDetour ) -{ - if( dPropagationLengthDirect <= 0.0f ) - ITA_EXCEPT1( INVALID_PARAMETER, "Diffraction direct path length can not be zero or negative" ); - - if( dPropagationLengthDetour <= 0.0f ) - ITA_EXCEPT1( INVALID_PARAMETER, "Diffraction detour path length can not be zero or negative" ) - - if( dPropagationLengthDetour < dPropagationLengthDirect ) - ITA_EXCEPT1( INVALID_PARAMETER, "Diffraction detour path length can not be smaller than direct path" ); - - const double dKirchhoffDelta = dPropagationLengthDetour - dPropagationLengthDirect; // Difference in path length, no magic here - return dKirchhoffDelta; -} - -void Kirchhoff::CalculateDiffractionFilter( const double dDirect, const double dDetour, ITABase::CHDFTSpectrum& oTransferFunction, const float fSpeedOfSound /*= 344.0f*/ ) -{ - assert( fSpeedOfSound > 0.0f ); - if( fSpeedOfSound <= 0.0f ) - ITA_EXCEPT1( INVALID_PARAMETER, "Speed of sound can't be zero or negative" ); - - // Per definition, DC value is real and 1.0 - oTransferFunction.SetCoeffRI( 0, 1.0f, 0.0f ); - - const int iDFTSize = oTransferFunction.GetSize(); - for( int i = 1; i < iDFTSize - 1; i++ ) - { - const double dFrequency = oTransferFunction.GetFrequencyResolution() * i; - const double dFresnelNumber = 2.0f * Kirchhoff::KirchhoffDelta( dDirect, dDetour ) * dFrequency / fSpeedOfSound; // Sometimes referred to as 'N' - oTransferFunction.SetCoeffRI( i, float( dFresnelNumber ) ); - } -} diff --git a/src/ITAPropagationModels/Maekawa.cpp b/src/ITAPropagationModels/Maekawa.cpp index dddd4a89dd6cf5bc1828bb0fb08b83fe30697dea..b8cfd4751b130277f24c68fa7d2f51650f0f5bfd 100644 --- a/src/ITAPropagationModels/Maekawa.cpp +++ b/src/ITAPropagationModels/Maekawa.cpp @@ -1,73 +1,71 @@ -#include <ITADiffractionMaekawa.h> +#include <ITAPropagationModels/Kirchhoff.h> + #include <ITAException.h> -bool IsMaekawaApplicable( const CITAGeoPropagationPath& oPropPath ) +using namespace ITAGeo; +using namespace ITAPropagationModels; + +bool Kirchhoff::IsApplicable( const CPropagationPath& oPropPath ) { if( oPropPath.size() < 3 ) - ITA_EXCEPT1( INVALID_PARAMETER, "Propagation path needs at least 3 anchors for Maekawa method" ); + ITA_EXCEPT1( INVALID_PARAMETER, "Propagation path needs at least 3 anchors for Kirchhoff method" ); - const CITAGeoPropagationAnchor* pAnchorDirectLazy( oPropPath[ 0 ] ); - if( pAnchorDirectLazy->iAnchorType == CITAGeoPropagationAnchor::ITA_ANCHOR_INVALID ) + auto pAnchorDirectLazy( oPropPath[ 0 ] ); + if( pAnchorDirectLazy->iAnchorType == CPropagationAnchor::INVALID ) ITA_EXCEPT1( INVALID_PARAMETER, "First geo propagation anchor is invalid, please purge first." ); - const CITAGeoPropagationAnchor* pAnchorTail( oPropPath[ oPropPath.size() - 1 ] ); - if( pAnchorTail->iAnchorType == CITAGeoPropagationAnchor::ITA_ANCHOR_INVALID ) + auto pAnchorTail( oPropPath[ oPropPath.size() - 1 ] ); + if( pAnchorTail->iAnchorType == CPropagationAnchor::INVALID ) ITA_EXCEPT1( INVALID_PARAMETER, "Last geo propagation anchor is invalid, please purge first." ); // We don't care for first and last anchor's type (except invalid) - double dIncrementalAngle = 0.0f; - for( size_t i = 1; i < oPropPath.size() - 1; i++ ) { - const CITAGeoPropagationAnchor* pAnchorPrev( oPropPath[ i - 1 ] ); - const CITAGeoPropagationAnchor* pAnchorCur( oPropPath[ i ] ); - const CITAGeoPropagationAnchor* pAnchorNext( oPropPath[ i + 1 ] ); + auto pAnchorPrev( oPropPath[ i - 1 ] ); + auto pAnchorCur( oPropPath[ i ] ); + auto pAnchorNext( oPropPath[ i + 1 ] ); - if( pAnchorCur->iAnchorType == CITAGeoPropagationAnchor::ITA_ANCHOR_INVALID ) + if( pAnchorCur->iAnchorType == CPropagationAnchor::INVALID ) ITA_EXCEPT1( INVALID_PARAMETER, "Geo propagation path has invalid anchors, please purge first." ); - if( pAnchorCur->iAnchorType == CITAGeoPropagationAnchor::ITA_EDGE_DIFFRACTION ) + if( pAnchorCur->iAnchorType == CPropagationAnchor::DIFFRACTION_APEX ) { - const CITADiffractionWedge* pWedge( ( const CITADiffractionWedge* ) pAnchorCur ); - dIncrementalAngle += pWedge->GetOpeningAngleRad(); - - if( dIncrementalAngle > ITAConstants::TWO_PI_D ) - return false; - - + auto pWedge = std::dynamic_pointer_cast< CITADiffractionWedgeAperture>( pAnchorCur ); + + // Check if prev and next anchors are occluded by wedge + if( !pWedge->IsOccluding( pAnchorPrev, pAnchorNext ) ) + return false; } - - } return true; } -void MaekawaDetourAndLength( const CITAGeoPropagationPath& oPropPath, double& dPropagationLengthDetour, double& dPropagationLengthDirect ) +void Kirchhoff::GetDirectLengthAndDetourLength( const CPropagationPath& oPropPath, double& dPropagationLengthDirect, double& dPropagationLengthDetour ) { if( oPropPath.size() < 3 ) - ITA_EXCEPT1( INVALID_PARAMETER, "Propagation path needs at least 3 anchors for Maekawa method" ); + ITA_EXCEPT1( INVALID_PARAMETER, "Propagation path needs at least 3 anchors for Kirchhoff method" ); - const CITAGeoPropagationAnchor* pAnchorDirectLazy( oPropPath[ 0 ] ); - if( pAnchorDirectLazy->iAnchorType == CITAGeoPropagationAnchor::ITA_ANCHOR_INVALID ) - ITA_EXCEPT1( INVALID_PARAMETER, "First geo propagation anchor is invalid, please purge first." ); + auto pAnchorDirectLazy( oPropPath[ 0 ] ); + if( pAnchorDirectLazy->iAnchorType == CPropagationAnchor::INVALID ) + ITA_EXCEPT1( INVALID_PARAMETER, "First geo propagation anchor is invalid, please purge." ); - const CITAGeoPropagationAnchor* pAnchorTail( oPropPath[ oPropPath.size() - 1 ] ); - if( pAnchorTail->iAnchorType == CITAGeoPropagationAnchor::ITA_ANCHOR_INVALID ) - ITA_EXCEPT1( INVALID_PARAMETER, "Last geo propagation anchor is invalid, please purge first." ); + auto pAnchorTail( oPropPath[ oPropPath.size() - 1 ] ); + if( pAnchorTail->iAnchorType == CPropagationAnchor::INVALID ) + ITA_EXCEPT1( INVALID_PARAMETER, "Last geo propagation anchor is invalid, please purge." ); // We don't care for first and last anchor's type (except invalid) - dPropagationLengthDetour = 0.0f; dPropagationLengthDirect = 0.0f; + dPropagationLengthDetour = 0.0f; - for( size_t i = 1; i < oPropPath.size() - 1; i++ ) + for( size_t i = 1; i < oPropPath.size(); i++ ) { - const CITAGeoPropagationAnchor* pAnchorPrev( oPropPath[ i - 1 ] ); - const CITAGeoPropagationAnchor* pAnchorCur( oPropPath[ i ] ); + auto pAnchorPrev( oPropPath[ i - 1 ] ); + auto pAnchorCur( oPropPath[ i ] ); - if( pAnchorCur->iAnchorType == CITAGeoPropagationAnchor::ITA_ANCHOR_INVALID ) + if( pAnchorCur->iAnchorType == CPropagationAnchor::INVALID ) ITA_EXCEPT1( INVALID_PARAMETER, "Geo propagation path has invalid anchors, please purge first." ); // Detour is everything ... @@ -76,12 +74,11 @@ void MaekawaDetourAndLength( const CITAGeoPropagationPath& oPropPath, double& dP dPropagationLengthDetour += dIntermediateLength; // ... but direct path skips diffraction anchors - if( pAnchorCur->iAnchorType != CITAGeoPropagationAnchor::ITA_EDGE_DIFFRACTION ) + if( pAnchorCur->iAnchorType != CPropagationAnchor::DIFFRACTION_APEX || pAnchorCur == pAnchorTail ) { const VistaVector3D vIntermediateDirectLine = pAnchorCur->v3InteractionPoint - pAnchorDirectLazy->v3InteractionPoint; const double dIntermediateDirectLine = vIntermediateDirectLine.GetLength(); - dPropagationLengthDirect += dIntermediateLength; - dPropagationLengthDetour += dIntermediateLength; + dPropagationLengthDirect += dIntermediateDirectLine; pAnchorDirectLazy = pAnchorCur; } } @@ -91,4 +88,37 @@ void MaekawaDetourAndLength( const CITAGeoPropagationPath& oPropPath, double& dP assert( dPropagationLengthDirect > 0.0f ); return; -} \ No newline at end of file +} + +double Kirchhoff::KirchhoffDelta( const double dPropagationLengthDirect, const double dPropagationLengthDetour ) +{ + if( dPropagationLengthDirect <= 0.0f ) + ITA_EXCEPT1( INVALID_PARAMETER, "Diffraction direct path length can not be zero or negative" ); + + if( dPropagationLengthDetour <= 0.0f ) + ITA_EXCEPT1( INVALID_PARAMETER, "Diffraction detour path length can not be zero or negative" ) + + if( dPropagationLengthDetour < dPropagationLengthDirect ) + ITA_EXCEPT1( INVALID_PARAMETER, "Diffraction detour path length can not be smaller than direct path" ); + + const double dKirchhoffDelta = dPropagationLengthDetour - dPropagationLengthDirect; // Difference in path length, no magic here + return dKirchhoffDelta; +} + +void Kirchhoff::CalculateDiffractionFilter( const double dDirect, const double dDetour, ITABase::CHDFTSpectrum& oTransferFunction, const float fSpeedOfSound /*= 344.0f*/ ) +{ + assert( fSpeedOfSound > 0.0f ); + if( fSpeedOfSound <= 0.0f ) + ITA_EXCEPT1( INVALID_PARAMETER, "Speed of sound can't be zero or negative" ); + + // Per definition, DC value is real and 1.0 + oTransferFunction.SetCoeffRI( 0, 1.0f, 0.0f ); + + const int iDFTSize = oTransferFunction.GetSize(); + for( int i = 1; i < iDFTSize - 1; i++ ) + { + const double dFrequency = oTransferFunction.GetFrequencyResolution() * i; + const double dFresnelNumber = 2.0f * Kirchhoff::KirchhoffDelta( dDirect, dDetour ) * dFrequency / fSpeedOfSound; // Sometimes referred to as 'N' + oTransferFunction.SetCoeffRI( i, float( dFresnelNumber ) ); + } +}