From 4d72e7a0500ef313d40c35a25966eb77fd209e4f Mon Sep 17 00:00:00 2001
From: "yifei.luo" <yifei.luo@rwth-aachen.de>
Date: Thu, 26 Sep 2024 11:50:24 +0200
Subject: [PATCH 1/6] Feat: working progress.

---
 CMakeLists.txt                                |   3 +
 .../ReflectionModules/BasicReflection.h       |  45 +++++++
 .../ReflectionModules/BasicReflection.cpp     | 127 ++++++++++++++++++
 3 files changed, 175 insertions(+)
 create mode 100644 include/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h
 create mode 100644 src/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3367c4d..b6d035c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,6 +40,7 @@ ihta_add_library (
 			include/ITApropagationModels/PropagationParameterEngine/PropagationModules/BaseModule.h
 			include/ITApropagationModels/PropagationParameterEngine/PropagationModules/ModuleFactory.h
 			include/ITApropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/DumbReflection.h
+			include/ITApropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h
 			include/ITApropagationModels/PropagationParameterEngine/PropagationModules/DiffractionModules/DumbDiffraction.h
 			include/ITApropagationModels/PropagationParameterEngine/PropagationModules/SpreadingLossModules/DumbSpreadingLoss.h
 			include/ITApropagationModels/PropagationParameterEngine/PropagationModules/AirAttenuationModules/DumbAirAttenuation.h
@@ -56,6 +57,7 @@ ihta_add_library (
 			src/ITApropagationModels/PropagationParameterEngine/PropagationConfig.cpp
 			src/ITApropagationModels/PropagationParameterEngine/PropagationModules/ModuleFactory.cpp
 			src/ITApropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/DumbReflection.cpp
+			src/ITApropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp
 			src/ITApropagationModels/PropagationParameterEngine/PropagationModules/DiffractionModules/DumbDiffraction.cpp
 			src/ITApropagationModels/PropagationParameterEngine/PropagationModules/SpreadingLossModules/DumbSpreadingLoss.cpp
 			src/ITApropagationModels/PropagationParameterEngine/PropagationModules/AirAttenuationModules/DumbAirAttenuation.cpp
@@ -63,6 +65,7 @@ ihta_add_library (
 			src/ITApropagationModels/PropagationParameterEngine/PropagationModules/PropagationDelayModules/DumbPropagationDelay.cpp
 			src/ITAPropagationModels/PropagationParameterEngine/UtilsPPE.cpp
 			src/ITAPropagationModels/PropagationParameterEngine/PropagationParameters/FrequencySpectrum.cpp
+
 	NAMESPACE ${PROJECT_NAME}
 	IDE_FOLDER "ITAGeometricalAcoustics"
 	OUT_LIB LIB_TARGET
diff --git a/include/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h b/include/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h
new file mode 100644
index 0000000..9f2c296
--- /dev/null
+++ b/include/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <ITAPropagationModels/Definitions.h>
+#include <ITAPropagationModels/PropagationParameterEngine/PropagationModules/BaseModule.h>
+
+#include <../../../ITAGeometricalAcoustics/ITAGeo/include/ITAGeo/Material/Material.h>
+
+#include <glm/glm.hpp>
+
+namespace ITAPropagationModels
+{
+	namespace PropagationParameterEngine
+	{
+		namespace PropagationModules
+		{
+			//! @brief Simple reflection class. Scales the frequency response by the given percent or, if no scale is provided, by 1 (nothing happens).
+			class ITA_PROPAGATION_MODELS_API CBasicReflection : public CBaseModules
+			{
+			private:
+				float m_scale { 1.0f };
+				//! @brief self register to factory
+				static bool registered;
+
+			public:
+				CBasicReflection( ) = default;
+				//! @param scale between 0 and 1
+				//! @throws std::invalid argument if scale out of range
+				CBasicReflection( const float scale );
+				~CBasicReflection( ) = default;
+
+				std::unordered_map<std::string, std::unique_ptr<ITAPropagationModels::PropagationParameterEngine::PropagationParameters::CBasePropagationParameter>> 
+				compute ( const propagation_path_list::PropagationPathList& ppl ) override ;
+				[[no_discard]] EModuleIdentifier get_identifier( ) const override { return EModuleIdentifier::REFLECTION; };
+
+				void compute_anchor_reflection_factor( std::shared_ptr< const propagation_path_list::PropagationAnchorBase > reflection_anchor, std::shared_ptr< const propagation_path_list::PropagationAnchorBase > previous_anchor, const std::shared_ptr<propagation_path_list::MaterialBase> && material_type ) {}
+				void get_reflection_factor_impedance( glm::vec3 incident_vector, glm::vec3 emitting_vector, float impedance ) {}
+				void interpolate_scalar_material_reflection_factor() {};
+				void interpolate_third_octave_material_reflecton_factor() {};
+				void compute_reflection_factor_impedance() {};
+				void compute_reflection_factor_absorption(double absorption) {};
+			};
+
+		} // namespace PropagationModules
+	} // namespace PropagationParameterEngine
+} // namespace ITAPropagationModels
diff --git a/src/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp b/src/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp
new file mode 100644
index 0000000..5b40ac0
--- /dev/null
+++ b/src/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp
@@ -0,0 +1,127 @@
+#include <ITAPropagationModels/PropagationParameterEngine/PropagationModules/ModuleFactory.h>
+#include <ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h>
+#include <ITAPropagationModels/PropagationParameterEngine/PropagationParameters/FrequencySpectrum.h>
+#include <ITAPropagationModels/PropagationParameterEngine/UtilsPPE.h>
+#include <exception>
+#include <memory>
+
+using namespace ITAPropagationModels::PropagationParameterEngine;
+
+//! @brief register to factory
+bool PropagationModules::CBasicReflection::registered = CFactory::registerModule<DumbReflectionConfig, CBasicReflection>( );
+
+PropagationModules::CBasicReflection::CBasicReflection( const float scale )
+{
+	if( scale > 1.0f || scale < 0.0f )
+		throw std::invalid_argument( "scale has to be between 0 and 1." );
+
+	this->m_scale = scale;
+}
+
+std::unordered_map<std::string, std::unique_ptr<PropagationParameters::CBasePropagationParameter>> PropagationModules::CBasicReflection::compute(
+    const propagation_path_list::PropagationPathList& ppl )
+{
+	std::unordered_map<std::string, std::unique_ptr<ITAPropagationModels::PropagationParameterEngine::PropagationParameters::CBasePropagationParameter>>
+	    module_output { };
+	//ppl.material_database
+	std::shared_ptr<propagation_path_list::PropagationAnchorBase> previous_anchor;
+	std::shared_ptr<propagation_path_list::PropagationAnchorBase> reflection_anchor;
+
+	for ( const propagation_path_list::PropagationPath& path: ppl.propagation_paths )
+	{
+		for ( auto&& anchor: path.propagation_anchors )
+		{
+			if (auto reflection_pointer = std::dynamic_pointer_cast<propagation_path_list::SpecularReflection>(anchor))
+			{
+				reflection_anchor = anchor;
+
+				// Reflection factor spectrum 
+				auto material_type = ppl.material_database.find(reflection_pointer->material_id);
+				if (material_type != ppl.material_database.end()) {
+					// The material ID exists in the database, get the shared_ptr
+					std::shared_ptr<propagation_path_list::MaterialBase> material_type = material_type;
+					compute_anchor_reflection_factor(reflection_anchor, previous_anchor, std::move(material_type));
+				} else {
+					// Handle the case where the material ID is not found in the database
+					std::cerr << "Material not found in the database!" << std::endl;
+				}
+				
+			}
+			else
+			{
+				previous_anchor = anchor;
+			}
+			
+		}
+		
+		PropagationParameters::CFrequencySpectrum path_spectrum( 1.0f );
+
+		module_output[path.identifier] = std::make_unique<PropagationParameters::CFrequencySpectrum>( path_spectrum );
+
+	}
+
+	return module_output;
+}
+
+void compute_anchor_reflection_factor( std::shared_ptr<const propagation_path_list::SpecularReflection> reflection_anchor, std::shared_ptr<const propagation_path_list::PropagationAnchorBase> previous_vector, const std::shared_ptr<propagation_path_list::MaterialBase> && material_type )
+{
+	const glm::vec3 face_normal( reflection_anchor->face_normal[0], reflection_anchor->face_normal[1], reflection_anchor->face_normal[2]);
+	const glm::vec3 incident_vector( previous_vector->interaction_point[0] - reflection_anchor->interaction_point[0],
+	previous_vector->interaction_point[1] - reflection_anchor->interaction_point[1],
+	previous_vector->interaction_point[2] - reflection_anchor->interaction_point[2]);
+
+	if (auto ScalarMaterial = std::dynamic_pointer_cast<propagation_path_list::ScalarMaterial>(material_type))
+	{
+		// only absorption is available for scalar materials
+		double absorption = 0.0;
+		compute_reflection_factor_absorption(absorption);
+		interpolate_scalar_material_reflection_factor();
+	}
+	
+	if (auto ThirdOctaveMaterial = std::dynamic_pointer_cast<propagation_path_list::ThirdOctaveMaterial>(material_type))
+	{
+		propagation_path_list::MagnitudeSpectra spectra_real = ThirdOctaveMaterial->impedance_real;
+		// if impedence is available, get reflection factor with impedence
+		if (TRUE)
+		{
+			for (auto freq = 0; freq < 31; freq++)
+			{
+				compute_reflection_factor_impedance();
+				interpolate_third_octave_material_reflecton_factor();
+			}
+		}
+		else
+		{
+			for (auto freq = 0; freq < 31; freq++)
+			{
+				double absorption = 0.0;
+				compute_reflection_factor_absorption(absorption);
+				interpolate_third_octave_material_reflecton_factor();
+			}
+		}
+		
+	}
+	
+}
+
+void interpolate_scalar_material_reflection_factor() 
+{
+	// 
+}
+
+void interpolate_third_octave_material_reflecton_factor() 
+{
+	// cubic spline
+}
+
+void compute_reflection_factor_impedance() 
+{
+	// function 3.3 in the book Auralization, Fundamentals of Acoustics, Modelling, Simulation, Algorithms and Acoustic Virtual Reality, second edition, page 32.
+	// To Do: only the function, the most reusable part.
+}
+			
+void compute_reflection_factor_absorption(double absorption) 
+{
+	// function 11.39 in the book Auralization, Fundamentals of Acoustics, Modelling, Simulation, Algorithms and Acoustic Virtual Reality, second edition, page 198.
+	//
+}
\ No newline at end of file
-- 
GitLab


From 14e65899b3061f63a642c9202f669573c9ade19b Mon Sep 17 00:00:00 2001
From: "yifei.luo" <yifei.luo@rwth-aachen.de>
Date: Mon, 21 Oct 2024 14:31:55 +0200
Subject: [PATCH 2/6] Work on progress.

---
 .../ReflectionModules/BasicReflection.h       |  22 ++--
 .../ReflectionModules/BasicReflection.cpp     | 121 ++++++++++++------
 2 files changed, 90 insertions(+), 53 deletions(-)

diff --git a/include/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h b/include/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h
index 9f2c296..b0eb87a 100644
--- a/include/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h
+++ b/include/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h
@@ -1,10 +1,8 @@
 #pragma once
 
+#include <../../../ITAGeometricalAcoustics/ITAGeo/include/ITAGeo/Material/Material.h>
 #include <ITAPropagationModels/Definitions.h>
 #include <ITAPropagationModels/PropagationParameterEngine/PropagationModules/BaseModule.h>
-
-#include <../../../ITAGeometricalAcoustics/ITAGeo/include/ITAGeo/Material/Material.h>
-
 #include <glm/glm.hpp>
 
 namespace ITAPropagationModels
@@ -28,16 +26,18 @@ namespace ITAPropagationModels
 				CBasicReflection( const float scale );
 				~CBasicReflection( ) = default;
 
-				std::unordered_map<std::string, std::unique_ptr<ITAPropagationModels::PropagationParameterEngine::PropagationParameters::CBasePropagationParameter>> 
-				compute ( const propagation_path_list::PropagationPathList& ppl ) override ;
+				std::unordered_map<std::string, std::unique_ptr<ITAPropagationModels::PropagationParameterEngine::PropagationParameters::CBasePropagationParameter>>
+				compute( const propagation_path_list::PropagationPathList& ppl ) override;
 				[[no_discard]] EModuleIdentifier get_identifier( ) const override { return EModuleIdentifier::REFLECTION; };
 
-				void compute_anchor_reflection_factor( std::shared_ptr< const propagation_path_list::PropagationAnchorBase > reflection_anchor, std::shared_ptr< const propagation_path_list::PropagationAnchorBase > previous_anchor, const std::shared_ptr<propagation_path_list::MaterialBase> && material_type ) {}
-				void get_reflection_factor_impedance( glm::vec3 incident_vector, glm::vec3 emitting_vector, float impedance ) {}
-				void interpolate_scalar_material_reflection_factor() {};
-				void interpolate_third_octave_material_reflecton_factor() {};
-				void compute_reflection_factor_impedance() {};
-				void compute_reflection_factor_absorption(double absorption) {};
+				void compute_anchor_reflection_factor( std::shared_ptr<const propagation_path_list::PropagationAnchorBase> reflection_anchor,
+				                                       std::shared_ptr<const propagation_path_list::PropagationAnchorBase> previous_anchor,
+				                                       const std::shared_ptr<propagation_path_list::MaterialBase>&& material_type );
+				void get_reflection_factor_impedance( glm::vec3 incident_vector, glm::vec3 emitting_vector, float impedance );
+				double interpolate_scalar_material_reflection_factor( );
+				void interpolate_third_octave_material_reflecton_factor( );
+				void compute_reflection_factor_impedance( );
+				void compute_reflection_factor_absorption( double absorption ) ;
 			};
 
 		} // namespace PropagationModules
diff --git a/src/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp b/src/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp
index 5b40ac0..a0ddad0 100644
--- a/src/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp
+++ b/src/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp
@@ -23,105 +23,142 @@ std::unordered_map<std::string, std::unique_ptr<PropagationParameters::CBaseProp
 {
 	std::unordered_map<std::string, std::unique_ptr<ITAPropagationModels::PropagationParameterEngine::PropagationParameters::CBasePropagationParameter>>
 	    module_output { };
-	//ppl.material_database
+	// ppl.material_database
 	std::shared_ptr<propagation_path_list::PropagationAnchorBase> previous_anchor;
 	std::shared_ptr<propagation_path_list::PropagationAnchorBase> reflection_anchor;
 
-	for ( const propagation_path_list::PropagationPath& path: ppl.propagation_paths )
+	for( const propagation_path_list::PropagationPath& path: ppl.propagation_paths )
 	{
-		for ( auto&& anchor: path.propagation_anchors )
+		for( auto&& anchor: path.propagation_anchors )
 		{
-			if (auto reflection_pointer = std::dynamic_pointer_cast<propagation_path_list::SpecularReflection>(anchor))
+			if( auto reflection_pointer = std::dynamic_pointer_cast<propagation_path_list::SpecularReflection>( anchor ) )
 			{
 				reflection_anchor = anchor;
 
-				// Reflection factor spectrum 
-				auto material_type = ppl.material_database.find(reflection_pointer->material_id);
-				if (material_type != ppl.material_database.end()) {
+				// Reflection factor spectrum
+				auto material_type = ppl.material_database.find( reflection_pointer->material_id );
+				if( material_type != ppl.material_database.end( ) )
+				{
 					// The material ID exists in the database, get the shared_ptr
 					std::shared_ptr<propagation_path_list::MaterialBase> material_type = material_type;
-					compute_anchor_reflection_factor(reflection_anchor, previous_anchor, std::move(material_type));
-				} else {
+					compute_anchor_reflection_factor( reflection_pointer, previous_anchor, std::move( material_type ) );
+				}
+				else
+				{
 					// Handle the case where the material ID is not found in the database
 					std::cerr << "Material not found in the database!" << std::endl;
 				}
-				
 			}
 			else
 			{
 				previous_anchor = anchor;
 			}
-			
-		}
-		
+		}						
+
 		PropagationParameters::CFrequencySpectrum path_spectrum( 1.0f );
 
 		module_output[path.identifier] = std::make_unique<PropagationParameters::CFrequencySpectrum>( path_spectrum );
-
 	}
 
 	return module_output;
 }
 
-void compute_anchor_reflection_factor( std::shared_ptr<const propagation_path_list::SpecularReflection> reflection_anchor, std::shared_ptr<const propagation_path_list::PropagationAnchorBase> previous_vector, const std::shared_ptr<propagation_path_list::MaterialBase> && material_type )
+void PropagationModules::CBasicReflection::compute_anchor_reflection_factor( std::shared_ptr<const propagation_path_list::PropagationAnchorBase> reflection_anchor,
+                                                                             std::shared_ptr<const propagation_path_list::PropagationAnchorBase> previous_anchor,
+                                                                             const std::shared_ptr<propagation_path_list::MaterialBase>&& material_type )
 {
-	const glm::vec3 face_normal( reflection_anchor->face_normal[0], reflection_anchor->face_normal[1], reflection_anchor->face_normal[2]);
-	const glm::vec3 incident_vector( previous_vector->interaction_point[0] - reflection_anchor->interaction_point[0],
-	previous_vector->interaction_point[1] - reflection_anchor->interaction_point[1],
-	previous_vector->interaction_point[2] - reflection_anchor->interaction_point[2]);
+	auto reflection_pointer = std::dynamic_pointer_cast<propagation_path_list::SpecularReflection>( reflection_anchor ) ;
+	const glm::vec3 face_normal( reflection_pointer->face_normal[0], reflection_pointer->face_normal[1], reflection_pointer->face_normal[2] );
+	const glm::vec3 incident_vector( previous_anchor->interaction_point[0] - reflection_anchor->interaction_point[0],
+	                                 previous_anchor->interaction_point[1] - reflection_anchor->interaction_point[1],
+	                                 previous_anchor->interaction_point[2] - reflection_anchor->interaction_point[2] );
 
-	if (auto ScalarMaterial = std::dynamic_pointer_cast<propagation_path_list::ScalarMaterial>(material_type))
+	if( auto ScalarMaterial = std::dynamic_pointer_cast<propagation_path_list::ScalarMaterial>( material_type ) )
 	{
 		// only absorption is available for scalar materials
 		double absorption = 0.0;
-		compute_reflection_factor_absorption(absorption);
-		interpolate_scalar_material_reflection_factor();
+		compute_reflection_factor_absorption( absorption );
+		interpolate_scalar_material_reflection_factor( );
 	}
-	
-	if (auto ThirdOctaveMaterial = std::dynamic_pointer_cast<propagation_path_list::ThirdOctaveMaterial>(material_type))
+
+	if( auto ThirdOctaveMaterial = std::dynamic_pointer_cast<propagation_path_list::ThirdOctaveMaterial>( material_type ) )
 	{
 		propagation_path_list::MagnitudeSpectra spectra_real = ThirdOctaveMaterial->impedance_real;
 		// if impedence is available, get reflection factor with impedence
-		if (TRUE)
+		if( TRUE )
 		{
-			for (auto freq = 0; freq < 31; freq++)
+			for( auto freq = 0; freq < 31; freq++ )
 			{
-				compute_reflection_factor_impedance();
-				interpolate_third_octave_material_reflecton_factor();
+				compute_reflection_factor_impedance( );
+				interpolate_third_octave_material_reflecton_factor( );
 			}
 		}
 		else
 		{
-			for (auto freq = 0; freq < 31; freq++)
+			for( auto freq = 0; freq < 31; freq++ )
 			{
 				double absorption = 0.0;
-				compute_reflection_factor_absorption(absorption);
-				interpolate_third_octave_material_reflecton_factor();
+				compute_reflection_factor_absorption( absorption );
+				interpolate_third_octave_material_reflecton_factor( );
 			}
 		}
-		
 	}
-	
-}
+}	
 
