00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef MODISFILEDATA_H
00021 #define MODISFILEDATA_H
00022
00023 #include "hdffiledata.h"
00024 #include "satellitefiledata.h"
00025 #include "pixel.h"
00026 #include "geometry.h"
00027
00032 typedef struct ModisCloudMask_1{
00033 unsigned int cloud_mask : 1;
00034 unsigned int FOV_quality : 2;
00035 unsigned int day_night : 1;
00036 unsigned int sunlight : 1;
00037 unsigned int snow_ice : 1;
00038 unsigned int land_water : 2;
00039 } ModisCloudMask_1;
00045 class MODISFileData : public SatelliteFileData, public HDFFileData {
00046 protected:
00047 typedef vector<double> GRingPoint;
00048 typedef vector<GRingPoint> GRingPolygon;
00049 typedef vector<GRingPolygon> GRing;
00050
00051
00052
00054 static const string latitude_sds_name;
00056 static const string longitude_sds_name;
00058 static const int fast_srch_frame_x;
00060 static const int fast_srch_frame_y;
00062 float colocation_tolerance;
00066 enum PlatformType {
00067 UNDEFINED_PLATFORM_TYPE = 0,
00068 TERRA,
00069 AQUA,
00070 };
00072 PlatformType platform;
00073
00077 enum Product_ID {
00078 UNDEFINED_PRODUCT_ID = 0,
00079 MYD02QKM,
00080 MYD02HKM,
00081 MYD021KM,
00082 MYD03,
00083 MYD02SSH,
00084 MYD04_L2,
00085 MYD05_L2,
00086 MYD06_L2,
00087 MOD06_L2,
00088 };
00090 Product_ID product_id;
00092 string product;
00094 float resolution;
00095
00097 float lat_min;
00099 float lat_max;
00101 float lon_min;
00103 float lon_max;
00105 vector <int> lat_lon_index_max;
00107 GRing gring;
00109 vector<PixelType> v_pixel;
00111 vector < float32 > lat_gran_corner;
00113 vector < float32 > lon_gran_corner;
00117 void init();
00121 void set_time_coverage();
00126 void parse_filename(const string & file_basename);
00132 bool check_filename(const string & file_basename) const;
00136 void set_lat_lon_index_max();
00141 void set_gring();
00149 const bool is_inside_gring( const float & lat, const float & lon ) const;
00155 virtual string get_gring_latitude_name(const string &product="") {
00156 return "GRINGPOINTLATITUDE";
00157 };
00163 virtual string get_gring_longitude_name(const string &product="") {
00164 return "GRINGPOINTLONGITUDE";
00165 };
00169 virtual void load_v_pixel() ;
00170
00174 void init_colocation_tolerance ();
00175
00176 public:
00178 static const int NB_MAX_X_10KM;
00180 static const int NB_MAX_Y_10KM;
00182 static const int NB_MAX_X_5KM;
00184 static const int NB_MAX_Y_5KM;
00186 static const int NB_MAX_X_1KM;
00188 static const int NB_MAX_Y_1KM;
00190 static const int NB_MAX_X_250M;
00192 static const int NB_MAX_Y_250M;
00193
00198 const int get_x_size_10km() {
00199 switch ( product_id ) {
00200 case ( MYD04_L2 ) :
00201 return ( lat_lon_index_max[1] + 1 );
00202 break;
00203 default :
00204 string msg ( "Unimplemented method for product " + product ) ;
00205 g_exception e( __FILE__ , __LINE__ , msg );
00206 throw e;
00207 break;
00208 }
00209 return - 1;
00210 }
00215 const int get_y_size_10km() {
00216 switch ( product_id ) {
00217 case ( MYD04_L2 ) :
00218 return ( lat_lon_index_max[0] + 1 );
00219 break;
00220 default :
00221 string msg ( "Unimplemented method for product " + product ) ;
00222 g_exception e( __FILE__ , __LINE__ , msg );
00223 throw e;
00224 break;
00225 }
00226 return - 1;
00227 }
00228
00233 const int get_x_size_5km() {
00234 switch ( product_id ) {
00235 case ( MYD06_L2 ) :
00236 case ( MOD06_L2 ) :
00237 case ( MYD05_L2 ) :
00238 case ( MYD021KM ) :
00239 return ( lat_lon_index_max[1] + 1 );
00240 break;
00241 default :
00242 string msg ( "Unimplemented method for product " + product ) ;
00243 g_exception e( __FILE__ , __LINE__ , msg );
00244 throw e;
00245 break;
00246 }
00247 return - 1;
00248 }
00253 const int get_y_size_5km() {
00254 switch ( product_id ) {
00255 case ( MYD06_L2 ) :
00256 case ( MOD06_L2 ) :
00257 case ( MYD05_L2 ) :
00258 case ( MYD021KM ) :
00259 return ( lat_lon_index_max[0] + 1 );
00260 break;
00261 default :
00262 string msg ( "Unimplemented method for product " + product ) ;
00263 g_exception e( __FILE__ , __LINE__ , msg );
00264 throw e;
00265 break;
00266 }
00267 return - 1;
00268 }
00273 const int get_x_size_1km() {
00274 switch ( product_id ) {
00275 case ( MYD06_L2 ) :
00276 case ( MOD06_L2 ) :
00277 case ( MYD05_L2 ) :
00278
00279 return ( get_x_size_5km () * 5 ) + 4;
00280 case ( MYD021KM ) :
00281
00282 return ( get_x_size_5km () * 5 ) - 1;
00283 case ( MYD02QKM ) :
00284 case ( MYD03 ) :
00285 return ( lat_lon_index_max[1] + 1 );
00286 break;
00287 default :
00288 string msg ( "Unimplemented method for product " + product ) ;
00289 g_exception e( __FILE__ , __LINE__ , msg );
00290 throw e;
00291 break;
00292 }
00293 return - 1;
00294 }
00295
00300 const int get_y_size_1km() {
00301 switch ( product_id ) {
00302 case ( MYD06_L2 ) :
00303 case ( MOD06_L2 ) :
00304 case ( MYD05_L2 ) :
00305 case ( MYD021KM ) :
00306 return ( get_y_size_5km () * 5 );
00307 case ( MYD02QKM ) :
00308 case ( MYD03 ) :
00309 return ( lat_lon_index_max[0] + 1 );
00310 break;
00311 default :
00312 string msg ( "Unimplemented method for product " + product ) ;
00313 g_exception e( __FILE__ , __LINE__ , msg );
00314 throw e;
00315 break;
00316 }
00317 return - 1;
00318 }
00319
00325 const int get_x_size_250m() {
00326 switch ( product_id ) {
00327 case ( MYD02QKM ) :
00328 return 4 * get_x_size_1km();
00329 break;
00330 default :
00331 string msg ( "Unimplemented method for product " + product ) ;
00332 g_exception e( __FILE__ , __LINE__ , msg );
00333 throw e;
00334 return - 1;
00335 break;
00336 }
00337 return -1;
00338 };
00339
00345 const int get_y_size_250m() {
00346 switch ( product_id ) {
00347 case ( MYD02QKM ) :
00348 return 4 * get_y_size_1km();
00349 break;
00350 default :
00351 string msg ( "At this time, this method is only supported for MYD02QKM products" ) ;
00352 g_exception e( __FILE__ , __LINE__ , msg );
00353 throw e;
00354 break;
00355 }
00356 return -1;
00357 };
00358
00364 MODISFileData(const string &_name, const string &mode="r");
00368 ~MODISFileData();
00372 void print_gring() const;
00373
00380 const string get_radix();
00389 const bool get_5_to_1km_index(const float &lat, const float &lon, int * one_km_indexes, const int * five_km_indexes=NULL);
00399 const bool get_1km_to_250m_pixel( const float32 lat, const float32 lon, const int i_pix_1km[2],
00400 int i_pix_250m[2]);
00410 const bool get_5km_to_1km_pixel( const float32 lat, const float32 lon, const int i_pix_5km[2],
00411 int i_pix_1km[2]);
00420 void get_5_to_1km_area(const int * five_km_idx, int * one_km_min_idx, int * one_km_max_idx);
00427 const int convert_5_to_1km_index(const int &five_km_index, const bool is_x_axis = false) const;
00428
00434 void convert_1km_to_250m_index( const int i_pix_1km [2],
00435 float i_pix_250m [2] ) const;
00443 const bool contain_data(const float &lat,const float &lon, const double &time, const double &tolerance=0.1);
00452 const bool contain_location(const float &lat,const float &lon, const double &tolerance=0.1) ;
00458 const vector<int> get_lat_lon_index_max_5km() const {
00459 return lat_lon_index_max;
00460 }
00461
00467 const vector<int> get_lat_lon_index_max_1km() const {
00468 vector<int> vect;
00469 vect.push_back(convert_5_to_1km_index(lat_lon_index_max[0],false)+2);
00470 vect.push_back(convert_5_to_1km_index(lat_lon_index_max[1],true)+1);
00471 return vect;
00472 }
00473
00478 string get_product() const {
00479 return product;
00480 }
00485 float get_resolution() const {
00486 return resolution;
00487 }
00492 void load_geolocation_data();
00496 void free_geolocation_data();
00500 virtual void close_data_file() {
00501 free_hdf_file();
00502 };
00506 virtual void open_data_file() {
00507 load_hdf_file();
00508 };
00512 const bool is_geolocation_data_loaded() const;
00523 void get_sds_calibration(const string &sds_name, double & scale, double & offset, const string &scale_name="scale_factor", const string &offset_name="add_offset", const int channel_nb=-1);
00545 template<class Value_T,class Count_T>
00546 Value_T* read_calibrated_data(Value_T* data,const char* sds_name = "Height", int start[]=NULL, int stride[]=NULL, int edges[]=NULL, int rank=-1, Value_T fill_value =Value_T(0), const string &scale_name="scale_factor", const string &offset_name="add_offset", const int channel_nb=-1);
00557 const bool get_index(const float &lat, const float& lon, const double time, int * near_point_idx, float coloc_tolerance=-1.);
00558
00569 const bool get_index(const float &lat, const float& lon, int & nearest_pix_idx, float coloc_tolerance=-1.);
00578 virtual void get_vindex(vector < vector < int > > &v_index, const float &lat, const float& lon,
00579 const float colocation_tolerance ) {
00580 UnimplementedMethod e(__FILE__,__LINE__,__PRETTY_FUNCTION__);
00581 throw e;
00582 };
00591 const float get_nearest_point_distance(const float &lat,const float &lon, float coloc_tolerance=-1.);
00599 virtual void get_pixel_coord ( const vector < int > & ipix, float &lat, float &lon, double &time ) {
00600 UnimplementedMethod e(__FILE__,__LINE__,__PRETTY_FUNCTION__);
00601 throw e;
00602 };
00607 vector< float32 > get_lat_gran_corner() const
00608 {
00609 return lat_gran_corner;
00610 }
00615 vector< float32 > get_lon_gran_corner() const
00616 {
00617 return lon_gran_corner;
00618 }
00619
00624 vector< int > get_geolocation_dim() const
00625 {
00626 vector < int > v_dim (2);
00627 v_dim [0] = lat_lon_index_max [0] + 1;
00628 v_dim [1] = lat_lon_index_max [1] + 1;
00629 return v_dim;
00630 }
00631
00640 inline void get_250m_pix_pos ( const int itk_250m, const int isc_250m,
00641 float32 & lat, float32 & lon );
00642
00651 inline void get_1km_pix_pos ( const int itk_1km, const int isc_1km,
00652 float & lat, float & lon );
00653
00666 inline void get_bounds_1km_to_250m ( const int itk_1km, const int isc_1km,
00667 int & itk_250m_min, int & itk_250m_max,
00668 int & isc_250m_min, int & isc_250m_max
00669 );
00670
00683 inline void get_bounds_5km_to_1km ( const int itk_5km, const int isc_5km,
00684 int & itk_1km_min, int & itk_1km_max,
00685 int & isc_1km_min, int & isc_1km_max
00686 );
00687
00688 protected:
00689
00694 void set_lat_lon_min_max();
00695
00706 inline void get_y_pos_1km_to_250m ( const int isc_1km,
00707 const int itk_p1_1km, const int itk_p2_1km,
00708 const int itk_250m,
00709 double & lat, double & lon );
00710
00722 inline void get_x_pos_1km_to_250m ( const double lat_left_250m, const double lon_left_250m,
00723 const int isc_left_1km,
00724 const double lat_right_250m, const double lon_right_250m,
00725 const int isc_right_1km,
00726 const int isc_250m,
00727 double & lat, double & lon );
00728
00739 inline void get_y_pos_5km_to_1km ( const int isc_5km,
00740 const int itk_p1_5km, const int itk_p2_5km,
00741 const int itk_1km,
00742 double & lat, double & lon );
00743
00755 inline void get_x_pos_5km_to_1km ( const double lat_left_1km, const double lon_left_1km,
00756 const int isc_left_5km,
00757 const double lat_right_1km, const double lon_right_1km,
00758 const int isc_right_5km,
00759 const int isc_1km,
00760 double & lat, double & lon );
00761
00762 };
00763
00764 template<class Value_T,class Count_T>
00765 Value_T * MODISFileData::read_calibrated_data( Value_T * data, const char * sds_name, int start[], int stride[], int edges[], int rank, Value_T fill_value, const string & scale_name, const string & offset_name, const int channel_nb )
00766 {
00767 bool are_limits_initialized[3];
00768 bool hdf_file_already_loaded = is_hdf_file_loaded();
00769 try {
00770 if (!hdf_file_already_loaded)
00771 load_hdf_file();
00772
00773 init_read_write_null_input_param(sds_name, start, stride, edges,rank, are_limits_initialized);
00774
00775 check_read_write_limits(sds_name, start,stride,edges,rank);
00776 int nb_data = 1;
00777 int i=0;
00778 for (i = 0 ; i<rank ; ++i)
00779 nb_data*=edges[i];
00780
00781 Count_T* count_data=NULL;
00782 count_data=static_cast<Count_T*>(read_data(count_data,sds_name,start,stride,edges,rank));
00783
00784 if (data==NULL) {
00785
00786 size_t data_type_size = hdf_file->get_sds_sizeof(sds_name);
00787 data = static_cast<Value_T*>(malloc(data_type_size*nb_data));
00788 }
00789
00790 double cal,offset;
00791 get_sds_calibration(sds_name,cal,offset,scale_name,offset_name,channel_nb);
00792
00793 Count_T count_fill_value;
00794 get_dataset_fill_value(sds_name,static_cast<void*>(&count_fill_value));
00795
00796 for (i=0;i<nb_data;++i) {
00797 if (count_data[i]!=count_fill_value)
00798
00799 data[i]=static_cast<Value_T>(cal)*(static_cast<Value_T>(count_data[i])-static_cast<Value_T>(offset));
00800 else
00801
00802 data[i]=fill_value;
00803 }
00804
00805
00806 free_read_write_allocations(are_limits_initialized, start, stride, edges);
00807 delete[] count_data;
00808 if (!hdf_file_already_loaded)
00809 free_hdf_file();
00810 return data;
00811
00812 } catch(exception &e) {
00813
00814
00815 if (!hdf_file_already_loaded)
00816 free_hdf_file();
00817 cerr<<e.what()<<endl;
00818 throw;
00819 } catch(...) {
00820
00821
00822 cout<< "Unknown exception in "<<__FILE__<<" line : "<<__LINE__<<endl;
00823 throw;
00824 }
00825
00826 }
00827
00828 void MODISFileData::get_y_pos_1km_to_250m ( const int isc_1km,
00829 const int itk_p1_1km, const int itk_p2_1km,
00830 const int itk_250m,
00831 double & lat, double & lon )
00832 {
00833
00834 if ( fabs ( itk_p1_1km - itk_p2_1km ) != 1. )
00835 {
00836 string msg ( "P1 and P2 are on the same cross-track line and must be successive" ) ;
00837 g_exception e( __FILE__ , __LINE__ , msg );
00838 throw e;
00839 }
00840
00841
00842 int sz_sc_1km = get_x_size_1km();
00843 int i_buf = itk_p1_1km * sz_sc_1km + isc_1km;
00844 float32 p1_1km_lat = lat_data [ i_buf ];
00845 float32 p1_1km_lon = lon_data [ i_buf ];
00846 i_buf = itk_p2_1km * sz_sc_1km + isc_1km;
00847 float32 p2_1km_lat = lat_data [ i_buf ];
00848 float32 p2_1km_lon = lon_data [ i_buf ];
00849
00850
00851
00852
00853
00854 if ( fabs ( p1_1km_lon - p2_1km_lon ) > 180. )
00855 {
00856 if ( p1_1km_lon < 0. )
00857 p1_1km_lon += 360.;
00858 else if ( p2_1km_lon < 0. )
00859 p2_1km_lon += 360.;
00860
00861 }
00862
00863
00864 double itk_p1_250m = 1.5 + 4. * itk_p1_1km;
00865 double itk_p2_250m = 1.5 + 4. * itk_p2_1km;
00866
00867
00868
00869
00870 double div = 1. / ( itk_p2_250m - itk_p1_250m );
00871 double dtk = ( itk_250m - itk_p1_250m );
00872 double alpha_lon = ( p2_1km_lon - p1_1km_lon ) * div;
00873 double alpha_lat = ( p2_1km_lat - p1_1km_lat ) * div;
00874 lon = p1_1km_lon + alpha_lon * dtk;
00875 lat = p1_1km_lat + alpha_lat * dtk;
00876
00877
00878
00879
00880 }
00881
00882 void MODISFileData::get_x_pos_1km_to_250m ( const double lat_left_250m, const double lon_left_250m,
00883 const int isc_left_1km,
00884 const double lat_right_250m, const double lon_right_250m,
00885 const int isc_right_1km,
00886 const int isc_250m,
00887 double & lat, double & lon )
00888 {
00889
00890 if ( fabs ( isc_left_1km - isc_right_1km ) != 1. )
00891 {
00892 string msg ( "The 2 borders are on the same along-track line and must be successive" ) ;
00893 g_exception e( __FILE__ , __LINE__ , msg );
00894 throw e;
00895 }
00896
00897
00898 int isc_left_250m = 4 * isc_left_1km;
00899 int isc_right_250m = 4 * isc_right_1km;
00900
00901
00902
00903
00904
00905
00906 double div = 1. / double ( isc_right_250m - isc_left_250m );
00907 double dsc = isc_250m - isc_left_250m;
00908 double alpha_lon = ( lon_right_250m - lon_left_250m ) * div;
00909 double alpha_lat = ( lat_right_250m - lat_left_250m ) * div;
00910
00911 lat = lat_left_250m + alpha_lat * dsc;
00912 lon = lon_left_250m + alpha_lon * dsc;
00913 }
00914
00915 void MODISFileData::get_250m_pix_pos ( const int itk_250m, const int isc_250m,
00916 float32 & lat, float32 & lon )
00917 {
00918 if ( product_id != MYD02QKM )
00919 {
00920 string msg ( "At this time, this method is only supported for MYD02QKM products" ) ;
00921 g_exception e( __FILE__ , __LINE__ , msg );
00922 throw e;
00923 }
00924
00925
00926
00927
00928
00929 int sz_tk_250m = get_y_size_250m ();
00930 int sz_sc_250m = get_x_size_250m ();
00931 if ( ( isc_250m < 0 ) or ( isc_250m > ( sz_sc_250m - 1 ) ) )
00932 {
00933 string msg ( "Invalid cross-track index " + MyTools::to_string ( isc_250m ) +
00934 ". Must in range [0," + MyTools::to_string ( sz_sc_250m - 1 ) ) ;
00935 g_exception e( __FILE__ , __LINE__ , msg );
00936 throw e;
00937 }
00938 if ( ( itk_250m < 0 ) or ( itk_250m > ( sz_tk_250m - 1 ) ) )
00939 {
00940 string msg ( "Invalid along-track index " + MyTools::to_string ( itk_250m ) +
00941 ". Must in range [0," + MyTools::to_string ( sz_tk_250m - 1 ) ) ;
00942 g_exception e( __FILE__ , __LINE__ , msg );
00943 throw e;
00944 }
00945
00946
00947
00948 double itk_1km = ( itk_250m - 1.5 ) / 4.;
00949 double isc_1km = isc_250m / 4.;
00950
00951
00952
00953
00954 int w_scan_250m = 40;
00955
00956 double itk_top_1km = -1.;
00957 double itk_bottom_1km = -1.;
00958 if ( ( itk_250m % w_scan_250m ) <= 1 ) {
00959 itk_top_1km = ceil ( itk_1km );
00960 itk_bottom_1km = itk_top_1km + 1.;
00961 } else if ( ( itk_250m % w_scan_250m ) >= 38 ) {
00962 itk_top_1km = floor ( itk_1km );
00963 itk_bottom_1km = itk_top_1km - 1.;
00964 } else {
00965 itk_top_1km = floor ( itk_1km );
00966 itk_bottom_1km = itk_top_1km + 1.;
00967 }
00968
00969
00970 double isc_left_1km = -1.;
00971 double isc_right_1km = -1.;
00972 if ( isc_1km >= 1353. ) {
00973 isc_left_1km = floor ( isc_1km ) - 1.;
00974 isc_right_1km = floor ( isc_1km );
00975 } else {
00976 isc_left_1km = floor ( isc_1km );
00977 isc_right_1km = isc_left_1km + 1.;
00978 }
00979
00980
00981
00982
00983 double lat_left_250m, lon_left_250m;
00984 get_y_pos_1km_to_250m (
00985 ( int ) ( isc_left_1km ), ( int ) ( itk_top_1km ), ( int ) ( itk_bottom_1km ),
00986 ( int ) ( itk_250m ),
00987 lat_left_250m, lon_left_250m );
00988
00989 double lat_right_250m, lon_right_250m;
00990 get_y_pos_1km_to_250m (
00991 ( int ) ( isc_right_1km ), ( int ) ( itk_top_1km ), ( int ) ( itk_bottom_1km ),
00992 ( int ) ( itk_250m ),
00993 lat_right_250m, lon_right_250m );
00994
00995
00996
00997
00998 if ( fabs ( lon_right_250m - lon_left_250m ) > 180. ) {
00999
01000
01001 if ( lon_left_250m < 0. )
01002 lon_left_250m += 360.;
01003 if ( lon_right_250m < 0. )
01004 lon_right_250m += 360.;
01005 }
01006
01007
01008 double dbl_lat, dbl_lon;
01009 get_x_pos_1km_to_250m ( lat_left_250m, lon_left_250m, ( int ) ( isc_left_1km ),
01010 lat_right_250m, lon_right_250m, ( int ) ( isc_right_1km ),
01011 isc_250m,
01012 dbl_lat, dbl_lon );
01013
01014
01015 if ( dbl_lon > 180. )
01016 dbl_lon -= 360.;
01017 if ( dbl_lon < -180. )
01018 dbl_lon += 360.;
01019
01020 lat = ( float32 ) ( dbl_lat );
01021 lon = ( float32 ) ( dbl_lon );
01022
01023
01024 }
01025
01026 void MODISFileData::get_bounds_1km_to_250m( const int itk_1km, const int isc_1km,
01027 int & itk_250m_min, int & itk_250m_max,
01028 int & isc_250m_min, int & isc_250m_max )
01029 {
01030
01031 float itk_250m = 1.5 + 4 * itk_1km;
01032 int isc_250m = 4 * isc_1km;
01033
01034
01035 int sz_sc_1km = get_x_size_1km();
01036
01037 itk_250m_min = ( int ) ( itk_250m - 1.5 );
01038 itk_250m_max = ( int ) ( itk_250m + 1.5 );
01039 if ( isc_1km == 0 ) {
01040 isc_250m_min = 0;
01041 isc_250m_max = isc_250m + 2;
01042 } else if ( isc_1km == sz_sc_1km - 1 ) {
01043 isc_250m_min = isc_250m - 2;
01044 isc_250m_max = isc_250m + 3;
01045 } else {
01046 isc_250m_min = isc_250m - 2;
01047 isc_250m_max = isc_250m + 2;
01048 }
01049 }
01050
01051 void MODISFileData::get_1km_pix_pos ( const int itk_1km, const int isc_1km,
01052 float & lat, float & lon )
01053 {
01054 if ( product_id != MYD06_L2 && product_id != MOD06_L2 &&
01055 product_id != MYD05_L2 && product_id != MYD021KM )
01056 {
01057 string msg ( "Method not implemented for products " + product ) ;
01058 g_exception e( __FILE__ , __LINE__ , msg );
01059 throw e;
01060 }
01061
01062
01063 int sz_tk_1km = get_y_size_1km ();
01064 int sz_sc_1km = get_x_size_1km ();
01065 if ( ( isc_1km < 0 ) || ( isc_1km > ( sz_sc_1km - 1 ) ) )
01066 {
01067 string msg ( "Invalid cross-track index " + MyTools::to_string ( isc_1km ) +
01068 ". Must in range [0," + MyTools::to_string ( sz_sc_1km - 1 ) ) ;
01069 g_exception e( __FILE__ , __LINE__ , msg );
01070 throw e;
01071 }
01072 if ( ( itk_1km < 0 ) || ( itk_1km > ( sz_tk_1km - 1 ) ) )
01073 {
01074 string msg ( "Invalid along-track index " + MyTools::to_string ( itk_1km ) +
01075 ". Must in range [0," + MyTools::to_string ( sz_tk_1km - 1 ) ) ;
01076 g_exception e( __FILE__ , __LINE__ , msg );
01077 throw e;
01078 }
01079
01080
01081
01082 double itk_5km = ( itk_1km - 2. ) / 5.;
01083 double isc_5km = ( isc_1km - 2. ) / 5.;
01084
01085
01086
01087
01088 int w_scan_1km = 10;
01089
01090 double itk_top_5km = -1.;
01091 double itk_bottom_5km = -1.;
01092
01093 if ( ( itk_1km % w_scan_1km ) <= 2 ) {
01094 itk_top_5km = ceil ( itk_5km );
01095 itk_bottom_5km = itk_top_5km + 1;
01096 } else if ( ( itk_1km % w_scan_1km ) >= 7 ) {
01097 itk_top_5km = floor ( itk_5km );
01098 itk_bottom_5km = itk_top_5km - 1;
01099 } else {
01100 itk_top_5km = floor ( itk_5km );
01101 itk_bottom_5km = itk_top_5km + 1;
01102 }
01103
01104 double isc_left_5km = -1.;
01105 double isc_right_5km = -1.;
01106 int sz_sc_5km = get_x_size_5km();
01107 if ( isc_1km <= 2 ) {
01108 isc_left_5km = 0;
01109 isc_right_5km = 1;
01110 } else if ( isc_5km >= ( sz_sc_5km - 1 ) ) {
01111 isc_left_5km = sz_sc_5km - 2;
01112 isc_right_5km = sz_sc_5km - 1;
01113 } else {
01114 isc_left_5km = floor ( isc_5km );
01115 isc_right_5km = isc_left_5km + 1;
01116 }
01117
01118
01119
01120
01121 double lat_left_1km, lon_left_1km;
01122 get_y_pos_5km_to_1km (
01123 ( int ) ( isc_left_5km ), ( int ) ( itk_top_5km ), ( int ) ( itk_bottom_5km ),
01124 ( int ) ( itk_1km ),
01125 lat_left_1km, lon_left_1km );
01126
01127 double lat_right_1km, lon_right_1km;
01128 get_y_pos_5km_to_1km (
01129 ( int ) ( isc_right_5km ), ( int ) ( itk_top_5km ), ( int ) ( itk_bottom_5km ),
01130 ( int ) ( itk_1km ),
01131 lat_right_1km, lon_right_1km );
01132
01133
01134
01135
01136 if ( fabs ( lon_right_1km - lon_left_1km ) > 180. ) {
01137
01138 if ( lon_left_1km < 0. )
01139 lon_left_1km += 360.;
01140 if ( lon_right_1km < 0. )
01141 lon_right_1km += 360.;
01142 }
01143
01144
01145 double dbl_lat, dbl_lon;
01146 get_x_pos_5km_to_1km ( lat_left_1km, lon_left_1km, ( int ) ( isc_left_5km ),
01147 lat_right_1km, lon_right_1km, ( int ) ( isc_right_5km ),
01148 isc_1km,
01149 dbl_lat, dbl_lon );
01150 lat = ( float ) ( dbl_lat );
01151 lon = ( float ) ( dbl_lon );
01152
01153
01154 if ( lon > 180. )
01155 lon = lon - 360.;
01156 else if ( lon < -180. )
01157 lon += 360.;
01158 }
01159
01160 void MODISFileData::get_y_pos_5km_to_1km ( const int isc_5km,
01161 const int itk_p1_5km, const int itk_p2_5km,
01162 const int itk_1km,
01163 double & lat, double & lon )
01164 {
01165
01166 if ( fabs ( itk_p1_5km - itk_p2_5km ) != 1. )
01167 {
01168 string msg ( "P1 and P2 are on the same cross-track line and must be successive" ) ;
01169 g_exception e( __FILE__ , __LINE__ , msg );
01170 throw e;
01171 }
01172
01173
01174 int sz_sc_5km = get_x_size_5km();
01175 int i_buf = itk_p1_5km * sz_sc_5km + isc_5km;
01176 float32 p1_5km_lat = lat_data [ i_buf ];
01177 float32 p1_5km_lon = lon_data [ i_buf ];
01178 i_buf = itk_p2_5km * sz_sc_5km + isc_5km;
01179 float32 p2_5km_lat = lat_data [ i_buf ];
01180 float32 p2_5km_lon = lon_data [ i_buf ];
01181
01182
01183
01184
01185 if ( fabs ( p1_5km_lon - p2_5km_lon ) > 180. )
01186 {
01187 if ( p1_5km_lon < 0. )
01188 p1_5km_lon += 360.;
01189 if ( p2_5km_lon < 0. )
01190 p2_5km_lon += 360.;
01191 }
01192
01193
01194 double itk_p1_1km = 2. + 5. * itk_p1_5km;
01195 double itk_p2_1km = 2. + 5. * itk_p2_5km;
01196
01197
01198
01199
01200 double div = 1. / ( itk_p2_1km - itk_p1_1km );
01201 double dtk = ( itk_1km - itk_p1_1km );
01202 double alpha_lon = ( p2_5km_lon - p1_5km_lon ) * div;
01203 double alpha_lat = ( p2_5km_lat - p1_5km_lat ) * div;
01204 lon = p1_5km_lon + alpha_lon * dtk;
01205 lat = p1_5km_lat + alpha_lat * dtk;
01206
01207
01208 if ( lon > 180. )
01209 lon -= 360.;
01210 else if ( lon < -180. )
01211 lon += 360.;
01212 }
01213
01214 void MODISFileData::get_x_pos_5km_to_1km ( const double lat_left_1km, const double lon_left_1km,
01215 const int isc_left_5km,
01216 const double lat_right_1km, const double lon_right_1km,
01217 const int isc_right_5km,
01218 const int isc_1km,
01219 double & lat, double & lon )
01220 {
01221
01222 if ( fabs ( isc_left_5km - isc_right_5km ) != 1. )
01223 {
01224 string msg ( "The 2 borders are on the same along-track line and must be successive" ) ;
01225 g_exception e( __FILE__ , __LINE__ , msg );
01226 throw e;
01227 }
01228
01229
01230 int isc_left_1km = 2 + 5 * isc_left_5km;
01231 int isc_right_1km = 2 + 5 * isc_right_5km;
01232
01233
01234
01235
01236
01237
01238 double div = 1. / double ( isc_right_1km - isc_left_1km );
01239 double dsc = isc_1km - isc_left_1km;
01240 double alpha_lon = ( lon_right_1km - lon_left_1km ) * div;
01241 double alpha_lat = ( lat_right_1km - lat_left_1km ) * div;
01242
01243 lat = lat_left_1km + alpha_lat * dsc;
01244 lon = lon_left_1km + alpha_lon * dsc;
01245 }
01246
01247 void MODISFileData::get_bounds_5km_to_1km( const int itk_5km, const int isc_5km,
01248 int & itk_1km_min, int & itk_1km_max,
01249 int & isc_1km_min, int & isc_1km_max )
01250 {
01251
01252 int itk_1km = 2 + 5 * itk_5km;
01253 int isc_1km = 2 + 5 * isc_5km;
01254
01255
01256 int sz_sc_5km = get_x_size_5km();
01257
01258 itk_1km_min = itk_1km - 2;
01259 itk_1km_max = itk_1km + 2;
01260
01261
01262 isc_1km_min = isc_1km - 2;
01263 isc_1km_max = isc_1km + 2;
01264
01265 if ( isc_5km == 0 ) {
01266 isc_1km_min = 0;
01267 isc_1km_max = isc_1km + 2;
01268 } else if ( isc_5km == sz_sc_5km - 1 ) {
01269 if ( product_id == MYD021KM )
01270
01271 isc_1km_max = isc_1km + 1;
01272 else
01273
01274 isc_1km_max = isc_1km + 6;
01275 }
01276 }
01277
01278 #endif