TerraGear Patches - 20090302

external: index back to: fgfs-050.htm
internal: preamble changes patches end

Preamble

This is the suggest changes to TerraGear for a native WIN32 port. This was using the 'git' repository, but it would seem ALL changes would also apply the the TerraGear CVS repository! Most changes are essential to be able to compile under native win32, using Microsoft Visual C++ (MSVC)

Changes

These can be divided in two types

  1. New - The new folders - projects/msvc and projects/win32
  2. Patches - Patches to existing files

The new are all in tg-msvc-01.zip (01/03/2009 136,405 bytes). This contains about 100 files, as follows -

Patches

The patches are all in tg-diff-01.txt, or tg-diff-01.patch - same thing in unix format, but here separated into file by file, with a brief explanation... most are essential to get TerraGear compiled by MSVC in native win32, but there are also a few enhancement, usually more 'help' and for 'raw2ascii' the ability to limit the output to min/max lat/lon...

src\Airports\GenAirports\main.cxx src\Airspace\airspace.cxx src\BuildTiles\Clipper\testclipper.cxx src\BuildTiles\Main\main.cxx src\BuildTiles\Main\master.cxx src\Lib\Array\testarray.cxx src\Lib\Geometry\poly_support.cxx src\Lib\Optimize\genfans.cxx src\Lib\poly2tri\construct.c src\Lib\TriangleJRS\showme.c src\Lib\TriangleJRS\triangle.c src\Prep\DemChop\testassem.cxx src\Prep\DemRaw2ascii\main.c src\Prep\DemRaw2ascii\rawdem.c src\Prep\DemRaw2ascii\rawdem.h src\Prep\MergerClipper\merger.cxx src\Prep\MergerClipper\merger.hxx src\Prep\MergerClipper\testmerger.cxx src\Prep\Terra\terra.cc

src\Airports\GenAirports\main.cxx

(a) move a large 2048, and smaller 256 byte buffer off the immediate stack, and put in 'static' data
(b) add a counter, to show airports processed

--- C:\FGCVS\terragear-cs\src\Airports\GenAirports\main.cxx        Thu Feb 19 12:01:34 2009
+++ C:\FG\27\terragear-cs\src\Airports\GenAirports\main.cxx     Wed Feb 25 20:10:36 2009
@@ -247,7 +247,8 @@
     string last_apt_info = "";
     string last_apt_type = "";
     string line;
-    char tmp[2048];
+    int counter = 0;
+    static char tmp[2048];
 
     while ( ! in.eof() ) {
        in.getline(tmp, 2048);
@@ -285,8 +286,9 @@
             
             string id = token[4];
             int elev = atoi( token[1].c_str() );
+            counter++;
             SG_LOG( SG_GENERAL, SG_INFO, "Next airport = " << id << " "
-                    << elev );
+                    << elev << " no " << counter );
 
             if ( !last_apt_id.empty()) {
                 if ( runways_list.size() ) {
@@ -304,7 +306,7 @@
 
                     if ( ready_to_go ) {
                         // check point our location
-                        char command[256];
+                        static char command[256];
                         sprintf( command,
                                  "echo before building %s >> last_apt",
                                  last_apt_id.c_str() );
@@ -442,7 +444,7 @@
         }
     }
 
-    SG_LOG(SG_GENERAL, SG_INFO, "[FINISHED CORRECTLY]");
+    SG_LOG(SG_GENERAL, SG_INFO, "[FINISHED CORRECTLY] count = " << counter );
 
     return 0;
 }

top

src\Airspace\airspace.cxx

(a) change from iostream.h to iostream, and fstream.h to fstream under _MSC_VER switch, but maybe this would also work for unix
(b) under _MSC_VER, remove netinet/in.h, not available in native win32
(c) under _MSC_VER, provide workarounds for 'trunc()' and 'round()' functions
(d) under _MSC_VER, declare using std::cout

--- C:\FGCVS\terragear-cs\src\Airspace\airspace.cxx        Thu Feb 19 12:01:34 2009
+++ C:\FG\27\terragear-cs\src\Airspace\airspace.cxx     Wed Feb 25 14:50:12 2009
@@ -76,15 +76,22 @@
 //////                                                                                  //////
 //////////////////////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////////////////
-                                                                      
+
+#ifdef _MSC_VER
+#include <iostream>
+#include <fstream>
+#else
 #include <iostream.h>
 #include <fstream.h>
+#endif
 #include <string>
 #include <stdio.h>
 
 #include <math.h>
 
+#ifndef _MSC_VER
 #include <netinet/in.h>
+#endif
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -95,6 +102,16 @@
 #include <simgear/math/sg_geodesy.hxx>
 #include <simgear/misc/sg_path.hxx>
 /************************************************************/
+#ifdef _MSC_VER
+static double trunc( double val ) { return floor(val); }
+static double round( double val ) { 
+   if( val < 0.0 )
+      return ceil(val);
+   else
+      return floor(val);
+}
+using std::cout;
+#endif
 
 using std::string;
 

top

src\BuildTiles\Clipper\testclipper.cxx

(a) under _MSC_VER, a macro to convert path string to 'unix'
(b) add some additional output information