-void interpolate_scalar_material_reflection_factor() 
+double PropagationModules::CBasicReflection::interpolate_scalar_material_reflection_factor( )
 {
-	// 
+	// **Undecided** Passing which parameters are better?
+	// **Temporary** Change the locally defined parameters to  
+	double desired_frequency = 450.0;
+	double scalar_reflection_factor = 0.8; 
+
+	return scalar_reflection_factor; //
 }
 
-void interpolate_third_octave_material_reflecton_factor() 
+void PropagationModules::CBasicReflection::interpolate_third_octave_material_reflecton_factor( )
 {
 	// cubic spline
+	// ** before programming ** 
+	// 1. Interpolate to ... ? A: 
+	// 
 }
 
-void compute_reflection_factor_impedance() 
+void PropagationModules::CBasicReflection::compute_reflection_factor_impedance( )
 {
 	// function 3.3 in the book Auralization, Fundamentals of Acoustics, Modelling, Simulation, Algorithms and Acoustic Virtual Reality, second edition, page 32.
-	// To Do: only the function, the most reusable part.
+
+	// temporary parameters, should be passed when calling the function
+	double Z = 0.5; // **invalid value** Wall impedance.
+	double Z0 = 1; // **invalid value**
+	double theta = 0.5; // incident angle between incident direction and the face normal
+
+	double numerator = Z * cos(theta) - Z0; // **<cmath> or other specific mathmatical repository?**
+    double denominator = Z * cos(theta) + Z0;
+
+	if (denominator == 0) {
+        //std::cerr << "Error: Division by zero in reflection coefficient calculation." << std::endl;
+        return ; // **To be updated from void**. Return -1? Any impossible value.
+    }
+
+    double R = numerator / denominator;
+
+	return; // **To be updated.** Return one value or return one spectrum or ...?
 }
