00001 #include <citrus/config.h>
00002 #include <stdlib.h>
00003
00004 #include <glib.h>
00005
00006 #include <vector>
00007
00008 #include <citrus/Unit.H>
00009 #include <citrus/Prefix.H>
00010 #include <citrus/UnitPower.H>
00011
00012 UnitPower::UnitPower()
00013 : m_unit(0), m_prfx(0), m_pwr(0)
00014 {
00015
00016 }
00017
00018 UnitPower::UnitPower( Unit* unit, Prefix* prfx, int pwr )
00019 : m_unit(unit), m_prfx( prfx ), m_pwr(pwr)
00020 {
00021
00022 }
00023
00024 bool UnitPower::operator ==( const UnitPower& other ) const
00025 {
00026
00027 return ( (m_unit == other.m_unit) && (m_pwr == other.m_pwr) ) ;
00028 }
00029
00030 UnitPower& UnitPower::operator =( const UnitPower& other )
00031 {
00032 if ( &other == this )
00033 return *this ;
00034
00035 m_unit = other.m_unit ;
00036 m_prfx = other.m_prfx ;
00037 m_pwr = other.m_pwr ;
00038 return *this ;
00039 }
00040
00041 bool UnitPower::isNull() const
00042 {
00043 return m_unit == 0 ;
00044 }
00045
00046 void UnitPower::print( const vector<UnitPower>& upwr, FILE* f )
00047 {
00048 vector<UnitPower>::const_iterator iter = upwr.begin() ;
00049 while ( iter != upwr.end() ) {
00050 if ( iter->m_prfx == 0 )
00051 if ( iter->m_pwr == 1 )
00052 fprintf( f, "(%s)", iter->m_unit->abbr() ) ;
00053 else
00054 fprintf( f, "(%s^%d)", iter->m_unit->abbr(), iter->m_pwr ) ;
00055 else
00056 if ( iter->m_pwr == 1 )
00057 fprintf( f, "(%s%s)", iter->m_prfx->abbr(), iter->m_unit->abbr() ) ;
00058 else
00059 fprintf( f, "(%s%s^%d)", iter->m_prfx->abbr(), iter->m_unit->abbr(),
00060 iter->m_pwr ) ;
00061 ++iter ;
00062 }
00063
00064 }
00065
00066 vector<UnitPower>::iterator find_unit( Unit* unit,
00067 vector<UnitPower>& upwr )
00068 {
00069 vector<UnitPower>::iterator iter = upwr.begin() ;
00070 while ( iter != upwr.end() ) {
00071 if ( iter->m_unit == unit )
00072 return iter ;
00073 ++iter ;
00074 }
00075 return upwr.end() ;
00076 }
00077
00079 xmlNodePtr UnitPower::mathML() const
00080 {
00081 if ( ! m_pwr )
00082 return NULL ;
00083
00084 xmlNodePtr upn ;
00085 CHAR* content ;
00086
00087 if ( abs(m_pwr) == 1 ) {
00088 upn = xmlNewNode( NULL, (const CHAR*)"mi" ) ;
00089 content = (CHAR*) g_strdup_printf( "%s%s", m_prfx ? m_prfx->abbr() : "",
00090 m_unit->abbr() ) ;
00091 xmlNodeSetContent( upn, content ) ;
00092 g_free( content ) ;
00093 } else {
00094 xmlNodePtr nd ;
00095 upn = xmlNewNode( NULL, (const CHAR*)"msup" ) ;
00096
00097 content = (CHAR*) g_strdup_printf( "%s%s", m_prfx ? m_prfx->abbr() : "",
00098 m_unit->abbr() ) ;
00099 nd = xmlNewChild( upn, NULL, (const CHAR*)"mi", content ) ;
00100 g_free( content ) ;
00101
00102 content = (CHAR*) g_strdup_printf( "%d", abs(m_pwr) ) ;
00103 nd = xmlNewChild( upn, NULL, (const CHAR*)"mn", content ) ;
00104 g_free( content ) ;
00105 }
00106
00107 return upn ;
00108 }
00109
00111 xmlNodePtr UnitPower::mathML( const vector<UnitPower>& upwr )
00112 {
00113 assert( upwr.size() != 0 ) ;
00114 int nnum = 0, nden = 0 ;
00115 xmlNodePtr item ;
00116 xmlNodePtr top = xmlNewNode( NULL, (const CHAR*)"mrow" ) ;
00117 xmlNodePtr frac = xmlNewChild( top, NULL, (const CHAR*)"mfrac", NULL ) ;
00118 xmlNodePtr numer = xmlNewChild( frac, NULL, (const CHAR*)"mrow", NULL ) ;
00119 xmlNodePtr denom = xmlNewChild( frac, NULL, (const CHAR*)"mrow", NULL ) ;
00120
00121 vector<UnitPower>::const_iterator iter = upwr.begin() ;
00122 while ( iter != upwr.end() ) {
00123 item = iter->mathML() ;
00124 if ( ! item )
00125 continue ;
00126
00127
00128
00129 if ( iter->m_pwr < 0 ) {
00130 if ( nden )
00131 xmlNewChild( denom, NULL,
00132 (const CHAR*)"mo", (const CHAR*)"·" ) ;
00133 xmlAddChild( denom, item ) ;
00134 nden++ ;
00135 } else {
00136 if ( nnum )
00137 xmlNewChild( numer, NULL,
00138 (const CHAR*)"mo", (const CHAR*)"·" ) ;
00139 xmlAddChild( numer, item ) ;
00140 nnum++ ;
00141 }
00142 iter++ ;
00143 }
00144 if ( !nnum ) {
00145 xmlNewChild( numer, NULL, (const CHAR*)"mi", (const CHAR*)"1" ) ;
00146 } else if ( !nden ) {
00147 xmlUnlinkNode( numer ) ;
00148 xmlUnlinkNode( frac ) ;
00149 xmlFreeNode( frac ) ;
00150 xmlAddChild( top, numer ) ;
00151 }
00152 return top ;
00153 }
00154