--- C:\FGCVS\terragear-cs\src\BuildTiles\Clipper\testclipper.cxx   Thu Feb 19 12:01:35 2009
+++ C:\FG\27\terragear-cs\src\BuildTiles\Clipper\testclipper.cxx        Fri Feb 27 19:54:15 2009
@@ -30,6 +30,12 @@
 using std::cout;
 using std::endl;
 
+#define set_unix_sep(s) {    \
+   size_t fnd = s.find('\\'); \
+   while( fnd != -1 ) {       \
+      s.replace(fnd, 1, "/"); \
+      fnd = s.find('\\'); }}
+
 
 int main( int argc, char **argv ) {
     point2d global_min, global_max;
@@ -51,6 +57,9 @@
     // process all specified polygon files
     for ( int i = 1; i < argc; i++ ) {
        string full_path = argv[i];
+#ifdef _MSC_VER
+   set_unix_sep(full_path);
+#endif
 
        // determine bucket for this polygon
        int pos = full_path.rfind("/");
@@ -64,7 +73,8 @@
        long int index;
        sscanf( base_name.c_str(), "%ld", &index);
        SGBucket b(index);
-       cout << "bucket = " << b << endl;
+       cout << "bucket = " << b << ". base path " << b.gen_base_path() <<
+      "/" << b.gen_index() << endl;
 
        // calculate bucket dimensions
        point2d c, min, max;

top

src\BuildTiles\Main\main.cxx

(a) under _MSC_VER, add sys\types.h and sys\stat.h for 'stat()', and direct.h for getcwd
(b) under _MSC_VER switch, add SKIPPING of .ind files, as is done in unix
(c) only parse a bucket IFF an array file found, returning true or false accordingly
(d) and advise failed, and return if no array found
(e) add function to check if file or directory
(f) check if directories given are valid, and only push onto vector if valid
(g) if not valid, also check if "'work dir' + 'given directory'" is valid, and push it if valid
(h) abort if NO directories given are valid
(i) under _MSC_VER _AND_ DEBUG, pause after each bucket processed for input

--- C:\FGCVS\terragear-cs\src\BuildTiles\Main\main.cxx  Thu Feb 19 12:01:35 2009
+++ C:\FG\27\terragear-cs\src\BuildTiles\Main\main.cxx  Sat Feb 28 12:10:20 2009
@@ -26,7 +26,10 @@
 #endif
 
 #ifdef _MSC_VER
-#  include <io.h>
+#include <sys\types.h>
+#include <sys\stat.h>
+#include <io.h>
+#include <direct.h>     // for getcwd()
 #else
 #  include <sys/types.h> // for directory reading
 #  include <dirent.h>            // for directory reading
@@ -68,6 +71,9 @@
 using std::endl;
 using std::string;
 using std::vector;
+#if (defined(_MSC_VER) && !defined(NDEBUG))
+using std::cin;
+#endif
 
 vector<string> load_dirs;
 
@@ -183,7 +189,7 @@
             cout << file << "  " << f_index << "  '" << ext << "'" << endl;
             full_path = dir + "/" + file;
             if ( (ext == "arr") || (ext == "arr.gz") || 
-                 (ext == "fit") || (ext == "fit.gz")) {
+                 (ext == "fit") || (ext == "fit.gz") || (ext == "ind")) {
                 // skip
             } else if (ext == "osgb36") {
                 cout << "Loading osgb36 poly definition file\n";
@@ -480,6 +486,7 @@
 // Load elevation data from an Array file, a regular grid of elevation
 // data) and return list of fitted nodes.
 static bool load_array( TGConstruct& c, TGArray& array) {
+   bool ret = false;
     string base = c.get_bucket().gen_base_path();
     int i;
 
@@ -490,17 +497,20 @@
 
        if ( array.open(array_path) ) {
            cout << "Found Array file " << array_path << endl;
+       ret = true;
            break;
        } else {
            cout << "Failed to open Array file " << array_path << endl;
        }
     }
 
+    if (ret) {
     SGBucket b = c.get_bucket();
     array.parse( b );
     array.remove_voids();
+    }
 
-    return true;
+    return ret;
 }
 
 
@@ -1046,7 +1056,11 @@
 
     // load grid of elevation data (Array)
     TGArray array;
-    load_array( c, array );
+    if ( !load_array( c, array ) ) {
+       cout << "Failed tile, bucket = " << c.get_bucket() << endl;
+       return;
+    }
+
 
     // load and clip 2d polygon data
     if ( load_polys( c, array ) == 0 ) {
@@ -1150,6 +1164,24 @@
     exit(-1);
 }
 
+#ifdef _MSC_VER
+#define M_ISDIR _S_IFDIR
+#else
+#define M_ISDIR __S_IFDIR
+#endif
+
+static int is_file_or_directory( string cur_item )
+{
+   struct stat buf;
+   if( stat( cur_item.c_str(), &buf ) == 0 ) {
+      if ( buf.st_mode & M_ISDIR )
+         return 1; // is directory
+      else
+         return 2; // is file
+   }
+   return 0;
+}
+
 
 int main(int argc, char **argv) {
     string output_dir = ".";
@@ -1213,8 +1245,24 @@
     }
     cout << "Nudge is " << nudge << endl;
     for (int i = arg_pos; i < argc; i++) {
-       load_dirs.push_back(argv[i]);
-       cout << "Load directory: " << argv[i] << endl;
+      string dir = argv[i];
+      if (is_file_or_directory( dir ) == 1 ) {
+         load_dirs.push_back(dir);
+         cout << "Load directory: " << dir << endl;
+      } else {
+         dir = work_dir + "/" + dir;
+         if (is_file_or_directory( dir ) == 1 ) {
+            load_dirs.push_back(dir);
+            cout << "Load directory: " << dir << endl;
+         } else {
+            cout << "ERROR: Load directory: " << argv[i] << " NOT FOUND!" << endl;
+         }
+      }
+    }
+    if ( load_dirs.size() == 0 ) {
+       cout << "ERROR: NO VALID LOAD DIRECTORIES!" << endl;
+       cout << "Current directory is [" << getcwd(NULL,0) << "]" << endl;
+       return 1;
     }
 
 #if defined( __CYGWIN__ ) || defined( __CYGWIN32__ ) || defined( _MSC_VER )
@@ -1308,7 +1356,10 @@
                        }
                    }
                }