-			
-void compute_reflection_factor_absorption(double absorption) 
+
+void PropagationModules::CBasicReflection::compute_reflection_factor_absorption( double absorption )
 {
 	// function 11.39 in the book Auralization, Fundamentals of Acoustics, Modelling, Simulation, Algorithms and Acoustic Virtual Reality, second edition, page 198.
-	//
+    // ** temporary parameters **
+	// ** to be updated to passed parameters **
+	double alpha = 0.5;// ** template ** 
+
+	if (alpha < 0 || alpha > 1) {
+        std::cerr << "Error: Absorption coefficient must be between 0 and 1." << std::endl; // ** use std::cerr or ...? **
+        return ;  // ** return an impossible value **
+    }
+
+    // Calculate the reflection factor |R|
+    double abs_reflection_factor = std::sqrt(1 - alpha);
+
+    return ; // ** return R or |R|?
 }
\ No newline at end of file
-- 
GitLab


From f6b32e945c7d89fdb29b188e78f36a21e3846b72 Mon Sep 17 00:00:00 2001
From: Pascal Palenda <pascal.palenda@akustik.rwth-aachen.de>
Date: Mon, 21 Oct 2024 16:15:23 +0200
Subject: [PATCH 3/6] Feat: add tinyspline library

---
 CMakeLists.txt               | 3 +--
 external_libs/CMakeLists.txt | 8 ++++++++
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b6d035c..e2841e5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,7 +19,6 @@ endif ()
 # ---External libs---
 add_subdirectory (external_libs)
 
