Compare commits
53
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b129b289c | ||
|
|
a89ceb96b9 | ||
|
|
9af5f9f094 | ||
|
|
6776c2e536 | ||
|
|
4c3b4219fe | ||
|
|
a09806bb98 | ||
|
|
e175c8cc4d | ||
|
|
a53faf4565 | ||
|
|
dc653ac46c | ||
|
|
c544777d37 | ||
|
|
93a37df90a | ||
|
|
1da02cca4c | ||
|
|
4b1d777ad4 | ||
|
|
fb0916be0f | ||
|
|
806083cb25 | ||
|
|
5ba74e30b8 | ||
|
|
c39e08cb2a | ||
|
|
e4653be9a1 | ||
|
|
cd5765be1e | ||
|
|
c481b06451 | ||
|
|
91ba4618e7 | ||
|
|
fdc5521389 | ||
|
|
e88c915206 | ||
|
|
1e60698053 | ||
|
|
5702bd7ee8 | ||
|
|
8eef3eb582 | ||
|
|
31db353173 | ||
|
|
2c4a0dd998 | ||
|
|
7d7e41dacc | ||
|
|
453a53b372 | ||
|
|
ef68d18f64 | ||
|
|
ded1d2343f | ||
|
|
e6241a2f73 | ||
|
|
467254ec66 | ||
|
|
135e137921 | ||
|
|
e13a5b57d4 | ||
|
|
f1c00cdd18 | ||
|
|
8c3de351b0 | ||
|
|
0bcdb7eb70 | ||
|
|
a92b71fffc | ||
|
|
89960ab715 | ||
|
|
2a369803ae | ||
|
|
b0134a377e | ||
|
|
502c650cd9 | ||
|
|
a1bf8d2229 | ||
|
|
25b743bdec | ||
|
|
dbf7db02a2 | ||
|
|
8c998659c6 | ||
|
|
4e23b3dff5 | ||
|
|
159d3c4c6c | ||
|
|
612b5ae0bc | ||
|
|
60cbe9c1d4 | ||
|
|
4dadd29727 |
@@ -1,3 +1,34 @@
|
||||
New in 0.0.14
|
||||
* Added a module to manage waypoints and routes, calculate bearing and
|
||||
distance to next waypoint, lateral distance off route, etc.
|
||||
* Moved some of the basic time management code over from flightgear.
|
||||
* Bucket dimensions can be returned in meters
|
||||
* Added SOCK_STREAM (TCP) socket support to the networking code.
|
||||
* Updated random number generator interface so application can provide
|
||||
it's own seed value as well as use the default time seed.
|
||||
* Added a routine to calculate the distance between a point and a line segment.
|
||||
* Updates to the property manager and the property list loader/saver.
|
||||
* Added an explanation of the rational behind our terrain texture coordinate
|
||||
generation code.
|
||||
* Fixed sky dome so that the color at the horizon will always match
|
||||
the specified fog color.
|
||||
* Did a fair amount of fg -> sg name space updating (lots left to do.)
|
||||
* December 14, 2000
|
||||
* Added support for KAI C++ on linux.
|
||||
* MSVC tweaks.
|
||||
* MacOS tweaks.
|
||||
* FreeBSD tweaks.
|
||||
|
||||
New in 0.0.13
|
||||
* September 14, 2000
|
||||
* Added support for reading and writing xml files (easyxml)
|
||||
* Then updates to property manager and xml code.
|
||||
* Update magnetic variation code.
|
||||
* Sky code now uses glPushAttrib and glPopAttrib so it plays better with
|
||||
other ssg based apps.
|
||||
* MacOS tweaks.
|
||||
* MSVC tweaks.
|
||||
|
||||
New in 0.0.12
|
||||
* July 19, 2000
|
||||
* Converted project license from GPL to LGPL.
|
||||
|
||||
@@ -392,3 +392,24 @@ if test "$have_timezone" = no; then
|
||||
AC_MSG_RESULT(no))
|
||||
fi
|
||||
])dnl
|
||||
|
||||
## AC_BZ_SET_COMPILER: Addition by Theodore Papadopoulo
|
||||
## Patch by Jim McKelvey: change sed -e 's/ /@/g' to sed -e 's/ /@/'
|
||||
AC_DEFUN(AC_SG_SET_COMPILER,
|
||||
[cxxwith=`echo $1 | sed -e 's/ /@/'`
|
||||
case "$cxxwith" in
|
||||
*:*@*) # Full initialization syntax
|
||||
CXX=`echo "$cxxwith" | sed -n -e 's/.*:\(.*\)@.*/\1/p'`
|
||||
CXXFLAGS=`echo "$cxxwith" | sed -n -e 's/.*:.*@\(.*\)/\1/p'`
|
||||
;;
|
||||
*:*) # Simple initialization syntax
|
||||
CXX=`echo "$cxxwith" | sed -n -e 's/.*:\(.*\)/\1/p'`
|
||||
CXXFLAGS=$3
|
||||
;;
|
||||
*) # Default values
|
||||
CXX=$2
|
||||
CXXFLAGS=$3
|
||||
CC="$2 --c"
|
||||
## CFLAGS=
|
||||
;;
|
||||
esac])
|
||||
|
||||
+21
-1
@@ -6,7 +6,24 @@ dnl $Id$
|
||||
AC_INIT(simgear/bucket/newbucket.cxx)
|
||||
|
||||
dnl Initialize the automake stuff
|
||||
AM_INIT_AUTOMAKE(SimGear, 0.0.12)
|
||||
AM_INIT_AUTOMAKE(SimGear, 0.0.14)
|
||||
|
||||
dnl Specify KAI C++ compiler and flags.
|
||||
dnl Borrowed with slight modification from blitz distribution.
|
||||
AC_ARG_WITH(cxx,
|
||||
[ --with-cxx=COMPILER[:name-flags] set options for COMPILER (KCC)],
|
||||
[case "$withval" in
|
||||
KCC*) # KAI C++ http://www.kai.com/
|
||||
echo "Configuring for KAI C++"
|
||||
AC_SG_SET_COMPILER($withval,"KCC","--restrict --strict_warnings")
|
||||
CXX_OPTIMIZE_FLAGS=="+K3 -O3"
|
||||
CXX_DEBUG_FLAGS="-g +K0"
|
||||
;;
|
||||
esac
|
||||
])
|
||||
|
||||
echo CXX = $CXX
|
||||
echo CC = $CC
|
||||
|
||||
dnl Checks for programs.
|
||||
AC_PROG_MAKE_SET
|
||||
@@ -251,17 +268,20 @@ AC_OUTPUT( \
|
||||
simgear/Makefile \
|
||||
simgear/version.h \
|
||||
simgear/bucket/Makefile \
|
||||
simgear/camera/Makefile \
|
||||
simgear/debug/Makefile \
|
||||
simgear/ephemeris/Makefile \
|
||||
simgear/io/Makefile \
|
||||
simgear/magvar/Makefile \
|
||||
simgear/math/Makefile \
|
||||
simgear/misc/Makefile \
|
||||
simgear/route/Makefile \
|
||||
simgear/screen/Makefile \
|
||||
simgear/serial/Makefile \
|
||||
simgear/sky/Makefile \
|
||||
simgear/timing/Makefile \
|
||||
simgear/xgl/Makefile \
|
||||
simgear/xml/Makefile \
|
||||
simgear/zlib/Makefile \
|
||||
)
|
||||
|
||||
|
||||
@@ -33,10 +33,12 @@ SUBDIRS = \
|
||||
math \
|
||||
$(METAR_DIRS) \
|
||||
misc \
|
||||
route \
|
||||
screen \
|
||||
$(SERIAL_DIRS) \
|
||||
sky \
|
||||
timing \
|
||||
xgl \
|
||||
xml \
|
||||
$(ZLIB_DIRS)
|
||||
|
||||
|
||||
@@ -14,4 +14,4 @@ libsgbucket_a_SOURCES = newbucket.cxx
|
||||
# $(top_builddir)/bucket/libsgbucket.a \
|
||||
# $(top_builddir)/misc/libsgmisc.a
|
||||
|
||||
INCLUDES += -I$(top_builddir)
|
||||
INCLUDES += -I$(top_srcdir)
|
||||
|
||||
+152
-12
@@ -36,8 +36,109 @@
|
||||
#include "newbucket.hxx"
|
||||
|
||||
|
||||
// default constructor
|
||||
SGBucket::SGBucket() {
|
||||
}
|
||||
|
||||
|
||||
// constructor for specified location
|
||||
SGBucket::SGBucket(const double dlon, const double dlat) {
|
||||
set_bucket(dlon, dlat);
|
||||
}
|
||||
|
||||
|
||||
// create an impossible bucket if false
|
||||
SGBucket::SGBucket(const bool is_good) {
|
||||
set_bucket(0.0, 0.0);
|
||||
if ( !is_good ) {
|
||||
lon = -1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Parse a unique scenery tile index and find the lon, lat, x, and y
|
||||
SGBucket::SGBucket(const long int bindex) {
|
||||
long int index = bindex;
|
||||
|
||||
lon = index >> 14;
|
||||
index -= lon << 14;
|
||||
lon -= 180;
|
||||
|
||||
lat = index >> 6;
|
||||
index -= lat << 6;
|
||||
lat -= 90;
|
||||
|
||||
y = index >> 3;
|
||||
index -= y << 3;
|
||||
|
||||
x = index;
|
||||
}
|
||||
|
||||
|
||||
// default destructor
|
||||
SGBucket::~SGBucket() {
|
||||
}
|
||||
|
||||
|
||||
// Set the bucket params for the specified lat and lon
|
||||
void SGBucket::set_bucket( double *lonlat ) {
|
||||
set_bucket( lonlat[0], lonlat[1] );
|
||||
}
|
||||
|
||||
|
||||
// Set the bucket params for the specified lat and lon
|
||||
void SGBucket::set_bucket( double dlon, double dlat ) {
|
||||
//
|
||||
// latitude first
|
||||
//
|
||||
double span = sg_bucket_span( dlat );
|
||||
double diff = dlon - (double)(int)dlon;
|
||||
|
||||
// cout << "diff = " << diff << " span = " << span << endl;
|
||||
|
||||
if ( (dlon >= 0) || (fabs(diff) < FG_EPSILON) ) {
|
||||
lon = (int)dlon;
|
||||
} else {
|
||||
lon = (int)dlon - 1;
|
||||
}
|
||||
|
||||
// find subdivision or super lon if needed
|
||||
if ( span < FG_EPSILON ) {
|
||||
// polar cap
|
||||
lon = 0;
|
||||
x = 0;
|
||||
} else if ( span <= 1.0 ) {
|
||||
x = (int)((dlon - lon) / span);
|
||||
} else {
|
||||
if ( (dlon >= 0) || (fabs(diff) < FG_EPSILON) ) {
|
||||
lon = (int)( (int)(lon / span) * span);
|
||||
} else {
|
||||
// cout << " lon = " << lon
|
||||
// << " tmp = " << (int)((lon-1) / span) << endl;
|
||||
lon = (int)( (int)((lon + 1) / span) * span - span);
|
||||
if ( lon < -180 ) {
|
||||
lon = -180;
|
||||
}
|
||||
}
|
||||
x = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// then latitude
|
||||
//
|
||||
diff = dlat - (double)(int)dlat;
|
||||
|
||||
if ( (dlat >= 0) || (fabs(diff) < FG_EPSILON) ) {
|
||||
lat = (int)dlat;
|
||||
} else {
|
||||
lat = (int)dlat - 1;
|
||||
}
|
||||
y = (int)((dlat - lat) * 8);
|
||||
}
|
||||
|
||||
|
||||
// Build the path name for this bucket
|
||||
string FGBucket::gen_base_path() const {
|
||||
string SGBucket::gen_base_path() const {
|
||||
// long int index;
|
||||
int top_lon, top_lat, main_lon, main_lat;
|
||||
char hem, pole;
|
||||
@@ -85,19 +186,58 @@ string FGBucket::gen_base_path() const {
|
||||
}
|
||||
|
||||
|
||||
// return width of the tile in degrees
|
||||
double SGBucket::get_width() const {
|
||||
return sg_bucket_span( get_center_lat() );
|
||||
}
|
||||
|
||||
|
||||
// return height of the tile in degrees
|
||||
double SGBucket::get_height() const {
|
||||
return SG_BUCKET_SPAN;
|
||||
}
|
||||
|
||||
|
||||
// return width of the tile in meters
|
||||
double SGBucket::get_width_m() const {
|
||||
double clat = (int)get_center_lat();
|
||||
if ( clat > 0 ) {
|
||||
clat = (int)clat + 0.5;
|
||||
} else {
|
||||
clat = (int)clat - 0.5;
|
||||
}
|
||||
double clat_rad = clat * DEG_TO_RAD;
|
||||
double cos_lat = cos( clat_rad );
|
||||
double local_radius = cos_lat * EQUATORIAL_RADIUS_M;
|
||||
double local_perimeter = 2.0 * local_radius * FG_PI;
|
||||
double degree_width = local_perimeter / 360.0;
|
||||
|
||||
return sg_bucket_span( get_center_lat() ) * degree_width;
|
||||
}
|
||||
|
||||
|
||||
// return height of the tile in meters
|
||||
double SGBucket::get_height_m() const {
|
||||
double perimeter = 2.0 * EQUATORIAL_RADIUS_M * FG_PI;
|
||||
double degree_height = perimeter / 360.0;
|
||||
|
||||
return SG_BUCKET_SPAN * degree_height;
|
||||
}
|
||||
|
||||
|
||||
// find the bucket which is offset by the specified tile units in the
|
||||
// X & Y direction. We need the current lon and lat to resolve
|
||||
// ambiguities when going from a wider tile to a narrower one above or
|
||||
// below. This assumes that we are feeding in
|
||||
FGBucket fgBucketOffset( double dlon, double dlat, int dx, int dy ) {
|
||||
FGBucket result( dlon, dlat );
|
||||
double clat = result.get_center_lat() + dy * FG_BUCKET_SPAN;
|
||||
SGBucket sgBucketOffset( double dlon, double dlat, int dx, int dy ) {
|
||||
SGBucket result( dlon, dlat );
|
||||
double clat = result.get_center_lat() + dy * SG_BUCKET_SPAN;
|
||||
|
||||
// walk dy units in the lat direction
|
||||
result.set_bucket( dlon, clat );
|
||||
|
||||
// find the lon span for the new latitude
|
||||
double span = bucket_span( clat );
|
||||
double span = sg_bucket_span( clat );
|
||||
|
||||
// walk dx units in the lon direction
|
||||
double tmp = dlon + dx * span;
|
||||
@@ -114,7 +254,7 @@ FGBucket fgBucketOffset( double dlon, double dlat, int dx, int dy ) {
|
||||
|
||||
|
||||
// calculate the offset between two buckets
|
||||
void fgBucketDiff( const FGBucket& b1, const FGBucket& b2, int *dx, int *dy ) {
|
||||
void sgBucketDiff( const SGBucket& b1, const SGBucket& b2, int *dx, int *dy ) {
|
||||
|
||||
// Latitude difference
|
||||
double c1_lat = b1.get_center_lat();
|
||||
@@ -122,12 +262,12 @@ void fgBucketDiff( const FGBucket& b1, const FGBucket& b2, int *dx, int *dy ) {
|
||||
double diff_lat = c2_lat - c1_lat;
|
||||
|
||||
#ifdef HAVE_RINT
|
||||
*dy = (int)rint( diff_lat / FG_BUCKET_SPAN );
|
||||
*dy = (int)rint( diff_lat / SG_BUCKET_SPAN );
|
||||
#else
|
||||
if ( diff_lat > 0 ) {
|
||||
*dy = (int)( diff_lat / FG_BUCKET_SPAN + 0.5 );
|
||||
*dy = (int)( diff_lat / SG_BUCKET_SPAN + 0.5 );
|
||||
} else {
|
||||
*dy = (int)( diff_lat / FG_BUCKET_SPAN - 0.5 );
|
||||
*dy = (int)( diff_lat / SG_BUCKET_SPAN - 0.5 );
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -136,10 +276,10 @@ void fgBucketDiff( const FGBucket& b1, const FGBucket& b2, int *dx, int *dy ) {
|
||||
double c2_lon = b2.get_center_lon();
|
||||
double diff_lon = c2_lon - c1_lon;
|
||||
double span;
|
||||
if ( bucket_span(c1_lat) <= bucket_span(c2_lat) ) {
|
||||
span = bucket_span(c1_lat);
|
||||
if ( sg_bucket_span(c1_lat) <= sg_bucket_span(c2_lat) ) {
|
||||
span = sg_bucket_span(c1_lat);
|
||||
} else {
|
||||
span = bucket_span(c2_lat);
|
||||
span = sg_bucket_span(c2_lat);
|
||||
}
|
||||
|
||||
#ifdef HAVE_RINT
|
||||
|
||||
+99
-215
@@ -44,7 +44,8 @@
|
||||
// already depending on how you defined FG_HAVE_STD_INCLUDES, but I
|
||||
// can go ahead and add this -- CLO
|
||||
#ifdef __MWERKS__
|
||||
# include <math.h> // needed fabs()
|
||||
FG_USING_STD(sprintf);
|
||||
FG_USING_STD(fabs);
|
||||
#endif
|
||||
|
||||
#include STL_STRING
|
||||
@@ -57,79 +58,16 @@ FG_USING_STD(ostream);
|
||||
|
||||
|
||||
|
||||
#define FG_BUCKET_SPAN 0.125 // 1/8 of a degree
|
||||
#define FG_HALF_BUCKET_SPAN 0.0625 // 1/2 of 1/8 of a degree = 1/16 = 0.0625
|
||||
#define SG_BUCKET_SPAN 0.125 // 1/8 of a degree
|
||||
#define SG_HALF_BUCKET_SPAN 0.0625 // 1/2 of 1/8 of a degree = 1/16 = 0.0625
|
||||
|
||||
class FGBucket;
|
||||
ostream& operator<< ( ostream&, const FGBucket& );
|
||||
bool operator== ( const FGBucket&, const FGBucket& );
|
||||
|
||||
class FGBucket {
|
||||
|
||||
private:
|
||||
double cx, cy; // centerpoint (lon, lat) in degrees of bucket
|
||||
int lon; // longitude index (-180 to 179)
|
||||
int lat; // latitude index (-90 to 89)
|
||||
int x; // x subdivision (0 to 7)
|
||||
int y; // y subdivision (0 to 7)
|
||||
|
||||
public:
|
||||
|
||||
// default constructor
|
||||
FGBucket();
|
||||
|
||||
// create a bucket which would contain the specified lon/lat
|
||||
FGBucket(const double lon, const double lat);
|
||||
|
||||
// create a bucket based on "long int" index
|
||||
FGBucket(const long int bindex);
|
||||
|
||||
// create an impossible bucket if false
|
||||
FGBucket(const bool is_good);
|
||||
|
||||
~FGBucket();
|
||||
|
||||
// Set the bucket params for the specified lat and lon
|
||||
void set_bucket( double dlon, double dlat );
|
||||
void set_bucket( double *lonlat ) {
|
||||
set_bucket( lonlat[0], lonlat[1] );
|
||||
}
|
||||
|
||||
void make_bad ( void );
|
||||
|
||||
// Generate the unique scenery tile index for this bucket
|
||||
long int gen_index();
|
||||
string gen_index_str() const;
|
||||
|
||||
// Build the path name for this bucket
|
||||
string gen_base_path() const;
|
||||
|
||||
// return the center lon of a tile
|
||||
double get_center_lon() const;
|
||||
|
||||
// return width of the tile
|
||||
double get_width() const;
|
||||
|
||||
// return the center lat of a tile
|
||||
double get_center_lat() const;
|
||||
|
||||
// return height of the tile
|
||||
double get_height() const;
|
||||
|
||||
// Informational methods
|
||||
inline int get_lon() const { return lon; }
|
||||
inline int get_lat() const { return lat; }
|
||||
inline int get_x() const { return x; }
|
||||
inline int get_y() const { return y; }
|
||||
|
||||
// friends
|
||||
friend ostream& operator<< ( ostream&, const FGBucket& );
|
||||
friend bool operator== ( const FGBucket&, const FGBucket& );
|
||||
};
|
||||
class SGBucket;
|
||||
ostream& operator<< ( ostream&, const SGBucket& );
|
||||
bool operator== ( const SGBucket&, const SGBucket& );
|
||||
|
||||
|
||||
// return the horizontal tile span factor based on latitude
|
||||
inline double bucket_span( double l ) {
|
||||
inline double sg_bucket_span( double l ) {
|
||||
if ( l >= 89.0 ) {
|
||||
return 360.0;
|
||||
} else if ( l >= 88.0 ) {
|
||||
@@ -164,179 +102,125 @@ inline double bucket_span( double l ) {
|
||||
}
|
||||
|
||||
|
||||
// Set the bucket params for the specified lat and lon
|
||||
inline void FGBucket::set_bucket( double dlon, double dlat ) {
|
||||
//
|
||||
// latitude first
|
||||
//
|
||||
double span = bucket_span( dlat );
|
||||
double diff = dlon - (double)(int)dlon;
|
||||
class SGBucket {
|
||||
|
||||
// cout << "diff = " << diff << " span = " << span << endl;
|
||||
private:
|
||||
double cx, cy; // centerpoint (lon, lat) in degrees of bucket
|
||||
int lon; // longitude index (-180 to 179)
|
||||
int lat; // latitude index (-90 to 89)
|
||||
int x; // x subdivision (0 to 7)
|
||||
int y; // y subdivision (0 to 7)
|
||||
|
||||
if ( (dlon >= 0) || (fabs(diff) < FG_EPSILON) ) {
|
||||
lon = (int)dlon;
|
||||
} else {
|
||||
lon = (int)dlon - 1;
|
||||
}
|
||||
public:
|
||||
|
||||
// find subdivision or super lon if needed
|
||||
if ( span < FG_EPSILON ) {
|
||||
// polar cap
|
||||
lon = 0;
|
||||
x = 0;
|
||||
} else if ( span <= 1.0 ) {
|
||||
x = (int)((dlon - lon) / span);
|
||||
} else {
|
||||
if ( (dlon >= 0) || (fabs(diff) < FG_EPSILON) ) {
|
||||
lon = (int)( (int)(lon / span) * span);
|
||||
} else {
|
||||
// cout << " lon = " << lon
|
||||
// << " tmp = " << (int)((lon-1) / span) << endl;
|
||||
lon = (int)( (int)((lon + 1) / span) * span - span);
|
||||
if ( lon < -180 ) {
|
||||
lon = -180;
|
||||
}
|
||||
}
|
||||
x = 0;
|
||||
}
|
||||
// default constructor
|
||||
SGBucket();
|
||||
|
||||
//
|
||||
// then latitude
|
||||
//
|
||||
diff = dlat - (double)(int)dlat;
|
||||
// constructor for specified location
|
||||
SGBucket(const double dlon, const double dlat);
|
||||
|
||||
if ( (dlat >= 0) || (fabs(diff) < FG_EPSILON) ) {
|
||||
lat = (int)dlat;
|
||||
} else {
|
||||
lat = (int)dlat - 1;
|
||||
}
|
||||
y = (int)((dlat - lat) * 8);
|
||||
}
|
||||
// create an impossible bucket if false
|
||||
SGBucket(const bool is_good);
|
||||
|
||||
// Parse a unique scenery tile index and find the lon, lat, x, and y
|
||||
SGBucket(const long int bindex);
|
||||
|
||||
// default constructor
|
||||
inline FGBucket::FGBucket() {}
|
||||
// default destructor
|
||||
~SGBucket();
|
||||
|
||||
// Set the bucket params for the specified lat and lon
|
||||
void set_bucket( double dlon, double dlat );
|
||||
void set_bucket( double *lonlat );
|
||||
|
||||
// constructor for specified location
|
||||
inline FGBucket::FGBucket(const double dlon, const double dlat) {
|
||||
set_bucket(dlon, dlat);
|
||||
}
|
||||
|
||||
|
||||
// create an impossible bucket if false
|
||||
inline FGBucket::FGBucket(const bool is_good) {
|
||||
set_bucket(0.0, 0.0);
|
||||
if ( !is_good ) {
|
||||
// create an impossible bucket
|
||||
inline void make_bad( void ) {
|
||||
set_bucket(0.0, 0.0);
|
||||
lon = -1000;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the unique scenery tile index for this bucket
|
||||
//
|
||||
// The index is constructed as follows:
|
||||
//
|
||||
// 9 bits - to represent 360 degrees of longitude (-180 to 179)
|
||||
// 8 bits - to represent 180 degrees of latitude (-90 to 89)
|
||||
//
|
||||
// Each 1 degree by 1 degree tile is further broken down into an 8x8
|
||||
// grid. So we also need:
|
||||
//
|
||||
// 3 bits - to represent x (0 to 7)
|
||||
// 3 bits - to represent y (0 to 7)
|
||||
|
||||
// Parse a unique scenery tile index and find the lon, lat, x, and y
|
||||
inline FGBucket::FGBucket(const long int bindex) {
|
||||
long int index = bindex;
|
||||
|
||||
lon = index >> 14;
|
||||
index -= lon << 14;
|
||||
lon -= 180;
|
||||
|
||||
lat = index >> 6;
|
||||
index -= lat << 6;
|
||||
lat -= 90;
|
||||
|
||||
y = index >> 3;
|
||||
index -= y << 3;
|
||||
|
||||
x = index;
|
||||
}
|
||||
|
||||
|
||||
// default destructor
|
||||
inline FGBucket::~FGBucket() {}
|
||||
|
||||
|
||||
// Generate the unique scenery tile index for this bucket
|
||||
//
|
||||
// The index is constructed as follows:
|
||||
//
|
||||
// 9 bits - to represent 360 degrees of longitude (-180 to 179)
|
||||
// 8 bits - to represent 180 degrees of latitude (-90 to 89)
|
||||
//
|
||||
// Each 1 degree by 1 degree tile is further broken down into an 8x8
|
||||
// grid. So we also need:
|
||||
//
|
||||
// 3 bits - to represent x (0 to 7)
|
||||
// 3 bits - to represent y (0 to 7)
|
||||
|
||||
inline long int FGBucket::gen_index() {
|
||||
return ((lon + 180) << 14) + ((lat + 90) << 6) + (y << 3) + x;
|
||||
}
|
||||
|
||||
inline string FGBucket::gen_index_str() const {
|
||||
char tmp[20];
|
||||
sprintf(tmp, "%ld",
|
||||
(((long)lon + 180) << 14) + ((lat + 90) << 6) + (y << 3) + x);
|
||||
return (string)tmp;
|
||||
}
|
||||
|
||||
|
||||
// return the center lon of a tile
|
||||
inline double FGBucket::get_center_lon() const {
|
||||
double span = bucket_span( lat + y / 8.0 + FG_HALF_BUCKET_SPAN );
|
||||
|
||||
if ( span >= 1.0 ) {
|
||||
return lon + span / 2.0;
|
||||
} else {
|
||||
return lon + x * span + span / 2.0;
|
||||
inline long int gen_index() const {
|
||||
return ((lon + 180) << 14) + ((lat + 90) << 6) + (y << 3) + x;
|
||||
}
|
||||
}
|
||||
|
||||
inline string gen_index_str() const {
|
||||
char tmp[20];
|
||||
sprintf(tmp, "%ld",
|
||||
(((long)lon + 180) << 14) + ((lat + 90) << 6) + (y << 3) + x);
|
||||
return (string)tmp;
|
||||
}
|
||||
|
||||
// Build the path name for this bucket
|
||||
string gen_base_path() const;
|
||||
|
||||
// return the center lon of a tile
|
||||
inline double get_center_lon() const {
|
||||
double span = sg_bucket_span( lat + y / 8.0 + SG_HALF_BUCKET_SPAN );
|
||||
|
||||
if ( span >= 1.0 ) {
|
||||
return lon + span / 2.0;
|
||||
} else {
|
||||
return lon + x * span + span / 2.0;
|
||||
}
|
||||
}
|
||||
|
||||
// return the center lat of a tile
|
||||
inline double get_center_lat() const {
|
||||
return lat + y / 8.0 + SG_HALF_BUCKET_SPAN;
|
||||
}
|
||||
|
||||
// return width of the tile in degrees
|
||||
double get_width() const;
|
||||
// return height of the tile in degrees
|
||||
double get_height() const;
|
||||
|
||||
// return width of the tile in meters
|
||||
double get_width_m() const;
|
||||
// return height of the tile in meters
|
||||
double get_height_m() const;
|
||||
|
||||
// Informational methods
|
||||
inline int get_lon() const { return lon; }
|
||||
inline int get_lat() const { return lat; }
|
||||
inline int get_x() const { return x; }
|
||||
inline int get_y() const { return y; }
|
||||
|
||||
// friends
|
||||
friend ostream& operator<< ( ostream&, const SGBucket& );
|
||||
friend bool operator== ( const SGBucket&, const SGBucket& );
|
||||
};
|
||||
|
||||
|
||||
// return the center lat of a tile
|
||||
inline double FGBucket::get_center_lat() const {
|
||||
return lat + y / 8.0 + FG_HALF_BUCKET_SPAN;
|
||||
}
|
||||
|
||||
|
||||
// return width of the tile
|
||||
inline double FGBucket::get_width() const {
|
||||
return bucket_span( get_center_lat() );
|
||||
}
|
||||
|
||||
|
||||
// return height of the tile
|
||||
inline double FGBucket::get_height() const {
|
||||
return FG_BUCKET_SPAN;
|
||||
}
|
||||
|
||||
|
||||
// create an impossible bucket
|
||||
inline void FGBucket::make_bad( void ) {
|
||||
set_bucket(0.0, 0.0);
|
||||
lon = -1000;
|
||||
}
|
||||
|
||||
|
||||
// offset a bucket struct by the specified tile units in the X & Y
|
||||
// direction
|
||||
FGBucket fgBucketOffset( double dlon, double dlat, int x, int y );
|
||||
// offset a bucket specified by dlon, dlat by the specified tile units
|
||||
// in the X & Y direction
|
||||
SGBucket sgBucketOffset( double dlon, double dlat, int x, int y );
|
||||
|
||||
|
||||
// calculate the offset between two buckets
|
||||
void fgBucketDiff( const FGBucket& b1, const FGBucket& b2, int *dx, int *dy );
|
||||
void sgBucketDiff( const SGBucket& b1, const SGBucket& b2, int *dx, int *dy );
|
||||
|
||||
|
||||
inline ostream&
|
||||
operator<< ( ostream& out, const FGBucket& b )
|
||||
operator<< ( ostream& out, const SGBucket& b )
|
||||
{
|
||||
return out << b.lon << ":" << b.x << ", " << b.lat << ":" << b.y;
|
||||
}
|
||||
|
||||
|
||||
inline bool
|
||||
operator== ( const FGBucket& b1, const FGBucket& b2 )
|
||||
operator== ( const SGBucket& b1, const SGBucket& b2 )
|
||||
{
|
||||
return ( b1.lon == b2.lon &&
|
||||
b1.lat == b2.lat &&
|
||||
|
||||
+20
-1
@@ -94,6 +94,25 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* KAI C++ */
|
||||
#if defined(__KCC)
|
||||
|
||||
# define FG_NAMESPACES
|
||||
# define FG_HAVE_STD
|
||||
# define FG_HAVE_STREAMBUF
|
||||
# define FG_HAVE_TRAITS
|
||||
# define FG_HAVE_STD_INCLUDES
|
||||
|
||||
# define STL_ALGORITHM <algorithm>
|
||||
# define STL_FUNCTIONAL <functional>
|
||||
# define STL_IOMANIP <iomanip>
|
||||
# define STL_IOSTREAM <iostream>
|
||||
# define STL_FSTREAM <fstream>
|
||||
# define STL_STDEXCEPT <stdexcept>
|
||||
# define STL_STRING <string>
|
||||
# define STL_STRSTREAM <strstream>
|
||||
#endif
|
||||
|
||||
//
|
||||
// Metrowerks
|
||||
//
|
||||
@@ -118,7 +137,7 @@
|
||||
# define bcopy(from, to, n) memcpy(to, from, n)
|
||||
|
||||
// -rp- please use FG_MEM_COPY everywhere !
|
||||
# define FG_MEM_COPY(to,from,n) memcpy(to, from, n)
|
||||
// #define FG_MEM_COPY(to,from,n) memcpy(to, from, n)
|
||||
|
||||
// -dw- currently used glut has no game mode stuff
|
||||
# define GLUT_WRONG_VERSION
|
||||
|
||||
+3
-2
@@ -86,13 +86,14 @@
|
||||
#define RESQ_FT 437882827922500. // ft
|
||||
#define RESQ_M 40680645877797.1344 // meter
|
||||
|
||||
#if 0
|
||||
// Value of earth flattening parameter from ref [8]
|
||||
//
|
||||
// Note: FP = f
|
||||
// E = 1-f
|
||||
// EPS = sqrt(1-(1-f)^2)
|
||||
//
|
||||
|
||||
|
||||
#define FP 0.003352813178
|
||||
#define E 0.996647186
|
||||
#define EPS 0.081819221
|
||||
@@ -103,7 +104,7 @@
|
||||
#define MJD0 2415020.0
|
||||
#define J2000 (2451545.0 - MJD0)
|
||||
#define SIDRATE .9972695677
|
||||
|
||||
#endif
|
||||
|
||||
// Conversions
|
||||
|
||||
|
||||
@@ -8,4 +8,4 @@ include_HEADERS = debug_types.h logstream.hxx
|
||||
|
||||
libsgdebug_a_SOURCES = logstream.cxx
|
||||
|
||||
INCLUDES += -I$(top_builddir)
|
||||
INCLUDES += -I$(top_srcdir)
|
||||
|
||||
@@ -49,8 +49,6 @@ FG_USING_STD(endl);
|
||||
#endif
|
||||
|
||||
#ifdef __MWERKS__
|
||||
# define cerr std::cerr
|
||||
# define endl std::endl
|
||||
FG_USING_STD(iostream);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -8,11 +8,11 @@ include_HEADERS = \
|
||||
jupiter.hxx \
|
||||
mars.hxx \
|
||||
mercury.hxx \
|
||||
moon.hxx \
|
||||
moonpos.hxx \
|
||||
neptune.hxx \
|
||||
saturn.hxx \
|
||||
star.hxx \
|
||||
stars.hxx \
|
||||
stardata.hxx \
|
||||
uranus.hxx \
|
||||
venus.hxx
|
||||
|
||||
@@ -22,13 +22,13 @@ libsgephem_a_SOURCES = \
|
||||
jupiter.cxx \
|
||||
mars.cxx \
|
||||
mercury.cxx \
|
||||
moon.cxx \
|
||||
moonpos.cxx \
|
||||
neptune.cxx \
|
||||
pluto.hxx \
|
||||
saturn.cxx \
|
||||
star.cxx \
|
||||
stars.cxx \
|
||||
stardata.cxx \
|
||||
uranus.cxx \
|
||||
venus.cxx
|
||||
|
||||
INCLUDES += -I$(top_builddir)
|
||||
INCLUDES += -I$(top_srcdir)
|
||||
|
||||
@@ -108,7 +108,7 @@ void CelestialBody::updatePosition(double mjd, Star *ourSun)
|
||||
}
|
||||
|
||||
FV = RAD_TO_DEG * acos( tmp );
|
||||
};
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* double CelestialBody::sgCalcEccAnom(double M, double e)
|
||||
|
||||
@@ -121,7 +121,7 @@ inline CelestialBody::CelestialBody(double Nf, double Ns,
|
||||
eFirst = ef; eSec = es;
|
||||
MFirst = Mf; MSec = Ms;
|
||||
updateOrbElements(mjd);
|
||||
};
|
||||
}
|
||||
|
||||
inline CelestialBody::CelestialBody(double Nf, double Ns,
|
||||
double If, double Is,
|
||||
@@ -136,7 +136,7 @@ inline CelestialBody::CelestialBody(double Nf, double Ns,
|
||||
aFirst = af; aSec = as;
|
||||
eFirst = ef; eSec = es;
|
||||
MFirst = Mf; MSec = Ms;
|
||||
};
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* inline void CelestialBody::updateOrbElements(double mjd)
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
// Constructor
|
||||
SGEphemeris::SGEphemeris( const string &path ) {
|
||||
our_sun = new Star;
|
||||
moon = new Moon;
|
||||
moon = new MoonPos;
|
||||
mercury = new Mercury;
|
||||
venus = new Venus;
|
||||
mars = new Mars;
|
||||
|
||||
@@ -36,22 +36,22 @@
|
||||
|
||||
#include <plib/sg.h>
|
||||
|
||||
#include "star.hxx"
|
||||
#include "moon.hxx"
|
||||
#include "mercury.hxx"
|
||||
#include "venus.hxx"
|
||||
#include "mars.hxx"
|
||||
#include "jupiter.hxx"
|
||||
#include "saturn.hxx"
|
||||
#include "uranus.hxx"
|
||||
#include "neptune.hxx"
|
||||
#include "stars.hxx"
|
||||
#include <simgear/ephemeris/star.hxx>
|
||||
#include <simgear/ephemeris/moonpos.hxx>
|
||||
#include <simgear/ephemeris/mercury.hxx>
|
||||
#include <simgear/ephemeris/venus.hxx>
|
||||
#include <simgear/ephemeris/mars.hxx>
|
||||
#include <simgear/ephemeris/jupiter.hxx>
|
||||
#include <simgear/ephemeris/saturn.hxx>
|
||||
#include <simgear/ephemeris/uranus.hxx>
|
||||
#include <simgear/ephemeris/neptune.hxx>
|
||||
#include <simgear/ephemeris/stardata.hxx>
|
||||
|
||||
|
||||
class SGEphemeris {
|
||||
|
||||
Star *our_sun;
|
||||
Moon *moon;
|
||||
MoonPos *moon;
|
||||
Mercury *mercury;
|
||||
Venus *venus;
|
||||
Mars *mars;
|
||||
@@ -91,7 +91,7 @@ public:
|
||||
}
|
||||
|
||||
// moon
|
||||
inline Moon *get_moon() const { return moon; }
|
||||
inline MoonPos *get_moon() const { return moon; }
|
||||
inline double getMoonRightAscension() const {
|
||||
return moon->getRightAscension();
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
#ifndef _JUPITER_HXX_
|
||||
#define _JUPITER_HXX_
|
||||
|
||||
#include "celestialBody.hxx"
|
||||
#include "star.hxx"
|
||||
#include <simgear/ephemeris/celestialBody.hxx>
|
||||
#include <simgear/ephemeris/star.hxx>
|
||||
|
||||
class Jupiter : public CelestialBody
|
||||
{
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
#ifndef _MARS_HXX_
|
||||
#define _MARS_HXX_
|
||||
|
||||
#include "celestialBody.hxx"
|
||||
#include "star.hxx"
|
||||
#include <simgear/ephemeris/celestialBody.hxx>
|
||||
#include <simgear/ephemeris/star.hxx>
|
||||
|
||||
class Mars : public CelestialBody
|
||||
{
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
#ifndef _MERCURY_HXX_
|
||||
#define _MERCURY_HXX_
|
||||
|
||||
#include "celestialBody.hxx"
|
||||
#include "star.hxx"
|
||||
#include <simgear/ephemeris/celestialBody.hxx>
|
||||
#include <simgear/ephemeris/star.hxx>
|
||||
|
||||
class Mercury : public CelestialBody
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**************************************************************************
|
||||
* moon.cxx
|
||||
* moonpos.cxx
|
||||
* Written by Durk Talsma. Originally started October 1997, for distribution
|
||||
* with the FlightGear project. Version 2 was written in August and
|
||||
* September 1998. This code is based upon algorithms and data kindly
|
||||
@@ -36,18 +36,18 @@
|
||||
|
||||
// #include <FDM/flight.hxx>
|
||||
|
||||
#include "moon.hxx"
|
||||
#include "moonpos.hxx"
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Moon::Moon(double mjd)
|
||||
* Public constructor for class Moon. Initializes the orbital elements and
|
||||
* MoonPos::MoonPos(double mjd)
|
||||
* Public constructor for class MoonPos. Initializes the orbital elements and
|
||||
* sets up the moon texture.
|
||||
* Argument: The current time.
|
||||
* the hard coded orbital elements for Moon are passed to
|
||||
* the hard coded orbital elements for MoonPos are passed to
|
||||
* CelestialBody::CelestialBody();
|
||||
************************************************************************/
|
||||
Moon::Moon(double mjd) :
|
||||
MoonPos::MoonPos(double mjd) :
|
||||
CelestialBody(125.1228, -0.0529538083,
|
||||
5.1454, 0.00000,
|
||||
318.0634, 0.1643573223,
|
||||
@@ -57,7 +57,7 @@ Moon::Moon(double mjd) :
|
||||
{
|
||||
}
|
||||
|
||||
Moon::Moon() :
|
||||
MoonPos::MoonPos() :
|
||||
CelestialBody(125.1228, -0.0529538083,
|
||||
5.1454, 0.00000,
|
||||
318.0634, 0.1643573223,
|
||||
@@ -68,18 +68,18 @@ Moon::Moon() :
|
||||
}
|
||||
|
||||
|
||||
Moon::~Moon()
|
||||
MoonPos::~MoonPos()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* void Moon::updatePosition(double mjd, Star *ourSun)
|
||||
* void MoonPos::updatePosition(double mjd, Star *ourSun)
|
||||
* this member function calculates the actual topocentric position (i.e.)
|
||||
* the position of the moon as seen from the current position on the surface
|
||||
* of the moon.
|
||||
****************************************************************************/
|
||||
void Moon::updatePosition(double mjd, double lst, double lat, Star *ourSun)
|
||||
void MoonPos::updatePosition(double mjd, double lst, double lat, Star *ourSun)
|
||||
{
|
||||
double
|
||||
eccAnom, ecl, actTime,
|
||||
@@ -1,5 +1,5 @@
|
||||
/**************************************************************************
|
||||
* moon.hxx
|
||||
* moonpos.hxx
|
||||
* Written by Durk Talsma. Originally started October 1997, for distribution
|
||||
* with the FlightGear project. Version 2 was written in August and
|
||||
* September 1998. This code is based upon algorithms and data kindly
|
||||
@@ -22,16 +22,17 @@
|
||||
*
|
||||
* $Id$
|
||||
**************************************************************************/
|
||||
#ifndef _MOON_HXX_
|
||||
#define _MOON_HXX_
|
||||
#ifndef _MOONPOS_HXX_
|
||||
#define _MOONPOS_HXX_
|
||||
|
||||
|
||||
#include <simgear/constants.h>
|
||||
|
||||
#include "celestialBody.hxx"
|
||||
#include "star.hxx"
|
||||
#include <simgear/ephemeris/celestialBody.hxx>
|
||||
#include <simgear/ephemeris/star.hxx>
|
||||
|
||||
class Moon : public CelestialBody
|
||||
|
||||
class MoonPos : public CelestialBody
|
||||
{
|
||||
|
||||
private:
|
||||
@@ -49,12 +50,12 @@ private:
|
||||
|
||||
public:
|
||||
|
||||
Moon(double mjd);
|
||||
Moon();
|
||||
~Moon();
|
||||
MoonPos(double mjd);
|
||||
MoonPos();
|
||||
~MoonPos();
|
||||
void updatePosition(double mjd, double lst, double lat, Star *ourSun);
|
||||
// void newImage();
|
||||
};
|
||||
|
||||
|
||||
#endif // _MOON_HXX_
|
||||
#endif // _MOONPOS_HXX_
|
||||
@@ -25,8 +25,8 @@
|
||||
#ifndef _NEPTUNE_HXX_
|
||||
#define _NEPTUNE_HXX_
|
||||
|
||||
#include "celestialBody.hxx"
|
||||
#include "star.hxx"
|
||||
#include <simgear/ephemeris/celestialBody.hxx>
|
||||
#include <simgear/ephemeris/star.hxx>
|
||||
|
||||
class Neptune : public CelestialBody
|
||||
{
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
#ifndef _SATURN_HXX_
|
||||
#define _SATURN_HXX_
|
||||
|
||||
#include "celestialBody.hxx"
|
||||
#include "star.hxx"
|
||||
#include <simgear/ephemeris/celestialBody.hxx>
|
||||
#include <simgear/ephemeris/star.hxx>
|
||||
|
||||
class Saturn : public CelestialBody
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define _STAR_HXX_
|
||||
|
||||
|
||||
#include "celestialBody.hxx"
|
||||
#include <simgear/ephemeris/celestialBody.hxx>
|
||||
|
||||
|
||||
class Star : public CelestialBody
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// stars.cxx -- manage star data
|
||||
// stardata.cxx -- manage star data
|
||||
//
|
||||
// Written by Curtis Olson, started March 2000.
|
||||
//
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/misc/fgstream.hxx>
|
||||
|
||||
#include "stars.hxx"
|
||||
#include "stardata.hxx"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
FG_USING_STD(getline);
|
||||
@@ -1,4 +1,4 @@
|
||||
// stars.hxx -- manage star data
|
||||
// stardata.hxx -- manage star data
|
||||
//
|
||||
// Written by Curtis Olson, started March 2000.
|
||||
//
|
||||
@@ -25,8 +25,8 @@
|
||||
#ifndef _URANUS_HXX_
|
||||
#define _URANUS_HXX_
|
||||
|
||||
#include "celestialBody.hxx"
|
||||
#include "star.hxx"
|
||||
#include <simgear/ephemeris/celestialBody.hxx>
|
||||
#include <simgear/ephemeris/star.hxx>
|
||||
|
||||
class Uranus : public CelestialBody
|
||||
{
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
#ifndef _VENUS_HXX_
|
||||
#define _VENUS_HXX_
|
||||
|
||||
#include "celestialBody.hxx"
|
||||
#include "star.hxx"
|
||||
#include <simgear/ephemeris/celestialBody.hxx>
|
||||
#include <simgear/ephemeris/star.hxx>
|
||||
|
||||
class Venus : public CelestialBody
|
||||
{
|
||||
|
||||
@@ -14,4 +14,12 @@ libsgio_a_SOURCES = \
|
||||
sg_serial.cxx \
|
||||
sg_socket.cxx
|
||||
|
||||
INCLUDES += -I$(top_builddir)
|
||||
INCLUDES += -I$(top_srcdir)
|
||||
|
||||
noinst_PROGRAMS = socktest
|
||||
|
||||
socktest_SOURCES = socktest.cxx
|
||||
|
||||
socktest_LDADD = \
|
||||
$(top_builddir)/simgear/io/libsgio.a \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a
|
||||
@@ -39,7 +39,7 @@ SGIOChannel::~SGIOChannel()
|
||||
|
||||
|
||||
// dummy configure routine
|
||||
bool SGIOChannel::open( SGProtocolDir dir ) {
|
||||
bool SGIOChannel::open( const SGProtocolDir d ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -57,13 +57,13 @@ int SGIOChannel::readline( char *buf, int length ) {
|
||||
|
||||
|
||||
// dummy process routine
|
||||
int SGIOChannel::write( char *buf, int length ) {
|
||||
int SGIOChannel::write( const char *buf, const int length ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// dummy process routine
|
||||
int SGIOChannel::writestring( char *str ) {
|
||||
int SGIOChannel::writestring( const char *str ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,21 +55,27 @@ enum SGChannelType {
|
||||
class SGIOChannel {
|
||||
|
||||
SGChannelType type;
|
||||
SGProtocolDir dir;
|
||||
bool valid;
|
||||
|
||||
public:
|
||||
|
||||
SGIOChannel();
|
||||
virtual ~SGIOChannel();
|
||||
|
||||
virtual bool open( SGProtocolDir dir );
|
||||
virtual bool open( const SGProtocolDir d );
|
||||
virtual int read( char *buf, int length );
|
||||
virtual int readline( char *buf, int length );
|
||||
virtual int write( char *buf, int length );
|
||||
virtual int writestring( char *str );
|
||||
virtual int write( const char *buf, const int length );
|
||||
virtual int writestring( const char *str );
|
||||
virtual bool close();
|
||||
|
||||
virtual void set_type( SGChannelType t ) { type = t; }
|
||||
virtual SGChannelType get_type() const { return type; }
|
||||
inline void set_type( SGChannelType t ) { type = t; }
|
||||
inline SGChannelType get_type() const { return type; }
|
||||
|
||||
inline void set_dir( const SGProtocolDir d ) { dir = d; }
|
||||
inline SGProtocolDir get_dir() const { return dir; }
|
||||
inline bool isvalid() const { return valid; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
+15
-37
@@ -47,22 +47,18 @@ SGFile::~SGFile() {
|
||||
|
||||
|
||||
// open the file based on specified direction
|
||||
bool SGFile::open( SGProtocolDir dir ) {
|
||||
if ( dir == SG_IO_OUT ) {
|
||||
bool SGFile::open( const SGProtocolDir d ) {
|
||||
set_dir( d );
|
||||
|
||||
if ( get_dir() == SG_IO_OUT ) {
|
||||
#ifdef _MSC_VER
|
||||
fp = _open( file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC,
|
||||
00666 );
|
||||
int mode = 00666;
|
||||
#else
|
||||
fp = std::open( file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
|
||||
S_IROTH | S_IWOTH );
|
||||
#endif
|
||||
} else if ( dir == SG_IO_IN ) {
|
||||
#ifdef _MSC_VER
|
||||
fp = _open( file_name.c_str(), O_RDONLY );
|
||||
#else
|
||||
fp = std::open( file_name.c_str(), O_RDONLY );
|
||||
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
|
||||
#endif
|
||||
fp = ::open( file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC, mode );
|
||||
} else if ( get_dir() == SG_IO_IN ) {
|
||||
fp = ::open( file_name.c_str(), O_RDONLY );
|
||||
} else {
|
||||
FG_LOG( FG_IO, FG_ALERT,
|
||||
"Error: bidirection mode not available for files." );
|
||||
@@ -81,13 +77,7 @@ bool SGFile::open( SGProtocolDir dir ) {
|
||||
// read a block of data of specified size
|
||||
int SGFile::read( char *buf, int length ) {
|
||||
// read a chunk
|
||||
#ifdef _MSC_VER
|
||||
int result = _read( fp, buf, length );
|
||||
#else
|
||||
int result = std::read( fp, buf, length );
|
||||
#endif
|
||||
|
||||
return result;
|
||||
return ::read( fp, buf, length );
|
||||
}
|
||||
|
||||
|
||||
@@ -97,11 +87,7 @@ int SGFile::readline( char *buf, int length ) {
|
||||
int pos = lseek( fp, 0, SEEK_CUR );
|
||||
|
||||
// read a chunk
|
||||
#ifdef _MSC_VER
|
||||
int result = _read( fp, buf, length );
|
||||
#else
|
||||
int result = std::read( fp, buf, length );
|
||||
#endif
|
||||
int result = ::read( fp, buf, length );
|
||||
|
||||
// find the end of line and reset position
|
||||
int i;
|
||||
@@ -121,12 +107,8 @@ int SGFile::readline( char *buf, int length ) {
|
||||
|
||||
|
||||
// write data to a file
|
||||
int SGFile::write( char *buf, int length ) {
|
||||
#ifdef _MSC_VER
|
||||
int result = _write( fp, buf, length );
|
||||
#else
|
||||
int result = std::write( fp, buf, length );
|
||||
#endif
|
||||
int SGFile::write( const char *buf, const int length ) {
|
||||
int result = ::write( fp, buf, length );
|
||||
if ( result != length ) {
|
||||
FG_LOG( FG_IO, FG_ALERT, "Error writing data: " << file_name );
|
||||
}
|
||||
@@ -136,7 +118,7 @@ int SGFile::write( char *buf, int length ) {
|
||||
|
||||
|
||||
// write null terminated string to a file
|
||||
int SGFile::writestring( char *str ) {
|
||||
int SGFile::writestring( const char *str ) {
|
||||
int length = strlen( str );
|
||||
return write( str, length );
|
||||
}
|
||||
@@ -144,11 +126,7 @@ int SGFile::writestring( char *str ) {
|
||||
|
||||
// close the port
|
||||
bool SGFile::close() {
|
||||
#ifdef _MSC_VER
|
||||
if ( _close( fp ) == -1 ) {
|
||||
#else
|
||||
if ( std::close( fp ) == -1 ) {
|
||||
#endif
|
||||
if ( ::close( fp ) == -1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
~SGFile();
|
||||
|
||||
// open the file based on specified direction
|
||||
bool open( SGProtocolDir dir );
|
||||
bool open( const SGProtocolDir dir );
|
||||
|
||||
// read a block of data of specified size
|
||||
int read( char *buf, int length );
|
||||
@@ -65,10 +65,10 @@ public:
|
||||
int readline( char *buf, int length );
|
||||
|
||||
// write data to a file
|
||||
int write( char *buf, int length );
|
||||
int write( const char *buf, const int length );
|
||||
|
||||
// write null terminated string to a file
|
||||
int writestring( char *str );
|
||||
int writestring( const char *str );
|
||||
|
||||
// close file
|
||||
bool close();
|
||||
|
||||
@@ -47,7 +47,9 @@ SGSerial::~SGSerial() {
|
||||
|
||||
|
||||
// open the serial port based on specified direction
|
||||
bool SGSerial::open( SGProtocolDir dir ) {
|
||||
bool SGSerial::open( const SGProtocolDir d ) {
|
||||
set_dir( d );
|
||||
|
||||
if ( ! port.open_port( device ) ) {
|
||||
FG_LOG( FG_IO, FG_ALERT, "Error opening device: " << device );
|
||||
return false;
|
||||
@@ -127,7 +129,7 @@ int SGSerial::readline( char *buf, int length ) {
|
||||
|
||||
|
||||
// write data to port
|
||||
int SGSerial::write( char *buf, int length ) {
|
||||
int SGSerial::write( const char *buf, const int length ) {
|
||||
int result = port.write_port( buf, length );
|
||||
|
||||
if ( result != length ) {
|
||||
@@ -139,7 +141,7 @@ int SGSerial::write( char *buf, int length ) {
|
||||
|
||||
|
||||
// write null terminated string to port
|
||||
int SGSerial::writestring( char *str ) {
|
||||
int SGSerial::writestring( const char *str ) {
|
||||
int length = strlen( str );
|
||||
return write( str, length );
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ public:
|
||||
~SGSerial();
|
||||
|
||||
// open the serial port based on specified direction
|
||||
bool open( SGProtocolDir dir );
|
||||
bool open( const SGProtocolDir d );
|
||||
|
||||
// read a block of data of specified size
|
||||
int read( char *buf, int length );
|
||||
@@ -70,10 +70,10 @@ public:
|
||||
int readline( char *buf, int length );
|
||||
|
||||
// write data to port
|
||||
int write( char *buf, int length );
|
||||
int write( const char *buf, const int length );
|
||||
|
||||
// write null terminated string to port
|
||||
int writestring( char *str );
|
||||
int writestring( const char *str );
|
||||
|
||||
// close port
|
||||
bool close();
|
||||
|
||||
+213
-81
@@ -23,7 +23,7 @@
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#if ! defined( _MSC_VER )
|
||||
#if !defined(_MSC_VER)
|
||||
# include <sys/time.h> // select()
|
||||
# include <sys/types.h> // socket(), bind(), select(), accept()
|
||||
# include <sys/socket.h> // socket(), bind(), listen(), accept()
|
||||
@@ -31,33 +31,28 @@
|
||||
# include <netdb.h> // gethostbyname()
|
||||
# include <unistd.h> // select(), fsync()/fdatasync(), fcntl()
|
||||
# include <fcntl.h> // fcntl()
|
||||
#else
|
||||
# include <sys/timeb.h> // select()
|
||||
# include <winsock2.h> // socket(), bind(), listen(), accept(),
|
||||
// struct sockaddr_in, gethostbyname()
|
||||
# include <windows.h>
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#if defined( sgi )
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#include STL_STRING
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include "sg_socket.hxx"
|
||||
|
||||
FG_USING_STD(string);
|
||||
|
||||
|
||||
SGSocket::SGSocket( const string& host, const string& port,
|
||||
const string& style ) :
|
||||
hostname(host),
|
||||
port_str(port),
|
||||
save_len(0)
|
||||
{
|
||||
hostname = host;
|
||||
port_str = port;
|
||||
#if defined(_MSC_VER)
|
||||
if (!wsock_init && !wsastartup()) {
|
||||
FG_LOG( FG_IO, FG_ALERT, "Winsock not available");
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( style == "udp" ) {
|
||||
sock_style = SOCK_DGRAM;
|
||||
@@ -77,7 +72,7 @@ SGSocket::~SGSocket() {
|
||||
}
|
||||
|
||||
|
||||
int SGSocket::make_server_socket () {
|
||||
SGSocket::SocketType SGSocket::make_server_socket () {
|
||||
struct sockaddr_in name;
|
||||
|
||||
#if defined( __CYGWIN__ ) || defined( __CYGWIN32__ ) || defined( sgi ) || defined( _MSC_VER )
|
||||
@@ -88,10 +83,10 @@ int SGSocket::make_server_socket () {
|
||||
|
||||
// Create the socket.
|
||||
sock = socket (PF_INET, sock_style, 0);
|
||||
if (sock < 0) {
|
||||
FG_LOG( FG_IO, FG_ALERT,
|
||||
"Error: socket() failed in make_server_socket()" );
|
||||
return -1;
|
||||
if (sock == INVALID_SOCKET) {
|
||||
FG_LOG( FG_IO, FG_ALERT,
|
||||
"Error: socket() failed in make_server_socket()" );
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
// Give the socket a name.
|
||||
@@ -99,18 +94,18 @@ int SGSocket::make_server_socket () {
|
||||
name.sin_addr.s_addr = INADDR_ANY;
|
||||
name.sin_port = htons(port); // set port to zero to let system pick
|
||||
name.sin_addr.s_addr = htonl (INADDR_ANY);
|
||||
if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
|
||||
FG_LOG( FG_IO, FG_ALERT,
|
||||
"Error: bind() failed in make_server_socket()" );
|
||||
return -1;
|
||||
if (bind (sock, (struct sockaddr *) &name, sizeof (name)) != 0) {
|
||||
FG_LOG( FG_IO, FG_ALERT,
|
||||
"Error: bind() failed in make_server_socket()" );
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
|
||||
// Find the assigned port number
|
||||
length = sizeof(struct sockaddr_in);
|
||||
if ( getsockname(sock, (struct sockaddr *) &name, &length) ) {
|
||||
FG_LOG( FG_IO, FG_ALERT,
|
||||
"Error: getsockname() failed in make_server_socket()" );
|
||||
return -1;
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
port = ntohs(name.sin_port);
|
||||
|
||||
@@ -118,7 +113,7 @@ int SGSocket::make_server_socket () {
|
||||
}
|
||||
|
||||
|
||||
int SGSocket::make_client_socket () {
|
||||
SGSocket::SocketType SGSocket::make_client_socket () {
|
||||
struct sockaddr_in name;
|
||||
struct hostent *hp;
|
||||
|
||||
@@ -126,10 +121,10 @@ int SGSocket::make_client_socket () {
|
||||
|
||||
// Create the socket.
|
||||
sock = socket (PF_INET, sock_style, 0);
|
||||
if (sock < 0) {
|
||||
FG_LOG( FG_IO, FG_ALERT,
|
||||
"Error: socket() failed in make_client_socket()" );
|
||||
return -1;
|
||||
if (sock == INVALID_SOCKET) {
|
||||
FG_LOG( FG_IO, FG_ALERT,
|
||||
"Error: socket() failed in make_server_socket()" );
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
// specify address family
|
||||
@@ -148,26 +143,48 @@ int SGSocket::make_client_socket () {
|
||||
name.sin_port = htons(port);
|
||||
|
||||
if ( connect(sock, (struct sockaddr *) &name,
|
||||
sizeof(struct sockaddr_in)) < 0 )
|
||||
sizeof(struct sockaddr_in)) != 0 )
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
_close(sock);
|
||||
#else
|
||||
std::close(sock);
|
||||
#endif
|
||||
closesocket(sock);
|
||||
FG_LOG( FG_IO, FG_ALERT,
|
||||
"Error: connect() failed in make_client_socket()" );
|
||||
return -1;
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
|
||||
// Wrapper functions
|
||||
size_t SGSocket::readsocket( int fd, void *buf, size_t count ) {
|
||||
#if defined(_MSC_VER)
|
||||
return ::recv( fd, (char *)buf, count, 0 );
|
||||
#else
|
||||
return ::read( fd, buf, count );
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t SGSocket::writesocket( int fd, const void *buf, size_t count ) {
|
||||
#if defined(_MSC_VER)
|
||||
return ::send( fd, (const char*)buf, count, 0 );
|
||||
#else
|
||||
return ::write( fd, buf, count );
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
int SGSocket::closesocket( int fd ) {
|
||||
return ::close( fd );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// If specified as a server (in direction for now) open the master
|
||||
// listening socket. If specified as a client (out direction), open a
|
||||
// connection to a server.
|
||||
bool SGSocket::open( SGProtocolDir dir ) {
|
||||
bool SGSocket::open( const SGProtocolDir d ) {
|
||||
set_dir( d );
|
||||
|
||||
if ( port_str == "" || port_str == "any" ) {
|
||||
port = 0;
|
||||
} else {
|
||||
@@ -176,36 +193,56 @@ bool SGSocket::open( SGProtocolDir dir ) {
|
||||
|
||||
// client_connections.clear();
|
||||
|
||||
if ( dir == SG_IO_IN ) {
|
||||
if ( get_dir() == SG_IO_IN ) {
|
||||
// this means server for now
|
||||
|
||||
// Setup socket to listen on. Set "port" before making this
|
||||
// call. A port of "0" indicates that we want to let the os
|
||||
// pick any available port.
|
||||
sock = make_server_socket();
|
||||
if ( sock == INVALID_SOCKET ) {
|
||||
FG_LOG( FG_IO, FG_ALERT, "socket creation failed" );
|
||||
return false;
|
||||
}
|
||||
|
||||
FG_LOG( FG_IO, FG_INFO, "socket is connected to port = " << port );
|
||||
|
||||
if ( sock_style == SOCK_DGRAM ) {
|
||||
// Non-blocking UDP
|
||||
fcntl( sock, F_SETFL, O_NONBLOCK );
|
||||
nonblock();
|
||||
} else {
|
||||
// Blocking TCP
|
||||
// Specify the maximum length of the connection queue
|
||||
listen( sock, SG_MAX_SOCKET_QUEUE );
|
||||
}
|
||||
|
||||
} else if ( dir == SG_IO_OUT ) {
|
||||
} else if ( get_dir() == SG_IO_OUT ) {
|
||||
// this means client for now
|
||||
|
||||
sock = make_client_socket();
|
||||
// TODO: check for error.
|
||||
|
||||
if ( sock_style == SOCK_DGRAM ) {
|
||||
// Non-blocking UDP
|
||||
fcntl( sock, F_SETFL, O_NONBLOCK );
|
||||
nonblock();
|
||||
}
|
||||
} else if ( get_dir() == SG_IO_BI && sock_style == SOCK_STREAM ) {
|
||||
// this means server for TCP sockets
|
||||
|
||||
// Setup socket to listen on. Set "port" before making this
|
||||
// call. A port of "0" indicates that we want to let the os
|
||||
// pick any available port.
|
||||
sock = make_server_socket();
|
||||
// TODO: check for error.
|
||||
|
||||
FG_LOG( FG_IO, FG_INFO, "socket is connected to port = " << port );
|
||||
|
||||
// Blocking TCP
|
||||
// Specify the maximum length of the connection queue
|
||||
listen( sock, SG_MAX_SOCKET_QUEUE );
|
||||
} else {
|
||||
FG_LOG( FG_IO, FG_ALERT,
|
||||
"Error: bidirection mode not available yet for sockets." );
|
||||
"Error: bidirection mode not available for UDP sockets." );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -215,6 +252,10 @@ bool SGSocket::open( SGProtocolDir dir ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// extra SOCK_STREAM stuff
|
||||
msgsock = INVALID_SOCKET;
|
||||
first_read = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -222,8 +263,11 @@ bool SGSocket::open( SGProtocolDir dir ) {
|
||||
// read data from socket (server)
|
||||
// read a block of data of specified size
|
||||
int SGSocket::read( char *buf, int length ) {
|
||||
int result = 0;
|
||||
if ( sock == INVALID_SOCKET ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
// check for potential input
|
||||
fd_set ready;
|
||||
FD_ZERO(&ready);
|
||||
@@ -237,11 +281,20 @@ int SGSocket::read( char *buf, int length ) {
|
||||
select(32, &ready, 0, 0, &tv);
|
||||
|
||||
if ( FD_ISSET(sock, &ready) ) {
|
||||
#ifdef _MSC_VER
|
||||
result = _read( sock, buf, length );
|
||||
#else
|
||||
result = std::read( sock, buf, length );
|
||||
#endif
|
||||
// cout << "data ready" << endl;
|
||||
|
||||
if ( sock_style == SOCK_STREAM ) {
|
||||
if ( msgsock == INVALID_SOCKET ) {
|
||||
msgsock = accept(sock, 0, 0);
|
||||
closesocket(sock);
|
||||
sock = msgsock;
|
||||
} else {
|
||||
result = readsocket( sock, buf, length );
|
||||
}
|
||||
} else {
|
||||
result = readsocket( sock, buf, length );
|
||||
}
|
||||
|
||||
if ( result != length ) {
|
||||
FG_LOG( FG_IO, FG_INFO,
|
||||
"Warning: read() not enough bytes." );
|
||||
@@ -254,7 +307,11 @@ int SGSocket::read( char *buf, int length ) {
|
||||
|
||||
// read a line of data, length is max size of input buffer
|
||||
int SGSocket::readline( char *buf, int length ) {
|
||||
int result = 0;
|
||||
if ( sock == INVALID_SOCKET ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// cout << "sock = " << sock << endl;
|
||||
|
||||
// check for potential input
|
||||
fd_set ready;
|
||||
@@ -266,22 +323,55 @@ int SGSocket::readline( char *buf, int length ) {
|
||||
|
||||
// test for any input read on sock (returning immediately, even if
|
||||
// nothing)
|
||||
select(32, &ready, 0, 0, &tv);
|
||||
int result = select(32, &ready, 0, 0, &tv);
|
||||
// cout << "result = " << result << endl;
|
||||
|
||||
if ( FD_ISSET(sock, &ready) ) {
|
||||
// cout << "fd change state\n";
|
||||
// read a chunk, keep in the save buffer until we have the
|
||||
// requested amount read
|
||||
|
||||
char *buf_ptr = save_buf + save_len;
|
||||
#ifdef _MSC_VER
|
||||
result = _read( sock, buf_ptr, SG_IO_MAX_MSG_SIZE - save_len );
|
||||
#else
|
||||
result = std::read( sock, buf_ptr, SG_IO_MAX_MSG_SIZE - save_len );
|
||||
#endif
|
||||
save_len += result;
|
||||
if ( sock_style == SOCK_STREAM ) {
|
||||
// cout << "sock_stream\n";
|
||||
if ( msgsock == INVALID_SOCKET ) {
|
||||
// cout << "msgsock == invalid\n";
|
||||
msgsock = accept(sock, 0, 0);
|
||||
closesocket(sock);
|
||||
sock = msgsock;
|
||||
} else {
|
||||
// cout << "ready to read\n";
|
||||
char *buf_ptr = save_buf + save_len;
|
||||
result = readsocket( sock, buf_ptr, SG_IO_MAX_MSG_SIZE
|
||||
- save_len );
|
||||
// cout << "read result = " << result << endl;
|
||||
|
||||
if ( result > 0 ) {
|
||||
first_read = true;
|
||||
}
|
||||
|
||||
save_len += result;
|
||||
|
||||
// Try and detect that the remote end died. This
|
||||
// could cause problems so if you see connections
|
||||
// dropping for unexplained reasons, LOOK HERE!
|
||||
if ( result == 0 && save_len == 0 && first_read == true ) {
|
||||
FG_LOG( FG_IO, FG_ALERT,
|
||||
"Connection closed by foreign host." );
|
||||
closesocket(sock);
|
||||
open( get_dir() );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
char *buf_ptr = save_buf + save_len;
|
||||
result = readsocket( sock, buf_ptr, SG_IO_MAX_MSG_SIZE - save_len );
|
||||
save_len += result;
|
||||
}
|
||||
|
||||
// cout << "current read = " << buf_ptr << endl;
|
||||
// cout << "current save_buf = " << save_buf << endl;
|
||||
// cout << "save_len = " << save_len << endl;
|
||||
} else {
|
||||
// cout << "no data ready\n";
|
||||
}
|
||||
|
||||
// look for the end of line in save_buf
|
||||
@@ -314,14 +404,14 @@ int SGSocket::readline( char *buf, int length ) {
|
||||
|
||||
|
||||
// write data to socket (client)
|
||||
int SGSocket::write( char *buf, int length ) {
|
||||
int SGSocket::write( const char *buf, const int length ) {
|
||||
if ( sock == INVALID_SOCKET ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool error_condition = false;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
if ( _write(sock, buf, length) < 0 ) {
|
||||
#else
|
||||
if ( std::write(sock, buf, length) < 0 ) {
|
||||
#endif
|
||||
if ( writesocket(sock, buf, length) < 0 ) {
|
||||
FG_LOG( FG_IO, FG_ALERT, "Error writing to socket: " << port );
|
||||
error_condition = true;
|
||||
}
|
||||
@@ -361,11 +451,7 @@ int SGSocket::write( char *buf, int length ) {
|
||||
// std::read( msgsock, junk, SG_IO_MAX_MSG_SIZE );
|
||||
|
||||
// write the interesting data to the socket
|
||||
#ifdef _MSC_VER
|
||||
if ( _write(msgsock, buf, length) < 0 ) {
|
||||
#else
|
||||
if ( std::write(msgsock, buf, length) < 0 ) {
|
||||
#endif
|
||||
if ( writesocket(msgsock, buf, length) == SOCKET_ERROR ) {
|
||||
FG_LOG( FG_IO, FG_ALERT, "Error writing to socket: " << port );
|
||||
error_condition = true;
|
||||
} else {
|
||||
@@ -387,7 +473,11 @@ int SGSocket::write( char *buf, int length ) {
|
||||
|
||||
|
||||
// write null terminated string to socket (server)
|
||||
int SGSocket::writestring( char *str ) {
|
||||
int SGSocket::writestring( const char *str ) {
|
||||
if ( sock == INVALID_SOCKET ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int length = strlen( str );
|
||||
return write( str, length );
|
||||
}
|
||||
@@ -395,21 +485,63 @@ int SGSocket::writestring( char *str ) {
|
||||
|
||||
// close the port
|
||||
bool SGSocket::close() {
|
||||
#if 0
|
||||
for ( int i = 0; i < (int)client_connections.size(); ++i ) {
|
||||
int msgsock = client_connections[i];
|
||||
#ifdef _MSC_VER
|
||||
_close( msgsock );
|
||||
#else
|
||||
std::close( msgsock );
|
||||
#endif
|
||||
if ( sock == INVALID_SOCKET ) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
_close( sock );
|
||||
closesocket( sock );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// configure the socket as non-blocking
|
||||
bool SGSocket::nonblock() {
|
||||
if ( sock == INVALID_SOCKET ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
u_long arg = 1;
|
||||
if (ioctlsocket( sock, FIONBIO, &arg ) != 0) {
|
||||
int error_code = WSAGetLastError();
|
||||
FG_LOG( FG_IO, FG_ALERT,
|
||||
"Error " << error_code << ": unable to set non-blocking mode"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
std::close( sock );
|
||||
fcntl( sock, F_SETFL, O_NONBLOCK );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
bool SGSocket::wsock_init = false;
|
||||
|
||||
bool
|
||||
SGSocket::wsastartup() {
|
||||
WORD wVersionRequested;
|
||||
WSADATA wsaData;
|
||||
|
||||
//wVersionRequested = MAKEWORD( 2, 2 );
|
||||
wVersionRequested = MAKEWORD( 1, 1 );
|
||||
int err = WSAStartup( wVersionRequested, &wsaData );
|
||||
if (err != 0)
|
||||
{
|
||||
FG_LOG( FG_IO, FG_ALERT, "Error: Couldn't load winsock" );
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if ( LOBYTE( wsaData.wVersion ) != 2 ||
|
||||
HIBYTE( wsaData.wVersion ) != 2 ) {
|
||||
FG_LOG( FG_IO, FG_ALERT, "Couldn't load a suitable winsock");
|
||||
WSACleanup( );
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
wsock_init = true;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
+38
-11
@@ -31,37 +31,61 @@
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <string>
|
||||
#include STL_STRING
|
||||
|
||||
#include <simgear/math/fg_types.hxx>
|
||||
|
||||
#include "iochannel.hxx"
|
||||
#include <simgear/math/sg_types.hxx>
|
||||
#include <simgear/io/iochannel.hxx>
|
||||
|
||||
FG_USING_STD(string);
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# include <winsock.h>
|
||||
#endif
|
||||
|
||||
#define SG_MAX_SOCKET_QUEUE 32
|
||||
|
||||
|
||||
class SGSocket : public SGIOChannel {
|
||||
public:
|
||||
#if defined(_MSC_VER)
|
||||
typedef SOCKET SocketType;
|
||||
#else
|
||||
typedef int SocketType;
|
||||
# define INVALID_SOCKET (-1)
|
||||
#endif
|
||||
|
||||
private:
|
||||
string hostname;
|
||||
string port_str;
|
||||
|
||||
char save_buf[ 2 * SG_IO_MAX_MSG_SIZE ];
|
||||
int save_len;
|
||||
|
||||
int sock;
|
||||
SocketType sock;
|
||||
SocketType msgsock;
|
||||
short unsigned int port;
|
||||
int sock_style; // SOCK_STREAM or SOCK_DGRAM
|
||||
|
||||
bool first_read;
|
||||
|
||||
// make a server (master listening) socket
|
||||
int make_server_socket();
|
||||
SocketType make_server_socket();
|
||||
|
||||
// make a client socket
|
||||
int make_client_socket();
|
||||
SocketType make_client_socket();
|
||||
|
||||
// int_list client_connections;
|
||||
// wrapper functions
|
||||
size_t readsocket( int fd, void *buf, size_t count );
|
||||
size_t writesocket( int fd, const void *buf, size_t count );
|
||||
#if !defined(_MSC_VER)
|
||||
int closesocket(int fd);
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Ensure winsock has been initialised.
|
||||
static bool wsock_init;
|
||||
static bool wsastartup();
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
@@ -71,7 +95,7 @@ public:
|
||||
// If specified as a server (in direction for now) open the master
|
||||
// listening socket. If specified as a client (out direction),
|
||||
// open a connection to a server.
|
||||
bool open( SGProtocolDir dir );
|
||||
bool open( const SGProtocolDir d );
|
||||
|
||||
// read data from socket
|
||||
int read( char *buf, int length );
|
||||
@@ -80,14 +104,17 @@ public:
|
||||
int readline( char *buf, int length );
|
||||
|
||||
// write data to a socket
|
||||
int write( char *buf, int length );
|
||||
int write( const char *buf, const int length );
|
||||
|
||||
// write null terminated string to a socket
|
||||
int writestring( char *str );
|
||||
int writestring( const char *str );
|
||||
|
||||
// close file
|
||||
bool close();
|
||||
|
||||
// Enable non-blocking mode.
|
||||
bool nonblock();
|
||||
|
||||
inline string get_hostname() const { return hostname; }
|
||||
inline string get_port_str() const { return port_str; }
|
||||
};
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "sg_socket.hxx"
|
||||
|
||||
int main() {
|
||||
|
||||
SGSocket s( "", "5500", "tcp" );
|
||||
|
||||
if ( !s.open( SG_IO_BI ) ) {
|
||||
cout << "error can't open socket\n";
|
||||
}
|
||||
|
||||
char buf[256];
|
||||
|
||||
while ( true ) {
|
||||
if ( s.readline( buf, 256 ) > 0 ) {
|
||||
cout << "result = " << buf;
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,9 @@ lib_LIBRARIES = libsgmagvar.a
|
||||
|
||||
include_HEADERS = magvar.hxx
|
||||
|
||||
libsgmagvar_a_SOURCES = magvar.cxx
|
||||
libsgmagvar_a_SOURCES = \
|
||||
coremag.hxx coremag.cxx \
|
||||
magvar.cxx
|
||||
|
||||
noinst_PROGRAMS = testmagvar
|
||||
|
||||
@@ -12,4 +14,4 @@ testmagvar_SOURCES = testmagvar.cxx
|
||||
|
||||
testmagvar_LDADD = $(top_builddir)/simgear/magvar/libsgmagvar.a
|
||||
|
||||
INCLUDES += -I$(top_builddir)
|
||||
INCLUDES += -I$(top_srcdir)
|
||||
|
||||
@@ -0,0 +1,453 @@
|
||||
// coremag.cxx -- compute local magnetic variation given position,
|
||||
// altitude, and date
|
||||
//
|
||||
// This is an implementation of the NIMA (formerly DMA) WMM2000
|
||||
//
|
||||
// http://www.nima.mil/GandG/ngdc-wmm2000.html
|
||||
//
|
||||
// Copyright (C) 2000 Edward A Williams <Ed_Williams@compuserve.com>
|
||||
//
|
||||
// Adapted from Excel 3.0 version 3/27/94 EAW
|
||||
// Recoded in C++ by Starry Chan
|
||||
// WMM95 added and rearranged in ANSI-C EAW 7/9/95
|
||||
// Put shell around program and made Borland & GCC compatible EAW 11/22/95
|
||||
// IGRF95 added 2/96 EAW
|
||||
// WMM2000 IGR2000 added 2/00 EAW
|
||||
// Released under GPL 3/26/00 EAW
|
||||
// Adaptions and modifications for the SimGear project 3/27/2000 CLO
|
||||
//
|
||||
// Removed all pow() calls and made static roots[][] arrays to
|
||||
// save many sqrt() calls on subsequent invocations
|
||||
// left old code as SGMagVarOrig() for testing purposes
|
||||
// 3/28/2000 Norman Vine -- nhv@yahoo.com
|
||||
//
|
||||
// Put in some bullet-proofing to handle magnetic and geographic poles.
|
||||
// 3/28/2000 EAW
|
||||
|
||||
// The routine uses a spherical harmonic expansion of the magnetic
|
||||
// potential up to twelfth order, together with its time variation, as
|
||||
// described in Chapter 4 of "Geomagnetism, Vol 1, Ed. J.A.Jacobs,
|
||||
// Academic Press (London 1987)". The program first converts geodetic
|
||||
// coordinates (lat/long on elliptic earth and altitude) to spherical
|
||||
// geocentric (spherical lat/long and radius) coordinates. Using this,
|
||||
// the spherical (B_r, B_theta, B_phi) magnetic field components are
|
||||
// computed from the model. These are finally referred to surface (X, Y,
|
||||
// Z) coordinates.
|
||||
//
|
||||
// Fields are accurate to better than 200nT, variation and dip to
|
||||
// better than 0.5 degrees, with the exception of the declination near
|
||||
// the magnetic poles (where it is ill-defined) where the error may reach
|
||||
// 4 degrees or more.
|
||||
//
|
||||
// Variation is undefined at both the geographic and
|
||||
// magnetic poles, even though the field itself is well-behaved. To
|
||||
// avoid the routine blowing up, latitude entries corresponding to
|
||||
// the geographic poles are slightly offset. At the magnetic poles,
|
||||
// the routine returns zero variation.
|
||||
|
||||
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the
|
||||
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
// Boston, MA 02111-1307, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <simgear/constants.h>
|
||||
|
||||
#include "coremag.hxx"
|
||||
|
||||
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
static const double pi = 3.14159265358979;
|
||||
static const double a = 6378.16; /* major radius (km) IAU66 ellipsoid */
|
||||
static const double f = 1.0 / 298.25; /* inverse flattening IAU66 ellipsoid */
|
||||
static const double b = 6378.16 * (1.0 -1.0 / 298.25 );
|
||||
/* minor radius b=a*(1-f) */
|
||||
static const double r_0 = 6371.2; /* "mean radius" for spherical harmonic expansion */
|
||||
|
||||
static double gnm_wmm2000[13][13] =
|
||||
{
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{-29616.0, -1722.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{-2266.7, 3070.2, 1677.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{1322.4, -2291.5, 1255.9, 724.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{932.1, 786.3, 250.6, -401.5, 106.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{-211.9, 351.6, 220.8, -134.5, -168.8, -13.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{73.8, 68.2, 74.1, -163.5, -3.8, 17.1, -85.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{77.4, -73.9, 2.2, 35.7, 7.3, 5.2, 8.4, -1.5, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{23.3, 7.3, -8.5, -6.6, -16.9, 8.6, 4.9, -7.8, -7.6, 0.0, 0.0, 0.0, 0.0},
|
||||
{5.7, 8.5, 2.0, -9.8, 7.6, -7.0, -2.0, 9.2, -2.2, -6.6, 0.0, 0.0, 0.0},
|
||||
{-2.2, -5.7, 1.6, -3.7, -0.6, 4.1, 2.2, 2.2, 4.6, 2.3, 0.1, 0.0, 0.0},
|
||||
{3.3, -1.1, -2.4, 2.6, -1.3, -1.7, -0.6, 0.4, 0.7, -0.3, 2.3, 4.2, 0.0},
|
||||
{-1.5, -0.2, -0.3, 0.5, 0.2, 0.9, -1.4, 0.6, -0.6, -1.0, -0.3, 0.3, 0.4},
|
||||
};
|
||||
|
||||
static double hnm_wmm2000[13][13]=
|
||||
{
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 5194.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, -2484.8, -467.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, -224.7, 293.0, -486.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 273.3, -227.9, 120.9, -302.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 42.0, 173.8, -135.0, -38.6, 105.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, -17.4, 61.2, 63.2, -62.9, 0.2, 43.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, -62.3, -24.5, 8.9, 23.4, 15.0, -27.6, -7.8, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 12.4, -20.8, 8.4, -21.2, 15.5, 9.1, -15.5, -5.4, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, -20.4, 13.9, 12.0, -6.2, -8.6, 9.4, 5.0, -8.4, 3.2, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.9, -0.7, 3.9, 4.8, -5.3, -1.0, -2.4, 1.3, -2.3, -6.4, 0.0, 0.0},
|
||||
{0.0, -1.5, 0.7, -1.1, -2.3, 1.3, -0.6, -2.8, -1.6, -0.1, -1.9, 1.4, 0.0},
|
||||
{0.0, -1.0, 0.7, 2.2, -2.5, -0.2, 0.0, -0.2, 0.0, 0.2, -0.9, -0.2, 1.0},
|
||||
};
|
||||
|
||||
static double gtnm_wmm2000[13][13]=
|
||||
{
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{14.7, 11.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{-13.6, -0.7, -1.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.3, -4.3, 0.9, -8.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{-1.6, 0.9, -7.6, 2.2, -3.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{-0.9, -0.2, -2.5, -2.7, -0.9, 1.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{1.2, 0.2, 1.7, 1.6, -0.1, -0.3, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{-0.4, -0.8, -0.2, 1.1, 0.4, 0.0, -0.2, -0.2, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{-0.3, 0.6, -0.8, 0.3, -0.2, 0.5, 0.0, -0.6, 0.1, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
};
|
||||
|
||||
static double htnm_wmm2000[13][13]=
|
||||
{
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, -20.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, -21.5, -9.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 6.4, -1.3, -13.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 2.3, 0.7, 3.7, -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 2.1, 2.3, 3.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, -0.3, -1.7, -0.9, -1.0, -0.1, 1.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 1.4, 0.2, 0.7, 0.4, -0.3, -0.8, -0.1, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, -0.5, 0.1, -0.2, 0.0, 0.1, -0.1, 0.3, 0.2, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
};
|
||||
|
||||
static const int nmax = 12;
|
||||
|
||||
static double P[13][13];
|
||||
static double DP[13][13];
|
||||
static double gnm[13][13];
|
||||
static double hnm[13][13];
|
||||
static double sm[13];
|
||||
static double cm[13];
|
||||
|
||||
static double root[13];
|
||||
static double roots[13][13][2];
|
||||
|
||||
/* Convert date to Julian day 1950-2049 */
|
||||
unsigned long int yymmdd_to_julian_days( int yy, int mm, int dd )
|
||||
{
|
||||
unsigned long jd;
|
||||
|
||||
yy = (yy < 50) ? (2000 + yy) : (1900 + yy);
|
||||
jd = dd - 32075L + 1461L * (yy + 4800L + (mm - 14) / 12 ) / 4;
|
||||
jd = jd + 367L * (mm - 2 - (mm - 14) / 12*12) / 12;
|
||||
jd = jd - 3 * ((yy + 4900L + (mm - 14) / 12) / 100) / 4;
|
||||
|
||||
/* printf("julian date = %d\n", jd ); */
|
||||
return jd;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* return variation (in radians) given geodetic latitude (radians),
|
||||
* longitude(radians), height (km) and (Julian) date
|
||||
* N and E lat and long are positive, S and W negative
|
||||
*/
|
||||
|
||||
double calc_magvar( double lat, double lon, double h, long dat, double* field )
|
||||
{
|
||||
/* output field B_r,B_th,B_phi,B_x,B_y,B_z */
|
||||
int n,m;
|
||||
/* reference dates */
|
||||
long date0_wmm2000 = yymmdd_to_julian_days(0,1,1);
|
||||
|
||||
double yearfrac,sr,r,theta,c,s,psi,fn,fn_0,B_r,B_theta,B_phi,X,Y,Z;
|
||||
double sinpsi, cospsi, inv_s;
|
||||
|
||||
static int been_here = 0;
|
||||
|
||||
double sinlat = sin(lat);
|
||||
double coslat = cos(lat);
|
||||
|
||||
/* convert to geocentric coords: */
|
||||
// sr = sqrt(pow(a*coslat,2.0)+pow(b*sinlat,2.0));
|
||||
sr = sqrt(a*a*coslat*coslat + b*b*sinlat*sinlat);
|
||||
/* sr is effective radius */
|
||||
theta = atan2(coslat * (h*sr + a*a),
|
||||
sinlat * (h*sr + b*b));
|
||||
/* theta is geocentric co-latitude */
|
||||
|
||||
r = h*h + 2.0*h * sr +
|
||||
(a*a*a*a - ( a*a*a*a - b*b*b*b ) * sinlat*sinlat ) /
|
||||
(a*a - (a*a - b*b) * sinlat*sinlat );
|
||||
|
||||
r = sqrt(r);
|
||||
|
||||
/* r is geocentric radial distance */
|
||||
c = cos(theta);
|
||||
s = sin(theta);
|
||||
/* protect against zero divide at geographic poles */
|
||||
inv_s = 1.0 / (s + (s == 0.)*1.0e-8);
|
||||
|
||||
/* zero out arrays */
|
||||
for ( n = 0; n <= nmax; n++ ) {
|
||||
for ( m = 0; m <= n; m++ ) {
|
||||
P[n][m] = 0;
|
||||
DP[n][m] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* diagonal elements */
|
||||
P[0][0] = 1;
|
||||
P[1][1] = s;
|
||||
DP[0][0] = 0;
|
||||
DP[1][1] = c;
|
||||
P[1][0] = c ;
|
||||
DP[1][0] = -s;
|
||||
|
||||
// these values will not change for subsequent function calls
|
||||
if( !been_here ) {
|
||||
for ( n = 2; n <= nmax; n++ ) {
|
||||
root[n] = sqrt((2.0*n-1) / (2.0*n));
|
||||
}
|
||||
|
||||
for ( m = 0; m <= nmax; m++ ) {
|
||||
double mm = m*m;
|
||||
for ( n = max(m + 1, 2); n <= nmax; n++ ) {
|
||||
roots[m][n][0] = sqrt((n-1)*(n-1) - mm);
|
||||
roots[m][n][1] = 1.0 / sqrt( n*n - mm);
|
||||
}
|
||||
}
|
||||
been_here = 1;
|
||||
}
|
||||
|
||||
for ( n=2; n <= nmax; n++ ) {
|
||||
// double root = sqrt((2.0*n-1) / (2.0*n));
|
||||
P[n][n] = P[n-1][n-1] * s * root[n];
|
||||
DP[n][n] = (DP[n-1][n-1] * s + P[n-1][n-1] * c) *
|
||||
root[n];
|
||||
}
|
||||
|
||||
/* lower triangle */
|
||||
for ( m = 0; m <= nmax; m++ ) {
|
||||
// double mm = m*m;
|
||||
for ( n = max(m + 1, 2); n <= nmax; n++ ) {
|
||||
// double root1 = sqrt((n-1)*(n-1) - mm);
|
||||
// double root2 = 1.0 / sqrt( n*n - mm);
|
||||
P[n][m] = (P[n-1][m] * c * (2.0*n-1) -
|
||||
P[n-2][m] * roots[m][n][0]) *
|
||||
roots[m][n][1];
|
||||
|
||||
DP[n][m] = ((DP[n-1][m] * c - P[n-1][m] * s) *
|
||||
(2.0*n-1) - DP[n-2][m] * roots[m][n][0]) *
|
||||
roots[m][n][1];
|
||||
}
|
||||
}
|
||||
|
||||
/* compute gnm, hnm at dat */
|
||||
/* WMM2000 */
|
||||
yearfrac = (dat - date0_wmm2000) / 365.25;
|
||||
for ( n = 1; n <= nmax; n++ ) {
|
||||
for ( m = 0; m <= nmax; m++ ) {
|
||||
gnm[n][m] = gnm_wmm2000[n][m] + yearfrac * gtnm_wmm2000[n][m];
|
||||
hnm[n][m] = hnm_wmm2000[n][m] + yearfrac * htnm_wmm2000[n][m];
|
||||
}
|
||||
}
|
||||
|
||||
/* compute sm (sin(m lon) and cm (cos(m lon)) */
|
||||
for ( m = 0; m <= nmax; m++ ) {
|
||||
sm[m] = sin(m * lon);
|
||||
cm[m] = cos(m * lon);
|
||||
}
|
||||
|
||||
/* compute B fields */
|
||||
B_r = 0.0;
|
||||
B_theta = 0.0;
|
||||
B_phi = 0.0;
|
||||
fn_0 = r_0/r;
|
||||
fn = fn_0 * fn_0;
|
||||
|
||||
for ( n = 1; n <= nmax; n++ ) {
|
||||
double c1_n=0;
|
||||
double c2_n=0;
|
||||
double c3_n=0;
|
||||
for ( m = 0; m <= n; m++ ) {
|
||||
double tmp = (gnm[n][m] * cm[m] + hnm[n][m] * sm[m]);
|
||||
c1_n=c1_n + tmp * P[n][m];
|
||||
c2_n=c2_n + tmp * DP[n][m];
|
||||
c3_n=c3_n + m * (gnm[n][m] * sm[m] - hnm[n][m] * cm[m]) * P[n][m];
|
||||
}
|
||||
// fn=pow(r_0/r,n+2.0);
|
||||
fn *= fn_0;
|
||||
B_r = B_r + (n + 1) * c1_n * fn;
|
||||
B_theta = B_theta - c2_n * fn;
|
||||
B_phi = B_phi + c3_n * fn * inv_s;
|
||||
}
|
||||
|
||||
/* Find geodetic field components: */
|
||||
psi = theta - ((pi / 2.0) - lat);
|
||||
sinpsi = sin(psi);
|
||||
cospsi = cos(psi);
|
||||
X = -B_theta * cospsi - B_r * sinpsi;
|
||||
Y = B_phi;
|
||||
Z = B_theta * sinpsi - B_r * cospsi;
|
||||
|
||||
field[0]=B_r;
|
||||
field[1]=B_theta;
|
||||
field[2]=B_phi;
|
||||
field[3]=X;
|
||||
field[4]=Y;
|
||||
field[5]=Z; /* output fields */
|
||||
|
||||
/* find variation in radians */
|
||||
/* return zero variation at magnetic pole X=Y=0. */
|
||||
/* E is positive */
|
||||
return (X != 0. || Y != 0.) ? atan2(Y, X) : (double) 0.;
|
||||
}
|
||||
|
||||
|
||||
#ifdef TEST_NHV_HACKS
|
||||
double SGMagVarOrig( double lat, double lon, double h, long dat, double* field )
|
||||
{
|
||||
/* output field B_r,B_th,B_phi,B_x,B_y,B_z */
|
||||
int n,m;
|
||||
/* reference dates */
|
||||
long date0_wmm2000 = yymmdd_to_julian_days(0,1,1);
|
||||
|
||||
double yearfrac,sr,r,theta,c,s,psi,fn,B_r,B_theta,B_phi,X,Y,Z;
|
||||
|
||||
/* convert to geocentric coords: */
|
||||
sr = sqrt(pow(a*cos(lat),2.0)+pow(b*sin(lat),2.0));
|
||||
/* sr is effective radius */
|
||||
theta = atan2(cos(lat) * (h * sr + a * a),
|
||||
sin(lat) * (h * sr + b * b));
|
||||
/* theta is geocentric co-latitude */
|
||||
|
||||
r = h * h + 2.0*h * sr +
|
||||
(pow(a,4.0) - (pow(a,4.0) - pow(b,4.0)) * pow(sin(lat),2.0)) /
|
||||
(a * a - (a * a - b * b) * pow(sin(lat),2.0));
|
||||
|
||||
r = sqrt(r);
|
||||
|
||||
/* r is geocentric radial distance */
|
||||
c = cos(theta);
|
||||
s = sin(theta);
|
||||
|
||||
/* zero out arrays */
|
||||
for ( n = 0; n <= nmax; n++ ) {
|
||||
for ( m = 0; m <= n; m++ ) {
|
||||
P[n][m] = 0;
|
||||
DP[n][m] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* diagonal elements */
|
||||
P[0][0] = 1;
|
||||
P[1][1] = s;
|
||||
DP[0][0] = 0;
|
||||
DP[1][1] = c;
|
||||
P[1][0] = c ;
|
||||
DP[1][0] = -s;
|
||||
|
||||
for ( n = 2; n <= nmax; n++ ) {
|
||||
P[n][n] = P[n-1][n-1] * s * sqrt((2.0*n-1) / (2.0*n));
|
||||
DP[n][n] = (DP[n-1][n-1] * s + P[n-1][n-1] * c) *
|
||||
sqrt((2.0*n-1) / (2.0*n));
|
||||
}
|
||||
|
||||
/* lower triangle */
|
||||
for ( m = 0; m <= nmax; m++ ) {
|
||||
for ( n = max(m + 1, 2); n <= nmax; n++ ) {
|
||||
P[n][m] = (P[n-1][m] * c * (2.0*n-1) - P[n-2][m] *
|
||||
sqrt(1.0*(n-1)*(n-1) - m * m)) /
|
||||
sqrt(1.0* n * n - m * m);
|
||||
DP[n][m] = ((DP[n-1][m] * c - P[n-1][m] * s) *
|
||||
(2.0*n-1) - DP[n-2][m] *
|
||||
sqrt(1.0*(n-1) * (n-1) - m * m)) /
|
||||
sqrt(1.0* n * n - m * m);
|
||||
}
|
||||
}
|
||||
|
||||
/* compute gnm, hnm at dat */
|
||||
/* WMM2000 */
|
||||
yearfrac = (dat - date0_wmm2000) / 365.25;
|
||||
for ( n = 1; n <= nmax; n++ ) {
|
||||
for ( m = 0; m <= nmax; m++ ) {
|
||||
gnm[n][m] = gnm_wmm2000[n][m] + yearfrac * gtnm_wmm2000[n][m];
|
||||
hnm[n][m] = hnm_wmm2000[n][m] + yearfrac * htnm_wmm2000[n][m];
|
||||
}
|
||||
}
|
||||
|
||||
/* compute sm (sin(m lon) and cm (cos(m lon)) */
|
||||
for ( m = 0; m <= nmax; m++ ) {
|
||||
sm[m] = sin(m * lon);
|
||||
cm[m] = cos(m * lon);
|
||||
}
|
||||
|
||||
/* compute B fields */
|
||||
B_r = 0.0;
|
||||
B_theta = 0.0;
|
||||
B_phi = 0.0;
|
||||
|
||||
for ( n = 1; n <= nmax; n++ ) {
|
||||
double c1_n=0;
|
||||
double c2_n=0;
|
||||
double c3_n=0;
|
||||
for ( m = 0; m <= n; m++ ) {
|
||||
c1_n=c1_n + (gnm[n][m] * cm[m] + hnm[n][m] * sm[m]) * P[n][m];
|
||||
c2_n=c2_n + (gnm[n][m] * cm[m] + hnm[n][m] * sm[m]) * DP[n][m];
|
||||
c3_n=c3_n + m * (gnm[n][m] * sm[m] - hnm[n][m] * cm[m]) * P[n][m];
|
||||
}
|
||||
fn=pow(r_0/r,n+2.0);
|
||||
B_r = B_r + (n + 1) * c1_n * fn;
|
||||
B_theta = B_theta - c2_n * fn;
|
||||
B_phi = B_phi + c3_n * fn / s;
|
||||
}
|
||||
|
||||
/* Find geodetic field components: */
|
||||
psi = theta - (pi / 2.0 - lat);
|
||||
X = -B_theta * cos(psi) - B_r * sin(psi);
|
||||
Y = B_phi;
|
||||
Z = B_theta * sin(psi) - B_r * cos(psi);
|
||||
|
||||
field[0]=B_r;
|
||||
field[1]=B_theta;
|
||||
field[2]=B_phi;
|
||||
field[3]=X;
|
||||
field[4]=Y;
|
||||
field[5]=Z; /* output fields */
|
||||
|
||||
/* find variation, leave in radians! */
|
||||
return atan2(Y, X); /* E is positive */
|
||||
}
|
||||
#endif // TEST_NHV_HACKS
|
||||
@@ -0,0 +1,51 @@
|
||||
// coremag.hxx -- compute local magnetic variation given position,
|
||||
// altitude, and date
|
||||
//
|
||||
// This is an implimentation of the NIMA WMM 2000
|
||||
//
|
||||
// http://www.nima.mil/GandG/ngdc-wmm2000.html
|
||||
//
|
||||
// Copyright (C) 2000 Edward A Williams <Ed_Williams@compuserve.com>
|
||||
//
|
||||
// Adapted from Excel 3.0 version 3/27/94 EAW
|
||||
// Recoded in C++ by Starry Chan
|
||||
// WMM95 added and rearranged in ANSI-C EAW 7/9/95
|
||||
// Put shell around program and made Borland & GCC compatible EAW 11/22/95
|
||||
// IGRF95 added 2/96 EAW
|
||||
// WMM2000 IGR2000 added 2/00 EAW
|
||||
// Released under GPL 3/26/00 EAW
|
||||
// Adaptions and modifications for the SimGear project 3/27/2000 CLO
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the
|
||||
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
// Boston, MA 02111-1307, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
|
||||
#ifndef SG_MAGVAR_HXX
|
||||
#define SG_MAGVAR_HXX
|
||||
|
||||
|
||||
/* Convert date to Julian day 1950-2049 */
|
||||
unsigned long int yymmdd_to_julian_days( int yy, int mm, int dd );
|
||||
|
||||
/* return variation (in degrees) given geodetic latitude (radians), longitude
|
||||
(radians) ,height (km) and (Julian) date
|
||||
N and E lat and long are positive, S and W negative
|
||||
*/
|
||||
double calc_magvar( double lat, double lon, double h, long dat, double* field );
|
||||
|
||||
|
||||
#endif // SG_MAGVAR_HXX
|
||||
+30
-444
@@ -1,465 +1,51 @@
|
||||
// magvar.cxx -- compute local magnetic variation given position,
|
||||
// altitude, and date
|
||||
// magvar.cxx -- magnetic variation wrapper class
|
||||
//
|
||||
// This is an implementation of the NIMA (formerly DMA) WMM2000
|
||||
// Written by Curtis Olson, started July 2000.
|
||||
//
|
||||
// http://www.nima.mil/GandG/ngdc-wmm2000.html
|
||||
// Copyright (C) 2000 Curtis L. Olson - curt@flightgear.org
|
||||
//
|
||||
// Copyright (C) 2000 Edward A Williams <Ed_Williams@compuserve.com>
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// Adapted from Excel 3.0 version 3/27/94 EAW
|
||||
// Recoded in C++ by Starry Chan
|
||||
// WMM95 added and rearranged in ANSI-C EAW 7/9/95
|
||||
// Put shell around program and made Borland & GCC compatible EAW 11/22/95
|
||||
// IGRF95 added 2/96 EAW
|
||||
// WMM2000 IGR2000 added 2/00 EAW
|
||||
// Released under GPL 3/26/00 EAW
|
||||
// Adaptions and modifications for the SimGear project 3/27/2000 CLO
|
||||
//
|
||||
// Removed all pow() calls and made static roots[][] arrays to
|
||||
// save many sqrt() calls on subsequent invocations
|
||||
// left old code as SGMagVarOrig() for testing purposes
|
||||
// 3/28/2000 Norman Vine -- nhv@yahoo.com
|
||||
//
|
||||
// Put in some bullet-proofing to handle magnetic and geographic poles.
|
||||
// 3/28/2000 EAW
|
||||
|
||||
// The routine uses a spherical harmonic expansion of the magnetic
|
||||
// potential up to twelfth order, together with its time variation, as
|
||||
// described in Chapter 4 of "Geomagnetism, Vol 1, Ed. J.A.Jacobs,
|
||||
// Academic Press (London 1987)". The program first converts geodetic
|
||||
// coordinates (lat/long on elliptic earth and altitude) to spherical
|
||||
// geocentric (spherical lat/long and radius) coordinates. Using this,
|
||||
// the spherical (B_r, B_theta, B_phi) magnetic field components are
|
||||
// computed from the model. These are finally referred to surface (X, Y,
|
||||
// Z) coordinates.
|
||||
//
|
||||
// Fields are accurate to better than 200nT, variation and dip to
|
||||
// better than 0.5 degrees, with the exception of the declination near
|
||||
// the magnetic poles (where it is ill-defined) where the error may reach
|
||||
// 4 degrees or more.
|
||||
//
|
||||
// Variation is undefined at both the geographic and
|
||||
// magnetic poles, even though the field itself is well-behaved. To
|
||||
// avoid the routine blowing up, latitude entries corresponding to
|
||||
// the geographic poles are slightly offset. At the magnetic poles,
|
||||
// the routine returns zero variation.
|
||||
|
||||
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the
|
||||
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
// Boston, MA 02111-1307, USA.
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <simgear/misc/fgpath.hxx>
|
||||
#include <simgear/magvar/magvar.hxx>
|
||||
|
||||
#include "coremag.hxx"
|
||||
#include "magvar.hxx"
|
||||
|
||||
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
SGMagVar::SGMagVar() {
|
||||
}
|
||||
|
||||
static const double pi = 3.14159265358979;
|
||||
static const double a = 6378.16; /* major radius (km) IAU66 ellipsoid */
|
||||
static const double f = 1.0 / 298.25; /* inverse flattening IAU66 ellipsoid */
|
||||
static const double b = 6378.16 * (1.0 -1.0 / 298.25 );
|
||||
/* minor radius b=a*(1-f) */
|
||||
static const double r_0 = 6371.2; /* "mean radius" for spherical harmonic expansion */
|
||||
|
||||
static double gnm_wmm2000[13][13] =
|
||||
{
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{-29616.0, -1722.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{-2266.7, 3070.2, 1677.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{1322.4, -2291.5, 1255.9, 724.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{932.1, 786.3, 250.6, -401.5, 106.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{-211.9, 351.6, 220.8, -134.5, -168.8, -13.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{73.8, 68.2, 74.1, -163.5, -3.8, 17.1, -85.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{77.4, -73.9, 2.2, 35.7, 7.3, 5.2, 8.4, -1.5, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{23.3, 7.3, -8.5, -6.6, -16.9, 8.6, 4.9, -7.8, -7.6, 0.0, 0.0, 0.0, 0.0},
|
||||
{5.7, 8.5, 2.0, -9.8, 7.6, -7.0, -2.0, 9.2, -2.2, -6.6, 0.0, 0.0, 0.0},
|
||||
{-2.2, -5.7, 1.6, -3.7, -0.6, 4.1, 2.2, 2.2, 4.6, 2.3, 0.1, 0.0, 0.0},
|
||||
{3.3, -1.1, -2.4, 2.6, -1.3, -1.7, -0.6, 0.4, 0.7, -0.3, 2.3, 4.2, 0.0},
|
||||
{-1.5, -0.2, -0.3, 0.5, 0.2, 0.9, -1.4, 0.6, -0.6, -1.0, -0.3, 0.3, 0.4},
|
||||
};
|
||||
|
||||
static double hnm_wmm2000[13][13]=
|
||||
{
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 5194.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, -2484.8, -467.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, -224.7, 293.0, -486.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 273.3, -227.9, 120.9, -302.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 42.0, 173.8, -135.0, -38.6, 105.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, -17.4, 61.2, 63.2, -62.9, 0.2, 43.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, -62.3, -24.5, 8.9, 23.4, 15.0, -27.6, -7.8, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 12.4, -20.8, 8.4, -21.2, 15.5, 9.1, -15.5, -5.4, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, -20.4, 13.9, 12.0, -6.2, -8.6, 9.4, 5.0, -8.4, 3.2, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.9, -0.7, 3.9, 4.8, -5.3, -1.0, -2.4, 1.3, -2.3, -6.4, 0.0, 0.0},
|
||||
{0.0, -1.5, 0.7, -1.1, -2.3, 1.3, -0.6, -2.8, -1.6, -0.1, -1.9, 1.4, 0.0},
|
||||
{0.0, -1.0, 0.7, 2.2, -2.5, -0.2, 0.0, -0.2, 0.0, 0.2, -0.9, -0.2, 1.0},
|
||||
};
|
||||
|
||||
static double gtnm_wmm2000[13][13]=
|
||||
{
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{14.7, 11.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{-13.6, -0.7, -1.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.3, -4.3, 0.9, -8.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{-1.6, 0.9, -7.6, 2.2, -3.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{-0.9, -0.2, -2.5, -2.7, -0.9, 1.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{1.2, 0.2, 1.7, 1.6, -0.1, -0.3, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{-0.4, -0.8, -0.2, 1.1, 0.4, 0.0, -0.2, -0.2, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{-0.3, 0.6, -0.8, 0.3, -0.2, 0.5, 0.0, -0.6, 0.1, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
};
|
||||
|
||||
static double htnm_wmm2000[13][13]=
|
||||
{
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, -20.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, -21.5, -9.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 6.4, -1.3, -13.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 2.3, 0.7, 3.7, -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 2.1, 2.3, 3.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, -0.3, -1.7, -0.9, -1.0, -0.1, 1.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 1.4, 0.2, 0.7, 0.4, -0.3, -0.8, -0.1, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, -0.5, 0.1, -0.2, 0.0, 0.1, -0.1, 0.3, 0.2, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
};
|
||||
|
||||
static const int nmax = 12;
|
||||
|
||||
static double P[13][13];
|
||||
static double DP[13][13];
|
||||
static double gnm[13][13];
|
||||
static double hnm[13][13];
|
||||
static double sm[13];
|
||||
static double cm[13];
|
||||
|
||||
static double root[13];
|
||||
static double roots[13][13][2];
|
||||
|
||||
/* Convert date to Julian day 1950-2049 */
|
||||
unsigned long int yymmdd_to_julian_days( int yy, int mm, int dd )
|
||||
{
|
||||
unsigned long jd;
|
||||
|
||||
yy = (yy < 50) ? (2000 + yy) : (1900 + yy);
|
||||
jd = dd - 32075L + 1461L * (yy + 4800L + (mm - 14) / 12 ) / 4;
|
||||
jd = jd + 367L * (mm - 2 - (mm - 14) / 12*12) / 12;
|
||||
jd = jd - 3 * ((yy + 4900L + (mm - 14) / 12) / 100) / 4;
|
||||
|
||||
/* printf("julian date = %d\n", jd ); */
|
||||
return jd;
|
||||
}
|
||||
|
||||
|
||||
/* Convert degrees to radians */
|
||||
double deg_to_rad( double deg )
|
||||
{
|
||||
return deg*pi/180.;
|
||||
SGMagVar::~SGMagVar() {
|
||||
}
|
||||
|
||||
|
||||
/* Convert radians to degrees */
|
||||
double rad_to_deg( double rad )
|
||||
{
|
||||
return rad*180./pi;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* return variation (in radians) given geodetic latitude (radians),
|
||||
* longitude(radians), height (km) and (Julian) date
|
||||
* N and E lat and long are positive, S and W negative
|
||||
*/
|
||||
|
||||
double SGMagVar( double lat, double lon, double h, long dat, double* field )
|
||||
{
|
||||
/* output field B_r,B_th,B_phi,B_x,B_y,B_z */
|
||||
int n,m;
|
||||
/* reference dates */
|
||||
long date0_wmm2000 = yymmdd_to_julian_days(0,1,1);
|
||||
|
||||
double yearfrac,sr,r,theta,c,s,psi,fn,fn_0,B_r,B_theta,B_phi,X,Y,Z;
|
||||
double sinpsi, cospsi, inv_s;
|
||||
|
||||
static int been_here = 0;
|
||||
|
||||
double sinlat = sin(lat);
|
||||
double coslat = cos(lat);
|
||||
|
||||
/* convert to geocentric coords: */
|
||||
// sr = sqrt(pow(a*coslat,2.0)+pow(b*sinlat,2.0));
|
||||
sr = sqrt(a*a*coslat*coslat + b*b*sinlat*sinlat);
|
||||
/* sr is effective radius */
|
||||
theta = atan2(coslat * (h*sr + a*a),
|
||||
sinlat * (h*sr + b*b));
|
||||
/* theta is geocentric co-latitude */
|
||||
|
||||
r = h*h + 2.0*h * sr +
|
||||
(a*a*a*a - ( a*a*a*a - b*b*b*b ) * sinlat*sinlat ) /
|
||||
(a*a - (a*a - b*b) * sinlat*sinlat );
|
||||
|
||||
r = sqrt(r);
|
||||
|
||||
/* r is geocentric radial distance */
|
||||
c = cos(theta);
|
||||
s = sin(theta);
|
||||
/* protect against zero divide at geographic poles */
|
||||
inv_s = 1.0 / (s + (s == 0.)*1.0e-8);
|
||||
|
||||
/* zero out arrays */
|
||||
for ( n = 0; n <= nmax; n++ ) {
|
||||
for ( m = 0; m <= n; m++ ) {
|
||||
P[n][m] = 0;
|
||||
DP[n][m] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* diagonal elements */
|
||||
P[0][0] = 1;
|
||||
P[1][1] = s;
|
||||
DP[0][0] = 0;
|
||||
DP[1][1] = c;
|
||||
P[1][0] = c ;
|
||||
DP[1][0] = -s;
|
||||
|
||||
// these values will not change for subsequent function calls
|
||||
if( !been_here ) {
|
||||
for ( n = 2; n <= nmax; n++ ) {
|
||||
root[n] = sqrt((2.0*n-1) / (2.0*n));
|
||||
}
|
||||
|
||||
for ( m = 0; m <= nmax; m++ ) {
|
||||
double mm = m*m;
|
||||
for ( n = max(m + 1, 2); n <= nmax; n++ ) {
|
||||
roots[m][n][0] = sqrt((n-1)*(n-1) - mm);
|
||||
roots[m][n][1] = 1.0 / sqrt( n*n - mm);
|
||||
}
|
||||
}
|
||||
been_here = 1;
|
||||
}
|
||||
|
||||
for ( n=2; n <= nmax; n++ ) {
|
||||
// double root = sqrt((2.0*n-1) / (2.0*n));
|
||||
P[n][n] = P[n-1][n-1] * s * root[n];
|
||||
DP[n][n] = (DP[n-1][n-1] * s + P[n-1][n-1] * c) *
|
||||
root[n];
|
||||
}
|
||||
|
||||
/* lower triangle */
|
||||
for ( m = 0; m <= nmax; m++ ) {
|
||||
// double mm = m*m;
|
||||
for ( n = max(m + 1, 2); n <= nmax; n++ ) {
|
||||
// double root1 = sqrt((n-1)*(n-1) - mm);
|
||||
// double root2 = 1.0 / sqrt( n*n - mm);
|
||||
P[n][m] = (P[n-1][m] * c * (2.0*n-1) -
|
||||
P[n-2][m] * roots[m][n][0]) *
|
||||
roots[m][n][1];
|
||||
|
||||
DP[n][m] = ((DP[n-1][m] * c - P[n-1][m] * s) *
|
||||
(2.0*n-1) - DP[n-2][m] * roots[m][n][0]) *
|
||||
roots[m][n][1];
|
||||
}
|
||||
}
|
||||
|
||||
/* compute gnm, hnm at dat */
|
||||
/* WMM2000 */
|
||||
yearfrac = (dat - date0_wmm2000) / 365.25;
|
||||
for ( n = 1; n <= nmax; n++ ) {
|
||||
for ( m = 0; m <= nmax; m++ ) {
|
||||
gnm[n][m] = gnm_wmm2000[n][m] + yearfrac * gtnm_wmm2000[n][m];
|
||||
hnm[n][m] = hnm_wmm2000[n][m] + yearfrac * htnm_wmm2000[n][m];
|
||||
}
|
||||
}
|
||||
|
||||
/* compute sm (sin(m lon) and cm (cos(m lon)) */
|
||||
for ( m = 0; m <= nmax; m++ ) {
|
||||
sm[m] = sin(m * lon);
|
||||
cm[m] = cos(m * lon);
|
||||
}
|
||||
|
||||
/* compute B fields */
|
||||
B_r = 0.0;
|
||||
B_theta = 0.0;
|
||||
B_phi = 0.0;
|
||||
fn_0 = r_0/r;
|
||||
fn = fn_0 * fn_0;
|
||||
|
||||
for ( n = 1; n <= nmax; n++ ) {
|
||||
double c1_n=0;
|
||||
double c2_n=0;
|
||||
double c3_n=0;
|
||||
for ( m = 0; m <= n; m++ ) {
|
||||
double tmp = (gnm[n][m] * cm[m] + hnm[n][m] * sm[m]);
|
||||
c1_n=c1_n + tmp * P[n][m];
|
||||
c2_n=c2_n + tmp * DP[n][m];
|
||||
c3_n=c3_n + m * (gnm[n][m] * sm[m] - hnm[n][m] * cm[m]) * P[n][m];
|
||||
}
|
||||
// fn=pow(r_0/r,n+2.0);
|
||||
fn *= fn_0;
|
||||
B_r = B_r + (n + 1) * c1_n * fn;
|
||||
B_theta = B_theta - c2_n * fn;
|
||||
B_phi = B_phi + c3_n * fn * inv_s;
|
||||
}
|
||||
|
||||
/* Find geodetic field components: */
|
||||
psi = theta - ((pi / 2.0) - lat);
|
||||
sinpsi = sin(psi);
|
||||
cospsi = cos(psi);
|
||||
X = -B_theta * cospsi - B_r * sinpsi;
|
||||
Y = B_phi;
|
||||
Z = B_theta * sinpsi - B_r * cospsi;
|
||||
|
||||
field[0]=B_r;
|
||||
field[1]=B_theta;
|
||||
field[2]=B_phi;
|
||||
field[3]=X;
|
||||
field[4]=Y;
|
||||
field[5]=Z; /* output fields */
|
||||
|
||||
/* find variation in radians */
|
||||
/* return zero variation at magnetic pole X=Y=0. */
|
||||
/* E is positive */
|
||||
return (X != 0. || Y != 0.) ? atan2(Y, X) : (double) 0.;
|
||||
void SGMagVar::update( double lon, double lat, double alt_m, double jd ) {
|
||||
// Calculate local magnetic variation
|
||||
double field[6];
|
||||
// cout << "alt_m = " << alt_m << endl;
|
||||
magvar = calc_magvar( lat, lon, alt_m / 1000.0, (long)jd, field );
|
||||
magdip = atan(field[5]/sqrt(field[3]*field[3]+field[4]*field[4]));
|
||||
}
|
||||
|
||||
|
||||
#ifdef TEST_NHV_HACKS
|
||||
double SGMagVarOrig( double lat, double lon, double h, long dat, double* field )
|
||||
{
|
||||
/* output field B_r,B_th,B_phi,B_x,B_y,B_z */
|
||||
int n,m;
|
||||
/* reference dates */
|
||||
long date0_wmm2000 = yymmdd_to_julian_days(0,1,1);
|
||||
|
||||
double yearfrac,sr,r,theta,c,s,psi,fn,B_r,B_theta,B_phi,X,Y,Z;
|
||||
|
||||
/* convert to geocentric coords: */
|
||||
sr = sqrt(pow(a*cos(lat),2.0)+pow(b*sin(lat),2.0));
|
||||
/* sr is effective radius */
|
||||
theta = atan2(cos(lat) * (h * sr + a * a),
|
||||
sin(lat) * (h * sr + b * b));
|
||||
/* theta is geocentric co-latitude */
|
||||
|
||||
r = h * h + 2.0*h * sr +
|
||||
(pow(a,4.0) - (pow(a,4.0) - pow(b,4.0)) * pow(sin(lat),2.0)) /
|
||||
(a * a - (a * a - b * b) * pow(sin(lat),2.0));
|
||||
|
||||
r = sqrt(r);
|
||||
|
||||
/* r is geocentric radial distance */
|
||||
c = cos(theta);
|
||||
s = sin(theta);
|
||||
|
||||
/* zero out arrays */
|
||||
for ( n = 0; n <= nmax; n++ ) {
|
||||
for ( m = 0; m <= n; m++ ) {
|
||||
P[n][m] = 0;
|
||||
DP[n][m] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* diagonal elements */
|
||||
P[0][0] = 1;
|
||||
P[1][1] = s;
|
||||
DP[0][0] = 0;
|
||||
DP[1][1] = c;
|
||||
P[1][0] = c ;
|
||||
DP[1][0] = -s;
|
||||
|
||||
for ( n = 2; n <= nmax; n++ ) {
|
||||
P[n][n] = P[n-1][n-1] * s * sqrt((2.0*n-1) / (2.0*n));
|
||||
DP[n][n] = (DP[n-1][n-1] * s + P[n-1][n-1] * c) *
|
||||
sqrt((2.0*n-1) / (2.0*n));
|
||||
}
|
||||
|
||||
/* lower triangle */
|
||||
for ( m = 0; m <= nmax; m++ ) {
|
||||
for ( n = max(m + 1, 2); n <= nmax; n++ ) {
|
||||
P[n][m] = (P[n-1][m] * c * (2.0*n-1) - P[n-2][m] *
|
||||
sqrt(1.0*(n-1)*(n-1) - m * m)) /
|
||||
sqrt(1.0* n * n - m * m);
|
||||
DP[n][m] = ((DP[n-1][m] * c - P[n-1][m] * s) *
|
||||
(2.0*n-1) - DP[n-2][m] *
|
||||
sqrt(1.0*(n-1) * (n-1) - m * m)) /
|
||||
sqrt(1.0* n * n - m * m);
|
||||
}
|
||||
}
|
||||
|
||||
/* compute gnm, hnm at dat */
|
||||
/* WMM2000 */
|
||||
yearfrac = (dat - date0_wmm2000) / 365.25;
|
||||
for ( n = 1; n <= nmax; n++ ) {
|
||||
for ( m = 0; m <= nmax; m++ ) {
|
||||
gnm[n][m] = gnm_wmm2000[n][m] + yearfrac * gtnm_wmm2000[n][m];
|
||||
hnm[n][m] = hnm_wmm2000[n][m] + yearfrac * htnm_wmm2000[n][m];
|
||||
}
|
||||
}
|
||||
|
||||
/* compute sm (sin(m lon) and cm (cos(m lon)) */
|
||||
for ( m = 0; m <= nmax; m++ ) {
|
||||
sm[m] = sin(m * lon);
|
||||
cm[m] = cos(m * lon);
|
||||
}
|
||||
|
||||
/* compute B fields */
|
||||
B_r = 0.0;
|
||||
B_theta = 0.0;
|
||||
B_phi = 0.0;
|
||||
|
||||
for ( n = 1; n <= nmax; n++ ) {
|
||||
double c1_n=0;
|
||||
double c2_n=0;
|
||||
double c3_n=0;
|
||||
for ( m = 0; m <= n; m++ ) {
|
||||
c1_n=c1_n + (gnm[n][m] * cm[m] + hnm[n][m] * sm[m]) * P[n][m];
|
||||
c2_n=c2_n + (gnm[n][m] * cm[m] + hnm[n][m] * sm[m]) * DP[n][m];
|
||||
c3_n=c3_n + m * (gnm[n][m] * sm[m] - hnm[n][m] * cm[m]) * P[n][m];
|
||||
}
|
||||
fn=pow(r_0/r,n+2.0);
|
||||
B_r = B_r + (n + 1) * c1_n * fn;
|
||||
B_theta = B_theta - c2_n * fn;
|
||||
B_phi = B_phi + c3_n * fn / s;
|
||||
}
|
||||
|
||||
/* Find geodetic field components: */
|
||||
psi = theta - (pi / 2.0 - lat);
|
||||
X = -B_theta * cos(psi) - B_r * sin(psi);
|
||||
Y = B_phi;
|
||||
Z = B_theta * sin(psi) - B_r * cos(psi);
|
||||
|
||||
field[0]=B_r;
|
||||
field[1]=B_theta;
|
||||
field[2]=B_phi;
|
||||
field[3]=X;
|
||||
field[4]=Y;
|
||||
field[5]=Z; /* output fields */
|
||||
|
||||
/* find variation, leave in radians! */
|
||||
return atan2(Y, X); /* E is positive */
|
||||
}
|
||||
#endif // TEST_NHV_HACKS
|
||||
|
||||
+44
-43
@@ -1,57 +1,58 @@
|
||||
// magvar.hxx -- compute local magnetic variation given position,
|
||||
// altitude, and date
|
||||
// magvar.hxx -- magnetic variation wrapper class
|
||||
//
|
||||
// This is an implimentation of the NIMA WMM 2000
|
||||
// Written by Curtis Olson, started July 2000.
|
||||
//
|
||||
// http://www.nima.mil/GandG/ngdc-wmm2000.html
|
||||
// Copyright (C) 2000 Curtis L. Olson - curt@flightgear.org
|
||||
//
|
||||
// Copyright (C) 2000 Edward A Williams <Ed_Williams@compuserve.com>
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// Adapted from Excel 3.0 version 3/27/94 EAW
|
||||
// Recoded in C++ by Starry Chan
|
||||
// WMM95 added and rearranged in ANSI-C EAW 7/9/95
|
||||
// Put shell around program and made Borland & GCC compatible EAW 11/22/95
|
||||
// IGRF95 added 2/96 EAW
|
||||
// WMM2000 IGR2000 added 2/00 EAW
|
||||
// Released under GPL 3/26/00 EAW
|
||||
// Adaptions and modifications for the SimGear project 3/27/2000 CLO
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the
|
||||
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
// Boston, MA 02111-1307, USA.
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
|
||||
#ifndef SG_MAGVAR_HXX
|
||||
#define SG_MAGVAR_HXX
|
||||
#ifndef _MAGVAR_HXX
|
||||
#define _MAGVAR_HXX
|
||||
|
||||
|
||||
/* Convert date to Julian day 1950-2049 */
|
||||
unsigned long int yymmdd_to_julian_days( int yy, int mm, int dd );
|
||||
|
||||
/* Convert degrees to radians */
|
||||
double deg_to_rad( double deg );
|
||||
|
||||
/* Convert radians to degrees */
|
||||
double rad_to_deg( double rad );
|
||||
|
||||
/* return variation (in degrees) given geodetic latitude (radians), longitude
|
||||
(radians) ,height (km) and (Julian) date
|
||||
N and E lat and long are positive, S and W negative
|
||||
*/
|
||||
double SGMagVar( double lat, double lon, double h, long dat, double* field );
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
|
||||
#endif // SG_MAGVAR_HXX
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
class SGMagVar {
|
||||
|
||||
private:
|
||||
|
||||
double magvar;
|
||||
double magdip;
|
||||
|
||||
public:
|
||||
|
||||
SGMagVar();
|
||||
~SGMagVar();
|
||||
|
||||
// recalculate the magnetic offset and dip
|
||||
void update( double lon, double lat, double alt_m, double jd );
|
||||
|
||||
double get_magvar() const { return magvar; }
|
||||
double get_magdip() const { return magdip; }
|
||||
};
|
||||
|
||||
|
||||
#endif // _LIGHT_HXX
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "magvar.hxx"
|
||||
#include <simgear/constants.h>
|
||||
|
||||
#include "coremag.hxx"
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@@ -40,15 +42,15 @@ if (argc == 8){
|
||||
}
|
||||
|
||||
|
||||
var = SGMagVar( deg_to_rad(lat_deg), deg_to_rad(lon_deg), h,
|
||||
yymmdd_to_julian_days(yy,mm,dd), field );
|
||||
var = calc_magvar( DEG_TO_RAD * lat_deg, DEG_TO_RAD * lon_deg, h,
|
||||
yymmdd_to_julian_days(yy,mm,dd), field );
|
||||
|
||||
fprintf(stdout,"%6.0lf %6.0lf %6.0lf\n", field[0], field[1], field[2] );
|
||||
fprintf(stdout,"%6.0lf %6.0lf %6.0lf\n", field[3], field[4], field[5] );
|
||||
fprintf(stdout,"%6.0lf %6.0lf %6.0lf %4.2lf %4.2lf \n",
|
||||
field[3],field[4],field[5],
|
||||
rad_to_deg(atan(field[5]/pow(field[3]*field[3]+field[4]*field[4],0.5))),
|
||||
rad_to_deg(var));
|
||||
RAD_TO_DEG * (atan(field[5]/pow(field[3]*field[3]+field[4]*field[4],0.5))),
|
||||
RAD_TO_DEG * var);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,30 +3,31 @@ includedir = @includedir@/math
|
||||
if HAVE_ZLIB
|
||||
ZLIB_INCL =
|
||||
else
|
||||
ZLIB_INCL = -I$(top_builddir)/src/zlib
|
||||
ZLIB_INCL = -I$(top_srcdir)/src/zlib
|
||||
endif
|
||||
|
||||
lib_LIBRARIES = libsgmath.a
|
||||
|
||||
include_HEADERS = \
|
||||
fg_geodesy.hxx \
|
||||
fg_memory.h \
|
||||
fg_random.h \
|
||||
fg_types.hxx \
|
||||
interpolater.hxx \
|
||||
leastsqs.hxx \
|
||||
localconsts.hxx \
|
||||
point3d.hxx \
|
||||
polar3d.hxx \
|
||||
sg_geodesy.hxx \
|
||||
sg_random.h \
|
||||
sg_types.hxx \
|
||||
vector.hxx
|
||||
|
||||
EXTRA_DIST = linintp2.h linintp2.inl sphrintp.h sphrintp.inl
|
||||
|
||||
libsgmath_a_SOURCES = \
|
||||
fg_geodesy.cxx \
|
||||
fg_random.c \
|
||||
interpolater.cxx \
|
||||
leastsqs.cxx \
|
||||
polar3d.cxx \
|
||||
sg_geodesy.cxx \
|
||||
sg_random.c \
|
||||
vector.cxx
|
||||
|
||||
INCLUDES += -I$(top_builddir) $(ZLIB_INCL)
|
||||
INCLUDES += -I$(top_srcdir) $(ZLIB_INCL)
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// localconsts.hxx -- various constant that are shared
|
||||
//
|
||||
// Written by Curtis Olson, started September 2000.
|
||||
//
|
||||
// Copyright (C) 2000 Curtis L. Olson - curt@flightgear.org
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the
|
||||
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
// Boston, MA 02111-1307, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
|
||||
#ifndef _SG_LOCAL_CONSTS_HXX
|
||||
#define _SG_LOCAL_CONSTS_HXX
|
||||
|
||||
|
||||
// Value of earth flattening parameter from ref [8]
|
||||
//
|
||||
// Note: FP = f
|
||||
// E = 1-f
|
||||
// EPS = sqrt(1-(1-f)^2)
|
||||
//
|
||||
|
||||
static const double FP = 0.003352813178;
|
||||
static const double E = 0.996647186;
|
||||
static const double EPS = 0.081819221;
|
||||
static const double INVG = 0.031080997;
|
||||
|
||||
|
||||
#endif // _SG_LOCAL_CONSTS_HXX
|
||||
@@ -46,6 +46,8 @@
|
||||
# include <math.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/math/localconsts.hxx>
|
||||
|
||||
// I don't understand ... <math.h> or <cmath> should be included
|
||||
// already depending on how you defined FG_HAVE_STD_INCLUDES, but I
|
||||
// can go ahead and add this -- CLO
|
||||
|
||||
@@ -40,13 +40,13 @@
|
||||
// Find the Altitude above the Ellipsoid (WGS84) given the Earth
|
||||
// Centered Cartesian coordinate vector Distances are specified in
|
||||
// meters.
|
||||
double fgGeodAltFromCart(const Point3D& cp);
|
||||
double sgGeodAltFromCart(const Point3D& cp);
|
||||
|
||||
|
||||
// Convert a polar coordinate to a cartesian coordinate. Lon and Lat
|
||||
// must be specified in radians. The FG convention is for distances
|
||||
// must be specified in radians. The SG convention is for distances
|
||||
// to be specified in meters
|
||||
inline Point3D fgPolarToCart3d(const Point3D& p) {
|
||||
inline Point3D sgPolarToCart3d(const Point3D& p) {
|
||||
double tmp = cos( p.lat() ) * p.radius();
|
||||
|
||||
return Point3D( cos( p.lon() ) * tmp,
|
||||
@@ -57,7 +57,7 @@ inline Point3D fgPolarToCart3d(const Point3D& p) {
|
||||
|
||||
// Convert a cartesian coordinate to polar coordinates (lon/lat
|
||||
// specified in radians. Distances are specified in meters.
|
||||
inline Point3D fgCartToPolar3d(const Point3D& cp) {
|
||||
inline Point3D sgCartToPolar3d(const Point3D& cp) {
|
||||
return Point3D( atan2( cp.y(), cp.x() ),
|
||||
FG_PI_2 -
|
||||
atan2( sqrt(cp.x()*cp.x() + cp.y()*cp.y()), cp.z() ),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// fg_geodesy.cxx -- routines to convert between geodetic and geocentric
|
||||
// sg_geodesy.cxx -- routines to convert between geodetic and geocentric
|
||||
// coordinate systems.
|
||||
//
|
||||
// Copied and adapted directly from LaRCsim/ls_geodesy.c
|
||||
@@ -21,7 +21,9 @@
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include "point3d.hxx"
|
||||
#include "fg_geodesy.hxx"
|
||||
#include "sg_geodesy.hxx"
|
||||
#include "localconsts.hxx"
|
||||
|
||||
|
||||
#ifndef FG_HAVE_NATIVE_SGI_COMPILERS
|
||||
FG_USING_STD(cout);
|
||||
@@ -31,7 +33,7 @@ FG_USING_STD(cout);
|
||||
#define ONE_SECOND 4.848136811E-6
|
||||
|
||||
|
||||
// fgGeocToGeod(lat_geoc, radius, *lat_geod, *alt, *sea_level_r)
|
||||
// sgGeocToGeod(lat_geoc, radius, *lat_geod, *alt, *sea_level_r)
|
||||
// INPUTS:
|
||||
// lat_geoc Geocentric latitude, radians, + = North
|
||||
// radius C.G. radius to earth center (meters)
|
||||
@@ -43,7 +45,7 @@ FG_USING_STD(cout);
|
||||
// local vertical (surface normal) of C.G. (meters)
|
||||
|
||||
|
||||
void fgGeocToGeod( double lat_geoc, double radius, double
|
||||
void sgGeocToGeod( double lat_geoc, double radius, double
|
||||
*lat_geod, double *alt, double *sea_level_r )
|
||||
{
|
||||
double t_lat, x_alpha, mu_alpha, delt_mu, r_alpha, l_point, rho_alpha;
|
||||
@@ -89,7 +91,7 @@ void fgGeocToGeod( double lat_geoc, double radius, double
|
||||
|
||||
// check for domain error
|
||||
if ( errno == EDOM ) {
|
||||
FG_LOG( FG_GENERAL, FG_ALERT, "Domain ERROR in fgGeocToGeod!!!!" );
|
||||
FG_LOG( FG_GENERAL, FG_ALERT, "Domain ERROR in sgGeocToGeod!!!!" );
|
||||
*sea_level_r = 0.0;
|
||||
}
|
||||
}
|
||||
@@ -97,7 +99,7 @@ void fgGeocToGeod( double lat_geoc, double radius, double
|
||||
}
|
||||
|
||||
|
||||
// fgGeodToGeoc( lat_geod, alt, *sl_radius, *lat_geoc )
|
||||
// sgGeodToGeoc( lat_geod, alt, *sl_radius, *lat_geoc )
|
||||
// INPUTS:
|
||||
// lat_geod Geodetic latitude, radians, + = North
|
||||
// alt C.G. altitude above mean sea level (meters)
|
||||
@@ -109,7 +111,7 @@ void fgGeocToGeod( double lat_geoc, double radius, double
|
||||
//
|
||||
|
||||
|
||||
void fgGeodToGeoc( double lat_geod, double alt, double *sl_radius,
|
||||
void sgGeodToGeoc( double lat_geod, double alt, double *sl_radius,
|
||||
double *lat_geoc )
|
||||
{
|
||||
double lambda_sl, sin_lambda_sl, cos_lambda_sl, sin_mu, cos_mu, px, py;
|
||||
@@ -1,4 +1,4 @@
|
||||
// fg_geodesy.hxx -- routines to convert between geodetic and geocentric
|
||||
// sg_geodesy.hxx -- routines to convert between geodetic and geocentric
|
||||
// coordinate systems.
|
||||
//
|
||||
// Copied and adapted directly from LaRCsim/ls_geodesy.c
|
||||
@@ -8,8 +8,8 @@
|
||||
// $Id$
|
||||
|
||||
|
||||
#ifndef _FG_GEODESY_HXX
|
||||
#define _FG_GEODESY_HXX
|
||||
#ifndef _SG_GEODESY_HXX
|
||||
#define _SG_GEODESY_HXX
|
||||
|
||||
|
||||
#ifndef __cplusplus
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <simgear/math/polar3d.hxx>
|
||||
|
||||
|
||||
// fgGeocToGeod(lat_geoc, radius, *lat_geod, *alt, *sea_level_r)
|
||||
// sgGeocToGeod(lat_geoc, radius, *lat_geod, *alt, *sea_level_r)
|
||||
// INPUTS:
|
||||
// lat_geoc Geocentric latitude, radians, + = North
|
||||
// radius C.G. radius to earth center (meters)
|
||||
@@ -32,11 +32,11 @@
|
||||
// sea_level_r radius from earth center to sea level at
|
||||
// local vertical (surface normal) of C.G. (meters)
|
||||
|
||||
void fgGeocToGeod( double lat_geoc, double radius, double
|
||||
void sgGeocToGeod( double lat_geoc, double radius, double
|
||||
*lat_geod, double *alt, double *sea_level_r );
|
||||
|
||||
|
||||
// fgGeodToGeoc( lat_geod, alt, *sl_radius, *lat_geoc )
|
||||
// sgGeodToGeoc( lat_geod, alt, *sl_radius, *lat_geoc )
|
||||
// INPUTS:
|
||||
// lat_geod Geodetic latitude, radians, + = North
|
||||
// alt C.G. altitude above mean sea level (meters)
|
||||
@@ -47,27 +47,27 @@ void fgGeocToGeod( double lat_geoc, double radius, double
|
||||
// lat_geoc Geocentric latitude, radians, + = North
|
||||
//
|
||||
|
||||
void fgGeodToGeoc( double lat_geod, double alt, double *sl_radius,
|
||||
void sgGeodToGeoc( double lat_geod, double alt, double *sl_radius,
|
||||
double *lat_geoc );
|
||||
|
||||
|
||||
// convert a geodetic point lon(radians), lat(radians), elev(meter) to
|
||||
// a cartesian point
|
||||
|
||||
inline Point3D fgGeodToCart(const Point3D& geod) {
|
||||
inline Point3D sgGeodToCart(const Point3D& geod) {
|
||||
double gc_lon, gc_lat, sl_radius;
|
||||
|
||||
// printf("A geodetic point is (%.2f, %.2f, %.2f)\n",
|
||||
// geod[0], geod[1], geod[2]);
|
||||
|
||||
gc_lon = geod.lon();
|
||||
fgGeodToGeoc(geod.lat(), geod.radius(), &sl_radius, &gc_lat);
|
||||
sgGeodToGeoc(geod.lat(), geod.radius(), &sl_radius, &gc_lat);
|
||||
|
||||
// printf("A geocentric point is (%.2f, %.2f, %.2f)\n", gc_lon,
|
||||
// gc_lat, sl_radius+geod[2]);
|
||||
|
||||
Point3D pp = Point3D( gc_lon, gc_lat, sl_radius + geod.radius());
|
||||
return fgPolarToCart3d(pp);
|
||||
return sgPolarToCart3d(pp);
|
||||
}
|
||||
|
||||
|
||||
@@ -172,4 +172,4 @@ $Header$
|
||||
--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#endif // _FG_GEODESY_HXX
|
||||
#endif // _SG_GEODESY_HXX
|
||||
@@ -1,4 +1,4 @@
|
||||
// fg_random.c -- routines to handle random number generation
|
||||
// sg_random.c -- routines to handle random number generation
|
||||
//
|
||||
// Written by Curtis Olson, started July 1997.
|
||||
//
|
||||
@@ -30,7 +30,7 @@
|
||||
#include <stdlib.h> // for random(), srandom()
|
||||
#include <time.h> // for time() to seed srandom()
|
||||
|
||||
#include "fg_random.h"
|
||||
#include "sg_random.h"
|
||||
|
||||
#ifndef HAVE_RAND
|
||||
# ifdef sgi
|
||||
@@ -49,9 +49,7 @@
|
||||
|
||||
// Seed the random number generater with time() so we don't see the
|
||||
// same sequence every time
|
||||
void fg_srandom(void) {
|
||||
// fgPrintf( FG_MATH, FG_INFO, "Seeding random number generater\n");
|
||||
|
||||
void sg_srandom_time(void) {
|
||||
#ifdef HAVE_RAND
|
||||
srand(time(NULL));
|
||||
#else
|
||||
@@ -60,8 +58,19 @@ void fg_srandom(void) {
|
||||
}
|
||||
|
||||
|
||||
// Seed the random number generater with your own seed so can set up
|
||||
// repeatable randomization.
|
||||
void sg_srandom( unsigned int seed ) {
|
||||
#ifdef HAVE_RAND
|
||||
srand( seed );
|
||||
#else
|
||||
srandom( seed );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// return a random number between [0.0, 1.0)
|
||||
double fg_random(void) {
|
||||
double sg_random(void) {
|
||||
#ifdef HAVE_RAND
|
||||
return(rand() / (double)RAND_MAX);
|
||||
#else
|
||||
@@ -1,4 +1,4 @@
|
||||
// fg_random.h -- routines to handle random number generation
|
||||
// sg_random.h -- routines to handle random number generation
|
||||
//
|
||||
// Written by Curtis Olson, started July 1997.
|
||||
//
|
||||
@@ -22,8 +22,8 @@
|
||||
// $Id$
|
||||
|
||||
|
||||
#ifndef _FG_RANDOM_H
|
||||
#define _FG_RANDOM_H
|
||||
#ifndef _SG_RANDOM_H
|
||||
#define _SG_RANDOM_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -33,10 +33,14 @@ extern "C" {
|
||||
|
||||
// Seed the random number generater with time() so we don't see the
|
||||
// same sequence every time
|
||||
void fg_srandom(void);
|
||||
void sg_srandom_time(void);
|
||||
|
||||
// Seed the random number generater with your own seed so can set up
|
||||
// repeatable randomization.
|
||||
void sg_srandom( unsigned int seed );
|
||||
|
||||
// return a random number between [0.0, 1.0)
|
||||
double fg_random(void);
|
||||
double sg_random(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -44,6 +48,6 @@ double fg_random(void);
|
||||
#endif
|
||||
|
||||
|
||||
#endif // _FG_RANDOM_H
|
||||
#endif // _SG_RANDOM_H
|
||||
|
||||
|
||||
+51
-8
@@ -30,10 +30,54 @@
|
||||
#include "vector.hxx"
|
||||
|
||||
|
||||
// Given a point p, and a line through p0 with direction vector d,
|
||||
// find the closest point (p1) on the line
|
||||
void sgClosestPointToLine( sgVec3 p1, const sgVec3 p, const sgVec3 p0,
|
||||
const sgVec3 d ) {
|
||||
|
||||
sgVec3 u, u1;
|
||||
|
||||
// u = p - p0
|
||||
sgSubVec3(u, p, p0);
|
||||
|
||||
// calculate the projection, u1, of u along d.
|
||||
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
|
||||
sgScaleVec3( u1, d, sgScalarProductVec3(u,d) / sgScalarProductVec3(d,d) );
|
||||
|
||||
// calculate the point p1 along the line that is closest to p
|
||||
// p0 = p1 + u1
|
||||
sgAddVec3(p1, p0, u1);
|
||||
}
|
||||
|
||||
|
||||
// Given a point p, and a line through p0 with direction vector d,
|
||||
// find the closest point (p1) on the line
|
||||
void sgdClosestPointToLine( sgdVec3 p1, const sgdVec3 p, const sgdVec3 p0,
|
||||
const sgdVec3 d ) {
|
||||
|
||||
sgdVec3 u, u1;
|
||||
|
||||
// u = p - p0
|
||||
sgdSubVec3(u, p, p0);
|
||||
|
||||
// calculate the projection, u1, of u along d.
|
||||
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
|
||||
double ud = sgdScalarProductVec3(u, d);
|
||||
double dd = sgdScalarProductVec3(d, d);
|
||||
double tmp = ud / dd;
|
||||
|
||||
sgdScaleVec3(u1, d, tmp);;
|
||||
|
||||
// calculate the point p1 along the line that is closest to p
|
||||
// p0 = p1 + u1
|
||||
sgdAddVec3(p1, p0, u1);
|
||||
}
|
||||
|
||||
|
||||
// Given a point p, and a line through p0 with direction vector d,
|
||||
// find the shortest distance (squared) from the point to the line
|
||||
double sgPointLineDistSquared( const sgVec3 p, const sgVec3 p0,
|
||||
const sgVec3 d ) {
|
||||
double sgClosestPointToLineDistSquared( const sgVec3 p, const sgVec3 p0,
|
||||
const sgVec3 d ) {
|
||||
|
||||
sgVec3 u, u1, v;
|
||||
|
||||
@@ -54,20 +98,19 @@ double sgPointLineDistSquared( const sgVec3 p, const sgVec3 p0,
|
||||
|
||||
// Given a point p, and a line through p0 with direction vector d,
|
||||
// find the shortest distance (squared) from the point to the line
|
||||
double sgdPointLineDistSquared( const sgdVec3 p, const sgdVec3 p0,
|
||||
const sgdVec3 d ) {
|
||||
double sgdClosestPointToLineDistSquared( const sgdVec3 p, const sgdVec3 p0,
|
||||
const sgdVec3 d ) {
|
||||
|
||||
sgdVec3 u, u1, v;
|
||||
double ud, dd, tmp;
|
||||
|
||||
// u = p - p0
|
||||
sgdSubVec3(u, p, p0);
|
||||
|
||||
// calculate the projection, u1, of u along d.
|
||||
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
|
||||
ud = sgdScalarProductVec3(u, d);
|
||||
dd = sgdScalarProductVec3(d, d);
|
||||
tmp = ud / dd;
|
||||
double ud = sgdScalarProductVec3(u, d);
|
||||
double dd = sgdScalarProductVec3(d, d);
|
||||
double tmp = ud / dd;
|
||||
|
||||
sgdScaleVec3(u1, d, tmp);;
|
||||
|
||||
|
||||
+15
-5
@@ -93,14 +93,24 @@ inline void sgCopyNegateVec4( sgVec4 dst, sgVec4 src )
|
||||
}
|
||||
|
||||
// Given a point p, and a line through p0 with direction vector d,
|
||||
// find the shortest distance (squared) from the point to the line
|
||||
double sgPointLineDistSquared( const sgVec3 p, const sgVec3 p0,
|
||||
const sgVec3 d );
|
||||
// find the closest point (p1) on the line
|
||||
void sgClosestPointToLine( sgVec3 p1, const sgVec3 p, const sgVec3 p0,
|
||||
const sgVec3 d );
|
||||
|
||||
// Given a point p, and a line through p0 with direction vector d,
|
||||
// find the closest point (p1) on the line
|
||||
void sgdClosestPointToLine( sgdVec3 p1, const sgdVec3 p, const sgdVec3 p0,
|
||||
const sgdVec3 d );
|
||||
|
||||
// Given a point p, and a line through p0 with direction vector d,
|
||||
// find the shortest distance (squared) from the point to the line
|
||||
double sgdPointLineDistSquared( const sgdVec3 p, const sgdVec3 p0,
|
||||
const sgdVec3 d );
|
||||
double sgClosestPointToLineDistSquared( const sgVec3 p, const sgVec3 p0,
|
||||
const sgVec3 d );
|
||||
|
||||
// Given a point p, and a line through p0 with direction vector d,
|
||||
// find the shortest distance (squared) from the point to the line
|
||||
double sgdClosestPointToLineDistSquared( const sgdVec3 p, const sgdVec3 p0,
|
||||
const sgdVec3 d );
|
||||
|
||||
// This is same as
|
||||
// sgMakeMatTrans4( sgMat4 sgTrans, sgVec3 trans )
|
||||
|
||||
@@ -9,4 +9,4 @@ libsgmetar_a_SOURCES = \
|
||||
MetarStation.cpp MetarStation.h \
|
||||
Prtdmetr.cpp Stspack2.cpp Stspack3.cpp
|
||||
|
||||
INCLUDES += -I$(top_builddir)
|
||||
INCLUDES += -I$(top_srcdir)
|
||||
|
||||
@@ -86,10 +86,10 @@ CMetarStation::CMetarStation(
|
||||
double ualtitude = atoi( s ) * FEET_TO_METER;
|
||||
Point3D p( longitude, latitude, altitude+EQUATORIAL_RADIUS_M );
|
||||
m_locationPolar = p;
|
||||
m_locationCart = fgPolarToCart3d( p );
|
||||
m_locationCart = sgPolarToCart3d( p );
|
||||
Point3D up( ulongitude, ulatitude, ualtitude+EQUATORIAL_RADIUS_M );
|
||||
m_upperLocationPolar = up;
|
||||
m_upperLocationCart = fgPolarToCart3d( up );
|
||||
m_upperLocationCart = sgPolarToCart3d( up );
|
||||
s = t;
|
||||
m_pFlag = s[0];
|
||||
}
|
||||
@@ -100,44 +100,42 @@ CMetarStation::CMetarStation(
|
||||
|
||||
int CMetarStation::initialize()
|
||||
{
|
||||
// Read the list of metar stations, decoding and adding to global list.
|
||||
// Read the list of metar stations, decoding and adding to global list.
|
||||
|
||||
CMetarStation *m;
|
||||
char buf[256];
|
||||
CMetarStation *m;
|
||||
char buf[256];
|
||||
|
||||
// Goto the Flight Gear installation directory
|
||||
// Goto the Flight Gear installation directory
|
||||
#ifdef TESTPROG
|
||||
FGPath weatherPath( "/mkv/Build/FlightGear" );
|
||||
//FGPath weatherPath( "/mkv/Build/FlightGear" );
|
||||
FGPath weatherPath( ":Data" );
|
||||
#else
|
||||
FGPath weatherPath( current_options.get_fg_root() );
|
||||
#endif
|
||||
|
||||
weatherPath.append( "Weather/MetarStations" );
|
||||
// Open the metar station list
|
||||
FILE *f = fopen( weatherPath.c_str(), "r" );
|
||||
weatherPath.append( "Weather" );
|
||||
weatherPath.append( "MetarStations" );
|
||||
// Open the metar station list
|
||||
FILE *f = fopen( weatherPath.c_str(), "r" );
|
||||
|
||||
|
||||
if ( f != NULL )
|
||||
{
|
||||
// Read each line, create an instance of a station, and add it to the vector
|
||||
while ( fgets( buf, 256, f) != NULL && feof( f ) == 0 )
|
||||
{
|
||||
//std::cout << buf << std::endl;
|
||||
m = new CMetarStation( buf );
|
||||
//m->dump();
|
||||
METAR_Stations.push_back( m );
|
||||
}
|
||||
if ( f != NULL ) {
|
||||
// Read each line, create an instance of a station, and add it to the vector
|
||||
while ( fgets( buf, 256, f) != NULL && feof( f ) == 0 ) {
|
||||
//std::cout << buf << std::endl;
|
||||
m = new CMetarStation( buf );
|
||||
//m->dump();
|
||||
METAR_Stations.push_back( m );
|
||||
}
|
||||
|
||||
// Close the list
|
||||
fclose( f );
|
||||
std::cout << METAR_Stations.size() << " Metar stations" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Could not open MetarStations file " << std::endl;
|
||||
return 0;
|
||||
}
|
||||
// Close the list
|
||||
fclose( f );
|
||||
// std::cout << METAR_Stations.size() << " Metar stations" << std::endl;
|
||||
return 1;
|
||||
} else {
|
||||
// std::cout << "Could not open MetarStations file " << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ includedir = @includedir@/misc
|
||||
if HAVE_ZLIB
|
||||
ZLIB_INCL =
|
||||
else
|
||||
ZLIB_INCL = -I$(top_builddir)/src/zlib
|
||||
ZLIB_INCL = -I$(top_srcdir)/src/zlib
|
||||
endif
|
||||
|
||||
lib_LIBRARIES = libsgmisc.a
|
||||
@@ -21,8 +21,9 @@ libsgmisc_a_SOURCES = \
|
||||
fgpath.cxx \
|
||||
fgstream.cxx \
|
||||
props.cxx \
|
||||
props_io.cxx \
|
||||
strutils.cxx \
|
||||
texcoord.cxx \
|
||||
zfstream.cxx
|
||||
|
||||
INCLUDES += -I$(top_builddir) $(ZLIB_INCL)
|
||||
INCLUDES += -I$(top_srcdir) $(ZLIB_INCL)
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
FG_USING_STD(string);
|
||||
|
||||
|
||||
#ifdef MACOS
|
||||
#ifdef macintosh
|
||||
# define FG_PATH_SEP ':'
|
||||
# define FG_BAD_PATH_SEP '/'
|
||||
#else
|
||||
|
||||
+325
-102
@@ -264,7 +264,7 @@ SGValue::getBoolValue () const
|
||||
return (getRawDouble() == 0.0 ? false : true);
|
||||
case UNKNOWN:
|
||||
case STRING:
|
||||
return ((getRawString() == "false" || getIntValue() == 0) ? false : true);
|
||||
return ((getRawString() == "true" || getIntValue() != 0) ? true : false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -304,8 +304,6 @@ float
|
||||
SGValue::getFloatValue () const
|
||||
{
|
||||
switch (_type) {
|
||||
case UNKNOWN:
|
||||
return 0.0;
|
||||
case BOOL:
|
||||
return (float)(getRawBool());
|
||||
case INT:
|
||||
@@ -314,6 +312,7 @@ SGValue::getFloatValue () const
|
||||
return getRawFloat();
|
||||
case DOUBLE:
|
||||
return (float)(getRawDouble());
|
||||
case UNKNOWN:
|
||||
case STRING:
|
||||
return (float)atof(getRawString().c_str());
|
||||
}
|
||||
@@ -330,8 +329,6 @@ double
|
||||
SGValue::getDoubleValue () const
|
||||
{
|
||||
switch (_type) {
|
||||
case UNKNOWN:
|
||||
return 0.0;
|
||||
case BOOL:
|
||||
return (double)(getRawBool());
|
||||
case INT:
|
||||
@@ -340,6 +337,7 @@ SGValue::getDoubleValue () const
|
||||
return (double)(getRawFloat());
|
||||
case DOUBLE:
|
||||
return getRawDouble();
|
||||
case UNKNOWN:
|
||||
case STRING:
|
||||
return atof(getRawString().c_str());
|
||||
}
|
||||
@@ -357,8 +355,6 @@ SGValue::getStringValue () const
|
||||
{
|
||||
char buf[512];
|
||||
switch (_type) {
|
||||
case UNKNOWN:
|
||||
return getRawString();
|
||||
case BOOL:
|
||||
if (getRawBool())
|
||||
string_val = "true";
|
||||
@@ -377,6 +373,7 @@ SGValue::getStringValue () const
|
||||
sprintf(buf, "%f", getRawDouble());
|
||||
string_val = buf;
|
||||
return string_val;
|
||||
case UNKNOWN:
|
||||
case STRING:
|
||||
return getRawString();
|
||||
}
|
||||
@@ -392,12 +389,24 @@ SGValue::getStringValue () const
|
||||
bool
|
||||
SGValue::setBoolValue (bool value)
|
||||
{
|
||||
if (_type == UNKNOWN || _type == BOOL) {
|
||||
_type = BOOL;
|
||||
if (_type == UNKNOWN)
|
||||
_type = INT;
|
||||
switch (_type) {
|
||||
case BOOL:
|
||||
return setRawBool(value);
|
||||
} else {
|
||||
return false;
|
||||
case INT:
|
||||
return setRawInt((int)value);
|
||||
case FLOAT:
|
||||
return setRawFloat((float)value);
|
||||
case DOUBLE:
|
||||
return setRawDouble((double)value);
|
||||
case STRING:
|
||||
if (value)
|
||||
return setRawString("true");
|
||||
else
|
||||
return setRawString("false");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -409,12 +418,26 @@ SGValue::setBoolValue (bool value)
|
||||
bool
|
||||
SGValue::setIntValue (int value)
|
||||
{
|
||||
if (_type == UNKNOWN || _type == INT) {
|
||||
if (_type == UNKNOWN)
|
||||
_type = INT;
|
||||
switch (_type) {
|
||||
case BOOL:
|
||||
if (value == 0)
|
||||
return setRawBool(false);
|
||||
else
|
||||
return setRawBool(true);
|
||||
case INT:
|
||||
return setRawInt(value);
|
||||
} else {
|
||||
return false;
|
||||
case FLOAT:
|
||||
return setRawFloat((float)value);
|
||||
case DOUBLE:
|
||||
return setRawDouble((double)value);
|
||||
case STRING:
|
||||
char buf[128];
|
||||
sprintf(buf, "%d", value);
|
||||
return setRawString(buf);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -426,12 +449,26 @@ SGValue::setIntValue (int value)
|
||||
bool
|
||||
SGValue::setFloatValue (float value)
|
||||
{
|
||||
if (_type == UNKNOWN || _type == FLOAT) {
|
||||
if (_type == UNKNOWN)
|
||||
_type = FLOAT;
|
||||
switch (_type) {
|
||||
case BOOL:
|
||||
if (value == 0.0)
|
||||
return setRawBool(false);
|
||||
else
|
||||
return setRawBool(true);
|
||||
case INT:
|
||||
return setRawInt((int)value);
|
||||
case FLOAT:
|
||||
return setRawFloat(value);
|
||||
} else {
|
||||
return false;
|
||||
case DOUBLE:
|
||||
return setRawDouble((double)value);
|
||||
case STRING:
|
||||
char buf[128];
|
||||
sprintf(buf, "%f", value);
|
||||
return setRawString(buf);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -443,12 +480,26 @@ SGValue::setFloatValue (float value)
|
||||
bool
|
||||
SGValue::setDoubleValue (double value)
|
||||
{
|
||||
if (_type == UNKNOWN || _type == DOUBLE) {
|
||||
if (_type == UNKNOWN)
|
||||
_type = DOUBLE;
|
||||
switch (_type) {
|
||||
case BOOL:
|
||||
if (value == 0.0L)
|
||||
return setRawBool(false);
|
||||
else
|
||||
return setRawBool(true);
|
||||
case INT:
|
||||
return setRawInt((int)value);
|
||||
case FLOAT:
|
||||
return setRawFloat((float)value);
|
||||
case DOUBLE:
|
||||
return setRawDouble(value);
|
||||
} else {
|
||||
return false;
|
||||
case STRING:
|
||||
char buf[128];
|
||||
sprintf(buf, "%lf", value);
|
||||
return setRawString(buf);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -460,12 +511,25 @@ SGValue::setDoubleValue (double value)
|
||||
bool
|
||||
SGValue::setStringValue (const string &value)
|
||||
{
|
||||
if (_type == UNKNOWN || _type == STRING) {
|
||||
if (_type == UNKNOWN)
|
||||
_type = STRING;
|
||||
|
||||
switch (_type) {
|
||||
case BOOL:
|
||||
if (value == "true" || atoi(value.c_str()) != 0)
|
||||
return setRawBool(true);
|
||||
else
|
||||
return setRawBool(false);
|
||||
case INT:
|
||||
return setRawInt(atoi(value.c_str()));
|
||||
case FLOAT:
|
||||
return setRawFloat(atof(value.c_str()));
|
||||
case DOUBLE:
|
||||
return setRawDouble(atof(value.c_str()));
|
||||
case STRING:
|
||||
return setRawString(value);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -477,11 +541,23 @@ SGValue::setStringValue (const string &value)
|
||||
bool
|
||||
SGValue::setUnknownValue (const string &value)
|
||||
{
|
||||
if (_type == UNKNOWN || _type == STRING) {
|
||||
switch (_type) {
|
||||
case BOOL:
|
||||
if (value == "true" || atoi(value.c_str()) != 0)
|
||||
return setRawBool(true);
|
||||
else
|
||||
return setRawBool(false);
|
||||
case INT:
|
||||
return setRawInt(atoi(value.c_str()));
|
||||
case FLOAT:
|
||||
return setRawFloat(atof(value.c_str()));
|
||||
case DOUBLE:
|
||||
return setRawDouble(atof(value.c_str()));
|
||||
case STRING:
|
||||
case UNKNOWN:
|
||||
return setRawString(value);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -494,13 +570,13 @@ SGValue::setUnknownValue (const string &value)
|
||||
* Returns true on success (i.e. the value is not currently tied).
|
||||
*/
|
||||
bool
|
||||
SGValue::tieBool (bool_getter getter, bool_setter setter = 0,
|
||||
bool useDefault = true)
|
||||
SGValue::tieBool (bool_getter getter, bool_setter setter,
|
||||
bool useDefault)
|
||||
{
|
||||
if (_tied) {
|
||||
return false;
|
||||
} else {
|
||||
if (useDefault && setter && _type != UNKNOWN)
|
||||
if (useDefault && setter)
|
||||
(*setter)(getBoolValue());
|
||||
_tied = true;
|
||||
_type = BOOL;
|
||||
@@ -520,13 +596,13 @@ SGValue::tieBool (bool_getter getter, bool_setter setter = 0,
|
||||
* Returns true on success (i.e. the value is not currently tied).
|
||||
*/
|
||||
bool
|
||||
SGValue::tieInt (int_getter getter, int_setter setter = 0,
|
||||
bool useDefault = true)
|
||||
SGValue::tieInt (int_getter getter, int_setter setter,
|
||||
bool useDefault)
|
||||
{
|
||||
if (_tied) {
|
||||
return false;
|
||||
} else {
|
||||
if (useDefault && setter && _type != UNKNOWN)
|
||||
if (useDefault && setter)
|
||||
(*setter)(getIntValue());
|
||||
_tied = true;
|
||||
_type = INT;
|
||||
@@ -546,13 +622,13 @@ SGValue::tieInt (int_getter getter, int_setter setter = 0,
|
||||
* Returns true on success (i.e. the value is not currently tied).
|
||||
*/
|
||||
bool
|
||||
SGValue::tieFloat (float_getter getter, float_setter setter = 0,
|
||||
bool useDefault = true)
|
||||
SGValue::tieFloat (float_getter getter, float_setter setter,
|
||||
bool useDefault)
|
||||
{
|
||||
if (_tied) {
|
||||
return false;
|
||||
} else {
|
||||
if (useDefault && setter && _type != UNKNOWN)
|
||||
if (useDefault && setter)
|
||||
(*setter)(getFloatValue());
|
||||
_tied = true;
|
||||
_type = FLOAT;
|
||||
@@ -572,13 +648,13 @@ SGValue::tieFloat (float_getter getter, float_setter setter = 0,
|
||||
* Returns true on success (i.e. the value is not currently tied).
|
||||
*/
|
||||
bool
|
||||
SGValue::tieDouble (double_getter getter, double_setter setter = 0,
|
||||
bool useDefault = true)
|
||||
SGValue::tieDouble (double_getter getter, double_setter setter,
|
||||
bool useDefault)
|
||||
{
|
||||
if (_tied) {
|
||||
return false;
|
||||
} else {
|
||||
if (useDefault && setter && _type != UNKNOWN)
|
||||
if (useDefault && setter)
|
||||
(*setter)(getDoubleValue());
|
||||
_tied = true;
|
||||
_type = DOUBLE;
|
||||
@@ -598,13 +674,13 @@ SGValue::tieDouble (double_getter getter, double_setter setter = 0,
|
||||
* Returns true on success (i.e. the value is not currently tied).
|
||||
*/
|
||||
bool
|
||||
SGValue::tieString (string_getter getter, string_setter setter = 0,
|
||||
bool useDefault = true)
|
||||
SGValue::tieString (string_getter getter, string_setter setter,
|
||||
bool useDefault)
|
||||
{
|
||||
if (_tied) {
|
||||
return false;
|
||||
} else {
|
||||
if (useDefault && setter && _type != UNKNOWN)
|
||||
if (useDefault && setter)
|
||||
(*setter)(getStringValue());
|
||||
_tied = true;
|
||||
_type = STRING;
|
||||
@@ -688,6 +764,20 @@ SGPropertyList::~SGPropertyList ()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if a value is present.
|
||||
*/
|
||||
bool
|
||||
SGPropertyList::hasValue (const string &name) const
|
||||
{
|
||||
const_iterator el = _props.find(name);
|
||||
if (el == _props.end())
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Look up the SGValue structure associated with a property.
|
||||
*
|
||||
@@ -696,14 +786,14 @@ SGPropertyList::~SGPropertyList ()
|
||||
* and must not end with '/'.
|
||||
*/
|
||||
SGValue *
|
||||
SGPropertyList::getValue (const string &name, bool create = false)
|
||||
SGPropertyList::getValue (const string &name, bool create)
|
||||
{
|
||||
const_iterator el = _props.find(name);
|
||||
if (el == _props.end()) {
|
||||
if (!create)
|
||||
return 0;
|
||||
else {
|
||||
FG_LOG(FG_GENERAL, FG_INFO, "Creating new property '" << name << '\'');
|
||||
FG_LOG(FG_GENERAL, FG_DEBUG, "Creating new property '" << name << '\'');
|
||||
if (name.size() == 0 ||
|
||||
name[0] != '/' ||
|
||||
name[name.size()-1] == '/' ||
|
||||
@@ -739,11 +829,11 @@ SGPropertyList::getValue (const string &name) const
|
||||
* better to get the SGValue and query it repeatedly.
|
||||
*/
|
||||
bool
|
||||
SGPropertyList::getBoolValue (const string &name) const
|
||||
SGPropertyList::getBoolValue (const string &name, bool defaultValue) const
|
||||
{
|
||||
const SGValue * val = getValue(name);
|
||||
if (val == 0)
|
||||
return false;
|
||||
return defaultValue;
|
||||
else
|
||||
return val->getBoolValue();
|
||||
}
|
||||
@@ -756,11 +846,11 @@ SGPropertyList::getBoolValue (const string &name) const
|
||||
* better to get the SGValue and query it repeatedly.
|
||||
*/
|
||||
int
|
||||
SGPropertyList::getIntValue (const string &name) const
|
||||
SGPropertyList::getIntValue (const string &name, int defaultValue) const
|
||||
{
|
||||
const SGValue * val = getValue(name);
|
||||
if (val == 0)
|
||||
return 0;
|
||||
return defaultValue;
|
||||
else
|
||||
return val->getIntValue();
|
||||
}
|
||||
@@ -773,11 +863,11 @@ SGPropertyList::getIntValue (const string &name) const
|
||||
* better to get the SGValue and query it repeatedly.
|
||||
*/
|
||||
float
|
||||
SGPropertyList::getFloatValue (const string &name) const
|
||||
SGPropertyList::getFloatValue (const string &name, float defaultValue) const
|
||||
{
|
||||
const SGValue * val = getValue(name);
|
||||
if (val == 0)
|
||||
return 0.0;
|
||||
return defaultValue;
|
||||
else
|
||||
return val->getFloatValue();
|
||||
}
|
||||
@@ -790,11 +880,11 @@ SGPropertyList::getFloatValue (const string &name) const
|
||||
* better to get the SGValue and query it repeatedly.
|
||||
*/
|
||||
double
|
||||
SGPropertyList::getDoubleValue (const string &name) const
|
||||
SGPropertyList::getDoubleValue (const string &name, double defaultValue) const
|
||||
{
|
||||
const SGValue * val = getValue(name);
|
||||
if (val == 0)
|
||||
return 0.0;
|
||||
return defaultValue;
|
||||
else
|
||||
return val->getDoubleValue();
|
||||
}
|
||||
@@ -807,11 +897,12 @@ SGPropertyList::getDoubleValue (const string &name) const
|
||||
* better to save the SGValue and query it repeatedly.
|
||||
*/
|
||||
const string &
|
||||
SGPropertyList::getStringValue (const string &name) const
|
||||
SGPropertyList::getStringValue (const string &name,
|
||||
const string &defaultValue) const
|
||||
{
|
||||
const SGValue * val = getValue(name);
|
||||
if (val == 0)
|
||||
return empty_string;
|
||||
return defaultValue;
|
||||
else
|
||||
return val->getStringValue();
|
||||
}
|
||||
@@ -916,9 +1007,10 @@ bool
|
||||
SGPropertyList::tieBool (const string &name,
|
||||
bool_getter getter,
|
||||
bool_setter setter,
|
||||
bool useDefault = true)
|
||||
bool useDefault)
|
||||
{
|
||||
FG_LOG(FG_GENERAL, FG_INFO, "Tying bool property '" << name << '\'');
|
||||
FG_LOG(FG_GENERAL, FG_DEBUG, "Tying bool property '" << name << '\'');
|
||||
useDefault = useDefault && hasValue(name);
|
||||
return getValue(name, true)->tieBool(getter, setter, useDefault);
|
||||
}
|
||||
|
||||
@@ -932,9 +1024,10 @@ bool
|
||||
SGPropertyList::tieInt (const string &name,
|
||||
int_getter getter,
|
||||
int_setter setter,
|
||||
bool useDefault = true)
|
||||
bool useDefault)
|
||||
{
|
||||
FG_LOG(FG_GENERAL, FG_INFO, "Tying int property '" << name << '\'');
|
||||
FG_LOG(FG_GENERAL, FG_DEBUG, "Tying int property '" << name << '\'');
|
||||
useDefault = useDefault && hasValue(name);
|
||||
return getValue(name, true)->tieInt(getter, setter, useDefault);
|
||||
}
|
||||
|
||||
@@ -948,9 +1041,10 @@ bool
|
||||
SGPropertyList::tieFloat (const string &name,
|
||||
float_getter getter,
|
||||
float_setter setter,
|
||||
bool useDefault = true)
|
||||
bool useDefault)
|
||||
{
|
||||
FG_LOG(FG_GENERAL, FG_INFO, "Tying float property '" << name << '\'');
|
||||
FG_LOG(FG_GENERAL, FG_DEBUG, "Tying float property '" << name << '\'');
|
||||
useDefault = useDefault && hasValue(name);
|
||||
return getValue(name, true)->tieFloat(getter, setter, useDefault);
|
||||
}
|
||||
|
||||
@@ -964,9 +1058,10 @@ bool
|
||||
SGPropertyList::tieDouble (const string &name,
|
||||
double_getter getter,
|
||||
double_setter setter,
|
||||
bool useDefault = true)
|
||||
bool useDefault)
|
||||
{
|
||||
FG_LOG(FG_GENERAL, FG_INFO, "Tying double property '" << name << '\'');
|
||||
FG_LOG(FG_GENERAL, FG_DEBUG, "Tying double property '" << name << '\'');
|
||||
useDefault = useDefault && hasValue(name);
|
||||
return getValue(name, true)->tieDouble(getter, setter, useDefault);
|
||||
}
|
||||
|
||||
@@ -980,9 +1075,10 @@ bool
|
||||
SGPropertyList::tieString (const string &name,
|
||||
string_getter getter,
|
||||
string_setter setter,
|
||||
bool useDefault = true)
|
||||
bool useDefault)
|
||||
{
|
||||
FG_LOG(FG_GENERAL, FG_INFO, "Tying string property '" << name << '\'');
|
||||
FG_LOG(FG_GENERAL, FG_DEBUG, "Tying string property '" << name << '\'');
|
||||
useDefault = useDefault && hasValue(name);
|
||||
return getValue(name, true)->tieString(getter, setter, useDefault);
|
||||
}
|
||||
|
||||
@@ -995,7 +1091,7 @@ SGPropertyList::tieString (const string &name,
|
||||
bool
|
||||
SGPropertyList::untie (const string &name)
|
||||
{
|
||||
FG_LOG(FG_GENERAL, FG_INFO, "Untying property '" << name << '\'');
|
||||
FG_LOG(FG_GENERAL, FG_DEBUG, "Untying property '" << name << '\'');
|
||||
return getValue(name, true)->untie();
|
||||
}
|
||||
|
||||
@@ -1039,9 +1135,9 @@ get_base (const string &parent, const string &child,
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
SGPropertyNode::SGPropertyNode (const string &path = "",
|
||||
SGPropertyList * props = 0)
|
||||
: _props(props)
|
||||
SGPropertyNode::SGPropertyNode (const string &path,
|
||||
SGPropertyList * props)
|
||||
: _props(props), _node(0)
|
||||
{
|
||||
setPath(path);
|
||||
}
|
||||
@@ -1052,6 +1148,8 @@ SGPropertyNode::SGPropertyNode (const string &path = "",
|
||||
*/
|
||||
SGPropertyNode::~SGPropertyNode ()
|
||||
{
|
||||
delete _node;
|
||||
_node = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1089,24 +1187,6 @@ SGPropertyNode::getName () const
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the value of the current node.
|
||||
*
|
||||
* Currently, this does a lookup each time, but we could cache the
|
||||
* value safely as long as it's non-zero.
|
||||
*
|
||||
* Note that this will not create the value if it doesn't already exist.
|
||||
*/
|
||||
SGValue *
|
||||
SGPropertyNode::getValue ()
|
||||
{
|
||||
if (_props == 0 || _path.size() == 0)
|
||||
return 0;
|
||||
else
|
||||
return _props->getValue(_path);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the number of children for the current node.
|
||||
*/
|
||||
@@ -1143,17 +1223,18 @@ SGPropertyNode::size () const
|
||||
* A return value of true means success; otherwise, the node supplied
|
||||
* is unmodified.
|
||||
*/
|
||||
bool
|
||||
SGPropertyNode::getParent (SGPropertyNode &parent) const
|
||||
SGPropertyNode &
|
||||
SGPropertyNode::getParent () const
|
||||
{
|
||||
if (_node == 0)
|
||||
_node = new SGPropertyNode();
|
||||
|
||||
string::size_type pos = _path.rfind('/');
|
||||
if (pos != string::npos) {
|
||||
parent.setPath(_path.substr(0, pos-1));
|
||||
parent.setPropertyList(_props);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
_node->setPropertyList(_props);
|
||||
_node->setPath(_path.substr(0, pos-1));
|
||||
}
|
||||
return *_node;
|
||||
}
|
||||
|
||||
|
||||
@@ -1163,11 +1244,14 @@ SGPropertyNode::getParent (SGPropertyNode &parent) const
|
||||
* A return value of true means success; otherwise, the node supplied
|
||||
* is unmodified.
|
||||
*/
|
||||
bool
|
||||
SGPropertyNode::getChild (SGPropertyNode &child, int n) const
|
||||
SGPropertyNode &
|
||||
SGPropertyNode::getChild (int n) const
|
||||
{
|
||||
if (_node == 0)
|
||||
_node = new SGPropertyNode();
|
||||
|
||||
if (_props == 0)
|
||||
return false;
|
||||
return *_node;
|
||||
|
||||
int s = 0;
|
||||
string base;
|
||||
@@ -1180,12 +1264,9 @@ SGPropertyNode::getChild (SGPropertyNode &child, int n) const
|
||||
while (it != end) {
|
||||
if (get_base(pattern, it->first, base) && base != lastBase) {
|
||||
if (s == n) {
|
||||
string path = _path;
|
||||
path += '/';
|
||||
path += base;
|
||||
child.setPath(path);
|
||||
child.setPropertyList(_props);
|
||||
return true;
|
||||
_node->setPropertyList(_props);
|
||||
_node->setPath(_path + string("/") + base);
|
||||
return *_node;
|
||||
} else {
|
||||
s++;
|
||||
lastBase = base;
|
||||
@@ -1194,7 +1275,149 @@ SGPropertyNode::getChild (SGPropertyNode &child, int n) const
|
||||
it++;
|
||||
}
|
||||
|
||||
return false;
|
||||
return *_node;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a node for an arbitrary subpath.
|
||||
*
|
||||
* Never returns 0.
|
||||
*/
|
||||
SGPropertyNode &
|
||||
SGPropertyNode::getSubNode (const string &subpath) const
|
||||
{
|
||||
if (_node == 0)
|
||||
_node = new SGPropertyNode();
|
||||
|
||||
_node->setPropertyList(_props);
|
||||
_node->setPath(_path + string("/") + subpath);
|
||||
return *_node;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test whether the specified subpath has a value.
|
||||
*/
|
||||
bool
|
||||
SGPropertyNode::hasValue (const string &subpath) const
|
||||
{
|
||||
if (_props == 0)
|
||||
return false;
|
||||
|
||||
if (subpath.size() == 0)
|
||||
return _props->hasValue(_path);
|
||||
else
|
||||
return _props->hasValue(_path + string("/") + subpath);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the value of the current node.
|
||||
*
|
||||
* Currently, this does a lookup each time, but we could cache the
|
||||
* value safely as long as it's non-zero.
|
||||
*
|
||||
* Note that this will not create the value if it doesn't already exist.
|
||||
*/
|
||||
SGValue *
|
||||
SGPropertyNode::getValue (const string &subpath)
|
||||
{
|
||||
if (_props == 0)
|
||||
return 0;
|
||||
|
||||
if (subpath.size() == 0)
|
||||
return _props->getValue(_path);
|
||||
else
|
||||
return _props->getValue(_path + string("/") + subpath);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a bool value.
|
||||
*/
|
||||
bool
|
||||
SGPropertyNode::getBoolValue (const string &subpath, bool defaultValue) const
|
||||
{
|
||||
if (_props == 0)
|
||||
return defaultValue;
|
||||
|
||||
if (subpath == "")
|
||||
return _props->getBoolValue(_path, defaultValue);
|
||||
else
|
||||
return _props->getBoolValue(_path + string("/") + subpath,
|
||||
defaultValue);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an int value.
|
||||
*/
|
||||
int
|
||||
SGPropertyNode::getIntValue (const string &subpath, int defaultValue) const
|
||||
{
|
||||
if (_props == 0)
|
||||
return defaultValue;
|
||||
|
||||
if (subpath == "")
|
||||
return _props->getIntValue(_path, defaultValue);
|
||||
else
|
||||
return _props->getIntValue(_path + string("/") + subpath,
|
||||
defaultValue);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a float value.
|
||||
*/
|
||||
float
|
||||
SGPropertyNode::getFloatValue (const string &subpath, float defaultValue) const
|
||||
{
|
||||
if (_props == 0)
|
||||
return defaultValue;
|
||||
|
||||
if (subpath == "")
|
||||
return _props->getFloatValue(_path, defaultValue);
|
||||
else
|
||||
return _props->getFloatValue(_path + string("/") + subpath,
|
||||
defaultValue);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a double value.
|
||||
*/
|
||||
double
|
||||
SGPropertyNode::getDoubleValue (const string &subpath,
|
||||
double defaultValue) const
|
||||
{
|
||||
if (_props == 0)
|
||||
return defaultValue;
|
||||
|
||||
if (subpath == "")
|
||||
return _props->getDoubleValue(_path, defaultValue);
|
||||
else
|
||||
return _props->getDoubleValue(_path + string("/") + subpath,
|
||||
defaultValue);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a string value.
|
||||
*/
|
||||
const string &
|
||||
SGPropertyNode::getStringValue (const string &subpath,
|
||||
const string &defaultValue) const
|
||||
{
|
||||
if (_props == 0)
|
||||
return defaultValue;
|
||||
|
||||
if (subpath == "")
|
||||
return _props->getStringValue(_path, defaultValue);
|
||||
else
|
||||
return _props->getStringValue(_path + string("/") + subpath,
|
||||
defaultValue);
|
||||
}
|
||||
|
||||
|
||||
// end of props.cxx
|
||||
|
||||
+86
-11
@@ -19,9 +19,42 @@
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
||||
using std::string;
|
||||
using std::map;
|
||||
using std::istream;
|
||||
using std::ostream;
|
||||
|
||||
#ifdef UNKNOWN
|
||||
#pragma warn A sloppy coder has defined UNKNOWN as a macro!
|
||||
#undef UNKNOWN
|
||||
#endif
|
||||
|
||||
#ifdef BOOL
|
||||
#pragma warn A sloppy coder has defined BOOL as a macro!
|
||||
#undef BOOL
|
||||
#endif
|
||||
|
||||
#ifdef INT
|
||||
#pragma warn A sloppy coder has defined INT as a macro!
|
||||
#undef INT
|
||||
#endif
|
||||
|
||||
#ifdef FLOAT
|
||||
#pragma warn A sloppy coder has defined FLOAT as a macro!
|
||||
#undef FLOAT
|
||||
#endif
|
||||
|
||||
#ifdef DOUBLE
|
||||
#pragma warn A sloppy coder has defined DOUBLE as a macro!
|
||||
#undef DOUBLE
|
||||
#endif
|
||||
|
||||
#ifdef STRING
|
||||
#pragma warn A sloppy coder has defined STRING as a macro!
|
||||
#undef STRING
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -80,7 +113,7 @@ public:
|
||||
virtual int getIntValue () const;
|
||||
virtual float getFloatValue () const;
|
||||
virtual double getDoubleValue () const;
|
||||
virtual const string &getStringValue () const;
|
||||
virtual const string & getStringValue () const;
|
||||
|
||||
// Setters.
|
||||
virtual bool setBoolValue (bool value);
|
||||
@@ -228,14 +261,22 @@ public:
|
||||
virtual const_iterator begin () const { return _props.begin(); }
|
||||
virtual const_iterator end () const { return _props.end(); }
|
||||
|
||||
virtual bool hasValue (const string &name) const;
|
||||
|
||||
virtual SGValue * getValue (const string &name, bool create = false);
|
||||
virtual const SGValue * getValue (const string &name) const;
|
||||
|
||||
virtual bool getBoolValue (const string &name) const;
|
||||
virtual int getIntValue (const string &name) const;
|
||||
virtual float getFloatValue (const string &name) const;
|
||||
virtual double getDoubleValue (const string &name) const;
|
||||
virtual const string &getStringValue (const string &name) const;
|
||||
virtual bool getBoolValue (const string &name,
|
||||
bool defaultValue = false) const;
|
||||
virtual int getIntValue (const string &name,
|
||||
int defaultValue = 0) const;
|
||||
virtual float getFloatValue (const string &name,
|
||||
float defaultValue = 0.0) const;
|
||||
virtual double getDoubleValue (const string &name,
|
||||
double defaultValue = 0.0L) const;
|
||||
virtual const string & getStringValue (const string &name,
|
||||
const string &defaultValue = "")
|
||||
const;
|
||||
|
||||
virtual bool setBoolValue (const string &name, bool value);
|
||||
virtual bool setIntValue (const string &name, int value);
|
||||
@@ -331,17 +372,51 @@ public:
|
||||
// Accessors for derived information.
|
||||
virtual int size () const;
|
||||
virtual const string &getName () const;
|
||||
virtual SGValue * getValue ();
|
||||
virtual bool getParent (SGPropertyNode &parent) const;
|
||||
virtual bool getChild (SGPropertyNode &child, int n) const;
|
||||
virtual SGPropertyNode &getParent () const;
|
||||
virtual SGPropertyNode &getChild (int n) const;
|
||||
virtual SGPropertyNode &getSubNode (const string &subpath) const;
|
||||
|
||||
// Check for a value.
|
||||
virtual bool hasValue (const string &subpath = "") const;
|
||||
|
||||
// Get values directly.
|
||||
virtual SGValue * getValue (const string &subpath = "");
|
||||
virtual bool getBoolValue (const string &subpath = "",
|
||||
bool defaultValue = false) const;
|
||||
virtual int getIntValue (const string &subpath = "",
|
||||
int defaultValue = 0) const;
|
||||
virtual float getFloatValue (const string &subpath = "",
|
||||
float defaultValue = 0.0) const;
|
||||
virtual double getDoubleValue (const string &subpath = "",
|
||||
double defaultValue = 0.0L) const;
|
||||
virtual const string &
|
||||
getStringValue (const string &subpath = "",
|
||||
const string &defaultValue = "") const;
|
||||
|
||||
private:
|
||||
string _path;
|
||||
mutable string _name; // for pointer persistence only
|
||||
SGPropertyList * _props;
|
||||
// for pointer persistence...
|
||||
// NOT THREAD SAFE!!!
|
||||
// (each thread must have its own node
|
||||
// object)
|
||||
mutable string _name;
|
||||
mutable SGPropertyNode * _node;
|
||||
};
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Input and output.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern bool readPropertyList (istream &input, SGPropertyList * props);
|
||||
extern bool readPropertyList (const string &file, SGPropertyList * props);
|
||||
extern bool writePropertyList (ostream &output, const SGPropertyList * props);
|
||||
extern bool writePropertyList (const string &file,
|
||||
const SGPropertyList * props);
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Global property manager.
|
||||
@@ -350,6 +425,6 @@ private:
|
||||
extern SGPropertyList current_properties;
|
||||
|
||||
|
||||
#endif __PROPS_HXX
|
||||
#endif // __PROPS_HXX
|
||||
|
||||
// end of props.hxx
|
||||
|
||||
@@ -0,0 +1,369 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h> // strcmp()
|
||||
#include <stdlib.h> // atof() atoi()
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/xml/easyxml.hxx>
|
||||
|
||||
#include "props.hxx"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
FG_USING_STD(ofstream);
|
||||
FG_USING_STD(ifstream);
|
||||
FG_USING_STD(string);
|
||||
FG_USING_STD(vector);
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Visitor class for building the property list.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class PropVisitor : public XMLVisitor
|
||||
{
|
||||
public:
|
||||
PropVisitor (SGPropertyList * props) : _props(props), _level(0), _ok(true) {}
|
||||
void startDocument ();
|
||||
void startElement (const char * name, const XMLAttributes &atts);
|
||||
void endElement (const char * name);
|
||||
void data (const char * s, int length);
|
||||
void warning (const char * message, int line, int col);
|
||||
void error (const char * message, int line, int col);
|
||||
|
||||
bool isOK () const { return _ok; }
|
||||
|
||||
private:
|
||||
|
||||
void pushState (const char * name) {
|
||||
_states.push_back(_state);
|
||||
_level++;
|
||||
_state.name = name;
|
||||
_state.type = SGValue::UNKNOWN;
|
||||
_state.data = "";
|
||||
_state.hasChildren = false;
|
||||
_state.hasData = false;
|
||||
}
|
||||
|
||||
void popState () {
|
||||
_state = _states.back();
|
||||
_states.pop_back();
|
||||
_level--;
|
||||
}
|
||||
|
||||
struct State
|
||||
{
|
||||
State () : hasChildren(false), hasData(false) {}
|
||||
string name;
|
||||
SGValue::Type type;
|
||||
string data;
|
||||
bool hasChildren;
|
||||
bool hasData;
|
||||
};
|
||||
|
||||
SGPropertyList * _props;
|
||||
State _state;
|
||||
vector<State> _states;
|
||||
int _level;
|
||||
bool _ok;
|
||||
};
|
||||
|
||||
void
|
||||
PropVisitor::startDocument ()
|
||||
{
|
||||
_level = 0;
|
||||
_ok = true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PropVisitor::startElement (const char * name, const XMLAttributes &atts)
|
||||
{
|
||||
if (!_ok)
|
||||
return;
|
||||
|
||||
if (_level == 0 && strcmp(name, "PropertyList")) {
|
||||
_ok = false;
|
||||
FG_LOG(FG_INPUT, FG_ALERT, "XML document has root element \""
|
||||
<< name << "\" instead of \"PropertyList\"");
|
||||
return;
|
||||
}
|
||||
|
||||
// Mixed content?
|
||||
_state.hasChildren = true;
|
||||
if (_state.hasData) {
|
||||
FG_LOG(FG_INPUT, FG_ALERT,
|
||||
"XML element has mixed elements and data in element "
|
||||
<< _state.name);
|
||||
_ok = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Start a new state.
|
||||
pushState(name);
|
||||
|
||||
// See if there's a type specified.
|
||||
const char * type = atts.getValue("type");
|
||||
if (type == 0 || !strcmp("unknown", type))
|
||||
_state.type = SGValue::UNKNOWN;
|
||||
else if (!strcmp("bool", type))
|
||||
_state.type = SGValue::BOOL;
|
||||
else if (!strcmp("int", type))
|
||||
_state.type = SGValue::INT;
|
||||
else if (!strcmp("float", type))
|
||||
_state.type = SGValue::FLOAT;
|
||||
else if (!strcmp("double", type))
|
||||
_state.type = SGValue::DOUBLE;
|
||||
else if (!strcmp("string", type))
|
||||
_state.type = SGValue::STRING;
|
||||
else
|
||||
FG_LOG(FG_INPUT, FG_ALERT, "Unrecognized type " << type
|
||||
<< ", using UNKNOWN");
|
||||
}
|
||||
|
||||
void
|
||||
PropVisitor::endElement (const char * name)
|
||||
{
|
||||
if (!_ok)
|
||||
return;
|
||||
|
||||
// See if there's a property to add.
|
||||
if (_state.hasData) {
|
||||
bool status = false;
|
||||
|
||||
// Figure out the path name.
|
||||
string path = "";
|
||||
for (int i = 2; i < _level; i++) {
|
||||
path += '/';
|
||||
path += _states[i].name;
|
||||
}
|
||||
path += '/';
|
||||
path += _state.name;
|
||||
|
||||
// Set the value
|
||||
switch (_state.type) {
|
||||
case SGValue::BOOL:
|
||||
if (_state.data == "true" || _state.data == "TRUE") {
|
||||
status = _props->setBoolValue(path, true);
|
||||
} else if (atof(_state.data.c_str()) != 0.0) {
|
||||
status = _props->setBoolValue(path, true);
|
||||
} else {
|
||||
status =_props->setBoolValue(path, false);
|
||||
}
|
||||
break;
|
||||
case SGValue::INT :
|
||||
status = _props->setIntValue(path, atoi(_state.data.c_str()));
|
||||
break;
|
||||
case SGValue::FLOAT:
|
||||
status = _props->setFloatValue(path, atof(_state.data.c_str()));
|
||||
break;
|
||||
case SGValue::DOUBLE:
|
||||
status = _props->setDoubleValue(path, atof(_state.data.c_str()));
|
||||
break;
|
||||
case SGValue::STRING:
|
||||
status = _props->setStringValue(path, _state.data);
|
||||
break;
|
||||
default:
|
||||
status = _props->setUnknownValue(path, _state.data);
|
||||
break;
|
||||
}
|
||||
if (!status)
|
||||
FG_LOG(FG_INPUT, FG_ALERT, "Failed to set property "
|
||||
<< path << " to " << _state.data);
|
||||
}
|
||||
|
||||
// Pop the stack.
|
||||
popState();
|
||||
}
|
||||
|
||||
void
|
||||
PropVisitor::data (const char * s, int length)
|
||||
{
|
||||
if (!_ok)
|
||||
return;
|
||||
|
||||
// Check if there is any non-whitespace
|
||||
if (!_state.hasData)
|
||||
for (int i = 0; i < length; i++)
|
||||
if (s[i] != ' ' && s[i] != '\t' && s[i] != '\n' && s[i] != '\r')
|
||||
_state.hasData = true;
|
||||
|
||||
_state.data += string(s, length); // FIXME: inefficient
|
||||
}
|
||||
|
||||
void
|
||||
PropVisitor::warning (const char * message, int line, int col)
|
||||
{
|
||||
FG_LOG(FG_INPUT, FG_ALERT, "Warning importing property list: "
|
||||
<< message << " (" << line << ',' << col << ')');
|
||||
}
|
||||
|
||||
void
|
||||
PropVisitor::error (const char * message, int line, int col)
|
||||
{
|
||||
FG_LOG(FG_INPUT, FG_ALERT, "Error importing property list: "
|
||||
<< message << " (" << line << ',' << col << ')');
|
||||
_ok = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Property list reader.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool
|
||||
readPropertyList (istream &input, SGPropertyList * props)
|
||||
{
|
||||
PropVisitor visitor(props);
|
||||
return readXML(input, visitor) && visitor.isOK();
|
||||
}
|
||||
|
||||
bool
|
||||
readPropertyList (const string &file, SGPropertyList * props)
|
||||
{
|
||||
ifstream input(file.c_str());
|
||||
if (input.good()) {
|
||||
return readPropertyList(input, props);
|
||||
} else {
|
||||
FG_LOG(FG_INPUT, FG_ALERT, "Error reading property list from file "
|
||||
<< file);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Property list writer.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define INDENT_STEP 2
|
||||
|
||||
/**
|
||||
* Return the type name.
|
||||
*/
|
||||
static const char *
|
||||
getTypeName (SGValue::Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case SGValue::UNKNOWN:
|
||||
return "unknown";
|
||||
case SGValue::BOOL:
|
||||
return "bool";
|
||||
case SGValue::INT:
|
||||
return "int";
|
||||
case SGValue::FLOAT:
|
||||
return "float";
|
||||
case SGValue::DOUBLE:
|
||||
return "double";
|
||||
case SGValue::STRING:
|
||||
return "string";
|
||||
}
|
||||
|
||||
return "unknown"; // avoid a compiler warning
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Escape characters for output.
|
||||
*/
|
||||
static void
|
||||
writeData (ostream &output, const string &data)
|
||||
{
|
||||
for (int i = 0; i < (int)data.size(); i++) {
|
||||
switch (data[i]) {
|
||||
case '&':
|
||||
output << "&";
|
||||
break;
|
||||
case '<':
|
||||
output << "<";
|
||||
break;
|
||||
case '>':
|
||||
output << ">";
|
||||
break;
|
||||
default:
|
||||
output << data[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
doIndent (ostream &output, int indent)
|
||||
{
|
||||
while (indent-- > 0) {
|
||||
output << ' ';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
writeNode (ostream &output, SGPropertyNode node, int indent)
|
||||
{
|
||||
const string &name = node.getName();
|
||||
int size = node.size();
|
||||
|
||||
// Write out the literal value, if any.
|
||||
SGValue * value = node.getValue();
|
||||
if (value != 0) {
|
||||
SGValue::Type type = value->getType();
|
||||
doIndent(output, indent);
|
||||
output << '<' << name;
|
||||
if (type != SGValue::UNKNOWN)
|
||||
output << " type=\"" << getTypeName(type) << '"';
|
||||
output << '>';
|
||||
writeData(output, value->getStringValue());
|
||||
output << "</" << name << '>' << endl;
|
||||
}
|
||||
|
||||
// Write out the children, if any.
|
||||
if (size > 0) {
|
||||
doIndent(output, indent);
|
||||
output << '<' << name << '>' << endl;;
|
||||
for (int i = 0; i < size; i++) {
|
||||
writeNode(output, node.getChild(i), indent + INDENT_STEP);
|
||||
}
|
||||
doIndent(output, indent);
|
||||
output << "</" << name << '>' << endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
writePropertyList (ostream &output, const SGPropertyList * props)
|
||||
{
|
||||
SGPropertyNode root ("/", (SGPropertyList *)props); // FIXME
|
||||
|
||||
output << "<?xml version=\"1.0\"?>" << endl << endl;
|
||||
output << "<PropertyList>" << endl;
|
||||
|
||||
for (int i = 0; i < root.size(); i++) {
|
||||
writeNode(output, root.getChild(i), INDENT_STEP);
|
||||
}
|
||||
|
||||
output << "</PropertyList>" << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
writePropertyList (const string &file, const SGPropertyList * props)
|
||||
{
|
||||
ofstream output(file.c_str());
|
||||
if (output.good()) {
|
||||
return writePropertyList(output, props);
|
||||
} else {
|
||||
FG_LOG(FG_INPUT, FG_ALERT, "Cannot write property list to file "
|
||||
<< file);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+121
-6
@@ -22,12 +22,130 @@
|
||||
// $Id$
|
||||
|
||||
|
||||
/* The following is an explanation of our somewhat conveluted and
|
||||
tricky texture scaling/offset scheme:
|
||||
|
||||
MAX_TEX_COORD is a value I arrived at by trial and error for my
|
||||
voodoo2/3 video card. If you use texture coordinates that are too
|
||||
big, you quickly start getting into round off problems and the texture
|
||||
jumps and moves relative to the polygon.
|
||||
|
||||
The point of all of this code is that I wanted to be able to define
|
||||
this size in meters of a texture and have it be applied seamlessly to
|
||||
the terrain. I wanted to be able to change the defined size (in
|
||||
meters) of textures at run time. In other words I want to be able to
|
||||
scale the textures at run time and still have them seamlessly tile
|
||||
together across fans.
|
||||
|
||||
The problem is that I have to pregenerate all the texture coordinates
|
||||
when I create the scenery, and I didn't want to burn CPU doing this
|
||||
again when I load the scenery at run time.
|
||||
|
||||
It ended up taking me a lot of thought, a lot of trial and error, and
|
||||
a lot of fiddling around to come up with a scheme that worked.
|
||||
|
||||
----------
|
||||
|
||||
Ok, so think about what needs to be done to have the texture tile
|
||||
across a series of triangles and fans ...
|
||||
|
||||
Basically you want to use some function of lon/lat mod your max
|
||||
texture coordinate size to calculate the texture coordinate of each
|
||||
vertex. This should result in nice tiling across distinct triangles
|
||||
and fans.
|
||||
|
||||
Pretend our MAX_TEX_COORD = 4.0 and half of this is 2.0
|
||||
|
||||
Imagine the following two adjacent polygons with the "X" component of
|
||||
the initial texture coordinate based on longitude (Note they are drawn
|
||||
spaced apart, but in reality the two polygons are adjacent):
|
||||
|
||||
7.0 8.6 8.6 9.0
|
||||
*-----* *------*
|
||||
| | | |
|
||||
|
||||
Now, this exceeds our MAX_TEX_COORD of 4.0 so we have to scale these
|
||||
texture coordinates by some integer value. Let's say we always want
|
||||
to minimize the tex coordinates to minimize rounding error so we will
|
||||
offset the first polygon by 7.0 and the second by 8.0:
|
||||
|
||||
0.0 --- 1.6 and 0.6 --- 1.0
|
||||
|
||||
Our tiling is maintianed becuase the coordinates are continous (mod
|
||||
1.0) and we still get the double repeat across both polygons.
|
||||
|
||||
We want to be able to scale these values by an arbitrary constant and
|
||||
still have proper tiling.
|
||||
|
||||
Let's try doubling the coordinates:
|
||||
|
||||
0.0 --- 3.2 and 1.2 --- 2.0
|
||||
|
||||
Everything still tiles nicely (because the coordinates are continuous
|
||||
mod 1.0) and the texture is now repeated 4x across the two polygons.
|
||||
Before it was repeated 2x.
|
||||
|
||||
Let's try halving the coordinates:
|
||||
|
||||
0.0 --- 0.8 and 0.3 --- 0.5
|
||||
|
||||
Ooop! We lost continuity in texture coordinate space ... no we will
|
||||
have a visual discontinuity in the texture tiling!
|
||||
|
||||
Ok, so we need some other scheme to keep our texture coordinates
|
||||
smaller than MAX_TEX_COORD that preserves continuity in texture
|
||||
space. <Deep breath> let's try the scheme that I have coded up that
|
||||
you are asking about ... <fingers crossed> :-)
|
||||
|
||||
Going way back to the top before we shifted the texture coordinates.
|
||||
tmin for the first polygon is 7.0, this is then adjusted to:
|
||||
|
||||
(int)(tmin.x() / HALF_MAX_TEX_COORD) ) * HALF_MAX_TEX_COORD
|
||||
|
||||
= (int)(7.0/2.0) * 2.0 = 3.0 * 2.0 = 6.0
|
||||
|
||||
The two texture coordinates are offset by 6.0 which yields 1.0 -- 2.6
|
||||
|
||||
tmin for the second polygon is 8.6 which is adjusted to:
|
||||
|
||||
(int)(tmin.x() / HALF_MAX_TEX_COORD) ) * HALF_MAX_TEX_COORD
|
||||
= (int)( 8.6 / 2.0 ) * 2.0 = 4.0 * 2.0 = 8.0
|
||||
|
||||
The offset for the second polygon is 8.0 which yields 0.6 --- 1.0
|
||||
|
||||
So now we have:
|
||||
|
||||
1.0 --- 2.6 and 0.6 --- 1.0
|
||||
|
||||
This still tiles nicely and strethes our texture across completely, so
|
||||
far we haven't done any damage.
|
||||
|
||||
Now let's double the coordinates:
|
||||
|
||||
2.0 --- 5.2 and 1.2 --- 2.0
|
||||
|
||||
The texture is repeated 4x as it should be and is still continuous.
|
||||
|
||||
How about halfing the coordinates. This is where the first scheme
|
||||
broke down. Halving the coordinates yields
|
||||
|
||||
0.5 --- 1.3 and 0.3 --- 0.5
|
||||
|
||||
Woohoo, we still have texture space continuity (mod 1.0) and the
|
||||
texture is repeated 1x.
|
||||
|
||||
Note, it took me almost as long to re-figure this out and write this
|
||||
explanation as it did to figure out the scheme originally. I better
|
||||
enter this in the official comments in case I forget again. :-)
|
||||
|
||||
*/
|
||||
|
||||
#include "texcoord.hxx"
|
||||
|
||||
|
||||
#define FG_STANDARD_TEXTURE_DIMENSION 1000.0 // meters
|
||||
#define MAX_TEX_COORD 8.0
|
||||
#define HALF_MAX_TEX_COORD ( MAX_TEX_COORD / 2.0 )
|
||||
#define HALF_MAX_TEX_COORD ( MAX_TEX_COORD * 0.5 )
|
||||
|
||||
|
||||
// return the basic unshifted/unmoded texture coordinate for a lat/lon
|
||||
@@ -37,7 +155,7 @@ inline Point3D basic_tex_coord( const Point3D& p,
|
||||
{
|
||||
return Point3D( p.x() * ( degree_width * scale /
|
||||
FG_STANDARD_TEXTURE_DIMENSION ),
|
||||
p.y() * ( degree_width * scale /
|
||||
p.y() * ( degree_height * scale /
|
||||
FG_STANDARD_TEXTURE_DIMENSION ),
|
||||
0.0 );
|
||||
}
|
||||
@@ -45,7 +163,7 @@ inline Point3D basic_tex_coord( const Point3D& p,
|
||||
|
||||
// traverse the specified fan/strip/list of vertices and attempt to
|
||||
// calculate "none stretching" texture coordinates
|
||||
point_list calc_tex_coords( const FGBucket& b, const point_list& geod_nodes,
|
||||
point_list calc_tex_coords( const SGBucket& b, const point_list& geod_nodes,
|
||||
const int_list& fan, double scale )
|
||||
{
|
||||
// cout << "calculating texture coordinates for a specific fan of size = "
|
||||
@@ -113,14 +231,12 @@ point_list calc_tex_coords( const FGBucket& b, const point_list& geod_nodes,
|
||||
double dy = fabs( tmax.y() - tmin.y() );
|
||||
// cout << "dx = " << dx << " dy = " << dy << endl;
|
||||
|
||||
bool do_shift = false;
|
||||
// Point3D mod_shift;
|
||||
if ( (dx > HALF_MAX_TEX_COORD) || (dy > HALF_MAX_TEX_COORD) ) {
|
||||
// structure is too big, we'll just have to shift it so that
|
||||
// tmin = (0,0). This messes up subsequent texture scaling,
|
||||
// but is the best we can do.
|
||||
// cout << "SHIFTING" << endl;
|
||||
do_shift = true;
|
||||
if ( tmin.x() < 0 ) {
|
||||
tmin.setx( (double)( (int)tmin.x() - 1 ) );
|
||||
} else {
|
||||
@@ -193,7 +309,6 @@ point_list calc_tex_coords( const FGBucket& b, const point_list& geod_nodes,
|
||||
t = basic_tex_coord( p, degree_width, degree_height, scale );
|
||||
// cout << "second t = " << t << endl;
|
||||
|
||||
// if ( do_shift ) {
|
||||
adjusted_t = t - tmin;
|
||||
#if 0
|
||||
} else {
|
||||
|
||||
@@ -32,12 +32,12 @@
|
||||
|
||||
|
||||
#include <simgear/bucket/newbucket.hxx>
|
||||
#include <simgear/math/fg_types.hxx>
|
||||
#include <simgear/math/sg_types.hxx>
|
||||
|
||||
|
||||
// traverse the specified fan/strip/list of vertices and attempt to
|
||||
// calculate "none stretching" texture coordinates
|
||||
point_list calc_tex_coords( const FGBucket& b, const point_list& geod_nodes,
|
||||
point_list calc_tex_coords( const SGBucket& b, const point_list& geod_nodes,
|
||||
const int_list& fan, double scale = 1.0 );
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
includedir = @includedir@/route
|
||||
|
||||
lib_LIBRARIES = libsgroute.a
|
||||
|
||||
include_HEADERS = route.hxx waypoint.hxx
|
||||
|
||||
libsgroute_a_SOURCES = \
|
||||
route.cxx \
|
||||
waypoint.cxx
|
||||
|
||||
INCLUDES += -I$(top_srcdir)
|
||||
|
||||
noinst_PROGRAMS = waytest routetest
|
||||
|
||||
waytest_SOURCES = waytest.cxx
|
||||
|
||||
waytest_LDADD = \
|
||||
$(top_builddir)/simgear/route/libsgroute.a \
|
||||
$(top_builddir)/simgear/math/libsgmath.a \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a
|
||||
|
||||
routetest_SOURCES = routetest.cxx
|
||||
|
||||
routetest_LDADD = \
|
||||
$(top_builddir)/simgear/route/libsgroute.a \
|
||||
$(top_builddir)/simgear/math/libsgmath.a \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a
|
||||
@@ -0,0 +1,70 @@
|
||||
// route.cxx -- Class to manage a list of waypoints (route)
|
||||
//
|
||||
// Written by Curtis Olson, started October 2000.
|
||||
//
|
||||
// Copyright (C) 2000 Curtis L. Olson - curt@hfrl.umn.edu
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
|
||||
#include <plib/sg.h>
|
||||
|
||||
#include <simgear/math/vector.hxx>
|
||||
|
||||
#include "route.hxx"
|
||||
|
||||
|
||||
// constructor
|
||||
SGRoute::SGRoute() {
|
||||
route.clear();
|
||||
}
|
||||
|
||||
|
||||
// destructor
|
||||
SGRoute::~SGRoute() {
|
||||
}
|
||||
|
||||
|
||||
// Calculate perpendicular distance from the current route segment
|
||||
// This routine assumes all points are laying on a flat plane and
|
||||
// ignores the altitude (or Z) dimension. For best results, use with
|
||||
// CARTESIAN way points.
|
||||
double SGRoute::distance_off_route( double x, double y ) const {
|
||||
if ( current_wp > 0 ) {
|
||||
int n0 = current_wp - 1;
|
||||
int n1 = current_wp;
|
||||
sgdVec3 p, p0, p1, d;
|
||||
sgdSetVec3( p, x, y, 0.0 );
|
||||
sgdSetVec3( p0,
|
||||
route[n0].get_target_lon(), route[n0].get_target_lat(),
|
||||
0.0 );
|
||||
sgdSetVec3( p1,
|
||||
route[n1].get_target_lon(), route[n1].get_target_lat(),
|
||||
0.0 );
|
||||
sgdSubVec3( d, p0, p1 );
|
||||
|
||||
return sqrt( sgdClosestPointToLineDistSquared( p, p0, d ) );
|
||||
|
||||
} else {
|
||||
// We are tracking the first waypoint so there is no route
|
||||
// segment. If you add the current location as the first
|
||||
// waypoint and the actual waypoint as the second, then we
|
||||
// will have a route segment and calculate distance from it.
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
// route.hxx -- Class to manage a list of waypoints (route)
|
||||
//
|
||||
// Written by Curtis Olson, started October 2000.
|
||||
//
|
||||
// Copyright (C) 2000 Curtis L. Olson - curt@hfrl.umn.edu
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
|
||||
#ifndef _ROUTE_HXX
|
||||
#define _ROUTE_HXX
|
||||
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include STL_STRING
|
||||
#include <vector>
|
||||
|
||||
FG_USING_STD(string);
|
||||
FG_USING_STD(vector);
|
||||
|
||||
#include <simgear/route/waypoint.hxx>
|
||||
|
||||
|
||||
class SGRoute {
|
||||
|
||||
private:
|
||||
|
||||
typedef vector < SGWayPoint > route_list;
|
||||
route_list route;
|
||||
int current_wp;
|
||||
|
||||
public:
|
||||
|
||||
SGRoute();
|
||||
~SGRoute();
|
||||
|
||||
// clear the entire route
|
||||
inline void clear() {
|
||||
route.clear();
|
||||
current_wp = 0;
|
||||
}
|
||||
|
||||
// add a waypoint
|
||||
inline void add_waypoint( const SGWayPoint &wp ) {
|
||||
route.push_back( wp );
|
||||
|
||||
int size = route.size();
|
||||
if ( size > 1 ) {
|
||||
SGWayPoint next_to_last = route[ size - 2 ];
|
||||
double tmpd, tmpc;
|
||||
wp.CourseAndDistance( next_to_last, &tmpc, &tmpd );
|
||||
route[size - 1].set_distance( tmpd );
|
||||
}
|
||||
}
|
||||
|
||||
// get the number of waypoints
|
||||
inline int size() const { return route.size(); }
|
||||
|
||||
// get the front waypoint
|
||||
inline SGWayPoint get_first() const {
|
||||
if ( route.size() ) {
|
||||
return route[0];
|
||||
} else {
|
||||
return SGWayPoint( 0.0, 0.0, 0.0, SGWayPoint::WGS84, "invalid" );
|
||||
}
|
||||
}
|
||||
|
||||
// get the current waypoint
|
||||
inline SGWayPoint get_current() const {
|
||||
if ( current_wp < (int)route.size() ) {
|
||||
return route[current_wp];
|
||||
} else {
|
||||
return SGWayPoint( 0.0, 0.0, 0.0, SGWayPoint::WGS84, "invalid" );
|
||||
}
|
||||
}
|
||||
|
||||
// set the current waypoint
|
||||
inline void set_current( int n ) {
|
||||
if ( n >= 0 && n < (int)route.size() ) {
|
||||
current_wp = n;
|
||||
}
|
||||
}
|
||||
|
||||
// increment the current waypoint
|
||||
inline void increment_current() {
|
||||
if ( current_wp < (int)route.size() - 1 ) {
|
||||
++current_wp;
|
||||
}
|
||||
}
|
||||
|
||||
// get the nth waypoint
|
||||
inline SGWayPoint get_waypoint( const int n ) const {
|
||||
if ( n < (int)route.size() ) {
|
||||
return route[n];
|
||||
} else {
|
||||
return SGWayPoint( 0.0, 0.0, 0.0, SGWayPoint::WGS84, "invalid" );
|
||||
}
|
||||
}
|
||||
|
||||
// delete the front waypoint
|
||||
inline void delete_first() {
|
||||
if ( route.size() ) {
|
||||
route.erase( route.begin() );
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate perpendicular distance from the current route segment
|
||||
// This routine assumes all points are laying on a flat plane and
|
||||
// ignores the altitude (or Z) dimension. For best results, use
|
||||
// with CARTESIAN way points.
|
||||
double distance_off_route( double x, double y ) const;
|
||||
};
|
||||
|
||||
|
||||
#endif // _ROUTE_HXX
|
||||
@@ -0,0 +1,27 @@
|
||||
#include <simgear/constants.h>
|
||||
|
||||
#include "route.hxx"
|
||||
#include "waypoint.hxx"
|
||||
|
||||
int main() {
|
||||
SGRoute route;
|
||||
|
||||
route.add_waypoint( SGWayPoint(0, 0, 0, SGWayPoint::CARTESIAN, "Start") );
|
||||
route.add_waypoint( SGWayPoint(1, 0, 0, SGWayPoint::CARTESIAN, "1") );
|
||||
route.add_waypoint( SGWayPoint(2, 0, 0, SGWayPoint::CARTESIAN, "2") );
|
||||
route.add_waypoint( SGWayPoint(2, 2, 0, SGWayPoint::CARTESIAN, "3") );
|
||||
route.add_waypoint( SGWayPoint(4, 2, 0, SGWayPoint::CARTESIAN, "4") );
|
||||
|
||||
route.set_current( 1 );
|
||||
|
||||
cout << "( 0.5, 0 ) = " << route.distance_off_route( 0.5, 0 ) << endl;
|
||||
cout << "( 0.5, 1 ) = " << route.distance_off_route( 0.5, 1 ) << endl;
|
||||
cout << "( 0.5, -1 ) = " << route.distance_off_route( 0.5, 1 ) << endl;
|
||||
|
||||
route.set_current( 3 );
|
||||
|
||||
cout << "( 2, 4 ) = " << route.distance_off_route( 2, 4 ) << endl;
|
||||
cout << "( 2.5, 4 ) = " << route.distance_off_route( 2.5, 4 ) << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
// waypoint.cxx -- Class to hold data and return info relating to a waypoint
|
||||
//
|
||||
// Written by Curtis Olson, started September 2000.
|
||||
//
|
||||
// Copyright (C) 2000 Curtis L. Olson - curt@hfrl.umn.edu
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
|
||||
#include <simgear/math/polar3d.hxx>
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
|
||||
#include "waypoint.hxx"
|
||||
|
||||
|
||||
// Constructor
|
||||
SGWayPoint::SGWayPoint( const double lon, const double lat, const double alt,
|
||||
const modetype m, const string s ) {
|
||||
target_lon = lon;
|
||||
target_lat = lat;
|
||||
target_alt = alt;
|
||||
mode = m;
|
||||
id = s;
|
||||
}
|
||||
|
||||
|
||||
SGWayPoint::SGWayPoint() {
|
||||
SGWayPoint( 0.0, 0.0, 0.0, WGS84, "" );
|
||||
}
|
||||
|
||||
|
||||
// Destructor
|
||||
SGWayPoint::~SGWayPoint() {
|
||||
}
|
||||
|
||||
|
||||
// Calculate course and distances. For WGS84 and SPHERICAL
|
||||
// coordinates lat, lon, and course are in degrees, alt and distance
|
||||
// are in meters. For CARTESIAN coordinates x = lon, y = lat. Course
|
||||
// is in degrees and distance is in what ever units x and y are in.
|
||||
void SGWayPoint::CourseAndDistance( const double cur_lon,
|
||||
const double cur_lat,
|
||||
const double cur_alt,
|
||||
double *course, double *distance ) const {
|
||||
if ( mode == WGS84 ) {
|
||||
double reverse;
|
||||
geo_inverse_wgs_84( cur_alt, cur_lat, cur_lon, target_lat, target_lon,
|
||||
course, &reverse, distance );
|
||||
} else if ( mode == SPHERICAL ) {
|
||||
Point3D current( cur_lon * DEG_TO_RAD, cur_lat * DEG_TO_RAD, 0.0 );
|
||||
Point3D target( target_lon * DEG_TO_RAD, target_lat * DEG_TO_RAD, 0.0 );
|
||||
calc_gc_course_dist( current, target, course, distance );
|
||||
*course = 360.0 - *course * RAD_TO_DEG;
|
||||
} else if ( mode == CARTESIAN ) {
|
||||
double dx = target_lon - cur_lon;
|
||||
double dy = target_lat - cur_lat;
|
||||
*course = -atan2( dy, dx ) * RAD_TO_DEG - 90;
|
||||
while ( *course < 0 ) {
|
||||
*course += 360.0;
|
||||
}
|
||||
while ( *course > 360.0 ) {
|
||||
*course -= 360.0;
|
||||
}
|
||||
*distance = sqrt( dx * dx + dy * dy );
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate course and distances between two waypoints
|
||||
void SGWayPoint::CourseAndDistance( const SGWayPoint &wp,
|
||||
double *course, double *distance ) const {
|
||||
CourseAndDistance( wp.get_target_lon(),
|
||||
wp.get_target_lat(),
|
||||
wp.get_target_alt(),
|
||||
course, distance );
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
// waypoint.hxx -- Class to hold data and return info relating to a waypoint
|
||||
//
|
||||
// Written by Curtis Olson, started September 2000.
|
||||
//
|
||||
// Copyright (C) 2000 Curtis L. Olson - curt@hfrl.umn.edu
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
|
||||
#ifndef _WAYPOINT_HXX
|
||||
#define _WAYPOINT_HXX
|
||||
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include STL_STRING
|
||||
|
||||
FG_USING_STD(string);
|
||||
|
||||
|
||||
class SGWayPoint {
|
||||
|
||||
public:
|
||||
|
||||
enum modetype {
|
||||
WGS84 = 0,
|
||||
SPHERICAL = 1,
|
||||
CARTESIAN = 2
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
modetype mode;
|
||||
|
||||
double target_lon;
|
||||
double target_lat;
|
||||
double target_alt;
|
||||
double distance;
|
||||
|
||||
string id;
|
||||
|
||||
public:
|
||||
|
||||
SGWayPoint();
|
||||
SGWayPoint( const double lon, const double lat, const double alt,
|
||||
const modetype m = WGS84, const string s = "" );
|
||||
~SGWayPoint();
|
||||
|
||||
// Calculate course and distances. For WGS84 and SPHERICAL
|
||||
// coordinates lat, lon, and course are in degrees, alt and
|
||||
// distance are in meters. For CARTESIAN coordinates x = lon, y =
|
||||
// lat. Course is in degrees and distance is in what ever units x
|
||||
// and y are in.
|
||||
void CourseAndDistance( const double cur_lon, const double cur_lat,
|
||||
const double cur_alt,
|
||||
double *course, double *distance ) const;
|
||||
|
||||
// Calculate course and distances between two waypoints
|
||||
void CourseAndDistance( const SGWayPoint &wp,
|
||||
double *course, double *distance ) const;
|
||||
|
||||
inline modetype get_mode() const { return mode; }
|
||||
inline double get_target_lon() const { return target_lon; }
|
||||
inline double get_target_lat() const { return target_lat; }
|
||||
inline double get_target_alt() const { return target_alt; }
|
||||
inline double get_distance() const { return distance; }
|
||||
inline string get_id() const { return id; }
|
||||
|
||||
inline void set_distance( double d ) { distance = d; }
|
||||
};
|
||||
|
||||
|
||||
#endif // _WAYPOINT_HXX
|
||||
@@ -0,0 +1,59 @@
|
||||
#include <simgear/constants.h>
|
||||
#include "waypoint.hxx"
|
||||
|
||||
int main() {
|
||||
SGWayPoint a1(-93.216923, 44.880547, 0.0, SGWayPoint::WGS84, "KMSP");
|
||||
SGWayPoint a2(-93.216923, 44.880547, 0.0, SGWayPoint::SPHERICAL, "KMSP");
|
||||
|
||||
// KMSN (Madison)
|
||||
double cur_lon = -89.336939;
|
||||
double cur_lat = 43.139541;
|
||||
double cur_alt = 0.0;
|
||||
|
||||
double course, distance;
|
||||
|
||||
a1.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||
cout << "Course to " << a1.get_id() << " is " << course << endl;
|
||||
cout << "Distance to " << a1.get_id() << " is " << distance * METER_TO_NM
|
||||
<< endl;
|
||||
|
||||
a2.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||
cout << "Course to " << a2.get_id() << " is " << course << endl;
|
||||
cout << "Distance to " << a2.get_id() << " is " << distance * METER_TO_NM
|
||||
<< endl;
|
||||
cout << endl;
|
||||
|
||||
SGWayPoint b1(-88.237037, 43.041038, 0.0, SGWayPoint::WGS84, "KUES");
|
||||
SGWayPoint b2(-88.237037, 43.041038, 0.0, SGWayPoint::SPHERICAL, "KUES");
|
||||
|
||||
b1.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||
cout << "Course to " << b1.get_id() << " is " << course << endl;
|
||||
cout << "Distance to " << b1.get_id() << " is " << distance * METER_TO_NM
|
||||
<< endl;
|
||||
|
||||
b2.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||
cout << "Course to " << b2.get_id() << " is " << course << endl;
|
||||
cout << "Distance to " << b2.get_id() << " is " << distance * METER_TO_NM
|
||||
<< endl;
|
||||
cout << endl;
|
||||
|
||||
cur_lon = 10;
|
||||
cur_lat = 10;
|
||||
|
||||
SGWayPoint c1(-20, 10, 0, SGWayPoint::CARTESIAN, "Due East");
|
||||
c1.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||
cout << "Course to " << c1.get_id() << " is " << course << endl;
|
||||
cout << "Distance to " << c1.get_id() << " is " << distance << endl;
|
||||
|
||||
SGWayPoint c2(20, 20, 0, SGWayPoint::CARTESIAN, "Due SW");
|
||||
c2.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||
cout << "Course to " << c2.get_id() << " is " << course << endl;
|
||||
cout << "Distance to " << c2.get_id() << " is " << distance << endl;
|
||||
|
||||
SGWayPoint c3(20, 0, 0, SGWayPoint::CARTESIAN, "Due NW");
|
||||
c3.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||
cout << "Course to " << c3.get_id() << " is " << course << endl;
|
||||
cout << "Distance to " << c3.get_id() << " is " << distance << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -9,4 +9,4 @@ libsgscreen_a_SOURCES = \
|
||||
screen-dump.cxx \
|
||||
win32-printer.h
|
||||
|
||||
INCLUDES += -I$(top_builddir)
|
||||
INCLUDES += -I$(top_srcdir)
|
||||
|
||||
@@ -50,7 +50,11 @@ void my_glWritePPMFile(const char *filename, GLubyte *buffer, int win_width, int
|
||||
|
||||
ibuffer = (unsigned char *) malloc(win_width*win_height*RGB);
|
||||
|
||||
fp = fopen(filename, "wb");
|
||||
if ( (fp = fopen(filename, "wb")) == NULL ) {
|
||||
printf("Warning: cannot open %s\n", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(fp, "P6\n# CREATOR: glReadPixel()\n%d %d\n%d\n",
|
||||
win_width, win_height, UCHAR_MAX);
|
||||
q = 0;
|
||||
|
||||
@@ -14,4 +14,4 @@ testserial_LDADD = \
|
||||
$(top_builddir)/simgear/serial/libsgserial.a \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a
|
||||
|
||||
INCLUDES += -I$(top_builddir)
|
||||
INCLUDES += -I$(top_srcdir)
|
||||
|
||||
@@ -20,4 +20,4 @@ libsgsky_a_SOURCES = \
|
||||
sphere.cxx \
|
||||
stars.cxx
|
||||
|
||||
INCLUDES += -I$(top_builddir)
|
||||
INCLUDES += -I$(top_srcdir)
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
#include <plib/sg.h>
|
||||
#include <plib/ssg.h>
|
||||
|
||||
#include <simgear/math/fg_random.h>
|
||||
#include <simgear/math/point3d.hxx>
|
||||
#include <simgear/math/polar3d.hxx>
|
||||
#include <simgear/math/sg_random.h>
|
||||
|
||||
#include "cloud.hxx"
|
||||
|
||||
@@ -70,7 +70,7 @@ void SGCloudLayer::build( double s, double asl, double thickness,
|
||||
|
||||
sgSetVec3( vertex, -size, -size, 0.0f );
|
||||
sgVec2 base;
|
||||
sgSetVec2( base, fg_random(), fg_random() );
|
||||
sgSetVec2( base, sg_random(), sg_random() );
|
||||
sgSetVec2( tc, base[0], base[1] );
|
||||
cl->add( color );
|
||||
vl->add( vertex );
|
||||
|
||||
@@ -42,9 +42,9 @@ FG_USING_STD(string);
|
||||
|
||||
enum SGCloudType {
|
||||
SG_CLOUD_OVERCAST = 0,
|
||||
SG_CLOUD_MOSTLY_CLOUDY = 1,
|
||||
SG_CLOUD_MOSTLY_SUNNY = 2,
|
||||
SG_CLOUD_CIRRUS = 3,
|
||||
SG_CLOUD_MOSTLY_CLOUDY,
|
||||
SG_CLOUD_MOSTLY_SUNNY,
|
||||
SG_CLOUD_CIRRUS
|
||||
};
|
||||
|
||||
|
||||
|
||||
+18
-11
@@ -39,7 +39,6 @@
|
||||
#include <plib/sg.h>
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/math/fg_random.h>
|
||||
|
||||
#include "dome.hxx"
|
||||
|
||||
@@ -69,6 +68,13 @@
|
||||
static int sgSkyDomePreDraw( ssgEntity *e ) {
|
||||
/* cout << endl << "Dome Pre Draw" << endl << "----------------"
|
||||
<< endl << endl; */
|
||||
|
||||
ssgLeaf *f = (ssgLeaf *)e;
|
||||
if ( f -> hasState () ) f->getState()->apply() ;
|
||||
|
||||
glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_FOG_BIT );
|
||||
// cout << "push error = " << glGetError() << endl;
|
||||
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glDisable( GL_FOG );
|
||||
|
||||
@@ -78,9 +84,10 @@ static int sgSkyDomePreDraw( ssgEntity *e ) {
|
||||
static int sgSkyDomePostDraw( ssgEntity *e ) {
|
||||
/* cout << endl << "Dome Post Draw" << endl << "----------------"
|
||||
<< endl << endl; */
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
glEnable( GL_FOG );
|
||||
|
||||
glPopAttrib();
|
||||
// cout << "pop error = " << glGetError() << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -349,11 +356,11 @@ bool SGSkyDome::repaint( sgVec4 sky_color, sgVec4 fog_color, double sun_angle,
|
||||
lower_color[i][j] = fog_color[j] + outer_amt[j];
|
||||
|
||||
if ( upper_color[i][j] > 1.0 ) { upper_color[i][j] = 1.0; }
|
||||
if ( upper_color[i][j] < 0.1 ) { upper_color[i][j] = 0.1; }
|
||||
if ( upper_color[i][j] < 0.0 ) { upper_color[i][j] = 0.0; }
|
||||
if ( middle_color[i][j] > 1.0 ) { middle_color[i][j] = 1.0; }
|
||||
if ( middle_color[i][j] < 0.1 ) { middle_color[i][j] = 0.1; }
|
||||
if ( middle_color[i][j] < 0.0 ) { middle_color[i][j] = 0.0; }
|
||||
if ( lower_color[i][j] > 1.0 ) { lower_color[i][j] = 1.0; }
|
||||
if ( lower_color[i][j] < 0.1 ) { lower_color[i][j] = 0.1; }
|
||||
if ( lower_color[i][j] < 0.0 ) { lower_color[i][j] = 0.0; }
|
||||
}
|
||||
upper_color[i][3] = middle_color[i][3] = lower_color[i][3] = 1.0;
|
||||
|
||||
@@ -390,11 +397,11 @@ bool SGSkyDome::repaint( sgVec4 sky_color, sgVec4 fog_color, double sun_angle,
|
||||
lower_color[i][j] = fog_color[j] + outer_amt[j];
|
||||
|
||||
if ( upper_color[i][j] > 1.0 ) { upper_color[i][j] = 1.0; }
|
||||
if ( upper_color[i][j] < 0.1 ) { upper_color[i][j] = 0.1; }
|
||||
if ( upper_color[i][j] < 0.0 ) { upper_color[i][j] = 0.0; }
|
||||
if ( middle_color[i][j] > 1.0 ) { middle_color[i][j] = 1.0; }
|
||||
if ( middle_color[i][j] < 0.1 ) { middle_color[i][j] = 0.1; }
|
||||
if ( middle_color[i][j] < 0.0 ) { middle_color[i][j] = 0.0; }
|
||||
if ( lower_color[i][j] > 1.0 ) { lower_color[i][j] = 1.0; }
|
||||
if ( lower_color[i][j] < 0.1 ) { lower_color[i][j] = 0.1; }
|
||||
if ( lower_color[i][j] < 0.0 ) { lower_color[i][j] = 0.0; }
|
||||
}
|
||||
upper_color[i][3] = middle_color[i][3] = lower_color[i][3] = 1.0;
|
||||
|
||||
@@ -412,8 +419,8 @@ bool SGSkyDome::repaint( sgVec4 sky_color, sgVec4 fog_color, double sun_angle,
|
||||
printf("lower_color[%d] = %.2f %.2f %.2f %.2f\n", i,
|
||||
lower_color[i][0], lower_color[i][1], lower_color[i][2],
|
||||
lower_color[i][3]);
|
||||
*/
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
for ( i = 0; i < 12; i++ ) {
|
||||
sgCopyVec4( bottom_color[i], fog_color );
|
||||
|
||||
+28
-6
@@ -29,6 +29,8 @@
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
|
||||
@@ -45,6 +47,13 @@
|
||||
static int sgMoonOrbPreDraw( ssgEntity *e ) {
|
||||
/* cout << endl << "Moon orb pre draw" << endl << "----------------"
|
||||
<< endl << endl; */
|
||||
|
||||
ssgLeaf *f = (ssgLeaf *)e;
|
||||
if ( f -> hasState () ) f->getState()->apply() ;
|
||||
|
||||
glPushAttrib( GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT );
|
||||
// cout << "push error = " << glGetError() << endl;
|
||||
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glDisable( GL_FOG );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE ) ;
|
||||
@@ -55,10 +64,13 @@ static int sgMoonOrbPreDraw( ssgEntity *e ) {
|
||||
static int sgMoonOrbPostDraw( ssgEntity *e ) {
|
||||
/* cout << endl << "Moon orb post draw" << endl << "----------------"
|
||||
<< endl << endl; */
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
glEnable( GL_FOG );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
|
||||
// glEnable( GL_DEPTH_TEST );
|
||||
// glEnable( GL_FOG );
|
||||
// glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
|
||||
|
||||
glPopAttrib();
|
||||
// cout << "pop error = " << glGetError() << endl;
|
||||
|
||||
/* test
|
||||
glDisable( GL_LIGHTING );
|
||||
glDisable( GL_CULL_FACE );
|
||||
@@ -73,6 +85,13 @@ static int sgMoonOrbPostDraw( ssgEntity *e ) {
|
||||
static int sgMoonHaloPreDraw( ssgEntity *e ) {
|
||||
/* cout << endl << "Moon halo pre draw" << endl << "----------------"
|
||||
<< endl << endl; */
|
||||
|
||||
ssgLeaf *f = (ssgLeaf *)e;
|
||||
if ( f -> hasState () ) f->getState()->apply() ;
|
||||
|
||||
glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_FOG_BIT | GL_COLOR_BUFFER_BIT);
|
||||
// cout << "push error = " << glGetError() << endl;
|
||||
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glDisable( GL_FOG );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
|
||||
@@ -83,9 +102,12 @@ static int sgMoonHaloPreDraw( ssgEntity *e ) {
|
||||
static int sgMoonHaloPostDraw( ssgEntity *e ) {
|
||||
/* cout << endl << "Moon halo post draw" << endl << "----------------"
|
||||
<< endl << endl; */
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
glEnable( GL_FOG );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
|
||||
// glEnable( GL_DEPTH_TEST );
|
||||
// glEnable( GL_FOG );
|
||||
// glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
|
||||
|
||||
glPopAttrib();
|
||||
// cout << "pop error = " << glGetError() << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+26
-4
@@ -43,6 +43,13 @@
|
||||
static int sgSunOrbPreDraw( ssgEntity *e ) {
|
||||
/* cout << endl << "Sun orb pre draw" << endl << "----------------"
|
||||
<< endl << endl; */
|
||||
|
||||
ssgLeaf *f = (ssgLeaf *)e;
|
||||
if ( f -> hasState () ) f->getState()->apply() ;
|
||||
|
||||
glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_FOG_BIT );
|
||||
// cout << "push error = " << glGetError() << endl;
|
||||
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glDisable( GL_FOG );
|
||||
|
||||
@@ -52,8 +59,12 @@ static int sgSunOrbPreDraw( ssgEntity *e ) {
|
||||
static int sgSunOrbPostDraw( ssgEntity *e ) {
|
||||
/* cout << endl << "Sun orb post draw" << endl << "----------------"
|
||||
<< endl << endl; */
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
glEnable( GL_FOG );
|
||||
|
||||
glPopAttrib();
|
||||
// cout << "pop error = " << glGetError() << endl;
|
||||
|
||||
// glEnable( GL_DEPTH_TEST );
|
||||
// glEnable( GL_FOG );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -61,6 +72,13 @@ static int sgSunOrbPostDraw( ssgEntity *e ) {
|
||||
static int sgSunHaloPreDraw( ssgEntity *e ) {
|
||||
/* cout << endl << "Sun halo pre draw" << endl << "----------------"
|
||||
<< endl << endl; */
|
||||
|
||||
ssgLeaf *f = (ssgLeaf *)e;
|
||||
if ( f -> hasState () ) f->getState()->apply() ;
|
||||
|
||||
glPushAttrib( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_FOG_BIT );
|
||||
// cout << "push error = " << glGetError() << endl;
|
||||
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glDisable( GL_FOG );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
|
||||
@@ -71,8 +89,12 @@ static int sgSunHaloPreDraw( ssgEntity *e ) {
|
||||
static int sgSunHaloPostDraw( ssgEntity *e ) {
|
||||
/* cout << endl << "Sun halo post draw" << endl << "----------------"
|
||||
<< endl << endl; */
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
glEnable( GL_FOG );
|
||||
|
||||
glPopAttrib();
|
||||
// cout << "pop error = " << glGetError() << endl;
|
||||
|
||||
// glEnable( GL_DEPTH_TEST );
|
||||
// glEnable( GL_FOG );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+14
-12
@@ -30,7 +30,7 @@
|
||||
#include <plib/sg.h>
|
||||
#include <plib/ssg.h>
|
||||
|
||||
#include <simgear/math/fg_random.h>
|
||||
#include <simgear/math/sg_random.h>
|
||||
|
||||
#include "sky.hxx"
|
||||
|
||||
@@ -193,8 +193,10 @@ void SGSky::postDraw( float alt ) {
|
||||
|
||||
int in_cloud = -1; // cloud we are in
|
||||
|
||||
int i;
|
||||
|
||||
// check where we are relative to the cloud layers
|
||||
for ( int i = 0; i < (int)cloud_layers.size(); ++i ) {
|
||||
for ( i = 0; i < (int)cloud_layers.size(); ++i ) {
|
||||
float asl = cloud_layers[i]->get_asl();
|
||||
float thickness = cloud_layers[i]->get_thickness();
|
||||
|
||||
@@ -220,14 +222,14 @@ void SGSky::postDraw( float alt ) {
|
||||
|
||||
if ( pos == 0 ) {
|
||||
// we are below all the cloud layers, draw top to bottom
|
||||
for ( int i = cloud_layers.size() - 1; i >= 0; --i ) {
|
||||
for ( i = cloud_layers.size() - 1; i >= 0; --i ) {
|
||||
if ( i != in_cloud ) {
|
||||
cloud_layers[i]->draw();
|
||||
}
|
||||
}
|
||||
} else if ( pos >= (int)cloud_layers.size() ) {
|
||||
// we are above all the cloud layers, draw bottom to top
|
||||
for ( int i = 0; i < (int)cloud_layers.size(); ++i ) {
|
||||
for ( i = 0; i < (int)cloud_layers.size(); ++i ) {
|
||||
if ( i != in_cloud ) {
|
||||
cloud_layers[i]->draw();
|
||||
}
|
||||
@@ -235,12 +237,12 @@ void SGSky::postDraw( float alt ) {
|
||||
} else {
|
||||
// we are between cloud layers, draw lower layers bottom to
|
||||
// top and upper layers top to bottom
|
||||
for ( int i = 0; i < pos; ++i ) {
|
||||
for ( i = 0; i < pos; ++i ) {
|
||||
if ( i != in_cloud ) {
|
||||
cloud_layers[i]->draw();
|
||||
}
|
||||
}
|
||||
for ( int i = cloud_layers.size() - 1; i >= pos; --i ) {
|
||||
for ( i = cloud_layers.size() - 1; i >= pos; --i ) {
|
||||
if ( i != in_cloud ) {
|
||||
cloud_layers[i]->draw();
|
||||
}
|
||||
@@ -267,10 +269,10 @@ void SGSky::add_cloud_layer( double asl, double thickness,
|
||||
cloud_layers.push_back( layer );
|
||||
}
|
||||
|
||||
for ( int i = 0; i < (int)cloud_layers.size(); ++i ) {
|
||||
cout << "layer " << i << " = " << cloud_layers[i]->get_asl() << endl;
|
||||
}
|
||||
cout << endl;
|
||||
// for ( int i = 0; i < (int)cloud_layers.size(); ++i ) {
|
||||
// cout << "layer " << i << " = " << cloud_layers[i]->get_asl() << endl;
|
||||
// }
|
||||
// cout << endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -326,11 +328,11 @@ void SGSky::modify_vis( float alt, float time_factor ) {
|
||||
if ( ratio < 1.0 ) {
|
||||
if ( ! in_puff ) {
|
||||
// calc chance of entering cloud puff
|
||||
double rnd = fg_random();
|
||||
double rnd = sg_random();
|
||||
double chance = rnd * rnd * rnd;
|
||||
if ( chance > 0.95 /* * (diff - 25) / 50.0 */ ) {
|
||||
in_puff = true;
|
||||
puff_length = fg_random() * 2.0; // up to 2 seconds
|
||||
puff_length = sg_random() * 2.0; // up to 2 seconds
|
||||
puff_progression = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -39,11 +39,11 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "cloud.hxx"
|
||||
#include "dome.hxx"
|
||||
#include "moon.hxx"
|
||||
#include "oursun.hxx"
|
||||
#include "stars.hxx"
|
||||
#include <simgear/sky/cloud.hxx>
|
||||
#include <simgear/sky/dome.hxx>
|
||||
#include <simgear/sky/moon.hxx>
|
||||
#include <simgear/sky/oursun.hxx>
|
||||
#include <simgear/sky/stars.hxx>
|
||||
|
||||
FG_USING_STD(vector);
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <plib/sg.h>
|
||||
#include <plib/ssg.h>
|
||||
|
||||
FG_USING_NAMESPACE(std);
|
||||
|
||||
// return a sphere object as an ssgBranch
|
||||
ssgBranch *ssgMakeSphere( ssgSimpleState *state, ssgColourArray *cl,
|
||||
@@ -113,11 +114,11 @@ ssgBranch *ssgMakeSphere( ssgSimpleState *state, ssgColourArray *cl,
|
||||
new ssgVtxTable ( GL_TRIANGLE_STRIP, vl, nl, tl, cl );
|
||||
|
||||
if ( vl->getNum() != nl->getNum() ) {
|
||||
cout << "bad sphere1\n";
|
||||
std::cout << "bad sphere1\n";
|
||||
exit(-1);
|
||||
}
|
||||
if ( vl->getNum() != tl->getNum() ) {
|
||||
cout << "bad sphere2\n";
|
||||
std::cout << "bad sphere2\n";
|
||||
exit(-1);
|
||||
}
|
||||
slice->setState( state );
|
||||
|
||||
+14
-5
@@ -35,21 +35,27 @@
|
||||
#include <plib/sg.h>
|
||||
#include <plib/ssg.h>
|
||||
|
||||
#include <compiler.h>
|
||||
|
||||
#include "stars.hxx"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
FG_USING_STD(cout);
|
||||
FG_USING_STD(endl);
|
||||
#endif
|
||||
|
||||
|
||||
// Set up star rendering call backs
|
||||
static int sgStarPreDraw( ssgEntity *e ) {
|
||||
/* cout << endl << "Star pre draw" << endl << "----------------"
|
||||
<< endl << endl; */
|
||||
|
||||
ssgLeaf *f = (ssgLeaf *)e;
|
||||
if ( f -> hasState () ) f->getState()->apply() ;
|
||||
|
||||
glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_FOG_BIT );
|
||||
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glDisable( GL_FOG );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
|
||||
// glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -57,8 +63,11 @@ static int sgStarPreDraw( ssgEntity *e ) {
|
||||
static int sgStarPostDraw( ssgEntity *e ) {
|
||||
/* cout << endl << "Star post draw" << endl << "----------------"
|
||||
<< endl << endl; */
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
glEnable( GL_FOG );
|
||||
|
||||
glPopAttrib();
|
||||
|
||||
// glEnable( GL_DEPTH_TEST );
|
||||
// glEnable( GL_FOG );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ include_HEADERS = \
|
||||
geocoord.h \
|
||||
lowleveltime.h \
|
||||
sg_time.hxx \
|
||||
timestamp.hxx \
|
||||
timezone.h
|
||||
|
||||
libsgtiming_a_SOURCES = \
|
||||
@@ -20,4 +21,4 @@ libsgtiming_a_SOURCES = \
|
||||
# sunpos.cxx sunpos.hxx \
|
||||
# timestamp.hxx
|
||||
|
||||
INCLUDES += -I$(top_builddir)
|
||||
INCLUDES += -I$(top_srcdir)
|
||||
|
||||
@@ -304,7 +304,7 @@ static void fgtzset_internal (int always, const char *tz)
|
||||
/* User specified the empty string; use UTC explicitly. */
|
||||
tz = "Universal";
|
||||
|
||||
#ifdef MACOS
|
||||
#ifdef macintosh
|
||||
/* as you well know, mac paths contain leading colon, this code
|
||||
messes things up.... */
|
||||
#else
|
||||
|
||||
+30
-12
@@ -63,6 +63,11 @@
|
||||
#define RADHR(x) DEGHR(x*RAD_TO_DEG)
|
||||
|
||||
|
||||
static const double MJD0 = 2415020.0;
|
||||
static const double J2000 = 2451545.0 - MJD0;
|
||||
static const double SIDRATE = 0.9972695677;
|
||||
|
||||
|
||||
SGTime::SGTime( double lon, double lat, const string& root )
|
||||
{
|
||||
FG_LOG( FG_EVENT, FG_INFO, "Initializing Time" );
|
||||
@@ -75,18 +80,24 @@ SGTime::SGTime( double lon, double lat, const string& root )
|
||||
// cout << "Current local time = "
|
||||
// << asctime(localtime(&cur_time)) << endl;
|
||||
|
||||
FGPath zone( root );
|
||||
zone.append( "zone.tab" );
|
||||
FG_LOG( FG_EVENT, FG_DEBUG, "Reading timezone info from: " << zone.str() );
|
||||
tzContainer = new TimezoneContainer( zone.c_str() );
|
||||
if ( root != "" ) {
|
||||
FGPath zone( root );
|
||||
zone.append( "zone.tab" );
|
||||
FG_LOG( FG_EVENT, FG_DEBUG, "Reading timezone info from: "
|
||||
<< zone.str() );
|
||||
tzContainer = new TimezoneContainer( zone.c_str() );
|
||||
|
||||
GeoCoord location( RAD_TO_DEG * lat, RAD_TO_DEG * lon );
|
||||
GeoCoord* nearestTz = tzContainer->getNearest(location);
|
||||
GeoCoord location( RAD_TO_DEG * lat, RAD_TO_DEG * lon );
|
||||
GeoCoord* nearestTz = tzContainer->getNearest(location);
|
||||
|
||||
FGPath name( root );
|
||||
name.append( nearestTz->getDescription() );
|
||||
zonename = strdup( name.c_str() );
|
||||
// cout << "Using zonename = " << zonename << endl;
|
||||
FGPath name( root );
|
||||
name.append( nearestTz->getDescription() );
|
||||
zonename = strdup( name.c_str() );
|
||||
// cout << "Using zonename = " << zonename << endl;
|
||||
} else {
|
||||
tzContainer = NULL;
|
||||
zonename = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -95,9 +106,16 @@ SGTime::SGTime( const string& root ) {
|
||||
}
|
||||
|
||||
|
||||
SGTime::SGTime() {
|
||||
SGTime( 0.0, 0.0, "" );
|
||||
}
|
||||
|
||||
|
||||
SGTime::~SGTime()
|
||||
{
|
||||
delete tzContainer;
|
||||
if ( tzContainer != NULL ) {
|
||||
delete tzContainer;
|
||||
}
|
||||
|
||||
if ( zonename != NULL ) {
|
||||
delete zonename;
|
||||
@@ -400,7 +418,7 @@ time_t sgTimeGetGMT(int year, int month, int day, int hour, int min, int sec)
|
||||
# define TIMEZONE_OFFSET_WORKS 1
|
||||
# endif
|
||||
|
||||
long int start = mktime(&mt);
|
||||
time_t start = mktime(&mt);
|
||||
|
||||
FG_LOG( FG_EVENT, FG_DEBUG, "start1 = " << start );
|
||||
// the ctime() call can screw up time progression on some versions
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
# include <time.h>
|
||||
#endif
|
||||
|
||||
#include "timezone.h"
|
||||
#include <simgear/timing/timezone.h>
|
||||
|
||||
|
||||
// Define a structure containing time parameters
|
||||
@@ -86,6 +86,7 @@ public:
|
||||
|
||||
SGTime( double lon, double lat, const string& root );
|
||||
SGTime( const string& root );
|
||||
SGTime();
|
||||
~SGTime();
|
||||
|
||||
// Update the time related variables
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
// timestamp.hxx -- class for managing a timestamp (seconds & milliseconds.)
|
||||
//
|
||||
// Written by Curtis Olson, started December 1998.
|
||||
//
|
||||
// Copyright (C) 1998 Curtis L. Olson - curt@flightgear.org
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
|
||||
#ifndef _TIMESTAMP_HXX
|
||||
#define _TIMESTAMP_HXX
|
||||
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#ifdef FG_HAVE_STD_INCLUDES
|
||||
# include <ctime>
|
||||
#else
|
||||
# include <time.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TIMEB_H
|
||||
# include <sys/timeb.h> // for ftime() and struct timeb
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h> // for gettimeofday()
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
# include <sys/time.h> // for get/setitimer, gettimeofday, struct timeval
|
||||
#endif
|
||||
|
||||
// -dw- want to use metrowerks time.h
|
||||
#ifdef macintosh
|
||||
# include <time.h>
|
||||
# include <timer.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
# include <windows.h>
|
||||
# if defined( __CYGWIN__ ) || defined( __CYGWIN32__ )
|
||||
# define NEAR /* */
|
||||
# define FAR /* */
|
||||
# endif
|
||||
# include <mmsystem.h>
|
||||
#endif
|
||||
|
||||
// MSVC++ 6.0 kuldge - Need forward declaration of friends.
|
||||
class SGTimeStamp;
|
||||
SGTimeStamp operator + (const SGTimeStamp& t, const long& m);
|
||||
long operator - (const SGTimeStamp& a, const SGTimeStamp& b);
|
||||
|
||||
class SGTimeStamp {
|
||||
|
||||
private:
|
||||
|
||||
long seconds;
|
||||
long usec;
|
||||
|
||||
public:
|
||||
|
||||
SGTimeStamp();
|
||||
SGTimeStamp( const long s, const long m );
|
||||
~SGTimeStamp();
|
||||
|
||||
// Set time to current time
|
||||
void stamp();
|
||||
|
||||
SGTimeStamp& operator = ( const SGTimeStamp& t );
|
||||
|
||||
friend SGTimeStamp operator + (const SGTimeStamp& t, const long& m);
|
||||
friend long operator - (const SGTimeStamp& a, const SGTimeStamp& b);
|
||||
|
||||
inline long get_seconds() const { return seconds; }
|
||||
// inline long get_usec() const { return usec; }
|
||||
};
|
||||
|
||||
inline SGTimeStamp::SGTimeStamp() {
|
||||
}
|
||||
|
||||
inline SGTimeStamp::SGTimeStamp( const long s, const long u ) {
|
||||
seconds = s;
|
||||
usec = u;
|
||||
}
|
||||
|
||||
inline SGTimeStamp::~SGTimeStamp() {
|
||||
}
|
||||
|
||||
inline SGTimeStamp& SGTimeStamp::operator = (const SGTimeStamp& t)
|
||||
{
|
||||
seconds = t.seconds;
|
||||
usec = t.usec;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void SGTimeStamp::stamp() {
|
||||
#if defined( WIN32 )
|
||||
unsigned int t;
|
||||
t = timeGetTime();
|
||||
seconds = 0;
|
||||
usec = t * 1000;
|
||||
#elif defined( HAVE_GETTIMEOFDAY )
|
||||
struct timeval current;
|
||||
struct timezone tz;
|
||||
// sg_timestamp currtime;
|
||||
gettimeofday(¤t, &tz);
|
||||
seconds = current.tv_sec;
|
||||
usec = current.tv_usec;
|
||||
#elif defined( HAVE_GETLOCALTIME )
|
||||
SYSTEMTIME current;
|
||||
GetLocalTime(¤t);
|
||||
seconds = current.wSecond;
|
||||
usec = current.wMilliseconds * 1000;
|
||||
#elif defined( HAVE_FTIME )
|
||||
struct timeb current;
|
||||
ftime(¤t);
|
||||
seconds = current.time;
|
||||
usec = current.millitm * 1000;
|
||||
// -dw- uses time manager
|
||||
#elif defined( macintosh )
|
||||
UnsignedWide ms;
|
||||
Microseconds(&ms);
|
||||
|
||||
seconds = ms.lo / 1000000;
|
||||
usec = ms.lo - ( seconds * 1000000 );
|
||||
#else
|
||||
# error Port me
|
||||
#endif
|
||||
}
|
||||
|
||||
// increment the time stamp by the number of microseconds (usec)
|
||||
inline SGTimeStamp operator + (const SGTimeStamp& t, const long& m) {
|
||||
#ifdef WIN32
|
||||
return SGTimeStamp( 0, t.usec + m );
|
||||
#else
|
||||
return SGTimeStamp( t.seconds + ( t.usec + m ) / 1000000,
|
||||
( t.usec + m ) % 1000000 );
|
||||
#endif
|
||||
}
|
||||
|
||||
// difference between time stamps in microseconds (usec)
|
||||
inline long operator - (const SGTimeStamp& a, const SGTimeStamp& b)
|
||||
{
|
||||
#if defined( WIN32 )
|
||||
return a.usec - b.usec;
|
||||
#else
|
||||
return 1000000 * (a.seconds - b.seconds) + (a.usec - b.usec);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#endif // _TIMESTAMP_HXX
|
||||
|
||||
|
||||
@@ -30,9 +30,10 @@
|
||||
#ifndef _TIMEZONE_H_
|
||||
#define _TIMEZONE_H_
|
||||
|
||||
#include "geocoord.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include <simgear/timing/geocoord.h>
|
||||
|
||||
class Timezone : public GeoCoord
|
||||
{
|
||||
private:
|
||||
|
||||
@@ -6,4 +6,4 @@ include_HEADERS = xgl.h
|
||||
|
||||
libsgxgl_a_SOURCES = xgl.c xglUtils.c
|
||||
|
||||
INCLUDES += -I$(top_builddir)
|
||||
INCLUDES += -I$(top_srcdir)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
if HAVE_ZLIB
|
||||
ZLIB_INCL =
|
||||
else
|
||||
XLIB_INCL = -I$(top_srcdir)/src/zlib
|
||||
endif
|
||||
|
||||
lib_LIBRARIES = libsgxml.a
|
||||
|
||||
include_HEADERS = \
|
||||
easyxml.hxx
|
||||
|
||||
noinst_HEADERS = \
|
||||
xmltok_impl.c xmltok_ns.c
|
||||
|
||||
libsgxml_a_SOURCES = \
|
||||
asciitab.h \
|
||||
easyxml.cxx \
|
||||
hashtable.h hashtable.c \
|
||||
iasciitab.h latin1tab.h nametab.h utf8tab.h xmldef.h \
|
||||
xmlparse.h xmlparse.c \
|
||||
xmlrole.h xmlrole.c \
|
||||
xmltok.h xmltok.c \
|
||||
xmltok_impl.h
|
||||
|
||||
INCLUDES += -I$(top_srcdir) $(ZLIB_INCL)
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
The contents of this file are subject to the Mozilla Public License
|
||||
Version 1.1 (the "License"); you may not use this file except in
|
||||
compliance with the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS"
|
||||
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing rights and limitations
|
||||
under the License.
|
||||
|
||||
The Original Code is expat.
|
||||
|
||||
The Initial Developer of the Original Code is James Clark.
|
||||
Portions created by James Clark are Copyright (C) 1998, 1999
|
||||
James Clark. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms
|
||||
of the GNU General Public License (the "GPL"), in which case the
|
||||
provisions of the GPL are applicable instead of those above. If you
|
||||
wish to allow use of your version of this file only under the terms of
|
||||
the GPL and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by the
|
||||
GPL. If you do not delete the provisions above, a recipient may use
|
||||
your version of this file under either the MPL or the GPL.
|
||||
*/
|
||||
|
||||
/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
|
||||
/* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML,
|
||||
/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
|
||||
/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
|
||||
/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
|
||||
/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
|
||||
/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
|
||||
/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
|
||||
/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
|
||||
/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
|
||||
/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
|
||||
/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
|
||||
/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
|
||||
/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
|
||||
/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
|
||||
/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
|
||||
/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
|
||||
/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
@@ -0,0 +1,239 @@
|
||||
// easyxml.cxx - implementation of EasyXML interfaces.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <string.h> // strcmp()
|
||||
|
||||
#include "easyxml.hxx"
|
||||
#include "xmlparse.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of XMLAttributes.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
XMLAttributes::XMLAttributes ()
|
||||
{
|
||||
}
|
||||
|
||||
XMLAttributes::~XMLAttributes ()
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
XMLAttributes::findAttribute (const char * name) const
|
||||
{
|
||||
int s = size();
|
||||
for (int i = 0; i < s; i++) {
|
||||
if (strcmp(name, getName(i)) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool
|
||||
XMLAttributes::hasAttribute (const char * name) const
|
||||
{
|
||||
return (findAttribute(name) != -1);
|
||||
}
|
||||
|
||||
const char *
|
||||
XMLAttributes::getValue (const char * name) const
|
||||
{
|
||||
int pos = findAttribute(name);
|
||||
if (pos >= 0)
|
||||
return getValue(pos);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of XMLAttributesDefault.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
XMLAttributesDefault::XMLAttributesDefault ()
|
||||
{
|
||||
}
|
||||
|
||||
XMLAttributesDefault::XMLAttributesDefault (const XMLAttributes &atts)
|
||||
{
|
||||
int s = atts.size();
|
||||
for (int i = 0; i < s; i++)
|
||||
addAttribute(atts.getName(i), atts.getValue(i));
|
||||
}
|
||||
|
||||
XMLAttributesDefault::~XMLAttributesDefault ()
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
XMLAttributesDefault::size () const
|
||||
{
|
||||
return _atts.size() / 2;
|
||||
}
|
||||
|
||||
const char *
|
||||
XMLAttributesDefault::getName (int i) const
|
||||
{
|
||||
return _atts[i*2].c_str();
|
||||
}
|
||||
|
||||
const char *
|
||||
XMLAttributesDefault::getValue (int i) const
|
||||
{
|
||||
return _atts[i*2+1].c_str();
|
||||
}
|
||||
|
||||
void
|
||||
XMLAttributesDefault::addAttribute (const char * name, const char * value)
|
||||
{
|
||||
_atts.push_back(name);
|
||||
_atts.push_back(value);
|
||||
}
|
||||
|
||||
void
|
||||
XMLAttributesDefault::setName (int i, const char * name)
|
||||
{
|
||||
_atts[i*2] = name;
|
||||
}
|
||||
|
||||
void
|
||||
XMLAttributesDefault::setValue (int i, const char * name)
|
||||
{
|
||||
_atts[i*2+1] = name;
|
||||
}
|
||||
|
||||
void
|
||||
XMLAttributesDefault::setValue (const char * name, const char * value)
|
||||
{
|
||||
int pos = findAttribute(name);
|
||||
if (pos >= 0) {
|
||||
setName(pos, name);
|
||||
setValue(pos, value);
|
||||
} else {
|
||||
addAttribute(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Attribute list wrapper for Expat.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class ExpatAtts : public XMLAttributes
|
||||
{
|
||||
public:
|
||||
ExpatAtts (const char ** atts) : _atts(atts) {}
|
||||
|
||||
virtual int size () const;
|
||||
virtual const char * getName (int i) const;
|
||||
virtual const char * getValue (int i) const;
|
||||
|
||||
private:
|
||||
const char ** _atts;
|
||||
};
|
||||
|
||||
int
|
||||
ExpatAtts::size () const
|
||||
{
|
||||
int s = 0;
|
||||
for (int i = 0; _atts[i] != 0; i += 2)
|
||||
s++;
|
||||
return s;
|
||||
}
|
||||
|
||||
const char *
|
||||
ExpatAtts::getName (int i) const
|
||||
{
|
||||
return _atts[i*2];
|
||||
}
|
||||
|
||||
const char *
|
||||
ExpatAtts::getValue (int i) const
|
||||
{
|
||||
return _atts[i*2+1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Static callback functions for Expat.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define VISITOR (*((XMLVisitor*)userData))
|
||||
|
||||
static void
|
||||
start_element (void * userData, const char * name, const char ** atts)
|
||||
{
|
||||
VISITOR.startElement(name, ExpatAtts(atts));
|
||||
}
|
||||
|
||||
static void
|
||||
end_element (void * userData, const char * name)
|
||||
{
|
||||
VISITOR.endElement(name);
|
||||
}
|
||||
|
||||
static void
|
||||
character_data (void * userData, const char * s, int len)
|
||||
{
|
||||
VISITOR.data(s, len);
|
||||
}
|
||||
|
||||
static void
|
||||
processing_instruction (void * userData,
|
||||
const char * target,
|
||||
const char * data)
|
||||
{
|
||||
VISITOR.pi(target, data);
|
||||
}
|
||||
|
||||
#undef VISITOR
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of XMLReader.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool
|
||||
readXML (istream &input, XMLVisitor &visitor)
|
||||
{
|
||||
bool retval = true;
|
||||
|
||||
XML_Parser parser = XML_ParserCreate(0);
|
||||
XML_SetUserData(parser, &visitor);
|
||||
XML_SetElementHandler(parser, start_element, end_element);
|
||||
XML_SetCharacterDataHandler(parser, character_data);
|
||||
XML_SetProcessingInstructionHandler(parser, processing_instruction);
|
||||
|
||||
visitor.startXML();
|
||||
|
||||
char buf[16384];
|
||||
while (!input.eof()) {
|
||||
|
||||
input.read(buf,16384);
|
||||
// TODO: deal with bad stream.
|
||||
if (!XML_Parse(parser, buf, input.gcount(), false)) {
|
||||
visitor.error(XML_ErrorString(XML_GetErrorCode(parser)),
|
||||
XML_GetCurrentColumnNumber(parser),
|
||||
XML_GetCurrentLineNumber(parser));
|
||||
retval = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval)
|
||||
visitor.endXML();
|
||||
|
||||
XML_ParserFree(parser);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
// end of easyxml.cxx
|
||||
@@ -0,0 +1,91 @@
|
||||
#ifndef __EASYXML_HXX
|
||||
#define __EASYXML_HXX
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using std::istream;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
|
||||
/**
|
||||
* Interface for XML attributes.
|
||||
*/
|
||||
class XMLAttributes
|
||||
{
|
||||
public:
|
||||
XMLAttributes ();
|
||||
virtual ~ XMLAttributes ();
|
||||
|
||||
virtual int size () const = 0;
|
||||
virtual const char * getName (int i) const = 0;
|
||||
virtual const char * getValue (int i) const = 0;
|
||||
|
||||
virtual int findAttribute (const char * name) const;
|
||||
virtual bool hasAttribute (const char * name) const;
|
||||
virtual const char * getValue (const char * name) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Default mutable attributes implementation.
|
||||
*/
|
||||
class XMLAttributesDefault : public XMLAttributes
|
||||
{
|
||||
public:
|
||||
XMLAttributesDefault ();
|
||||
XMLAttributesDefault (const XMLAttributes & atts);
|
||||
virtual ~XMLAttributesDefault ();
|
||||
|
||||
virtual int size () const;
|
||||
virtual const char * getName (int i) const;
|
||||
virtual const char * getValue (int i) const;
|
||||
|
||||
virtual void addAttribute (const char * name, const char * value);
|
||||
virtual void setName (int i, const char * name);
|
||||
virtual void setValue (int i, const char * value);
|
||||
virtual void setValue (const char * name, const char * value);
|
||||
|
||||
private:
|
||||
vector<string> _atts;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Visitor class for an XML document.
|
||||
*
|
||||
* To read an XML document, a module must subclass the visitor to do
|
||||
* something useful for the different XML events.
|
||||
*/
|
||||
class XMLVisitor
|
||||
{
|
||||
public:
|
||||
// start an XML document
|
||||
virtual void startXML () {}
|
||||
// end an XML document
|
||||
virtual void endXML () {}
|
||||
// start an element
|
||||
virtual void startElement (const char * name, const XMLAttributes &atts) {}
|
||||
// end an element
|
||||
virtual void endElement (const char * name) {}
|
||||
// character data
|
||||
virtual void data (const char * s, int length) {}
|
||||
// processing instruction
|
||||
virtual void pi (const char * target, const char * data) {}
|
||||
// non-fatal warning
|
||||
virtual void warning (const char * message, int line, int column) {}
|
||||
// fatal error
|
||||
virtual void error (const char * message, int line, int column) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read an XML document.
|
||||
*/
|
||||
extern bool readXML (istream &input, XMLVisitor &visitor);
|
||||
|
||||
|
||||
#endif // __EASYXML_HXX
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
The contents of this file are subject to the Mozilla Public License
|
||||
Version 1.1 (the "License"); you may not use this file except in
|
||||
csompliance with the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS"
|
||||
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing rights and limitations
|
||||
under the License.
|
||||
|
||||
The Original Code is expat.
|
||||
|
||||
The Initial Developer of the Original Code is James Clark.
|
||||
Portions created by James Clark are Copyright (C) 1998, 1999
|
||||
James Clark. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms
|
||||
of the GNU General Public License (the "GPL"), in which case the
|
||||
provisions of the GPL are applicable instead of those above. If you
|
||||
wish to allow use of your version of this file only under the terms of
|
||||
the GPL and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by the
|
||||
GPL. If you do not delete the provisions above, a recipient may use
|
||||
your version of this file under either the MPL or the GPL.
|
||||
*/
|
||||
|
||||
#include "xmldef.h"
|
||||
|
||||
#ifdef XML_UNICODE_WCHAR_T
|
||||
#ifndef XML_UNICODE
|
||||
#define XML_UNICODE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "hashtable.h"
|
||||
|
||||
#define INIT_SIZE 64
|
||||
|
||||
static
|
||||
int keyeq(KEY s1, KEY s2)
|
||||
{
|
||||
for (; *s1 == *s2; s1++, s2++)
|
||||
if (*s1 == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
unsigned long hash(KEY s)
|
||||
{
|
||||
unsigned long h = 0;
|
||||
while (*s)
|
||||
h = (h << 5) + h + (unsigned char)*s++;
|
||||
return h;
|
||||
}
|
||||
|
||||
NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize)
|
||||
{
|
||||
size_t i;
|
||||
if (table->size == 0) {
|
||||
if (!createSize)
|
||||
return 0;
|
||||
table->v = calloc(INIT_SIZE, sizeof(NAMED *));
|
||||
if (!table->v)
|
||||
return 0;
|
||||
table->size = INIT_SIZE;
|
||||
table->usedLim = INIT_SIZE / 2;
|
||||
i = hash(name) & (table->size - 1);
|
||||
}
|
||||
else {
|
||||
unsigned long h = hash(name);
|
||||
for (i = h & (table->size - 1);
|
||||
table->v[i];
|
||||
i == 0 ? i = table->size - 1 : --i) {
|
||||
if (keyeq(name, table->v[i]->name))
|
||||
return table->v[i];
|
||||
}
|
||||
if (!createSize)
|
||||
return 0;
|
||||
if (table->used == table->usedLim) {
|
||||
/* check for overflow */
|
||||
size_t newSize = table->size * 2;
|
||||
NAMED **newV = calloc(newSize, sizeof(NAMED *));
|
||||
if (!newV)
|
||||
return 0;
|
||||
for (i = 0; i < table->size; i++)
|
||||
if (table->v[i]) {
|
||||
size_t j;
|
||||
for (j = hash(table->v[i]->name) & (newSize - 1);
|
||||
newV[j];
|
||||
j == 0 ? j = newSize - 1 : --j)
|
||||
;
|
||||
newV[j] = table->v[i];
|
||||
}
|
||||
free(table->v);
|
||||
table->v = newV;
|
||||
table->size = newSize;
|
||||
table->usedLim = newSize/2;
|
||||
for (i = h & (table->size - 1);
|
||||
table->v[i];
|
||||
i == 0 ? i = table->size - 1 : --i)
|
||||
;
|
||||
}
|
||||
}
|
||||
table->v[i] = calloc(1, createSize);
|
||||
if (!table->v[i])
|
||||
return 0;
|
||||
table->v[i]->name = name;
|
||||
(table->used)++;
|
||||
return table->v[i];
|
||||
}
|
||||
|
||||
void hashTableDestroy(HASH_TABLE *table)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < table->size; i++) {
|
||||
NAMED *p = table->v[i];
|
||||
if (p)
|
||||
free(p);
|
||||
}
|
||||
free(table->v);
|
||||
}
|
||||
|
||||
void hashTableInit(HASH_TABLE *p)
|
||||
{
|
||||
p->size = 0;
|
||||
p->usedLim = 0;
|
||||
p->used = 0;
|
||||
p->v = 0;
|
||||
}
|
||||
|
||||
void hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
|
||||
{
|
||||
iter->p = table->v;
|
||||
iter->end = iter->p + table->size;
|
||||
}
|
||||
|
||||
NAMED *hashTableIterNext(HASH_TABLE_ITER *iter)
|
||||
{
|
||||
while (iter->p != iter->end) {
|
||||
NAMED *tem = *(iter->p)++;
|
||||
if (tem)
|
||||
return tem;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
The contents of this file are subject to the Mozilla Public License
|
||||
Version 1.1 (the "License"); you may not use this file except in
|
||||
compliance with the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS"
|
||||
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing rights and limitations
|
||||
under the License.
|
||||
|
||||
The Original Code is expat.
|
||||
|
||||
The Initial Developer of the Original Code is James Clark.
|
||||
Portions created by James Clark are Copyright (C) 1998, 1999
|
||||
James Clark. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms
|
||||
of the GNU General Public License (the "GPL"), in which case the
|
||||
provisions of the GPL are applicable instead of those above. If you
|
||||
wish to allow use of your version of this file only under the terms of
|
||||
the GPL and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by the
|
||||
GPL. If you do not delete the provisions above, a recipient may use
|
||||
your version of this file under either the MPL or the GPL.
|
||||
*/
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef XML_UNICODE
|
||||
|
||||
#ifdef XML_UNICODE_WCHAR_T
|
||||
typedef const wchar_t *KEY;
|
||||
#else /* not XML_UNICODE_WCHAR_T */
|
||||
typedef const unsigned short *KEY;
|
||||
#endif /* not XML_UNICODE_WCHAR_T */
|
||||
|
||||
#else /* not XML_UNICODE */
|
||||
|
||||
typedef const char *KEY;
|
||||
|
||||
#endif /* not XML_UNICODE */
|
||||
|
||||
typedef struct {
|
||||
KEY name;
|
||||
} NAMED;
|
||||
|
||||
typedef struct {
|
||||
NAMED **v;
|
||||
size_t size;
|
||||
size_t used;
|
||||
size_t usedLim;
|
||||
} HASH_TABLE;
|
||||
|
||||
NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize);
|
||||
void hashTableInit(HASH_TABLE *);
|
||||
void hashTableDestroy(HASH_TABLE *);
|
||||
|
||||
typedef struct {
|
||||
NAMED **p;
|
||||
NAMED **end;
|
||||
} HASH_TABLE_ITER;
|
||||
|
||||
void hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
|
||||
NAMED *hashTableIterNext(HASH_TABLE_ITER *);
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
The contents of this file are subject to the Mozilla Public License
|
||||
Version 1.1 (the "License"); you may not use this file except in
|
||||
compliance with the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS"
|
||||
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing rights and limitations
|
||||
under the License.
|
||||
|
||||
The Original Code is expat.
|
||||
|
||||
The Initial Developer of the Original Code is James Clark.
|
||||
Portions created by James Clark are Copyright (C) 1998, 1999
|
||||
James Clark. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms
|
||||
of the GNU General Public License (the "GPL"), in which case the
|
||||
provisions of the GPL are applicable instead of those above. If you
|
||||
wish to allow use of your version of this file only under the terms of
|
||||
the GPL and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by the
|
||||
GPL. If you do not delete the provisions above, a recipient may use
|
||||
your version of this file under either the MPL or the GPL.
|
||||
*/
|
||||
|
||||
/* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */
|
||||
/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
|
||||
/* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML,
|
||||
/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
|
||||
/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
|
||||
/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
|
||||
/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
|
||||
/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
|
||||
/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
|
||||
/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
|
||||
/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
|
||||
/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
|
||||
/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
|
||||
/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
|
||||
/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
|
||||
/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
|
||||
/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
|
||||
/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
|
||||
/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
The contents of this file are subject to the Mozilla Public License
|
||||
Version 1.1 (the "License"); you may not use this file except in
|
||||
compliance with the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS"
|
||||
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing rights and limitations
|
||||
under the License.
|
||||
|
||||
The Original Code is expat.
|
||||
|
||||
The Initial Developer of the Original Code is James Clark.
|
||||
Portions created by James Clark are Copyright (C) 1998, 1999
|
||||
James Clark. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms
|
||||
of the GNU General Public License (the "GPL"), in which case the
|
||||
provisions of the GPL are applicable instead of those above. If you
|
||||
wish to allow use of your version of this file only under the terms of
|
||||
the GPL and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by the
|
||||
GPL. If you do not delete the provisions above, a recipient may use
|
||||
your version of this file under either the MPL or the GPL.
|
||||
*/
|
||||
|
||||
/* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
|
||||
/* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME,
|
||||
/* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
|
||||
/* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
|
||||
/* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
|
||||
/* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
@@ -0,0 +1,150 @@
|
||||
static const unsigned namingBitmap[] = {
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE,
|
||||
0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF,
|
||||
0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF,
|
||||
0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
|
||||
0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
|
||||
0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
|
||||
0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
|
||||
0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF,
|
||||
0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000,
|
||||
0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060,
|
||||
0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003,
|
||||
0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003,
|
||||
0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000,
|
||||
0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001,
|
||||
0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003,
|
||||
0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000,
|
||||
0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003,
|
||||
0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003,
|
||||
0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000,
|
||||
0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000,
|
||||
0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF,
|
||||
0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB,
|
||||
0x40000000, 0xF580C900, 0x00000007, 0x02010800,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF,
|
||||
0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF,
|
||||
0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF,
|
||||
0x00000000, 0x00004C40, 0x00000000, 0x00000000,
|
||||
0x00000007, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF,
|
||||
0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF,
|
||||
0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE,
|
||||
0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF,
|
||||
0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003,
|
||||
0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
|
||||
0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
|
||||
0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
|
||||
0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
|
||||
0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF,
|
||||
0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF,
|
||||
0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF,
|
||||
0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF,
|
||||
0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF,
|
||||
0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0,
|
||||
0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1,
|
||||
0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3,
|
||||
0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80,
|
||||
0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3,
|
||||
0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3,
|
||||
0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000,
|
||||
0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000,
|
||||
0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF,
|
||||
0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x1FFF0000, 0x00000002,
|
||||
0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF,
|
||||
0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF,
|
||||
};
|
||||
static const unsigned char nmstrtPages[] = {
|
||||
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00,
|
||||
0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
|
||||
0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
static const unsigned char namePages[] = {
|
||||
0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00,
|
||||
0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
|
||||
0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
|
||||
0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user