-               // string answer; cin >> answer;
+#if (defined(_MSC_VER) && !defined(NDEBUG))
+      cout << "Done bucket " << b_cur << ". Continue?" << endl;
+               string answer; cin >> answer;
+#endif
            }
        }
     } else {

top

src\BuildTiles\Main\master.cxx

under _MSC_VER, remove inclusion of 'unistd.h', not available in native win32

--- C:\FGCVS\terragear-cs\src\BuildTiles\Main\master.cxx        Thu Feb 19 12:01:35 2009
+++ C:\FG\27\terragear-cs\src\BuildTiles\Main\master.cxx        Wed Feb 25 14:45:20 2009
@@ -28,7 +28,9 @@
 
 #include <stdlib.h>    // for system()
 #include <sys/stat.h>  // for stat()
+#ifndef _MSC_VER
 #include <unistd.h>    // for stat()
+#endif
 
 #include <string>
 #include <iostream>

top

src\Lib\Array\testarray.cxx

(a) add config.h, under HAVE_CONFIG_H
(b) add more 'help' output
(c) search for -h or --help parameter
(d) verify that inputs lon, lat, dir are valid
(e) add that what is output is an altitude

--- C:\FGCVS\terragear-cs\src\Lib\Array\testarray.cxx   Thu Feb 19 12:01:36 2009
+++ C:\FG\27\terragear-cs\src\Lib\Array\testarray.cxx   Wed Feb 25 15:02:20 2009
@@ -1,26 +1,85 @@
+// testarray.cxx
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
 #include <simgear/compiler.h>
 #include <simgear/bucket/newbucket.hxx>
-
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <iostream>
 #include "array.hxx"
 
 using std::cout;
 using std::endl;
 
+static void give_help( char * name )
+{
+       cout << "Usage:   " << name << " longitude latitude work_dir" << endl;
+       cout << "example: " << name << " 151.18 -33.94 your\\work\\dir, for YSSY (Sydney)" << endl;
+}
+static void check_for_help( int argc, char **argv )
+{
+   for(int i = 1; i < argc; i++)
+   {
+      char * parg = argv[i];
+      if(( strcmp(parg,"-h") == 0 )||
+         ( strcmp(parg,"--help") == 0 ))
+      {
+         give_help( argv[0] );
+         exit(0);
+      }
+   }
+}
+
+static int is_file_or_directory( string cur_item )
+{
+   struct stat buf;
+   if( stat( cur_item.c_str(), &buf ) == 0 ) {
+      if ( buf.st_mode & _S_IFDIR )
+         return 1; // is directory
+      else
+         return 2; // is file
+   }
+   return 0;
+}
+
 int main( int argc, char **argv ) {
     double lon, lat;
 
-    if ( argc != 2 ) {
-       cout << "Usage: " << argv[0] << " work_dir" << endl;
+    check_for_help( argc, argv );
+
+    if ( argc != 4 ) {
+       give_help( argv[0] );
        exit(-1);
     }
 
-    string work_dir = argv[1];
-   
     lon = -146.248360; lat = 61.133950;  // PAVD (Valdez, AK)
     lon = -110.664244; lat = 33.352890;  // P13
+    lon = 150.156; lat = -38.474; // Lithgow, NSW, Australia
+    lat = -33.943392; lon = 151.179773; // YSSY Sydney Intl  tile=e150s30
+
+    lon = atof( argv[1] );
+    lat = atof( argv[2] );
+    string work_dir = argv[3];
+    if ( is_file_or_directory( work_dir ) != 1 ) {
+       cout << "ERROR: '" << work_dir << "' is not a valid directory!" << endl;
+       exit(1);
+    }
+    if( ( lon > 180.0 ) || ( lon < -180.0 ) ) {
+       cout << "ERROR: logitude '" << lon << "' not in world range! -180.0 to 180.0" << endl;
+       exit(1);
+    }
+    if( ( lat > 90.0 ) || ( lat < -90.0 ) ) {
+       cout << "ERROR: latitude '" << lat << "' not in world range! -90.0 to 90.0" << endl;
+       exit(1);
+    }
 
     SGBucket b( lon, lat );
+    cout << "input: lon=" << lon << ", lat=" << lat <<
+       ", Bucket = " << b << endl;
+
     string base = b.gen_base_path();
     string path = work_dir + "/" + base;
 
@@ -32,7 +91,8 @@
 
     lon *= 3600;
     lat *= 3600;
-    cout << "  " << a.altitude_from_grid(lon, lat) << endl;
+    cout << "  " << a.altitude_from_grid(lon, lat) <<
+       " is altitude indication." << endl;
 
     return 0;
 }

top

src\Lib\Geometry\poly_support.cxx

(a) under _MSC_VER and DEBUG, show the contour being processed
(b) process contour ONLY if it has .size(), and advise skipping a nil size

--- C:\FGCVS\terragear-cs\src\Lib\Geometry\poly_support.cxx     Thu Feb 19 12:01:36 2009
+++ C:\FG\27\terragear-cs\src\Lib\Geometry\poly_support.cxx     Wed Feb 25 19:16:50 2009
@@ -670,12 +670,15 @@
     TGPolygon tmp = poly;
     for ( int i = 0; i < tmp.contours(); ++i ) {
        contour = poly.get_contour( i );
-       // cout << "testing contour " << i << "  size = " << contour.size() 
-       //      << "  hole = " << poly.get_hole_flag( i ) << endl;
+#if (defined(_MSC_VER) && !defined(NDEBUG))
+       cout << "testing contour " << i << "  size = " << contour.size() 
+             << "  hole = " << poly.get_hole_flag( i ) << endl;
+#endif
        bool have_dups = true;
        while ( have_dups ) {
            have_dups = false;
            new_contour.clear();
+       if( contour.size() ) {
            Point3D last = contour[ contour.size() - 1 ];
            for ( int j = 0; j < (int)contour.size(); ++j ) {
                // cout << "  " << i << " " << j << endl;
@@ -688,10 +691,15 @@
                    last = cur;
                }
            }
+       } else {
+                   cout << "skipping iteration of null contour!" << endl;
+       }
            contour = new_contour;
        }
 
-       // cout << "  final size = " << contour.size() << endl;
+#if (defined(_MSC_VER) && !defined(NDEBUG))
+       cout << "  final size = " << contour.size() << endl;
+#endif
 
        if ( contour.size() ) {
            int flag = poly.get_hole_flag( i );

top

src\Lib\Optimize\genfans.cxx

(a) under _MSC_VER and DEBUG, show more info
(b) under _MSC_VER, reset iterator after a erase (deletion). Maybe only necessary under DEBUG?

--- C:\FGCVS\terragear-cs\src\Lib\Optimize\genfans.cxx  Thu Feb 19 12:01:37 2009
+++ C:\FG\27\terragear-cs\src\Lib\Optimize\genfans.cxx  Fri Feb 27 18:37:14 2009
@@ -207,8 +207,9 @@
            }
            node_list.push_back( t.get_n3() );
        }
-       // cout << "best list size = " << node_list.size() << endl;
-
+#if (defined(_MSC_VER) && !defined(NDEBUG))
+       cout << "best list size = " << node_list.size() << endl;
+#endif
        // add this fan to the fan list
        fans.push_back( node_list );
 
@@ -216,15 +217,23 @@
        triele_list_iterator t_current = tris.begin();
        triele_list_iterator t_last = tris.end();
        counter = 0;
+   index = 0;
        while ( t_current != t_last ) {
            if ( in_fan(counter, best_fan) ) {
-               // cout << "erasing " 
-               //      << t_current->get_n1() << ","
-               //      << t_current->get_n2() << ","
-               //      << t_current->get_n3()
-               //      << " from master tri pool"
-               //      << endl;
+#if (defined(_MSC_VER) && !defined(NDEBUG))
+                cout << "erasing " 
+                     << t_current->get_n1() << ","
+                     << t_current->get_n2() << ","
+                     << t_current->get_n3()
+                     << " from master tri pool. count=" << tris.size()
+                     << endl;
+#endif
                tris.erase( t_current );
+#ifdef _MSC_VER
+      t_last = tris.end();
+      t_current = tris.begin() + (counter - index);
+      index++;
+#endif // _MSC_VER
            } else {
                ++t_current;
            }

top

src\Lib\poly2tri\construct.c

(a) if an error, exit - do not continue
(b) fix use of an un-initialized variable, to what it should be

--- C:\FGCVS\terragear-cs\src\Lib\poly2tri\construct.c  Thu Feb 19 12:01:38 2009
+++ C:\FG\27\terragear-cs\src\Lib\poly2tri\construct.c  Wed Feb 25 15:10:49 2009
@@ -347,6 +347,7 @@
 
     default:
       fprintf(stderr, "Haggu !!!!!\n");
+      exit(1); // should exit, if really that bad!
       break;
     }
 }
