material.h 3.49 KB
#ifndef RTS_MATERIAL_H
#define RTS_MATERIAL_H

#include <vector>
#include <ostream>
#include <iostream>
#include <fstream>
#include <complex>
#include <algorithm>
#include <sstream>
#include "../math/complex.h"
#include "../math/constants.h"
#include "../math/function.h"

namespace stim{

//Material class - default representation for the material property is the refractive index (RI)
template<typename T>
class material : public function< T, complex<T> >{

public:
    enum wave_property{microns, inverse_cm};
    enum material_property{ri, absorbance};

private:

    using function< T, complex<T> >::X;
    using function< T, complex<T> >::Y;
    using function< T, complex<T> >::insert;
    using function< T, complex<T> >::bounding;

    std::string name;	//name for the material (defaults to file name)

    void process_header(std::string str, wave_property& wp, material_property& mp){

    	std::stringstream ss(str);	//create a stream from the data string
    	std::string line;
    	std::getline(ss, line);		//get the first line as a string
		while(line[0] == '#'){		//continue looping while the line is a comment

			std::stringstream lstream(line);	//create a stream from the line
			lstream.ignore();					//ignore the first character ('#')

			std::string prop;		//get the property name
			lstream>>prop;

			if(prop == "X"){
				std::string wp_name;
				lstream>>wp_name;
				if(wp_name == "microns") wp = microns;
				else if(wp_name == "inverse_cm") wp = inverse_cm;
			}
			else if(prop == "Y"){
				std::string mp_name;
				lstream>>mp_name;
				if(mp_name == "ri") mp = ri;
				else if(mp_name == "absorbance") mp = absorbance;
			}

			std::getline(ss, line);		//get the next line
		}

		function< T, stim::complex<T> >::process_string(str);
	}

    void from_inverse_cm(){
    	//convert inverse centimeters to wavelength (in microns)
    	for(unsigned int i=0; i<X.size(); i++)
    		X[i] = 10000 / X[i];

    	//reverse the function array
    	std::reverse(X.begin(), X.end());
    	std::reverse(Y.begin(), Y.end());

    }

    void init(){
    	bounding[0] = bounding[1] = stim::complex<T>(1, 0);
    }


public:

    material(std::string filename, wave_property wp, material_property mp){
    	name = filename;
    	load(filename, wp, mp);
    }

    material(std::string filename){
    	name = filename;
    	load(filename);
    }

    material(){
    	init();
    }

    complex<T> getN(T lambda){
    	return function< T, complex<T> >::linear(lambda);
    }

    void load(std::string filename, wave_property wp, material_property mp){

    	//load the file as a function
    	function< T, complex<T> >::load(filename);
    }

    void load(std::string filename){

    	wave_property wp = inverse_cm;
    	material_property mp = ri;
    	//turn the file into a string
    	std::ifstream t(filename.c_str());	//open the file as a stream

    	if(!t){
    		std::cout<<"ERROR: Couldn't open the material file '"<<filename<<"'"<<std::endl;
    		exit(1);
    	}
		std::string str((std::istreambuf_iterator<char>(t)),
		std::istreambuf_iterator<char>());

		//process the header information
		process_header(str, wp, mp);

		//convert units
		if(wp == inverse_cm)
			from_inverse_cm();
		//set the bounding values
		bounding[0] = Y[0];
		bounding[1] = Y.back();
    }
    std::string str(){
    	std::stringstream ss;
    	ss<<name<<std::endl;
    	ss<<function< T, complex<T> >::str();
    	return ss.str();
    }
    std::string get_name(){
    	return name;
    }

    void set_name(std::string str){
    	name = str;
    }

};

}




#endif