-
 # Library
 ihta_add_library (
 	NAME ${PROJECT_NAME}
@@ -99,7 +98,7 @@ target_link_libraries(
 target_link_libraries (
 	${LIB_TARGET}
 	PUBLIC ITABase::ITABase ITAGeo::ITAGeo ITAPropagationPathSim::ITAPropagationPathSim
-	PRIVATE ITAFFT::ITAFFT Spline::spline glm::glm au::au IHTA::propagation_path_list
+	PRIVATE ITAFFT::ITAFFT Spline::spline glm::glm au::au IHTA::propagation_path_list tinysplinecxx
 )
 
 # because of au::au header-only we have large obj files
diff --git a/external_libs/CMakeLists.txt b/external_libs/CMakeLists.txt
index e69a598..72cd481 100644
--- a/external_libs/CMakeLists.txt
+++ b/external_libs/CMakeLists.txt
@@ -29,3 +29,11 @@ if (EXISTS ${CMAKE_CURRENT_BINARY_DIR}/_external/au/include/au.hh
 
     set_property (TARGET au PROPERTY FOLDER "external_libs")
 endif()
+
+CPMAddPackage (
+	NAME tinySpline
+	GITHUB_REPOSITORY msteinbeck/tinyspline
+	VERSION 0.6.0
+	OPTIONS "TINYSPLINE_BUILD_EXAMPLES OFF" "TINYSPLINE_BUILD_TESTS OFF" "TINYSPLINE_BUILD_DOCS OFF"
+)
+set_property (TARGET tinyspline tinysplinecxx PROPERTY FOLDER "external_libs/tinyspline")
-- 
GitLab


From eaf00cda186b7ea6a25b4b9e1ce68fecf903e8d1 Mon Sep 17 00:00:00 2001
From: "yifei.luo" <yifei.luo@rwth-aachen.de>
Date: Wed, 30 Oct 2024 17:03:54 +0100
Subject: [PATCH 4/6] Perf: Reflection factor calculation completed but not
 tested.

---
 CMakeLists.txt                                |   3 +-
 .../ReflectionModules/BasicReflection.h       |  18 +-
 .../PropagationParameterEngine/ppe_config.hpp |   9 +
 .../ReflectionModules/BasicReflection.cpp     | 202 ++++++++++++------
 tests/UnitTest/test_ReflectionFactor.cpp      |  32 +++
 5 files changed, 189 insertions(+), 75 deletions(-)
 create mode 100644 tests/UnitTest/test_ReflectionFactor.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index e2841e5..15fc698 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -73,6 +73,7 @@ ihta_add_library (
 		tests/UnitTest/test_definitions.h
 		tests/UnitTest/test_PPE.cpp
 		tests/UnitTest/test_HomogeneousPropagationDelay.cpp
+		tests/UnitTest/test_ReflectionFactor.cpp
 	ADD_UNIT_TEST ${ITA_PROPAGATION_MODELS_WITH_TESTS}
 )
 
@@ -91,7 +92,7 @@ endif ()
 
 # Linking for UnitTests
 target_link_libraries(
-	${TEST_TARGET} PRIVATE ITAFFT::ITAFFT Spline::spline glm::glm au::au IHTA::propagation_path_list
+	${TEST_TARGET} PRIVATE ITAFFT::ITAFFT Spline::spline glm::glm au::au IHTA::propagation_path_list tinysplinecxx
 )
 
 # Linking
diff --git a/include/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h b/include/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h
index b0eb87a..559dd8b 100644
--- a/include/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h
+++ b/include/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h
@@ -4,6 +4,7 @@
 #include <ITAPropagationModels/Definitions.h>
 #include <ITAPropagationModels/PropagationParameterEngine/PropagationModules/BaseModule.h>
 #include <glm/glm.hpp>
+#include <tinysplinecxx.h>
 
 namespace ITAPropagationModels
 {
@@ -24,22 +25,21 @@ namespace ITAPropagationModels
 				//! @param scale between 0 and 1
 				//! @throws std::invalid argument if scale out of range
 				CBasicReflection( const float scale );
-				~CBasicReflection( ) = default;
+			~CBasicReflection( ) = default;
 
 				std::unordered_map<std::string, std::unique_ptr<ITAPropagationModels::PropagationParameterEngine::PropagationParameters::CBasePropagationParameter>>
 				compute( const propagation_path_list::PropagationPathList& ppl ) override;
 				[[no_discard]] EModuleIdentifier get_identifier( ) const override { return EModuleIdentifier::REFLECTION; };
 
-				void compute_anchor_reflection_factor( std::shared_ptr<const propagation_path_list::PropagationAnchorBase> reflection_anchor,
+				std::vector<std::complex<double>> compute_anchor_reflection_factor( std::shared_ptr<const propagation_path_list::SpecularReflection> reflection_anchor,
 				                                       std::shared_ptr<const propagation_path_list::PropagationAnchorBase> previous_anchor,
-				                                       const std::shared_ptr<propagation_path_list::MaterialBase>&& material_type );
-				void get_reflection_factor_impedance( glm::vec3 incident_vector, glm::vec3 emitting_vector, float impedance );
-				double interpolate_scalar_material_reflection_factor( );
-				void interpolate_third_octave_material_reflecton_factor( );
-				void compute_reflection_factor_impedance( );
-				void compute_reflection_factor_absorption( double absorption ) ;
+				                                       std::shared_ptr<propagation_path_list::MaterialBase> material_type );
+				std::vector<std::complex<double>> interpolate_scalar_material_reflection_factor( int number_of_bins, double scalar_reflection_factor );
+				std::vector<std::complex<double>> interpolate_third_octave_material_reflecton_factor( int bins, double sampling_rate, std::array<double, 31> reflection_factor_real, std::array<double, 31> reflection_factor_image );
+				double compute_reflection_factor_impedance( double impedance, double theta );
+				double compute_reflection_factor_absorption( double absorption ) ;
+				double calculate_incident_angle( const propagation_path_list::Vector& incident_vector, const propagation_path_list::Vector& face_normal) ;
 			};
-
 		} // namespace PropagationModules
 	} // namespace PropagationParameterEngine
 } // namespace ITAPropagationModels