@@ -797,14 +798,13 @@
          if (FP_EQUAL(tr[t].lo.y, tr[tlast].lo.y) && 
              FP_EQUAL(tr[t].lo.x, tr[tlast].lo.x) && tribot)
            {           /* bottom forms a triangle */
-             int tmpseg;
 
              if (is_swapped)   
                tmptriseg = seg[segnum].prev;
              else
                tmptriseg = seg[segnum].next;
 
-             if ((tmpseg > 0) && is_left_of(tmpseg, &s.v0))
+             if ((tmptriseg > 0) && is_left_of(tmptriseg, &s.v0))
                {
                  /* L-R downward cusp */
                  tr[tr[t].d1].u0 = t;

top

src\Lib\TriangleJRS\showme.c

under _MSC_VER, chop this whole X-windows module. Had intended to write a more cross platform 'showme', but that is for the future.

--- C:\FGCVS\terragear-cs\src\Lib\TriangleJRS\showme.c  Thu Feb 19 12:01:37 2009
+++ C:\FG\27\terragear-cs\src\Lib\TriangleJRS\showme.c  Wed Feb 25 14:45:20 2009
@@ -102,6 +102,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#ifndef _MSC_VER
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 #include <X11/Xatom.h>
@@ -3382,3 +3383,14 @@
     XNextEvent(display, &event);
   }
 }
