openModeller
Version 1.4.0
|
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 }