00001 /***************************************************************************** 00002 * 00003 * $RCSfile: georef_8c-source.html,v $ 00004 * 00005 * GPS4Palm Map File Georeference Decoding 00006 * 00007 * History: 00008 * 2003-10-19: first version 00009 * 00010 * Reads Georeference Parameters 00011 * - currently the parameters SCALE, LAT and LON are encoded in the filename 00012 * - the next step should be to get these parameters from the GIF87a 00013 * Comment Extension or PNG tEXt chunks, respectively 00014 * - the final implementation should use an appropriate file format like 00015 * GeoTiff, which contains both image data and georeferencing meta data 00016 * 00017 * 00018 * This program is Copyright (C) 10/2003 Matthias Prinke 00019 * <matthias.prinke@surfeu.de> and covered by GNU's GPL. 00020 * In particular, this program is free software and comes WITHOUT 00021 * ANY WARRANTY. 00022 * 00023 * $Author: mp $ 00024 * 00025 * $Date: 2007-10-08 20:40:33 $ 00026 * 00027 * $Revision: 1.7.2.1 $ 00028 * 00029 * $Log: georef_8c-source.html,v $ 00029 * Revision 1.7.2.1 2007-10-08 20:40:33 mp 00029 * updated for gps4palm V0.9.5 beta 00029 * 00030 * Revision 1.9 2005-05-15 12:36:04 mp 00031 * added map size to map search conditions 00032 * 00033 * Revision 1.8 2005/05/06 13:49:26 mp 00034 * modified documentation 00035 * 00036 * Revision 1.7 2005/05/06 13:42:40 mp 00037 * removed call to WinGetDisplayExtent() and supporting code 00038 * 00039 * Revision 1.6 2005/04/17 18:32:58 mp 00040 * added High-Density Display support to search_map() 00041 * 00042 * Revision 1.5 2005/02/19 14:39:17 mp 00043 * modified VFS support to search_map(), modified comments for doxygen 00044 * 00045 * Revision 1.4 2003/12/30 14:47:52 mp 00046 * filename cleared at start of search_map, removed debugging code 00047 * 00048 * Revision 1.3 2003/12/28 18:08:38 mp 00049 * fixed order of arguments to calcxy() 00050 * 00051 * Revision 1.2 2003/11/23 20:00:44 mp 00052 * added search_map() 00053 * 00054 * Revision 1.1 2003/10/19 16:56:30 mp 00055 * initial version 00056 * 00057 * 00058 ****************************************************************************/ 00059 #include <PalmOS.h> 00060 #include <PalmCompatibility.h> 00061 #include "stringil.h" 00062 #include "MapForm.h" 00063 #include "georef.h" 00064 #include "geo.h" 00065 #include "file_io.h" 00066 #include "getdir.h" 00067 #include "imginfo.h" 00068 #include "common.h" 00069 00070 /* Preferences data structure */ 00071 extern PrefsType gPrefs; 00072 00073 /* VFS Manager Feature Set */ 00074 extern Boolean gVfsManagerFtr; 00075 00076 00077 /**********************************************************************/ 00078 /** 00079 * \brief Get the map parameters SCALE, LAT and LON from the filename 00080 * 00081 * \param filename filename 00082 * \param map_lat Ptr to Latitude 00083 * \param map_lon Ptr to Longitude 00084 * \param map_scale Ptr to Scale 00085 * 00086 * \return true if all parameters decoded successfully, otherwise false 00087 * map_lat, map_lon, and map_scale 00088 * 00089 ****************************************************************************/ 00090 Boolean georef_filename(const Char *filename, double *map_lat, double *map_lon, 00091 UInt32 *map_scale) 00092 { 00093 UInt32 scale = 0; /* Scale */ 00094 double lat; /* Latitude */ 00095 double lon; /* Longitude */ 00096 FlpCompDouble dval; 00097 Char tmp[12]; 00098 UInt16 i; /* loop index */ 00099 UInt16 j; /* loop index */ 00100 Boolean valid = false; /* decoding valid flag */ 00101 00102 /* 00103 * Decode scale information 00104 * Scale information ends with 'k', 'M', '+' or '-' 00105 * and can contain at most 3 digits. 00106 */ 00107 00108 for (i=0; i<5; i++) { 00109 if (filename[i] == 'k') { 00110 /* multiply by 10^3 */ 00111 scale *= 1000; 00112 i++; 00113 valid = true; 00114 break; 00115 } 00116 if (filename[i] == 'M') { 00117 /* multiply by 10^6 */ 00118 scale *= 1000000L; 00119 i++; 00120 valid = true; 00121 break; 00122 } 00123 if ((filename[i] == '+') || (filename[i] == '-')) { 00124 valid = true; 00125 break; 00126 } 00127 if ((filename[i] >= '0') && (filename[i] <= '9')) { 00128 /* next digit */ 00129 scale *= 10; 00130 scale += filename[i] - '0'; 00131 } 00132 } 00133 00134 if (!valid) { 00135 /* Decoding scale info failed */ 00136 return false; 00137 } 00138 00139 00140 /* 00141 * Decode Latitude 00142 * Latitude information ends with '+' or '-' and consists of at most 00143 * 11 characters. 00144 * Example: +52.1614999 00145 */ 00146 if (filename[i] == '+') { 00147 lat = 1.0; 00148 } else if (filename[i] == '-') { 00149 lat = -1.0; 00150 } else { 00151 /* Lat. decoding failed - no sign found */ 00152 return false; 00153 } 00154 00155 /* sign done */ 00156 i++; 00157 00158 /* copy lat to temp. string */ 00159 for (j=0; j < 10; j++) { 00160 if ((filename[i] == '+') || (filename[i] == '-')) 00161 break; 00162 tmp[j] = filename[i++]; 00163 } 00164 00165 if ((filename[i] == '+') || (filename[i] == '-')) { 00166 /* valid end (sign of lon.) found, terminate temp. string */ 00167 tmp[j] = '\0'; 00168 00169 /* get floating point value from string */ 00170 FlpBufferAToF(&dval.fd, tmp); 00171 00172 /* store "double"-field of union FlpCompDouble in variable lat */ 00173 lat = lat * dval.d; 00174 } else { 00175 /* decoding failed */ 00176 return false; 00177 } 00178 00179 00180 /* 00181 * Decode Longitude 00182 * Longitude information ends with '.' and consists of 5 to 11 00183 * characters. 00184 * Example: -110.3126601 00185 */ 00186 if (filename[i] == '+') { 00187 lon = 1.0; 00188 } else if (filename[i] == '-') { 00189 lon = -1.0; 00190 } else { 00191 /* Lon. decoding failed - no sign found */ 00192 return false; 00193 } 00194 00195 /* sign done */ 00196 i++; 00197 00198 /* copy lon to temp. string */ 00199 for (j=0; j < 11; j++) { 00200 if ((j > 4) && (filename[i] == '.')) 00201 break; 00202 tmp[j] = filename[i++]; 00203 } 00204 00205 if (filename[i] == '.') { 00206 /* valid end (filename extension) found, terminate temp. string */ 00207 tmp[j] = '\0'; 00208 00209 /* get floating point value from string */ 00210 FlpBufferAToF(&dval.fd, tmp); 00211 00212 /* store "double"-field of union FlpCompDouble in variable lat */ 00213 lon = lon * dval.d; 00214 } else { 00215 /* decoding failed */ 00216 return false; 00217 } 00218 00219 /* return internal values */ 00220 *map_scale = scale; 00221 *map_lat = lat; 00222 *map_lon = lon; 00223 00224 /* decoding successful */ 00225 return true; 00226 } 00227 00228 00229 /**********************************************************************/ 00230 /** 00231 * \brief Search for usable map 00232 * 00233 * \note Currently search_map stops on the first map which fits, even 00234 * if there is a better map (i.e. with the map center closer to 00235 * the current position) available. 00236 * 00237 * \param filename filename or NULL (returned by reference) 00238 * \param card card/volume number and VFS flag 00239 * (returned by reference) 00240 * \param lat Latitude of current position 00241 * \param lon Longitude of current position 00242 * \param maxx Max. x-extent of screen 00243 * \param maxy Max. y-extent of screen 00244 * 00245 * \return true if usable map found, otherwise false 00246 ****************************************************************************/ 00247 Boolean search_map(char *filename, UInt32 *card, double lon, double lat, 00248 UInt16 maxx, UInt16 maxy) 00249 { 00250 static DmOpenRef scratch; /* scratchpad DB reference */ 00251 static char *filelist; /* filelist DB record */ 00252 static char *filecard; /* filecard DB record */ 00253 static char **filelp; /* filelp DB record */ 00254 Err err; /* error code */ 00255 FileDescrType filedescr; /* file descriptor */ 00256 UInt16 i; /* loop index */ 00257 UInt16 files = 0; /* number of files found */ 00258 Char **f; /* filename */ 00259 double map_lat; /* map center latitude */ 00260 double map_lon; /* map center longitude */ 00261 UInt32 map_scale; /* map scale */ 00262 Int32 x; /* map xoord. x */ 00263 Int32 y; /* map coord. y */ 00264 Int32 w; /* map width/2 */ 00265 Int32 h; /* map height/2 */ 00266 UInt16 width; /* map width */ 00267 UInt16 height; /* map height */ 00268 UInt8 type; /* map type */ 00269 Boolean found = false; /* map found */ 00270 00271 *filename = '\0'; 00272 *card = 0; 00273 00274 /* get directory */ 00275 CreateDatabase(&scratch, &filelist, &filecard, &filelp); 00276 files = getdir(filelist, filecard, filelp); 00277 00278 if (gVfsManagerFtr) { 00279 files = getdir_vfs(filelist, filecard, filelp, files); 00280 } 00281 00282 if (files == 0) { 00283 /* no map found */ 00284 /* free directory storage */ 00285 DestroyDatabase(scratch, filelist, filecard, filelp); 00286 00287 return false; 00288 } 00289 00290 /* file list pointer */ 00291 f = filelp; 00292 00293 /* search for usable map */ 00294 for (i = 0; i<files; i++, f++) { 00295 00296 /* get map parameters from filename, skip invalid files */ 00297 if (georef_filename(*f+SORTPREFIX, &map_lat, &map_lon, &map_scale)) { 00298 00299 /* check if current map has reqired scale */ 00300 if (map_scale == gPrefs.mapprefs.scale) { 00301 00302 /* calculate offset between position and map center */ 00303 calcxy(&x, &y, lon, lat, map_lon, map_lat, map_scale); 00304 00305 /* copy card/volume number and VFS flag */ 00306 memcpy(card, &filecard[i*4], 4); 00307 00308 /* get map's dimensions */ 00309 filedescr = fopen(*card, *f+SORTPREFIX, FILEDIR, &err); 00310 00311 if (!err) { 00312 if (imginfo(filedescr, &type, &width, &height)) { 00313 /* no valid info */ 00314 fclose(filedescr); 00315 continue; 00316 } 00317 fclose(filedescr); 00318 } else { 00319 width = 0; 00320 height = 0; 00321 } 00322 00323 /* offset from map center must be smaller than half image */ 00324 w = width/2; 00325 h = height/2; 00326 00327 /* check if current position is on map */ 00328 if ( (x > -w+CROSS_X) && 00329 (x < w-CROSS_X) && 00330 (y > -h+CROSS_Y) && 00331 (y < h-CROSS_Y) ) { 00332 StrCopy(filename, *f+SORTPREFIX); 00333 found = true; 00334 break; 00335 } 00336 } /* if (scale == gPrefs.mapprefs.scale) */ 00337 } /* if (georef_filename()) */ 00338 00339 } /* for (i = 0; i<files; i++) */ 00340 00341 /* free directory storage */ 00342 DestroyDatabase(scratch, filelist, filecard, filelp); 00343 00344 return found; 00345 }