+
+#else // is _MSC_VER
+// maybe one day do this ...
+int main(int argc, char **argv)
+{
+   printf("Does nothing! No X-Windows\n" );
+   return 1;
+}
+
+#endif // _MSC_VER y/n
+// eof - showme.c

top

src\Lib\TriangleJRS\triangle.c

modify to default to NO_TIMER, and TRILIBRARY. These could be added as a compiler switches

--- C:\FGCVS\terragear-cs\src\Lib\TriangleJRS\triangle.c        Thu Feb 19 12:01:37 2009
+++ C:\FG\27\terragear-cs\src\Lib\TriangleJRS\triangle.c        Wed Feb 25 14:38:33 2009
@@ -211,7 +211,7 @@
 /* If yours is not a Unix system, define the NO_TIMER compiler switch to     */
 /*   remove the Unix-specific timing code.                                   */
 
-/* #define NO_TIMER */
+#define NO_TIMER
 
 /* To insert lots of self-checks for internal errors, define the SELF_CHECK  */
 /*   symbol.  This will slow down the program significantly.  It is best to  */
@@ -225,7 +225,7 @@
 /*   TRILIBRARY symbol.  Read the file triangle.h for details on how to call */
 /*   the procedure triangulate() that results.                               */
 
-/* #define TRILIBRARY */
+#define TRILIBRARY
 
 /* It is possible to generate a smaller version of Triangle using one or     */
 /*   both of the following symbols.  Define the REDUCED symbol to eliminate  */

top

src\Prep\DemChop\testassem.cxx

remove missing, and no longer needed reference to mkdir.hpp

--- C:\FGCVS\terragear-cs\src\Prep\DemChop\testassem.cxx        Thu Feb 19 12:01:40 2009
+++ C:\FG\27\terragear-cs\src\Prep\DemChop\testassem.cxx        Wed Feb 25 14:45:20 2009
@@ -36,10 +36,6 @@
 #include <Array/array.hxx>
 #include <Polygon/point2d.hxx>
 
-#ifdef _MSC_VER
-#  include <Win32/mkdir.hpp>
-#endif
-
 using std::cout;
 using std::endl;
 using std::string;

top

src\Prep\DemRaw2ascii\main.c

(a) move fgRAWDEM, and directory/file buffer OFF local stack, into 'static' data - VERY IMPORTANT
(b) switch to TWO(2) digit exponent output - VERY IMPORTANT! see MORE on raw2ascii
(c) add sys/types.h and sys/stat.h for stat
(d) add additional 'help' output
(e) add function to check file or directory
(f) add new options to limit the DEM output min, max, lon, lat, and verify input
(g) verify the output directory exists, else will (silently) write nothing

