openModeller  Version 1.4.0
GeoTransform.cpp
Go to the documentation of this file.
00001 
00028 #include <openmodeller/env_io/GeoTransform.hh>
00029 #include <openmodeller/om_defs.hh>
00030 #include <openmodeller/Log.hh>
00031 
00032 #include <openmodeller/Exceptions.hh>
00033 
00034 #include <ogr_api.h>
00035 #include <ogr_spatialref.h>
00036 #include <cpl_error.h>
00037 
00038 using std::string;
00039 
00040 
00041 /****************************************************************/
00042 /******************** Geographic Transformation *****************/
00043 
00044 // Default spatial reference system.
00045 //
00046 #define OM_WGS84 "GEOGCS[\"WGS84\", DATUM[\"WGS84\", \
00047   SPHEROID[\"WGS84\", 6378137.0, 298.257223563]], \
00048   PRIMEM[\"Greenwich\", 0.0], \
00049   UNIT[\"degree\",0.017453292519943295], \
00050   AXIS[\"Longitude\",EAST], AXIS[\"Latitude\",NORTH]]"
00051 
00052 
00053 void
00054 errorHandler( CPLErr eErrClass, int err_no, const char *msg )
00055 {
00056   Log::instance()->info( "Error: %s\n", msg );
00057 }
00058 
00059 
00060 /******************/
00061 /*** construtor ***/
00062 
00063 GeoTransform::GeoTransform( ) :
00064   identity( true ),
00065   f_ctin( 0 ),
00066   f_ctout( 0 )
00067 { 
00068    
00069 }
00070 
00071 GeoTransform::GeoTransform( const string& dst_desc, const string& src_desc ) :
00072   identity( true ),
00073   f_ctin( 0 ),
00074   f_ctout( 0 )
00075 {  
00076   change( dst_desc, src_desc );
00077 }
00078 
00079 void 
00080 GeoTransform::change()
00081 {
00082   //
00083   // We need to change the geotransform.
00084   // Reset this to the identity - a nice sane state.
00085   identity = true;
00086   if (f_ctin)
00087     delete f_ctin;
00088   f_ctin = 0;
00089   if (f_ctout)
00090     delete f_ctout;
00091   f_ctout = 0;
00092 }
00093 
00094 void 
00095 GeoTransform::change( const string& dst_desc, const string& src_desc )
00096 {
00097 
00098   //
00099   // We need to change the geotransform.
00100   // Reset this to the identity - a nice sane state.
00101   identity = true;
00102   if (f_ctin)
00103     delete f_ctin;
00104   f_ctin = 0;
00105   if (f_ctout)
00106     delete f_ctout;
00107   f_ctout = 0;
00108 
00109   // If the two coordinate strings are the same, we need the identity transform.
00110   // So we can just return.
00111   if ( compareCoordSystemStrings( dst_desc.c_str(), src_desc.c_str() ) ) {
00112     return;
00113   }
00114 
00115   identity = false;
00116 
00117   OGRSpatialReference src, dst;
00118 
00119   // OGRSpatialReference::importFromWkt takes a char** as a parameter.
00120   // This parameter points to a variable pointing to the firs character
00121   // of the WKT.  The variable will be updated to point to the last
00122   // character of the WKT used.
00123   // Since pointer (dst_desc) are passed by value, we have our own
00124   // local copies and can safely take it's address and let importFromWkt
00125   // change it.
00126   // However, we still need to cast away const-ness :(
00127   char * src_desc_noconst = const_cast<char*>(src_desc.c_str());
00128   char * dst_desc_noconst = const_cast<char*>(dst_desc.c_str());
00129 
00130   if ( src.importFromWkt( &src_desc_noconst ) != OGRERR_NONE ||
00131        dst.importFromWkt( &dst_desc_noconst ) != OGRERR_NONE )
00132     {
00133       std::string msg = "Invalid GeoTransform projection:\n src (";
00134       msg += src_desc.c_str();
00135       msg += ")\n dst (";
00136       msg += dst_desc.c_str();
00137       msg += ")\n.";
00138       Log::instance()->error( msg.c_str() );
00139       throw InvalidParameterException( msg );
00140     }
00141 
00142   f_ctin = OGRCreateCoordinateTransformation( &src, &dst );
00143 
00144   if ( ! f_ctin )
00145     {
00146       std::string msg = "Invalid GeoTransform projection:\n src (";
00147       msg += src_desc.c_str();
00148       msg += ")\n dst (";
00149       msg += dst_desc.c_str();
00150       msg += ")\n.";
00151       Log::instance()->error( msg.c_str() );
00152       throw InvalidParameterException( msg );
00153     }
00154 
00155   f_ctout = OGRCreateCoordinateTransformation( &dst, &src );
00156 
00157   if ( ! f_ctout )
00158     {
00159       std::string msg = "Invalid GeoTransform projection:\n src (";
00160       msg += src_desc.c_str();
00161       msg += ")\n dst (";
00162       msg += dst_desc.c_str();
00163       msg += ")\n.";
00164       Log::instance()->error( msg.c_str() );
00165       throw InvalidParameterException( msg );
00166     }
00167 
00168   // Deactivate GDAL error messages.
00169   CPLSetErrorHandler( (CPLErrorHandler) errorHandler );
00170 }
00171 
00172 
00173 /*****************/
00174 /*** destrutor ***/
00175 
00176 GeoTransform::~GeoTransform()
00177 {
00178   if ( f_ctin )
00179     delete f_ctin;
00180   if ( f_ctout )
00181     delete f_ctout;
00182 }
00183 
00184 
00185 /*****************/
00186 /*** transf In ***/
00187 int
00188 GeoTransform::transfIn( double *x, double *y ) const
00189 {
00190   if ( identity )
00191     return 1;
00192 #ifndef GEO_TRANSFORMATIONS_OFF
00193   return f_ctin->Transform( 1, x, y );
00194 #else
00195   return 1;
00196 #endif
00197 }
00198 
00199 
00200 /*****************/
00201 /*** transf In ***/
00202 int
00203 GeoTransform::transfIn( double *x, double *y,
00204       double x0, double y0 ) const
00205 {
00206   *x = x0;
00207   *y = y0;
00208   if ( identity )
00209     return 1;
00210 
00211 #ifndef GEO_TRANSFORMATIONS_OFF
00212   return f_ctin->Transform( 1, x, y );
00213 #else
00214   return 1;
00215 #endif
00216 }
00217 
00218 
00219 /******************/
00220 /*** transf Out ***/
00221 int
00222 GeoTransform::transfOut( double *x, double *y ) const
00223 {
00224   if ( identity )
00225     return 1;
00226 #ifndef GEO_TRANSFORMATIONS_OFF
00227   return f_ctout->Transform( 1, x, y );
00228 #else
00229   return 1;
00230 #endif
00231 }
00232 
00233 
00234 /******************/
00235 /*** transf Out ***/
00236 int
00237 GeoTransform::transfOut( double *x, double *y,
00238                          double x0, double y0 ) const
00239 {
00240   *x = x0;
00241   *y = y0;
00242   if ( identity )
00243     return 1;
00244 
00245 #ifndef GEO_TRANSFORMATIONS_OFF
00246   return f_ctout->Transform( 1, x, y );
00247 #else
00248   return 1;
00249 #endif
00250 }
00251 
00252 /********************/
00253 /*** getDefaultCS ***/
00254 const char * GeoTransform::getDefaultCS()
00255 {
00256   return OM_WGS84;
00257 }
00258 
00259 
00260 /*********************************/
00261 /*** compareCoordSystemStrings ***/
00262 bool GeoTransform::compareCoordSystemStrings(char const * s1, char const * s2)
00263 {
00264  int i = 0, j = 0;
00265  while (s1[i])
00266  {
00267   // skip spaces in both strings
00268   while (s1[i] == ' ') i++;
00269   while (s2[j] == ' ') j++; 
00270 
00271   if (s1[i] != s2[j]) {
00272     return false;
00273   }  
00274 
00275   if (s1[i]) i++;
00276   if (s2[j]) j++;
00277  }
00278  // skip trailing spaces that s2 might still have
00279  while (s2[j] == ' ') j++;
00280 
00281  // both s1[i] and s2[j] should be NULL to be equal
00282  return (s1[i] == s2[j]);
00283 }