diff --git a/include/ITAPropagationModels/PropagationParameterEngine/ppe_config.hpp b/include/ITAPropagationModels/PropagationParameterEngine/ppe_config.hpp
index e6515c5..f5d7723 100644
--- a/include/ITAPropagationModels/PropagationParameterEngine/ppe_config.hpp
+++ b/include/ITAPropagationModels/PropagationParameterEngine/ppe_config.hpp
@@ -125,6 +125,15 @@ namespace ITAPropagationModels::PropagationParameterEngine
 		}
 	};
 
+	struct BasicReflectionConfig : public ReflectionConfig
+    {
+        template<class Archive>
+        void serialize( Archive& t_archive )
+        {
+            cereal::base_class<ReflectionConfig>( this ).base_ptr->serialize( t_archive );
+        }
+    };
+
 	///
 	/// \brief Base air attenuation module config
 	///
diff --git a/src/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp b/src/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp
index a0ddad0..e386ea0 100644
--- a/src/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp
+++ b/src/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp
@@ -1,3 +1,4 @@
+#include <ITAPropagationModels/PropagationParameterEngine/PropagationConfig.h>
 #include <ITAPropagationModels/PropagationParameterEngine/PropagationModules/ModuleFactory.h>
 #include <ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h>
 #include <ITAPropagationModels/PropagationParameterEngine/PropagationParameters/FrequencySpectrum.h>
@@ -8,7 +9,7 @@
 using namespace ITAPropagationModels::PropagationParameterEngine;
 
 //! @brief register to factory