--- C:\FGCVS\terragear-cs\src\Prep\DemRaw2ascii\main.c  Thu Feb 19 12:01:40 2009
+++ C:\FG\27\terragear-cs\src\Prep\DemRaw2ascii\main.c  Wed Feb 25 16:52:11 2009
@@ -1,6 +1,8 @@
 /* main.cxx -- main loop
  *
  * Written by Curtis Olson, started February 1998.
+ * Modified by Geoff R. McLane, February, 2009
+ * to add min, max, lon, lat, to limit the output of ASCII DEM files.
  *
  * Copyright (C) 1998, 1999  Curtis L. Olson  - http://www.flightgear.org/~curt
  *
@@ -35,30 +37,148 @@
 #ifdef HAVE_STDLIB_H
 #  include <stdlib.h>
 #endif
-
+#include <sys/types.h>
+#include <sys/stat.h>
 #include "rawdem.h"
 
+#ifdef _MSC_VER
+#define M_ISDIR _S_IFDIR
+#else
+#define M_ISDIR __S_IFDIR
+#endif
+
+void give_help( char * name )
+{
+   printf("Usage: %s [OPTIONS] <input_file_basename> <output_dir>\n", name);
+   printf("Options:\n");
+   printf(" --min-lat=<degs> - set minimum latitude for output.\n");
+   printf(" --max-lat=<degs> - set maximum latitude for output.\n");
+   printf(" --min-lon=<degs> - set minimum longitude for output.\n");
+   printf(" --max-lon=<degs> - set maximum longitude for output.\n");
+}
+
+static int is_file_or_directory( char * cur_item )
+{
+   struct stat buf;
+   if( stat( cur_item, &buf ) == 0 ) {
+      if ( buf.st_mode & M_ISDIR )
+         return 1; // is directory
+      else
+         return 2; // is file
+   }
+   return 0;
+}
 
 int main(int argc, char **argv) {
-    fgRAWDEM raw;
-    char basename[256], output_dir[256], hdr_file[256], dem_file[256];
+    static fgRAWDEM raw;
+    static char basename[256], output_dir[256], hdr_file[256], dem_file[256];
     int start_lat, end_lat;
     int i;
-    // double total;
-    // unsigned char buf[2];
-    // short int value;
-
-    if ( argc != 3 ) {
-       printf("Usage: %s <input_file_basename> <output_dir>\n", argv[0]);
-       exit(-1);
+    int last_arg = 1;
+    double min_lat, max_lat, min_lon, max_lon;
+
+#ifdef _MSC_VER // set 2-ditit exponent - defaults to 3
+    _set_output_format( _TWO_DIGIT_EXPONENT );
+#endif // _MSC_VER
+
+    min_lat = max_lat = min_lon = max_lon = BAD_LATLON;
+    for( i = 1; i < argc; i++ )
+    {
+       char * arg = argv[i];
+       if (*arg == '-') {
+          // option
+          if((strcmp(arg,"-h") == 0)||
+             (strcmp(arg,"--help") == 0)) {
+                give_help( argv[0] );
+                exit(0);
+          } else if( strncmp(arg,"--min-lon=", 10) == 0 ) {
+             min_lon = atof( &arg[10] );
+          } else if( strncmp(arg,"--max-lon=", 10) == 0 ) {
+             max_lon = atof( &arg[10] );
+          } else if( strncmp(arg,"--min-lat=", 10) == 0 ) {
+             min_lat = atof( &arg[10] );
+          } else if( strncmp(arg,"--max-lat=", 10) == 0 ) {
+             max_lat = atof( &arg[10] );
+          } else {
+             printf( "ERROR: Unknown argument [%s]. Use -h for help.\n", arg );
+             exit(1);
+          }
+          last_arg = i + 1;
+       } else
+          break;
     }
 
+    if ( (argc - last_arg) != 2 ) {
+       give_help( argv[0] );
+       exit(1);
+    }
+    if(( min_lat != BAD_LATLON )&&
+       (( min_lat < -90.0 )||( min_lat > 90.0 ))) {
+          printf( "ERROR: Bad min-lat [%f]!\n", min_lat );
+          exit(1);
+    }
+    if(( max_lat != BAD_LATLON )&&
+       (( max_lat < -90.0 )||( max_lat > 90.0 ))) {
+          printf( "ERROR: Bad max-lat [%f]!\n", max_lat );
+          exit(1);
+    }
+    if(( min_lon != BAD_LATLON )&&
+       (( min_lon < -180.0 )||( min_lon > 180.0 ))) {
+          printf( "ERROR: Bad min-lon [%f]!\n", min_lon );
+          exit(1);
+    }
+    if(( max_lon != BAD_LATLON )&&
+       (( max_lon < -180.0 )||( max_lon > 180.0 ))) {
+          printf( "ERROR: Bad max-lon [%f]!\n", max_lon );
+          exit(1);
+    }
+    if(( min_lat != BAD_LATLON )&&
+       ( max_lat != BAD_LATLON )&&
+       ( min_lat > max_lat ))
+    {
+       printf( "ERROR: Bad min-lat [%f] NOT less than max-lat [%f]!\n", min_lat, max_lat );
+       exit(1);
+    }
+    if(( min_lon != BAD_LATLON )&&
+       ( max_lon != BAD_LATLON )&&
+       ( min_lon > max_lon ))
+    {
+       printf( "ERROR: Bad min-lon [%f] NOT less than max-lon [%f]!\n", min_lon, max_lon );
+       exit(1);
+    }
+
+    if(( min_lat != BAD_LATLON )||
+       ( max_lat != BAD_LATLON )||
+       ( min_lon != BAD_LATLON )||
+       ( max_lon != BAD_LATLON ))
+    {
+      printf( "Limited to " );
+      if( min_lat != BAD_LATLON )
+         printf( "min lat [%f] ", min_lat );
+      if( max_lat != BAD_LATLON )
+         printf( "max lat [%f] ", max_lat );
+      if( min_lon != BAD_LATLON )
+         printf( "min lon [%f] ", min_lon );
+      if( max_lon != BAD_LATLON )
+         printf( "max lon [%f] ", max_lon );
+      printf( "\n" );
+    }
+
+    /* set any mins and max */
+    raw.min_lat = min_lat;
+    raw.min_lon = min_lon;
+    raw.max_lat = max_lat;
+    raw.max_lon = max_lon;
+
     /* get basename */
-    strcpy(basename, argv[1]);
+    strcpy(basename, argv[last_arg]);
 
     /* get output dir */
-    strcpy(output_dir, argv[2]);
-
+    strcpy(output_dir, argv[last_arg+1]);
+    if ( is_file_or_directory( output_dir ) != 1 ) {
+       printf( "ERROR: Ouput directory [%s], does not exist!\n", output_dir );
+       exit(1);
+    }
     /* generate header file name */
     strcpy(hdr_file, basename);
     strcat(hdr_file, ".HDR");
@@ -106,7 +226,7 @@
     printf("Latitude ranges from %d to %d\n", start_lat, end_lat);
 
     for ( i = start_lat + 1; i <= end_lat; i++ ) {
-       rawProcessStrip(&raw, i, output_dir);
+      rawProcessStrip(&raw, i, output_dir);
     }
 
     /* close the raw data file */

top

src\Prep\DemRaw2ascii\rawdem.c

