+/**
+ * @brief Helper class to wrap SGMagVar functionality and cache the variation and dip for
+ * a certain position.
+ */
+class MagneticVariation : public SGMagVar {
+public:
+ /**
+ * Constructor
+ */
+ MagneticVariation() : _lat(1), _lon(1), _alt(1) {
+ recalc( 0.0, 0.0, 0.0 );
+ }
+
+ /**
+ * @brief get the magnetic variation for a specific position at the current time
+ * @param lon the positions longitude in degrees
+ * @param lat the positions latitude in degrees
+ * @param alt the positions height above MSL (aka altitude) in feet
+ * @return the magnetic variation in degrees
+ */
+ double get_variation_deg( double lon, double lat, double alt );
+
+ /**
+ * @brief get the magnetic dip for a specific position at the current time
+ * @param lon the positions longitude in degrees
+ * @param lat the positions latitude in degrees
+ * @param alt the positions height above MSL (aka altitude) in feet
+ * @return the magnetic dip in degrees
+ */
+ double get_dip_deg( double lon, double lat, double alt );
+private:
+ void recalc( double lon, double lat, double alt );
+ SGTime _time;
+ double _lat, _lon, _alt;
+};
+
+inline void MagneticVariation::recalc( double lon, double lat, double alt )
+{
+ // calculation of magnetic variation is expensive. Cache the position
+ // and perform this calculation only if it has changed
+ if( _lon != lon || _lat != lat || _alt != alt ) {
+ SG_LOG(SG_ENVIRONMENT, SG_DEBUG, "Recalculating magvar for lon=" << lon << ", lat=" << lat << ", alt=" << alt );
+ _lon = lon;
+ _lat = lat;
+ _alt = alt;
+
+ lon *= SGD_DEGREES_TO_RADIANS;
+ lat *= SGD_DEGREES_TO_RADIANS;
+ alt *= SG_FEET_TO_METER;
+ _time.update( lon, lat, 0, 0 );
+ update( lon, lat, alt, _time.getJD() );
+ }
+}
+
+inline double MagneticVariation::get_variation_deg( double lon, double lat, double alt )
+{
+ recalc( lon, lat, alt );
+ return get_magvar() * SGD_RADIANS_TO_DEGREES;
+}
+
+inline double MagneticVariation::get_dip_deg( double lon, double lat, double alt )
+{
+ recalc( lon, lat, alt );
+ return get_magdip() * SGD_RADIANS_TO_DEGREES;
+}
+