-bool PropagationModules::CBasicReflection::registered = CFactory::registerModule<DumbReflectionConfig, CBasicReflection>( );
+bool PropagationModules::CBasicReflection::registered = CFactory::registerModule<BasicReflectionConfig, CBasicReflection>( );
 
 PropagationModules::CBasicReflection::CBasicReflection( const float scale )
 {
@@ -21,27 +22,40 @@ PropagationModules::CBasicReflection::CBasicReflection( const float scale )
 std::unordered_map<std::string, std::unique_ptr<PropagationParameters::CBasePropagationParameter>> PropagationModules::CBasicReflection::compute(
     const propagation_path_list::PropagationPathList& ppl )
 {
+	// Get config parameters for sampling_rate, air density, etc.
+	const CPropagationConfig* const config = CPropagationConfig::get_instance( );
+	float sampling_rate_value = config->sampling_rate.in(au::hertz);
+	int number_of_bins = config->bins;
+
 	std::unordered_map<std::string, std::unique_ptr<ITAPropagationModels::PropagationParameterEngine::PropagationParameters::CBasePropagationParameter>>
-	    module_output { };
-	// ppl.material_database
-	std::shared_ptr<propagation_path_list::PropagationAnchorBase> previous_anchor;
+	    module_output ;
+	std::shared_ptr<const propagation_path_list::PropagationAnchorBase> previous_pointer;
 	std::shared_ptr<propagation_path_list::PropagationAnchorBase> reflection_anchor;
 
+	// A list of the reflection_factors which are vectors of double for scalar materials or vectors of std::complex<double> for ThirdOctacveMaterials.
+	std::vector<PropagationParameters::CFrequencySpectrum> reflection_factor_list;
+
 	for( const propagation_path_list::PropagationPath& path: ppl.propagation_paths )
 	{
+		std::valarray<std::complex<float>> path_reflection_factor_array(number_of_bins, 1.0);
 		for( auto&& anchor: path.propagation_anchors )
 		{
-			if( auto reflection_pointer = std::dynamic_pointer_cast<propagation_path_list::SpecularReflection>( anchor ) )
+			if( auto reflection_pointer = std::dynamic_pointer_cast<const propagation_path_list::SpecularReflection>( anchor ) )
 			{
-				reflection_anchor = anchor;
-
 				// Reflection factor spectrum
 				auto material_type = ppl.material_database.find( reflection_pointer->material_id );
 				if( material_type != ppl.material_database.end( ) )
 				{
 					// The material ID exists in the database, get the shared_ptr
-					std::shared_ptr<propagation_path_list::MaterialBase> material_type = material_type;
-					compute_anchor_reflection_factor( reflection_pointer, previous_anchor, std::move( material_type ) );
+					//std::shared_ptr<propagation_path_list::MaterialBase> material_type = material_type;
+					
+					std::vector<std::complex<double>> path_reflection_factor_vector = compute_anchor_reflection_factor( reflection_pointer, previous_pointer, material_type->second); 
+					std::valarray<std::complex<float>> valarr(path_reflection_factor_vector.size());
+					for (size_t i = 0; i < path_reflection_factor_vector.size(); ++i) {
+						valarr[i] = static_cast<std::complex<float>>(path_reflection_factor_vector[i]);
+					}
+
+					path_reflection_factor_array = path_reflection_factor_array * valarr;
 				}
 				else
 				{
@@ -51,11 +65,13 @@ std::unordered_map<std::string, std::unique_ptr<PropagationParameters::CBaseProp
 			}
 			else
 			{
-				previous_anchor = anchor;
+				previous_pointer = anchor;
 			}
-		}						
+		}			
 
-		PropagationParameters::CFrequencySpectrum path_spectrum( 1.0f );
+		// Resize the spectrum to the length of config->bins and initializing with std::complex<float>(1.0f, 0.0f).
+		PropagationParameters::CFrequencySpectrum path_spectrum( 1.0f ); 
+		path_spectrum.set_frequency_spectrum( path_reflection_factor_array);
 
 		module_output[path.identifier] = std::make_unique<PropagationParameters::CFrequencySpectrum>( path_spectrum );
 	}
@@ -63,102 +79,158 @@ std::unordered_map<std::string, std::unique_ptr<PropagationParameters::CBaseProp
 	return module_output;
 }
 
-void PropagationModules::CBasicReflection::compute_anchor_reflection_factor( std::shared_ptr<const propagation_path_list::PropagationAnchorBase> reflection_anchor,
-                                                                             std::shared_ptr<const propagation_path_list::PropagationAnchorBase> previous_anchor,
-                                                                             const std::shared_ptr<propagation_path_list::MaterialBase>&& material_type )
+std::vector<std::complex<double>> PropagationModules::CBasicReflection::compute_anchor_reflection_factor( std::shared_ptr<const propagation_path_list::SpecularReflection> reflection_pointer,
+                                                                             std::shared_ptr<const propagation_path_list::PropagationAnchorBase> previous_pointer,
+                                                                             std::shared_ptr<propagation_path_list::MaterialBase> material_type )
 {
-	auto reflection_pointer = std::dynamic_pointer_cast<propagation_path_list::SpecularReflection>( reflection_anchor ) ;
-	const glm::vec3 face_normal( reflection_pointer->face_normal[0], reflection_pointer->face_normal[1], reflection_pointer->face_normal[2] );
-	const glm::vec3 incident_vector( previous_anchor->interaction_point[0] - reflection_anchor->interaction_point[0],
-	                                 previous_anchor->interaction_point[1] - reflection_anchor->interaction_point[1],
-	                                 previous_anchor->interaction_point[2] - reflection_anchor->interaction_point[2] );
+	const CPropagationConfig* const config = CPropagationConfig::get_instance( );
+	float sampling_rate_value = config->sampling_rate.in(au::hertz);
+	int number_of_bins = config->bins;
+
+	std::vector<std::complex<double>> reflection_factor_complex;
+	
+	const propagation_path_list::Vector face_normal( reflection_pointer->face_normal );
+	const propagation_path_list::Vector incident_vector{ previous_pointer->interaction_point[0] - reflection_pointer->interaction_point[0],
+	                                 previous_pointer->interaction_point[1] - reflection_pointer->interaction_point[1],
+	                                 previous_pointer->interaction_point[2] - reflection_pointer->interaction_point[2] };
+	double theta = calculate_incident_angle(incident_vector, face_normal);
 
 	if( auto ScalarMaterial = std::dynamic_pointer_cast<propagation_path_list::ScalarMaterial>( material_type ) )
 	{
-		// only absorption is available for scalar materials
-		double absorption = 0.0;
-		compute_reflection_factor_absorption( absorption );
-		interpolate_scalar_material_reflection_factor( );
+		// only one constant absorption in double is available for scalar materials
+		double reflection_factor_scalar = compute_reflection_factor_absorption( ScalarMaterial->absorption );
+		reflection_factor_complex = interpolate_scalar_material_reflection_factor( number_of_bins, reflection_factor_scalar);
 	}
 
 	if( auto ThirdOctaveMaterial = std::dynamic_pointer_cast<propagation_path_list::ThirdOctaveMaterial>( material_type ) )
 	{
 		propagation_path_list::MagnitudeSpectra spectra_real = ThirdOctaveMaterial->impedance_real;
+		propagation_path_list::MagnitudeSpectra spectra_image = ThirdOctaveMaterial->impedance_imag;
+		std::array<double, 31> reflection_factor_real;
+		std::array<double, 31> reflection_factor_image;
+		double theta = calculate_incident_angle(incident_vector, face_normal);
+		
 		// if impedence is available, get reflection factor with impedence
-		if( TRUE )
+		// Something like if (ThirdOctaveMaterial->impedance_real != NULL) ?
+		bool impedance_real_null = std::all_of(spectra_real.begin(), spectra_real.end(), [](double i){ return i <= 1.1e-5; }) ;
+		if( !impedance_real_null ) // ** IMPORTANT TO UPDATE ** Fill in if condition (impedance exists)
 		{
 			for( auto freq = 0; freq < 31; freq++ )
 			{
-				compute_reflection_factor_impedance( );
-				interpolate_third_octave_material_reflecton_factor( );
+				reflection_factor_real[freq] = compute_reflection_factor_impedance( spectra_real[freq], theta );
+				reflection_factor_image[freq] = compute_reflection_factor_impedance( spectra_image[freq], theta );
 			}
+			reflection_factor_complex = interpolate_third_octave_material_reflecton_factor( number_of_bins, double(sampling_rate_value), reflection_factor_real, reflection_factor_image );
 		}
-		else
+		else // Only absorption is available
 		{
 			for( auto freq = 0; freq < 31; freq++ )
 			{
-				double absorption = 0.0;
-				compute_reflection_factor_absorption( absorption );
-				interpolate_third_octave_material_reflecton_factor( );
+				reflection_factor_real[freq] = compute_reflection_factor_absorption( ThirdOctaveMaterial->absorption[freq] );
+				reflection_factor_image[freq] = compute_reflection_factor_absorption( 1.0 ); // Set image part as 1.0 to return 0.0 for image part of reflection factor.
 			}
+			reflection_factor_complex = interpolate_third_octave_material_reflecton_factor( number_of_bins, sampling_rate_value, reflection_factor_real, reflection_factor_image );
 		}
 	}
+
+	return reflection_factor_complex;
 }	
 
-double PropagationModules::CBasicReflection::interpolate_scalar_material_reflection_factor( )
+std::vector<std::complex<double>> PropagationModules::CBasicReflection::interpolate_scalar_material_reflection_factor( int number_of_bins, double scalar_reflection_factor )
 {
-	// **Undecided** Passing which parameters are better?
-	// **Temporary** Change the locally defined parameters to  
-	double desired_frequency = 450.0;
-	double scalar_reflection_factor = 0.8; 
+	std::vector<std::complex<double>> scalar_reflection_factor_spectrum;
 
-	return scalar_reflection_factor; //
+	for (size_t i = 0; i < number_of_bins; i++)
+	{
+		std::complex<double> t_complex(scalar_reflection_factor, 0.0);
+		scalar_reflection_factor_spectrum.push_back(t_complex);
+	}
+	
+	return scalar_reflection_factor_spectrum; 
 }
 
-void PropagationModules::CBasicReflection::interpolate_third_octave_material_reflecton_factor( )
+std::vector<std::complex<double>> PropagationModules::CBasicReflection::interpolate_third_octave_material_reflecton_factor( int bins, double sampling_rate, std::array<double, 31> reflection_factor_real, std::array<double, 31> reflection_factor_image )
 {
 	// cubic spline
-	// ** before programming ** 
-	// 1. Interpolate to ... ? A: 
-	// 
+	double start_frequency = 20.0;
+	double end_frequency = sampling_rate / 2.0;
+	// ** To Update ** interpolating_rate was not used. Now the returned vector only contains the reflection factor values, without the corresponding frequency values.
+	double interpolating_rate = (end_frequency - start_frequency) / (bins - 1);
+
+	std::vector<std::complex<double>> full_reflection_factor_spectrum;
+
+	int control_point_count = 31;
+	tinyspline::BSpline spline_real(control_point_count, 1, 3);
+	tinyspline::BSpline spline_image(control_point_count, 1, 3);
+	std::vector<tinyspline::real> ctrlp_real = spline_real.controlPoints();
+	std::vector<tinyspline::real> ctrlp_image = spline_image.controlPoints();
+    for (size_t i = 0; i < control_point_count; ++i) 
+	{
+        ctrlp_real[i] = reflection_factor_real[i];  
+		ctrlp_image[i] = reflection_factor_image[i];
+    }
+	spline_real.setControlPoints(ctrlp_real);
+	spline_image.setControlPoints(ctrlp_image);
+
+	for (double i = 0; i < bins; i++)
+	{
+		double t = i / (bins - 1);
+
+		std::complex<double> result(spline_real.eval(t).result()[0], spline_image.eval(t).result()[0]);
+		full_reflection_factor_spectrum.push_back(result);
+	}
+
+	return full_reflection_factor_spectrum; // ** Return single value to be more flexible? Return whole spectrum might have high memory complexity. **			
+
 }
 
-void PropagationModules::CBasicReflection::compute_reflection_factor_impedance( )
+double PropagationModules::CBasicReflection::compute_reflection_factor_impedance( double impedance, double theta )
 {
 	// function 3.3 in the book Auralization, Fundamentals of Acoustics, Modelling, Simulation, Algorithms and Acoustic Virtual Reality, second edition, page 32.
+	// To calculate single reflection factor with (double)impedance
+	const CPropagationConfig* const config = CPropagationConfig::get_instance( );
+	decltype( au::velocity( float( ) ) ) speed_of_sound = config->speed_of_sound;
+	decltype( au::density( float( ) ) ) air_density = config->air_density;
 
-	// temporary parameters, should be passed when calling the function
-	double Z = 0.5; // **invalid value** Wall impedance.
-	double Z0 = 1; // **invalid value**
-	double theta = 0.5; // incident angle between incident direction and the face normal
-
-	double numerator = Z * cos(theta) - Z0; // **<cmath> or other specific mathmatical repository?**
-    double denominator = Z * cos(theta) + Z0;
-
-	if (denominator == 0) {
-        //std::cerr << "Error: Division by zero in reflection coefficient calculation." << std::endl;
-        return ; // **To be updated from void**. Return -1? Any impossible value.
-    }
+	auto Z0 = air_density * speed_of_sound;
+	decltype(au::velocity( float() ) * au::density( float() )) Z = au::velocity( float(impedance) ) * au::density( 1.f );
 
-    double R = numerator / denominator;
+    auto R = ( Z * au::unos(cos(theta)) - Z0 ) / ( Z * au::unos(cos(theta)) + Z0 );
 
-	return; // **To be updated.** Return one value or return one spectrum or ...?
+	return R;
 }
 
-void PropagationModules::CBasicReflection::compute_reflection_factor_absorption( double absorption )
+double PropagationModules::CBasicReflection::compute_reflection_factor_absorption( double absorption )
 {
 	// function 11.39 in the book Auralization, Fundamentals of Acoustics, Modelling, Simulation, Algorithms and Acoustic Virtual Reality, second edition, page 198.
-    // ** temporary parameters **
-	// ** to be updated to passed parameters **
-	double alpha = 0.5;// ** template ** 
 
-	if (alpha < 0 || alpha > 1) {
+	if (absorption < 0 || absorption > 1) 
+	{
         std::cerr << "Error: Absorption coefficient must be between 0 and 1." << std::endl; // ** use std::cerr or ...? **
-        return ;  // ** return an impossible value **
+        return -1.0;  // ** return an impossible value **
     }
 
     // Calculate the reflection factor |R|
-    double abs_reflection_factor = std::sqrt(1 - alpha);
+    double abs_reflection_factor = std::sqrt(1 - absorption);
+
+    return abs_reflection_factor; 
+}
+
+double PropagationModules::CBasicReflection::calculate_incident_angle(const propagation_path_list::Vector& incident_vector, const propagation_path_list::Vector& face_normal)
+{
+	double dot_product = incident_vector[0] * face_normal[0] +
+                         incident_vector[1] * face_normal[1] +
+                         incident_vector[2] * face_normal[2];
 
-    return ; // ** return R or |R|?
-}
\ No newline at end of file
+	double incident_magnitude = std::sqrt(incident_vector[0] * incident_vector[0] +
+                                          incident_vector[1] * incident_vector[1] +
+                                          incident_vector[2] * incident_vector[2]);
+
+	double normal_magnitude = std::sqrt(face_normal[0] * face_normal[0] +
+                                        face_normal[1] * face_normal[1] +
+                                        face_normal[2] * face_normal[2]);
+	double cos_angle = dot_product / (incident_magnitude * normal_magnitude);
+	double theta = std::acos(cos_angle);
+
+	return theta;
+}
diff --git a/tests/UnitTest/test_ReflectionFactor.cpp b/tests/UnitTest/test_ReflectionFactor.cpp
new file mode 100644
index 0000000..06dce85
--- /dev/null
+++ b/tests/UnitTest/test_ReflectionFactor.cpp
@@ -0,0 +1,32 @@
+#include "test_definitions.h"
+#include <ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h>
+#include <au.hh>
+#include <fstream>
+#include <memory>
+
+using namespace ITAPropagationModels::PropagationParameterEngine;
+
+TEST_CASE( "ITAPropagationModels::PPE::PropModules::ReflectionFactor", "[ReflectionFactor]" )
+{
+	// Load PPl
+	propagation_path_list::PropagationPathList ppl;
+	const std::string input_ppl = ITA_PROPAGATION_MODELS_TEST_RESOURCE_DIR "/Rigid_pigeon30to30_dae.json";
+	std::ifstream input_stream( input_ppl );
+	if( input_stream.is_open( ) )
+	{
+		cereal::JSONInputArchive archive( input_stream );
+		ppl.serialize( archive );
+	}
+	REQUIRE( !ppl.propagation_paths.empty( ) );
+
+	PropagationModules::CBasicReflection reflection_factor;
+
+	SECTION( "Compute" )
+	{
+		REQUIRE_NOTHROW( reflection_factor.compute( ppl ) );
+	}
+
+	// TODO: The results above are dependend on the air speed set in the PropagationConfig. This test case has to be adapted
+	//  once the config class is reworked
+	REQUIRE( false );
+}
-- 
GitLab


From 8071a8d005cd8942a5ef3d80edb578b3fc011714 Mon Sep 17 00:00:00 2001
From: "yifei.luo" <yifei.luo@rwth-aachen.de>
Date: Thu, 31 Oct 2024 13:31:21 +0100
Subject: [PATCH 5/6] Pref: Added test materials and test paths to
 Rigid_pigeon30to30_dae.json.

---
 .../ReflectionModules/BasicReflection.cpp     |   2 +-
 .../resources/Rigid_pigeon30to30_dae.json     | 509 ++++++++++++++++++
 2 files changed, 510 insertions(+), 1 deletion(-)

diff --git a/src/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp b/src/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp
index e386ea0..386dae2 100644
--- a/src/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp
+++ b/src/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp
@@ -207,7 +207,7 @@ double PropagationModules::CBasicReflection::compute_reflection_factor_absorptio
 	if (absorption < 0 || absorption > 1) 
 	{
         std::cerr << "Error: Absorption coefficient must be between 0 and 1." << std::endl; // ** use std::cerr or ...? **
-        return -1.0;  // ** return an impossible value **
+        return -100.0; 
     }
 
     // Calculate the reflection factor |R|
diff --git a/tests/UnitTest/resources/Rigid_pigeon30to30_dae.json b/tests/UnitTest/resources/Rigid_pigeon30to30_dae.json
index a2271d3..fb854ba 100644
--- a/tests/UnitTest/resources/Rigid_pigeon30to30_dae.json
+++ b/tests/UnitTest/resources/Rigid_pigeon30to30_dae.json
@@ -88,6 +88,110 @@
                     ]
                 }
             ]