(a) remove line endings from input
(b) show more information about the decode in progress
(c) check for limits given, and avoid writing the file if outside, with message

--- C:\FGCVS\terragear-cs\src\Prep\DemRaw2ascii\rawdem.c        Thu Feb 19 12:01:40 2009
+++ C:\FG\27\terragear-cs\src\Prep\DemRaw2ascii\rawdem.c        Wed Feb 25 15:19:26 2009
@@ -100,7 +100,12 @@
     /* process each line */
     while ( (reads(fileno(hdr), line, 256) != 0) ) {
 
-       printf("%s", line);
+       len = strlen(line);
+   while(len && ((line[len - 1] == '\n')||(line[len - 1] == '\r'))) {
+      len--;
+      line[len] = 0; // kill EOL characters
+   }
+       printf("%s ", line);
        len = strlen(line);
 
        /* extract key */
@@ -128,13 +133,17 @@
        if ( strcmp(key, "BYTEORDER") == 0 ) {
            if ( strcmp( value, "M" ) == 0 ) {
                raw->big_endian = 1;
+      printf( "- set big_endian\n" );
            } else {
+      printf( "- unset big_endian (not 'M'!)\n" );
                raw->big_endian = 0;
            }
        } else if ( strcmp(key, "NROWS") == 0 ) {
            raw->nrows = atoi(value);
+       printf( "- set rows to %d\n", raw->nrows );
        } else if ( strcmp(key, "NCOLS") == 0 ) {
            raw->ncols = atoi(value);
+       printf( "- set cols to %d\n", raw->ncols );
        } else if ( strcmp(key, "ULXMAP") == 0 ) {
            tmp = atof(value);
 #ifdef HAVE_RINT
@@ -142,6 +151,8 @@
 #else
            raw->ulxmap = (int)round(tmp * 3600.0); /* convert to arcsec */
 #endif
+       printf( "- set ulxmap to %d arcsecs (%d degrees)\n", raw->ulxmap,
+          raw->ulxmap / 3600);
        } else if ( strcmp(key, "ULYMAP") == 0 ) {
            tmp = atof(value);
 #ifdef HAVE_RINT
@@ -149,6 +160,8 @@
 #else
            raw->ulymap = (int)round(tmp * 3600.0); /* convert to arcsec */
 #endif
+       printf( "- set ulymap to %d arcsecs (%d degrees)\n", raw->ulymap,
+          raw->ulymap / 3600);
        } else if ( strcmp(key, "XDIM") == 0 ) {
            tmp = atof(value);
 #ifdef HAVE_RINT
@@ -156,6 +169,8 @@
 #else
            raw->xdim = (int)round(tmp * 3600.0);   /* convert to arcsec */
 #endif
+       printf( "- set xdim to %d arcsecs (%f degrees)\n", raw->xdim,
+          (double)raw->xdim / 3600.0);
        } else if ( strcmp(key, "YDIM") == 0 ) {
            tmp = atof(value);
 #ifdef HAVE_RINT
@@ -163,8 +178,10 @@
 #else
            raw->ydim = (int)round(tmp * 3600.0);   /* convert to arcsec */
 #endif
+       printf( "- set ydim to %d arcsecs (%f degrees)\n", raw->ydim,
+          (double)raw->ydim / 3600.0);
        } else {
-           /* ignore for now */
+           printf( "- ignore for now\n" );
        }
     }
 
@@ -331,6 +348,16 @@
 
     sprintf(outfile, "%s/%c%03d%c%02d.dem", path, lon_sign, lon, lat_sign, lat);
 
