/***************************************************************************** ** ** MODULE NAME SI_units.h International System of Units (SI) ** ** DESCRIPTION ** The purpose of this header file is to provide a simple and efficient ** mechanism for associating physically meaningful units with floating ** point numbers. No extra space is required, and no runtime overhead ** is introduced; all type-checking occurs at compile time. ** ** ** HISTORY ** Name Date Description ** ** arvo 02/09/92 Replaced conversion macros with inline functions. ** arvo 10/16/91 Initial implementation. ** ** ** (c) Copyright 1991, 1992 ** Program of Computer Graphics, Cornell University, Ithaca, NY ** ALL RIGHTS RESERVED ** *****************************************************************************/ #ifndef SI_UNITS_H #define SI_UNITS_H #include namespace ArvoMath { const float SI_deci = 1.0E-1, SI_centi = 1.0E-2, SI_milli = 1.0E-3, SI_micro = 1.0E-6, SI_nano = 1.0E-9, SI_kilo = 1.0E+3, SI_mega = 1.0E+6, SI_giga = 1.0E+9, SI_tera = 1.0E+12; /******************************************************************************* * * * I N T E R N A T I O N A L S Y S T E M O F U N I T S * * * ******************************************************************************** * * * DIMENSION CLASS INITIALIZER SYMBOL BASE UNITS * * * * length SI_length meter m m * * time SI_time second s s * * mass SI_mass kilogram kg kg * * angle SI_angle radian rad rad * * solid angle SI_solid_angle steradian sr sr * * temperature SI_temperature kelvin K K * * luminous intensity SI_lum_inten candela cd cd * * area SI_area meter2 m2 m2 * * volume SI_volume meter3 m3 m3 * * frequency SI_frequency hertz Hz 1/s * * force SI_force newton N m kg/s2 * * energy SI_energy joule J m2 kg/s2 * * power SI_power watt W m2 kg/s3 * * radiance SI_radiance watts_per_m2sr W/m2sr kg/(s3 sr) * * irradiance SI_irradiance watts_per_m2 W/m2 kg/s3 * * radiant intensity SI_rad_inten watts_per_sr W/sr m2 kg/(s3 sr) * * luminance SI_luminance candela_per_m2 cd/m2 cd/m2 * * illuminance SI_illuminance lux lx cd sr/m2 * * luminous flux SI_lum_flux lumen lm cd sr * * luminous energy SI_lum_energy talbot tb cd sr s * * * *******************************************************************************/ class SI_dimensionless { public: float Value() const { return value; } ostream& Put( ostream &s, char *a ) { return s << value << " " << a; } protected: SI_dimensionless() { value = 0; } SI_dimensionless( float x ){ value = x; } float value; }; /******************************************************************************* * The following macro is used for creating new quantity classes and their * * corresponding initializing functions and abbreviations. This macro is * * not intended to be used outside of this file -- it is a compact means of * * defining generic operations for each quantity (e.g. scaling & comparing). * *******************************************************************************/ #define SI_Make( C, Initializer, Symbol ) \ struct C : SI_dimensionless { \ C ( ) : SI_dimensionless( ) {}; \ C ( float x ) : SI_dimensionless( x ) {}; \ C operator * ( float x ) { return C( value * x ); } \ C operator / ( float x ) { return C( value / x ); } \ C operator /= ( float x ) { return C( value /= x ); } \ C operator *= ( float x ) { return C( value *= x ); } \ C operator + ( C x ) { return C( value + x.Value() ); } \ C operator - ( ) { return C(-value ); } \ C operator - ( C x ) { return C( value - x.Value() ); } \ C operator += ( C x ) { return C( value += x.Value() ); } \ C operator -= ( C x ) { return C( value -= x.Value() ); } \ C operator = ( C x ) { return C( value = x.Value() ); } \ int operator > ( C x ) { return ( value > x.Value() ); } \ int operator < ( C x ) { return ( value < x.Value() ); } \ int operator >= ( C x ) { return ( value >= x.Value() ); } \ int operator <= ( C x ) { return ( value <= x.Value() ); } \ float operator / ( C x ) { return ( value / x.Value() ); } \ }; \ inline ostream& operator<<(ostream &s, C x) {return x.Put(s,Symbol);} \ inline C Initializer( float x ) { return C( x ); } \ inline C operator * ( float x, C y ) { return C( x * y.Value() ); } /******************************************************************************* * The following macros define permissible arithmetic operations among * * variables with different physical meanings. This ensures that the * * result of any such operation is ALWAYS another meaningful quantity. * *******************************************************************************/ #define SI_Square( A, B ) \ inline B operator*( A x, A y ) { return B( x.Value() * y.Value() ); } \ inline A operator/( B x, A y ) { return A( x.Value() / y.Value() ); } #define SI_Recip( A, B ) \ inline B operator/( float x, A y ) { return B( x / y.Value() ); } \ inline A operator/( float x, B y ) { return A( x / y.Value() ); } \ inline float operator*( A x, B y ) { return x.Value() * y.Value(); } \ inline float operator*( B x, A y ) { return x.Value() * y.Value(); } #define SI_Times( A, B, C ) \ inline C operator*( A x, B y ) { return C( x.Value() * y.Value() ); } \ inline C operator*( B x, A y ) { return C( x.Value() * y.Value() ); } \ inline A operator/( C x, B y ) { return A( x.Value() / y.Value() ); } \ inline B operator/( C x, A y ) { return B( x.Value() / y.Value() ); } /******************************************************************************* * The following macros create classes for a variety of quantities. These * * include base qunatities such as "time" and "length" as well as derived * * quantities such as "power" and "volume". Each quantity is provided with * * an initialization function in SI units and an abbreviation for printing. * *******************************************************************************/ SI_Make( SI_length , meter , "m" ); // Base Units: SI_Make( SI_mass , kilogram , "kg" ); SI_Make( SI_time , second , "s" ); SI_Make( SI_lum_inten , candela , "cd" ); SI_Make( SI_temperature , kelvin , "K" ); SI_Make( SI_angle , radian , "rad" ); // Supplementary: SI_Make( SI_solid_angle , steradian , "sr" ); SI_Make( SI_area , meter2 , "m2" ); // Derived units: SI_Make( SI_volume , meter3 , "m3" ); SI_Make( SI_frequency , hertz , "Hz" ); SI_Make( SI_force , newton , "N" ); SI_Make( SI_energy , joule , "J" ); SI_Make( SI_power , watt , "W" ); SI_Make( SI_radiance , watts_per_m2sr , "W/m2sr" ); SI_Make( SI_irradiance , watts_per_m2 , "W/m2" ); SI_Make( SI_rad_inten , watts_per_sr , "W/sr" ); SI_Make( SI_luminance , candela_per_m2 , "cd/m2" ); SI_Make( SI_illuminance , lux , "lx" ); SI_Make( SI_lum_flux , lumen , "lm" ); SI_Make( SI_lum_energy , talbot , "tb" ); SI_Make( SI_time2 , second2 , "s2" ); // Intermediate: SI_Make( SI_sa_area , meter2_sr , "m2sr" ); SI_Make( SI_inv_area , inv_meter2 , "1/m2" ); SI_Make( SI_inv_solid_angle, inv_steradian , "1/sr" ); SI_Make( SI_length_temp , meters_kelvin , "m K" ); SI_Make( SI_power_area , watts_m2 , "W m2" ); SI_Make( SI_power_per_volume, watts_per_m3 , "W/m3" ); SI_Square( SI_length , SI_area ); SI_Square( SI_time , SI_time2 ); SI_Recip ( SI_time , SI_frequency ); SI_Recip ( SI_area , SI_inv_area ); SI_Recip ( SI_solid_angle , SI_inv_solid_angle ); SI_Times( SI_area , SI_length , SI_volume ); SI_Times( SI_force , SI_length , SI_energy ); SI_Times( SI_power , SI_time , SI_energy ); SI_Times( SI_lum_flux , SI_time , SI_lum_energy ); SI_Times( SI_lum_inten , SI_solid_angle , SI_lum_flux ); SI_Times( SI_radiance , SI_solid_angle , SI_irradiance ); SI_Times( SI_rad_inten , SI_solid_angle , SI_power ); SI_Times( SI_irradiance , SI_area , SI_power ); SI_Times( SI_illuminance , SI_area , SI_lum_flux ); SI_Times( SI_solid_angle , SI_area , SI_sa_area ); SI_Times( SI_radiance , SI_sa_area , SI_power ); SI_Times( SI_irradiance , SI_inv_solid_angle, SI_radiance ); SI_Times( SI_power , SI_inv_solid_angle, SI_rad_inten ); SI_Times( SI_length , SI_temperature , SI_length_temp ); SI_Times( SI_power , SI_area , SI_power_area ); /******************************************************************************* * Following are some useful non-SI units. These units can be used in place of * * the unit-initializers above. Thus, a variable of type SI_length, for example* * may be initialized in "meters", "inches", or "centimeters". In all cases, * * however, the value is converted to the underlying SI unit (e.g. meters). * *******************************************************************************/ #define SI_Convert( SI, New, Old ) inline SI New( float x ) { return x * Old; } SI_Convert( SI_time , minute , second( 60.0 ) ); SI_Convert( SI_time , hour , minute( 60.0 ) ); SI_Convert( SI_force , dyne , newton( 1.0E-5 ) ); SI_Convert( SI_energy , erg , joule( 1.0E-7 ) ); SI_Convert( SI_power , kilowatt , watt( SI_kilo ) ); SI_Convert( SI_mass , gram , kilogram( SI_milli ) ); SI_Convert( SI_length , inch , meter( 2.54E-2 ) ); SI_Convert( SI_length , foot , inch( 12.0 ) ); SI_Convert( SI_length , centimeter , meter( SI_centi ) ); SI_Convert( SI_length , micron , meter( SI_micro ) ); SI_Convert( SI_length , angstrom , meter( 1.0E-10 ) ); SI_Convert( SI_area , barn , meter2( 1.0E-28 ) ); SI_Convert( SI_angle , degree , radian( 0.017453 ) ); SI_Convert( SI_illuminance , phot , lux( 1.0E+4 ) ); SI_Convert( SI_illuminance , footcandle , lux( 9.29E-2 ) ); SI_Convert( SI_luminance , stilb , candela_per_m2( 1.0E+4 ) ); /******************************************************************************* * Often there are multiple names for a single quantity. Below are some * * synonyms for the quantities defined above. These can be used in place of * * the original quantities and may be clearer in some contexts. * *******************************************************************************/ typedef SI_power SI_radiant_flux; typedef SI_irradiance SI_radiant_flux_density; typedef SI_irradiance SI_radiant_exitance; typedef SI_radiance SI_intensity; typedef SI_irradiance SI_radiosity; }; #endif