+        },
+        {
+            "identifier": "Reflection_On_Softwall",
+            "propagation_anchors": [
+                {
+                    "type": "Source",
+                    "interaction_point": [
+                        2.9019999504089357,
+                        1.5,
+                        -2.984999895095825
+                    ],
+                    "name": "E30deg",
+                    "directivity_id": "Loudspeaker_Genelec8020c_1x1",
+                    "orientation": [
+                        0.6830127239227295,
+                        0.6830127239227295,
+                        0.1830126941204071,
+                        -0.1830126941204071
+                    ]
+                },
+                {
+                    "type": "SpecularReflection",
+                    "interaction_point": [
+                        5.5,
+                        0.0,
+                        -2.984999895095825
+                    ],
+                    "polygon_id": 0,
+                    "material_id": "Test_Material_Soft_Wall",
+                    "face_normal": [
+                        0.0,
+                        1.0,
+                        0.0
+                    ]
+                },
+                {
+                    "type": "Receiver",
+                    "interaction_point": [
+                        8.097999572753907,
+                        1.5,
+                        -2.984999895095825
+                    ],
+                    "name": "S30deg",
+                    "directivity_id": "Omnidirectional",
+                    "orientation": [
+                        0.0,
+                        0.0,
+                        0.0,
+                        1.0
+                    ]
+                }
+            ]
+        },
+        {
+            "identifier": "Reflection_On_Hardwall",
+            "propagation_anchors": [
+                {
+                    "type": "Source",
+                    "interaction_point": [
+                        2.9019999504089357,
+                        1.5,
+                        -2.984999895095825
+                    ],
+                    "name": "E30deg",
+                    "directivity_id": "Loudspeaker_Genelec8020c_1x1",
+                    "orientation": [
+                        0.6830127239227295,
+                        0.6830127239227295,
+                        0.1830126941204071,
+                        -0.1830126941204071
+                    ]
+                },
+                {
+                    "type": "SpecularReflection",
+                    "interaction_point": [
+                        5.5,
+                        0.0,
+                        -2.984999895095825
+                    ],
+                    "polygon_id": 0,
+                    "material_id": "Test_Material_Hard_Wall",
+                    "face_normal": [
+                        0.0,
+                        1.0,
+                        0.0
+                    ]
+                },
+                {
+                    "type": "Receiver",
+                    "interaction_point": [
+                        8.097999572753907,
+                        1.5,
+                        -2.984999895095825
+                    ],
+                    "name": "S30deg",
+                    "directivity_id": "Omnidirectional",
+                    "orientation": [
+                        0.0,
+                        0.0,
+                        0.0,
+                        1.0
+                    ]
+                }
+            ]
         }
     ],
     "material_database": {
@@ -225,6 +329,411 @@
                 -7795.98291015625,
                 -6621.1396484375
             ]