+   if((( raw->min_lat != BAD_LATLON )&&((double)ilat < raw->min_lat ))||
+      (( raw->max_lat != BAD_LATLON)&&( (double)ilat > raw->max_lat ))||
+      (( raw->min_lon != BAD_LATLON)&&( (double)ilon < raw->min_lon ))||
+      (( raw->max_lon != BAD_LATLON)&&( (double)ilon > raw->max_lon )))
+   {
+       printf("outfile = %s not written. Outside range\n", outfile);
+       return;
+   }
+
+
     printf("outfile = %s\n", outfile);
 
     if ( (fd = fopen(outfile, "w")) == NULL ) {
@@ -468,7 +495,7 @@
     /* convert to arcsec */
     lat = lat_degrees * 3600;
 
-    printf("Max Latitude = %d arcsec\n", lat);
+    printf("Max Latitude = %d arcsec (%f degs)\n", lat, lat_degrees);
 
     /* validity check ... */
     if ( (lat > raw->rooty) || 

top

src\Prep\DemRaw2ascii\rawdem.h

add min, max, lat, lon limits to structure

--- C:\FGCVS\terragear-cs\src\Prep\DemRaw2ascii\rawdem.h        Thu Feb 19 12:01:40 2009
+++ C:\FG\27\terragear-cs\src\Prep\DemRaw2ascii\rawdem.h        Wed Feb 25 15:20:29 2009
@@ -29,6 +29,7 @@
 #define MAX_ROWS 6000
 #define MAX_COLS 7200
 #define MAX_COLS_X_2 14400
+#define BAD_LATLON  12345.0
 
 typedef struct {
     /* header info */
@@ -44,6 +45,8 @@
     int tmp_min;     /* current 1x1 degree tile minimum */
     int tmp_max;     /* current 1x1 degree tile maximum */
     
+    double min_lat, max_lat, min_lon, max_lon; /* some limits, if any */
+
     /* file ptr */
     int fd;          /* Raw DEM file descriptor */
 

top

src\Prep\MergerClipper\merger.cxx

add using std::endl

--- C:\FGCVS\terragear-cs\src\Prep\MergerClipper\merger.cxx     Thu Feb 19 12:01:40 2009
+++ C:\FG\27\terragear-cs\src\Prep\MergerClipper\merger.cxx     Wed Feb 25 14:34:16 2009
@@ -40,6 +40,7 @@
 #include "merger.hxx"
 
 using std::cout;
+using std::endl;
 
 // Constructor
 FGMerger::FGMerger( void ) {

top

src\Prep\MergerClipper\merger.hxx

add include of Clipper/priorities,hxx

--- C:\FGCVS\terragear-cs\src\Prep\MergerClipper\merger.hxx     Thu Feb 19 12:01:40 2009
+++ C:\FG\27\terragear-cs\src\Prep\MergerClipper\merger.hxx     Wed Feb 25 14:34:16 2009
@@ -36,6 +36,7 @@
 
 #include <Polygon/polygon.hxx>
 #include <Polygon/names.hxx>
+#include <Clipper/priorities.hxx>
 
 #include <string>
 

top

src\Prep\MergerClipper\testmerger.cxx

(a) under _MSC_VER, add sys/types.h and sys/stat.h to provided directory check
(b) fix a call to bucket get_width() on the correct variable

--- C:\FGCVS\terragear-cs\src\Prep\MergerClipper\testmerger.cxx Thu Feb 19 12:01:40 2009
+++ C:\FG\27\terragear-cs\src\Prep\MergerClipper\testmerger.cxx Wed Feb 25 14:48:15 2009
@@ -27,7 +27,12 @@
 #endif
 #include <simgear/debug/logstream.hxx>
 #include <simgear/bucket/newbucket.hxx>
+#ifdef _MSC_VER
+#include <sys/types.h>
+#include <sys/stat.h>
+#else
 #include <dirent.h>
+#endif
 
 #include <Polygon/point2d.hxx>
 
@@ -57,12 +62,21 @@
   string base_name;
   // process all specified polygon files
   string cur_dir=argv[0];
+#ifdef _MSC_VER
+   struct stat buf;
+   if(( stat( cur_dir.c_str(), &buf ) )||
+      !( buf.st_mode & _S_IFDIR )) {
+      cout << "cannot open directory " << cur_dir << "\n";
+      return 0;
+   }
+#else
   DIR *d;
   // struct dirent *de;
   if ( (d = opendir( cur_dir.c_str() )) == NULL ) {
         cout << "cannot open directory " << cur_dir << "\n";
         return 0;
   }
+#endif
 
   //  string file;
   //vector<char> files;
@@ -97,7 +111,7 @@
     
     c.x = b.get_center_lon();
     c.y = b.get_center_lat();
-    double span = c.get_width();
+    double span = b.get_width();
     
     if ( (c.y >= -89.0) && (c.y < 89.0) ) {
       min.x = c.x - span / 2.0;

top

src\Prep\Terra\terra.cc

add 'int' return to main function

--- C:\FGCVS\terragear-cs\src\Prep\Terra\terra.cc       Thu Feb 19 12:01:42 2009
+++ C:\FG\27\terragear-cs\src\Prep\Terra\terra.cc       Wed Feb 25 14:45:20 2009
@@ -1,5 +1,6 @@
 #include "terra.h"
 
+int
 main(int argc, char **argv)
 {
     Terra::process_cmdline(argc, argv);

top

As can be seen, most are minor but essential to compile TerraGear in native WIN32, using MSVC. There are some additional 'help' outputs, and specifically in 'raw2ascii', the ability to limit the area of output rather than blindly processing the whole DEM, generating sometimes thousands of files.

But two VERY essential 'fixes' to raw2ascii are :-
(a) to set the exponent output of things like fprintf() to two(2), otherwise errant ASCII DEM files will be generated. It will generate 000, instead of 00, which cause an errant alignment of the ASCII DEM file;
(b) the very large fgRAWDEM structure, and perhaps other things MUST be moved OFF the local stack, or else 'raw2ascii' will NOT run. Maybe it is possible to force an allocation of a LARGER local stack, but it also seems better to place such BIG items into the 'static' data, which, in native win32, is dynamically allocated by the EXE loader. Obviously unix/linux starts with a much larger 'local' application stack.
Back to src\Prep\DemRaw2ascii\main.c

I have already applied a slightly earlier version of these patches to my Ubuntu source, and made some corrections so it would also compiled there without problems. It is good to have this dual boot, so I can ensure any patches for win32 do not 'break' the unix make. As stated,
- all the 'new' items are in tg-msvc-01.zip, and
- the full 'patch' is in tg-diff-01.txt, or tg-diff-01.patch - same thing in unix format,
for easy quick downloading.

I hope all these make it into the repository soon so other native win32 developers can easily build this great set of tools for build world scenery ;=)) And while these directly apply to the 'git' repository, they are also applicable to the TerraGear CVS repository!

Enjoy!

Geoff R. McLane
20080302
Back to terragear build

EOP - fgfs-050a.htm

checked by tidy  Valid HTML 4.01 Transitional