core/vpgl/vpgl_lvcs.h
Go to the documentation of this file.
00001 #ifndef vpgl_lvcs_h_
00002 #define vpgl_lvcs_h_
00003 //-----------------------------------------------------------------------------
00004 //:
00005 // \file
00006 // \brief A geographic coordinate system
00007 // \author J. L. Mundy
00008 // \date December 31, 2005
00009 //
00010 //      lvcs is used to convert between a local vertical coordinate system
00011 //      any of the many Earth global coordinate systems. In the full
00012 //      constructor the user can establish the geographic coordinates of
00013 //      the origin and define which standard geo-coordinate system is to
00014 //      be used, e.g. wgs84.  The full constructor allows the specification
00015 //      of latitude and longitude scale factors in radians/meter.  If these
00016 //      scale factors are set to 0, then they will be computed using the
00017 //      location of the origin on the Earth's surface and the geoid
00018 //      specification.
00019 //
00020 //      original authors (c. 1992)
00021 //             Rajiv Gupta and Bill Hoffman
00022 //      with modifications by Rupert Curwen (1996)
00023 //             GE Corporate Research and Development
00024 //
00025 //
00026 // \verbatim
00027 //  Modifications
00028 //   Ozge C. Ozcanli  July 28 2012: added option to use UTM projection planes as local coordinate system
00029 //                                  origin point is still given in wgs84, 
00030 //                                  but it is converted to utm origin during local to global transformations and vice versa
00031 //                                  all the global coords are still either in wgs84, nad27n or wgs72
00032 //                                  if a utm zone is crossed 
00033 //
00034 // \endverbatim
00035 /////////////////////////////////////////////////////////////////////////////
00036 #include <vcl_iostream.h>
00037 #include <vsl/vsl_binary_io.h>
00038 #include <vbl/vbl_ref_count.h>
00039 #include <vpgl/vpgl_dll.h>
00040 class vpgl_lvcs : public vbl_ref_count
00041 {
00042   // PUBLIC INTERFACE----------------------------------------------------------
00043 
00044  public:
00045   enum LenUnits {FEET, METERS};
00046   enum AngUnits {RADIANS, DEG};
00047   enum cs_names { wgs84 =0, nad27n, wgs72, utm, NumNames};
00048   VPGL_DLL_DATA static const char* cs_name_strings[];
00049   static vpgl_lvcs::cs_names str_to_enum(const char*);
00050   // Constructors/Initializers/Destructors-------------------------------------
00051   vpgl_lvcs(double orig_lat=0,         //!< latitude of LVCS orig in radians.
00052             double orig_lon=0,         //!< longitude of LVCS  orig in radians.
00053             double orig_elev=0,        //!< elev of orig LVCS  in radians.
00054             cs_names cs_name=wgs84,    //!< nad27n, wgs84, wgs72 or utm
00055             double lat_scale=0,        //!< radians/meter along lat (custom geoid)
00056             double lon_scale=0,        //!< radians/meter along lon (custom geoid)
00057             AngUnits  ang_unit = DEG,  //!< angle units
00058             LenUnits len_unit=METERS,  //!< input in LVCS in these length units.
00059             double lox=0,              //!< Origin in local co-ordinates.
00060             double loy=0,              //!< Origin in local co-ordinates.
00061             double theta=0);           //!< Radians from y axis to north in local co-ordinates.
00062 
00063   vpgl_lvcs(double orig_lat,
00064             double orig_lon,
00065             double orig_elev, //!< simplified interface
00066             cs_names cs_name,
00067             AngUnits  ang_unit = DEG,
00068             LenUnits len_unit=METERS);
00069 
00070   vpgl_lvcs(double lat_low, double lon_low,  //!< lower corner bounding geo_rectangle
00071             double lat_high, double lon_high,//!< upper corner bounding geo_rectangle
00072             double elev,                     //!< elevation of all rectangle corners
00073             cs_names cs_name=wgs84,
00074             AngUnits ang_unit=DEG, LenUnits elev_unit=METERS);
00075 
00076   vpgl_lvcs(const vpgl_lvcs&);
00077   vpgl_lvcs& operator=(const vpgl_lvcs&);
00078 
00079 
00080   // Utility Methods-----------------------------------------------------------
00081   void local_to_global(const double lx, const double ly, const double lz,
00082                        cs_names cs_name,        // this is output global cs
00083                        double& lon, double& lat, double& gz,
00084                        AngUnits output_ang_unit=DEG,
00085                        LenUnits output_len_unit=METERS);
00086 
00087   void global_to_local(const double lon, const double lat, const double gz,
00088                        cs_names cs_name,        // this is input global cs
00089                        double& lx, double& ly, double& lz,
00090                        AngUnits output_ang_unit=DEG,
00091                        LenUnits output_len_unit=METERS);
00092 
00093   void radians_to_degrees(double& lon, double& lat, double& z);
00094   double radians_to_degrees(const double val);
00095   void degrees_to_dms(double, int& degrees, int& minutes, double& seconds);
00096   void radians_to_dms(double, int& degrees, int& minutes, double& seconds);
00097 
00098   // accessors
00099   void get_origin(double& lat, double& lon, double& elev) const;
00100   void get_scale(double& lat, double& lon) const;
00101   void get_transform(double& lox, double& loy, double& theta) const;
00102   void set_transform(const double lox, const double loy, const double theta);
00103   void set_origin(const double lon, const double lat, const double elev);
00104   cs_names get_cs_name() const;
00105   inline LenUnits local_length_unit() const{return this->localXYZUnit_;}
00106   inline AngUnits geo_angle_unit() const {return this->geo_angle_unit_;}
00107   void print(vcl_ostream&) const;
00108   bool save(vcl_string fname) { vcl_ofstream of(fname.c_str()); if (of) { print(of); return true; } return false; }
00109   void read(vcl_istream& strm);
00110   friend vcl_ostream& operator << (vcl_ostream& os, const vpgl_lvcs& local_coord_sys);
00111   friend vcl_istream& operator >> (vcl_istream& os, vpgl_lvcs& local_coord_sys);
00112   bool operator==(vpgl_lvcs const& r) const;
00113 
00114   void get_utm_origin(double& x, double& y, double& elev, int& zone) const;
00115 
00116   // INTERNALS-----------------------------------------------------------------
00117 
00118  protected:
00119   void compute_scale();
00120   void local_transform(double& x, double& y);
00121   void inverse_local_transform(double& x, double& y);
00122   void set_angle_conversions(AngUnits ang_unit, double& to_radians,
00123                              double& to_degrees);
00124   void set_length_conversions(LenUnits len_unit, double& to_meters,
00125                               double& to_feet);
00126  private:
00127 
00128   // Data Members--------------------------------------------------------------
00129 
00130  protected:
00131   cs_names local_cs_name_;    //!< Name of local frame's coord system ("nad27n", "wgs84" etc.)
00132   double localCSOriginLat_;   //!< Lat (in radians) of the origin
00133   double localCSOriginLon_;   //!< Lon (in radians) of the origin
00134   double localCSOriginElev_;  //!< Elev (in radians) of the origin
00135   double lat_scale_;          //!< radians/meter along lat at the origin)
00136   double lon_scale_;          //!< radians/meter along lon at the origin)
00137   AngUnits geo_angle_unit_;   //!< lat lon angle unit (degrees or radians)
00138   LenUnits localXYZUnit_;     //!< Input (x,y,z) unit (meters or feet) in local CS
00139   double lox_;                //!< Origin in local co-ordinates.
00140   double loy_;                //!< Origin in local co-ordinates.
00141   double theta_;              //!< Direction of north in radians.
00142   
00143   double localUTMOrigin_X_East_;  // in meters 
00144   double localUTMOrigin_Y_North_; // in meters 
00145   int localUTMOrigin_Zone_;      
00146 };
00147 
00148 //: return the scale for lat lon and elevation
00149 inline void vpgl_lvcs::get_scale(double& lat, double& lon) const
00150 {
00151   lat = lat_scale_;
00152   lon = lon_scale_;
00153 }
00154 
00155 //: return the coordinate system
00156 inline vpgl_lvcs::cs_names vpgl_lvcs::get_cs_name() const
00157 { return local_cs_name_; }
00158 
00159 
00160 //: return the origin of the local system
00161 inline void vpgl_lvcs::get_origin(double& lat, double& lon, double& elev) const
00162 {
00163   lat = localCSOriginLat_;
00164   lon = localCSOriginLon_;
00165   elev = localCSOriginElev_;
00166 }
00167 
00168 inline void vpgl_lvcs::get_utm_origin(double& x, double& y, double& elev, int& zone) const
00169 {
00170   x = localUTMOrigin_X_East_;
00171   y = localUTMOrigin_Y_North_;
00172   zone = localUTMOrigin_Zone_;
00173   elev = localCSOriginElev_;
00174 }
00175 
00176 //------------------------------------------------------------
00177 //: Return the compass alignment transform.
00178 inline void vpgl_lvcs::get_transform(double& lox, double& loy, double& theta) const
00179 {
00180   lox = lox_;
00181   loy = loy_;
00182   theta = theta_;
00183 }
00184 
00185 //------------------------------------------------------------
00186 //: Set the compass alignment transform.
00187 inline void vpgl_lvcs::set_transform(const double lox, const double loy,
00188                                      const double theta)
00189 {
00190   lox_ = lox;
00191   loy_ = loy;
00192   theta_ = theta;
00193 }
00194 
00195 //------------------------------------------------------------
00196 //: Set the origin of the local system
00197 inline void vpgl_lvcs::set_origin(const double lon, const double lat, const double elev)
00198 {
00199     localCSOriginLon_ = lon;
00200     localCSOriginLat_ = lat;
00201     localCSOriginElev_ = elev;
00202 }
00203 
00204 inline void vpgl_lvcs::radians_to_dms(double rad, int& degrees, int& minutes, double& seconds)
00205 {
00206   degrees_to_dms(radians_to_degrees(rad), degrees,  minutes, seconds);
00207 }
00208 #endif // vpgl_lvcs_h_
00209