+        },
+        "Test_Material_Soft_Wall": {
+            "type": "ThirdOctaveMaterial",
+            "absorption": [
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0   
+            ],
+            "scattering": [
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0    
+            ],
+            "impedance_real": [
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0   
+            ],
+            "impedance_imag": [
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0   
+            ]
+        },
+        "Test_Material_Hard_Wall": {
+            "type": "ThirdOctaveMaterial",
+            "absorption": [
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0   
+            ],
+            "scattering": [
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0    
+            ],
+            "impedance_real": [
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10,
+                8.88e10
+            ],
+            "impedance_imag": [
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0   
+            ]
+        },
+        "Test_Material_Matched_Wall_SeaLevel_25Degrees": {
+            "type":"ThirdOctaveMaterial",
+            "absorption":[
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0
+            ],
+            "scattering":[
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0 
+            ],
+            "impedance_real":[
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664,
+                409.664
+            ],
+            "impedance_imag": [
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0,
+                0.0   
+            ]
         }
     }
 }
\ No newline at end of file
-- 
GitLab


From fa3e707b79d837b1b19a59da84ac7a86473bde22 Mon Sep 17 00:00:00 2001
From: "yifei.luo" <yifei.luo@rwth-aachen.de>
Date: Thu, 31 Oct 2024 15:05:32 +0100
Subject: [PATCH 6/6] Refactor: added helping notes to reflection factor test
 framework.

---
 tests/UnitTest/test_ReflectionFactor.cpp | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/tests/UnitTest/test_ReflectionFactor.cpp b/tests/UnitTest/test_ReflectionFactor.cpp
index 06dce85..c72579d 100644
--- a/tests/UnitTest/test_ReflectionFactor.cpp
+++ b/tests/UnitTest/test_ReflectionFactor.cpp
@@ -20,10 +20,18 @@ TEST_CASE( "ITAPropagationModels::PPE::PropModules::ReflectionFactor", "[Reflect
 	REQUIRE( !ppl.propagation_paths.empty( ) );
 
 	PropagationModules::CBasicReflection reflection_factor;
-
+	std::unordered_map<std::string, std::unique_ptr<PropagationParameters::CBasePropagationParameter>> reflection_factor_map ;
+	
 	SECTION( "Compute" )
 	{
-		REQUIRE_NOTHROW( reflection_factor.compute( ppl ) );
+		REQUIRE_NOTHROW( reflection_factor_map = reflection_factor.compute( ppl ) );
+
+		// Test paths and test material examples from page 33, section 3.2.1, book "Auralization: Fundamentals of Acoustics, Modelling... (Michael Vorlaender, second edition) "
+		// Hard wall: Z = infinate; R = 1; alpha = 0
+		std::unique_ptr<PropagationParameters::CBasePropagationParameter>&  reflection_factor_Hardwall = reflection_factor_map["Reflection_On_Hardwall"];
+
+		// Soft wall: Z = 0; R = -1; alpha = 0
+		std::unique_ptr<PropagationParameters::CBasePropagationParameter>&  reflection_factor_Softwall = reflection_factor_map["Reflection_On_Softwall"];
 	}
 
 	// TODO: The results above are dependend on the air speed set in the PropagationConfig. This test case has to be adapted
-- 
GitLab