osgEarth 2.1.1
|
00001 /* -*-c++-*- */ 00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph 00003 * Copyright 2008-2010 Pelican Mapping 00004 * http://osgearth.org 00005 * 00006 * osgEarth is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> 00018 */ 00019 #ifndef OSGEARTH_UNITS_H 00020 #define OSGEARTH_UNITS_H 1 00021 00022 #include <osgEarth/Common> 00023 00024 namespace osgEarth 00025 { 00026 class OSGEARTH_EXPORT Units 00027 { 00028 public: 00029 // linear 00030 static const Units CENTIMETERS; 00031 static const Units DATA_MILES; 00032 static const Units FATHOMS; 00033 static const Units FEET; 00034 static const Units FEET_US_SURVEY; // http://www.wsdot.wa.gov/reference/metrics/foottometer.htm 00035 static const Units INCHES; 00036 static const Units KILOFEET; 00037 static const Units KILOMETERS; 00038 static const Units KILOYARDS; 00039 static const Units METERS; 00040 static const Units MILES; // statute miles 00041 static const Units MILLIMETERS; 00042 static const Units NAUTICAL_MILES; 00043 static const Units YARDS; 00044 00045 // angular 00046 static const Units BAM; 00047 static const Units DEGREES; 00048 static const Units NATO_MILS; // http://www.convertworld.com/en/angle/Mil+(NATO).html 00049 static const Units RADIANS; 00050 00051 // temporal 00052 static const Units DAYS; 00053 static const Units HOURS; 00054 static const Units MICROSECONDS; 00055 static const Units MILLISECONDS; 00056 static const Units MINUTES; 00057 static const Units SECONDS; 00058 static const Units WEEKS; 00059 00060 // speed 00061 static const Units FEET_PER_SECOND; 00062 static const Units YARDS_PER_SECOND; 00063 static const Units METERS_PER_SECOND; 00064 static const Units KILOMETERS_PER_SECOND; 00065 static const Units KILOMETERS_PER_HOUR; 00066 static const Units MILES_PER_HOUR; 00067 static const Units DATA_MILES_PER_HOUR; 00068 static const Units KNOTS; 00069 00070 enum Type { TYPE_LINEAR, TYPE_ANGULAR, TYPE_TEMPORAL, TYPE_SPEED, TYPE_INVALID }; 00071 00072 public: 00073 00074 static bool convert( const Units& from, const Units& to, double input, double& output ) { 00075 if ( canConvert(from, to) ) { 00076 if ( from._type == TYPE_LINEAR || from._type == TYPE_ANGULAR || from._type == TYPE_TEMPORAL ) 00077 convertSimple( from, to, input, output ); 00078 else if ( from._type == TYPE_SPEED ) 00079 convertSpeed( from, to, input, output ); 00080 return true; 00081 } 00082 return false; 00083 } 00084 00085 static double convert( const Units& from, const Units& to, double input ) { 00086 double output; 00087 convert( from, to, input, output ); 00088 return output; 00089 } 00090 00091 static bool canConvert( const Units& from, const Units& to ) { 00092 return from._type == to._type; 00093 } 00094 00095 bool canConvert( const Units& to ) const { 00096 return _type == to._type; 00097 } 00098 00099 bool convertTo( const Units& to, double input, double& output ) const { 00100 return convert( *this, to, input, output ); 00101 } 00102 00103 double convertTo( const Units& to, double input ) const { 00104 return convert( *this, to, input ); 00105 } 00106 00107 const std::string& getName() const { return _name; } 00108 00109 const std::string& getAbbr() const { return _abbr; } 00110 00111 const Type& getType() const { return _type; } 00112 00113 bool operator == ( const Units& rhs ) const { 00114 return _type == rhs._type && _toBase == rhs._toBase; } 00115 00116 bool operator != ( const Units& rhs ) const { 00117 return _type != rhs._type || _toBase != rhs._toBase; } 00118 00119 bool isLinear() const { return _type == TYPE_LINEAR; } 00120 00121 bool isAngular() const { return _type == TYPE_ANGULAR; } 00122 00123 bool isTemporal() const { return _type == TYPE_TEMPORAL; } 00124 00125 bool isSpeed() const { return _type == TYPE_SPEED; } 00126 00127 public: 00128 00129 // Make a new unit definition (LINEAR, ANGULAR, TEMPORAL) 00130 Units( const std::string& name, const std::string& abbr, const Type& type, double toBase ); 00131 00132 // Maks a new unit definition (SPEED) 00133 Units( const std::string& name, const std::string& abbr, const Units& distance, const Units& time ); 00134 00135 Units() : _type(TYPE_INVALID) { } 00136 00137 private: 00138 00139 static void convertSimple( const Units& from, const Units& to, double input, double& output ) { 00140 output = input * from._toBase / to._toBase; 00141 } 00142 static void convertSpeed( const Units& from, const Units& to, double input, double& output ) { 00143 double t = from._distance->convertTo( *to._distance, input ); 00144 output = to._time->convertTo( *from._time, t ); 00145 } 00146 00147 00148 std::string _name, _abbr; 00149 Type _type; 00150 double _toBase; 00151 const Units* _distance; 00152 const Units* _time; 00153 }; 00154 00155 struct Linear; 00156 00157 template<typename T> 00158 class qualified_double 00159 { 00160 public: 00161 qualified_double<T>( double value, const Units& units ) : _value(value), _units(units) { } 00162 00163 qualified_double<T>( const T& rhs ) : _value(rhs._value), _units(rhs._units) { } 00164 00165 void set( double value, const Units& units ) { 00166 _value = value; 00167 _units = units; 00168 } 00169 00170 T& operator = ( const T& rhs ) { 00171 if ( _units.canConvert(rhs._units) ) 00172 _value = rhs.as(_units); 00173 return static_cast<T&>(*this); 00174 } 00175 00176 T operator + ( const T& rhs ) const { 00177 return _units.canConvert(rhs._units) ? 00178 T(_value + rhs.as(_units), _units) : 00179 T(0, Units()); 00180 } 00181 00182 T operator - ( const T& rhs ) const { 00183 return _units.canConvert(rhs._units) ? 00184 T(_value - rhs.as(_units), _units) : 00185 T(0, Units()); 00186 } 00187 00188 bool operator == ( const T& rhs ) const { 00189 return _units.canConvert( rhs._units ) && rhs.as(_units) == _value; 00190 } 00191 00192 bool operator != ( const T& rhs ) const { 00193 return !_units.canConvert(rhs._units) || rhs.as(_units) != _value; 00194 } 00195 00196 bool operator < ( const T& rhs ) const { 00197 return _units.canConvert(rhs._units) && _value < rhs.as(_units); 00198 } 00199 00200 bool operator > ( const T& rhs ) const { 00201 return _units.canConvert(rhs._units) && _value > rhs.as(_units); 00202 } 00203 00204 double as( const Units& convertTo ) const { 00205 return _units.convertTo( convertTo, _value ); 00206 } 00207 00208 const Units& getUnits() const { return _units; } 00209 00210 private: 00211 double _value; 00212 Units _units; 00213 }; 00214 00215 struct Linear : public qualified_double<Linear> { 00216 Linear() : qualified_double<Linear>(0, Units::METERS) { } 00217 Linear(double value, const Units& units) : qualified_double<Linear>(value, units) { } 00218 }; 00219 00220 struct Angular : public qualified_double<Angular> { 00221 Angular() : qualified_double<Angular>(0, Units::DEGREES) { } 00222 Angular(double value) : qualified_double<Angular>(value, Units::DEGREES) { } 00223 Angular(double value, const Units& units) : qualified_double<Angular>(value, units) { } 00224 }; 00225 00226 struct Temporal : public qualified_double<Temporal> { 00227 Temporal() : qualified_double<Temporal>(0, Units::SECONDS) { } 00228 Temporal(double value, const Units& units) : qualified_double<Temporal>(value, units) { } 00229 }; 00230 00231 struct Speed : public qualified_double<Speed> { 00232 Speed() : qualified_double<Speed>(0, Units::METERS_PER_SECOND) { } 00233 Speed(double value, const Units& units) : qualified_double<Speed>(value, units) { } 00234 }; 00235 } 00236 00237 #endif // OSGEARTH_UNITS_H