Compare commits

...

220 Commits

Author SHA1 Message Date
curt
9fefaef31e One more pass at a reorg. 2000-02-16 22:01:06 +00:00
curt
689a942f19 One more pass at reorgs. 2000-02-16 22:00:51 +00:00
curt
cb9654f1f4 Removed autogenerated file. 2000-02-15 05:15:23 +00:00
curt
a8f8cef484 Code reorganization. 2000-02-15 02:30:02 +00:00
curt
6cf51c3222 Added ... 2000-02-15 01:07:49 +00:00
curt
0d8ae0cabe Restructuring subdirectories. 2000-02-14 17:37:54 +00:00
curt
49d6f93d8b Removed autogen'd files. 2000-02-09 19:33:04 +00:00
curt
5173d709e0 Initial revision 2000-02-09 19:27:02 +00:00
Tim Moore
778c3ab25c Moved everything from Lib to simgear 2009-09-16 08:06:28 +02:00
curt
aa17d9ac9a Updated for plib-1.1.x 2000-02-04 21:50:04 +00:00
curt
ffe1d9485e Converted sky colors from floats to GLubytes to try to work around Linux
nVidia bug, with no success. :-(
1999-12-30 16:41:43 +00:00
curt
71abebe837 Use a more standard texture/blend mode combination for sun/moon halos to
avoid render path that's not supported by all cards/drivers.
1999-11-03 15:17:50 +00:00
curt
ca07b64af0 Moved where glBlendFunc() is reset to main.cxx 1999-10-22 15:15:43 +00:00
curt
2fde2ce581 Reset glBlendFunc() here to. 1999-10-22 12:58:39 +00:00
curt
cb0da2ca5e Set glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ; when done drawing
the Sun so that the cloud texture alpha blending will work correctly.
1999-10-22 12:34:06 +00:00
curt
c0422839b9 MSVC++ portability fix. 1999-10-11 21:09:21 +00:00
curt
862b884f02 Various SGI portability tweaks. 1999-10-07 21:08:50 +00:00
curt
708e745cfd MACos fixes. 1999-09-11 14:35:28 +00:00
curt
bb882a1239 Borland C++ tweaks.
MacOS/Metrowerks tweaks.
Fix for fgText default constructor.
1999-06-20 01:52:31 +00:00
curt
6b2bf2fa8e Fixed a bug in handling windoze driver letter ":" notation. 1999-06-15 19:55:10 +00:00
curt
2640b43355 Add a method to return pointer to data array. 1999-06-12 21:09:41 +00:00
curt
d201e9b5c5 The next round of MacOS changes contributed by Darrell Walisser.
Starting work on fixing tringle slivers in scenery generation tools.
1999-06-05 12:45:40 +00:00
curt
8f0f79506c Mac portability changes contributed by "Darrell Walisser" <dwaliss1@purdue.edu> 1999-06-02 22:22:47 +00:00
curt
121d2f92cb Fixed an IRIX warning message where an inline function is referenced
before it is defined.
1999-06-01 21:16:33 +00:00
curt
87e641aeda Update README.plib with clearer wording.
Fixed the == compare in point3d.hxx.
1999-06-01 21:01:03 +00:00
curt
27403e2fef Whups, fixed a simple bug so you can now fly across the lon = +/-180
boundary without any problems.
1999-05-25 11:54:21 +00:00
curt
b5ceef5e68 Moved material property and texture management back to Simulator/Objects/ 1999-05-13 02:10:52 +00:00
curt
5d68470c95 Major shuffling to push basic material management out into FlightGear/Lib/
so it can be accessible from the scenery tools.
Also implimented JIT texture loading to save start time and memory.
1999-05-12 04:24:55 +00:00
curt
e176b4d8b6 Borland portability fixes contributed by Charlie Hotchkiss. 1999-05-08 02:33:13 +00:00
curt
218821f694 Tweaks for poles. 1999-05-06 02:27:24 +00:00
curt
a8f4a61dc2 Removed the test program for now ... 1999-04-27 19:37:09 +00:00
curt
9221604424 Changes for the MacOS port contributed by Darrell Walisser. 1999-04-27 19:27:45 +00:00
curt
5bddbd0ca9 MacOS portability improvements.
Added a class to encapsulate Mac vs. Unix path separator differences.
1999-04-27 15:56:22 +00:00
curt
f8dde93e05 MacOS portability improvements. 1999-04-27 15:54:39 +00:00
curt
489b562232 Borland tweak. 1999-04-22 18:46:40 +00:00
curt
294a0dde63 MAT3mat.c: Borland tweaks.
mat3.h:  Some inline assembly from Norman.
1999-04-22 18:46:27 +00:00
curt
53fbb98d4f Removed plib from the source distribution. It must be built and installed
separately before fgfs can be built and installed.
1999-04-12 02:03:32 +00:00
curt
8a2c08a0c1 Fixes for compiling with native Irix compilers. 1999-04-07 20:58:02 +00:00
curt
b15b40ea10 Initial revision. 1999-04-07 04:09:55 +00:00
curt
0c865f540f Removed in-src cvs logs. 1999-04-06 23:37:07 +00:00
curt
ef4a92859c Removed ... 1999-04-06 22:29:19 +00:00
curt
2a7b06f648 Tweaks to configure script so it can be run from the top level
configure script.
1999-04-06 02:42:10 +00:00
curt
6c2ca22b3f Initial revision. 1999-04-05 22:18:39 +00:00
curt
592690f8f2 Initial revision 1999-04-05 22:14:10 +00:00
curt
1eb87e7c73 Initial revision 1999-04-05 21:32:32 +00:00
curt
a0e40c1fc1 Integrated Steve's new "plib" conglomeration. 1999-04-03 04:19:39 +00:00
curt
2c920ae1df Added is_open() so we can check if the open() succeeded. 1999-03-27 14:04:25 +00:00
curt
bbde3b36bf Elimitated some const warnings from the compiler. 1999-03-27 05:34:05 +00:00
curt
88a016c516 Minor optimization tweaks. 1999-03-25 19:02:28 +00:00
curt
22d4058564 Jettisoned old bucketutils.[ch] for newbucket.[ch]xx 1999-03-25 19:01:47 +00:00
curt
79e6c529ea MSVC++ portability tweaks contributed by Bernie Bright.
Added using std::ostream declaration.
  Added forward declarations to work around a MSVC bug.
1999-03-15 17:58:41 +00:00
curt
7b22b8cd92 Moved to math subdirectory. 1999-03-13 17:34:44 +00:00
curt
bc2ae82e81 Added some informational methods. 1999-03-12 22:51:18 +00:00
curt
764f4037b0 Tweak for native SGI compilers. 1999-03-08 22:00:12 +00:00
curt
a60454a786 Tweaks for compiling with native SGI compilers. 1999-03-02 01:01:42 +00:00
curt
d136ad3e57 Added initial support for native SGI compilers. 1999-02-26 22:07:53 +00:00
curt
739588f9c3 Renamed bucketutils.c -> bucketutils.cxx 1999-02-17 20:52:02 +00:00
curt
505de4703b Added a routine to calculate the offset in bucket units between two buckets. 1999-02-11 01:09:33 +00:00
curt
236a1f2a2d Added a FG_CLIPPER debug type for the polygon clipper lib. 1999-02-09 00:08:48 +00:00
curt
91efc5ad87 Added a new "newbucket.[ch]xx" FGBucket class to replace the old
fgBUCKET struct and C routines.  This FGBucket class adjusts the tile
width towards the poles to ensure the tiles are at least 8 miles wide.
1999-02-08 23:52:13 +00:00
curt
123c816048 MSVC++ portability changes by Bernie Bright:
Lib/Serial/serial.[ch]xx: Initial Windows support - incomplete.
Simulator/Astro/stars.cxx: typo? included <stdio> instead of <cstdio>
Simulator/Cockpit/hud.cxx: Added Standard headers
Simulator/Cockpit/panel.cxx: Redefinition of default parameter
Simulator/Flight/flight.cxx: Replaced cout with FG_LOG.  Deleted <stdio.h>
Simulator/Main/fg_init.cxx:
Simulator/Main/GLUTmain.cxx:
Simulator/Main/options.hxx: Shuffled <fg_serial.hxx> dependency
Simulator/Objects/material.hxx:
Simulator/Time/timestamp.hxx: VC++ friend kludge
Simulator/Scenery/tile.[ch]xx: Fixed using std::X declarations
Simulator/Main/views.hxx: Added a constant
1999-02-02 20:13:23 +00:00
curt
fab6d05157 Optimizations from Norman Vine. 1999-02-01 21:08:28 +00:00
curt
3240464c7c Portability tweaks by Bernie Bright. 1999-01-27 04:46:14 +00:00
curt
a2ffd27b7c Moved DEM/ to the Tools/ subdir. 1999-01-27 04:45:56 +00:00
curt
af6c921757 Tweaked FDM interface.
Testing check sum support for NMEA serial output.
1999-01-20 13:42:21 +00:00
curt
180e2188ba MacOS portability changes contributed by "Robert Puyol" <puyol@abvent.fr> 1999-01-19 20:56:53 +00:00
curt
23fbd5919f Portability updates by Bernie Bright. 1999-01-19 20:53:34 +00:00
curt
8aec98017a Portability updates contributed by Bernie Bright. 1999-01-19 20:41:46 +00:00
curt
9b4fe7d92d Removed gpc from Libs since this is not "free ware" and the author has
explicitely refused our request to distribute source code for this library
with Flight Gear.
1999-01-19 17:50:36 +00:00
curt
99f11a01fc Use C++ style comments. 1998-12-09 18:48:08 +00:00
curt
b3eacb19f6 Portability improvements. 1998-12-07 21:10:26 +00:00
curt
f12840a72e Improvements to take advantage of memory portability changes. 1998-12-07 21:09:52 +00:00
curt
f472bc563d Added a const in a couple places to get rid of annoying compiler warnings. 1998-12-07 21:08:01 +00:00
curt
3e05a5780d Tweak for SGI portability. 1998-12-04 01:24:35 +00:00
curt
2454f8d269 tweak for un portability. 1998-12-03 01:11:56 +00:00
curt
b4a913e339 Having the class destructor close the fd was a bad idea ... especially if you
ever make a copy of the instance and then subsequently destroy either.
close_port() is now a separate member function.
1998-11-30 17:15:29 +00:00
curt
b82aef65e5 Remove call to cfmakeraw() 1998-11-25 01:33:23 +00:00
curt
3730ce404f Cygnus tools compatibility tweaks. 1998-11-23 21:47:00 +00:00
curt
d7748704d7 Borland portability tweaks. 1998-11-23 21:46:36 +00:00
curt
1690f5475d Add bucketutils.hxx to source list. 1998-11-23 21:46:13 +00:00
curt
a644bd2b03 Patch in fgGeoc2Geod() to avoid a floating explosion.
point3d.hxx include math.h for FreeBSD
1998-11-20 01:00:36 +00:00
curt
62ca2e0227 FreeBSD support. 1998-11-20 00:59:23 +00:00
curt
d56289f897 port configuration tweaks & experiments. 1998-11-19 13:52:54 +00:00
curt
aa02e72829 Updates ... 1998-11-19 03:35:43 +00:00
curt
a878570a8d Added an FG_SERIAL type to the FG_LOG macro. 1998-11-16 13:57:04 +00:00
curt
54352225f1 Added the Serial subdirectory 1998-11-16 13:56:45 +00:00
curt
0b7d4c8c1e Initial revision. 1998-11-16 13:53:01 +00:00
curt
2091bf2144 Check for domain error in fgGeoctoGeod() 1998-11-11 00:18:36 +00:00
curt
0fec7b2599 Initial revision. 1998-11-09 23:42:12 +00:00
curt
74d314558c Enable release builds using the --without-logging option to the configure
script.  Also a couple log message cleanups, plus some C to C++ comment
conversion.
1998-11-07 19:07:02 +00:00
curt
4fb45c4783 Initial revision. 1998-11-06 21:20:41 +00:00
curt
6816ecb3ea Converted to new logstream debugging facility. This allows release
builds with no messages at all (and no performance impact) by using
the -DFG_NDEBUG flag.
1998-11-06 21:17:23 +00:00
curt
6766825159 More portability improvements by Bernie Bright. 1998-11-06 14:05:12 +00:00
curt
3e63d6ca5d Additional win32 support. 1998-11-02 18:28:31 +00:00
curt
6ca9596807 Check for __CYGWIN__ (b20) as well as __CYGWIN32__ (pre b20 compilers)
Other misc. tweaks.
1998-11-02 18:25:32 +00:00
curt
5695fc84e1 Tweak for building with latest egcs. 1998-10-27 02:14:16 +00:00
curt
2aea6362db Added point3d.hxx to the list of source files. 1998-10-22 21:59:44 +00:00
curt
bb70329c25 Tweaks from Bernie Bright. 1998-10-20 18:21:49 +00:00
curt
75bc07dc42 Point3D tweaks. 1998-10-18 01:17:11 +00:00
curt
bac27f1ce3 c++-ifying. 1998-10-16 23:36:36 +00:00
curt
787591dd79 Renamed .c -> .h so we can start adding c++ supporting routines. 1998-10-16 19:30:37 +00:00
curt
c7c353df05 C++-ified the comments. 1998-10-16 19:30:07 +00:00
curt
8470a9eda6 Remove leading _ from a couple defines. 1998-10-16 00:50:56 +00:00
curt
c5adb85741 Added point3d.hxx to replace cheezy fgPoint3d struct. 1998-10-16 00:50:29 +00:00
curt
2f9619f02a More portability changes to help with windoze compilation problems. 1998-10-13 00:10:06 +00:00
curt
11cab90ce2 Udates from Steve. 1998-10-02 21:35:09 +00:00
curt
9ae48c2d7d added a working() method. 1998-09-29 14:54:57 +00:00
curt
00fc8205da Miscellaneous fixes under Steve's direction. 1998-09-29 02:00:38 +00:00
curt
62e85640da Tweaked the example a bit. 1998-09-25 16:01:19 +00:00
curt
1b99b2a25d Incorporated Steve's latest version of his audio library. This version
allows pitch and volume changes so we should be able tie this to the
throttle now.
1998-09-24 19:36:25 +00:00
curt
605ad52197 Additional enhancements. 1998-09-24 15:22:17 +00:00
curt
af80c5e018 Temporary destructor patch until Steve can release next version of PUI. 1998-09-15 02:10:03 +00:00
curt
18ac42b2e4 Tweaked compiled vs. lib vs. distributed file lists. 1998-09-08 21:39:34 +00:00
curt
9ea57fcc30 Fixes by Charlie Hotchkiss. 1998-09-08 21:39:07 +00:00
curt
7c27474164 Removed an extraneous extern "C" ... 1998-09-03 21:24:36 +00:00
curt
afdee14332 Tweaks for final 0.53 1998-09-02 21:30:58 +00:00
curt
7f5f12d37a Initial revision. 1998-09-01 19:06:28 +00:00
curt
cea0df71f8 Added a Lib/Misc/ subdirectory. 1998-09-01 18:59:19 +00:00
curt
aef484d5fc Various "inline" code optimizations contributed by Norman Vine. 1998-08-24 20:04:08 +00:00
curt
dacc051a57 Attempting to iron out seg faults and crashes.
Did some shuffling to fix a initialization order problem between view
position, scenery elevation.
1998-08-22 14:49:54 +00:00
curt
e111f530c3 Added Lib/gpc (generic polygon clipping library) 1998-08-22 01:18:27 +00:00
curt
c00ca055bc cosmetic ... 1998-08-06 12:42:40 +00:00
curt
305589cd01 Removed zlib support. 1998-07-30 23:42:14 +00:00
curt
6610244275 removed libtool support. 1998-07-30 23:41:43 +00:00
curt
e462e64d42 Added Irix audio support. 1998-07-30 23:41:23 +00:00
curt
39521df546 Version 1.1.3 1998-07-24 21:35:29 +00:00
curt
6dd8a1525c fgPointLine() rewritten into fgPointLineSquared() ... this ultimately saves
us from doing a sqrt().
1998-07-24 21:34:38 +00:00
curt
fca7a8fa47 Initial revision. 1998-07-16 17:48:11 +00:00
curt
1175179da1 HAVE_AUDIO_SUPPORT -> ENABLE_AUDIO_SUPPORT 1998-07-16 17:29:12 +00:00
curt
06ab581edb Incorporated next version of PUI. 1998-07-13 20:59:34 +00:00
curt
dbcecbd3b8 polar3d.[ch] renamed to polar3d.[ch]xx, vector.[ch] renamed to vector.[ch]xx
Updated fg_geodesy comments to reflect that routines expect and produce
  meters.
1998-07-08 14:40:07 +00:00
curt
4205c0a38d typedef'd struct fgBUCKET. 1998-07-04 00:46:47 +00:00
curt
a76904c314 Added #ifdef HAVE_CONFIG_H #include <config.h> #endif to get WIN32
definition.
1998-07-03 11:54:50 +00:00
curt
529ca14534 New version from Steve. 1998-06-17 21:32:42 +00:00
curt
7423077f95 Refine conditional audio compilation. 1998-06-17 21:31:45 +00:00
curt
f116ee7802 Pui -> PUI. 1998-06-12 14:26:19 +00:00
curt
09cf8c001e Renamed Pui -> PUI. 1998-06-12 01:05:51 +00:00
curt
cfe0e18e4e Initial revision. 1998-06-12 01:04:52 +00:00
curt
2caad4a27b Added Pui subdirectory. 1998-06-12 00:53:47 +00:00
curt
b5e7938ebe Added a Lib/Audio for Steve Baker's sound library. 1998-06-03 00:42:40 +00:00
curt
bd3e280fe5 initial checkin of notify 1998-06-02 21:42:22 +00:00
curt
39164d1438 initial checkin of modules 1998-06-02 21:42:22 +00:00
curt
a9c068ae3b initial checkin of cvswrappers 1998-06-02 21:42:22 +00:00
curt
6c7856549b initial checkin of taginfo 1998-06-02 21:42:21 +00:00
curt
d85cbc7b61 initial checkin of rcsinfo 1998-06-02 21:42:21 +00:00
curt
d8cbac4576 initial checkin of loginfo 1998-06-02 21:42:21 +00:00
curt
c0874a000e initial checkin of editinfo 1998-06-02 21:42:21 +00:00
curt
e317a39b2d initial checkin of commitinfo 1998-06-02 21:42:21 +00:00
curt
61d4bd8adf initial checkin of checkoutlist 1998-06-02 21:42:21 +00:00
curt
a8deedaa66 Rewrote a slightly ambiguous code fragment (contributed by Charlie Hotchkiss) 1998-06-01 17:49:44 +00:00
curt
15790ef4b4 Borland C++ fixes from the zlib author. A new version is due out soon. 1998-05-29 20:30:11 +00:00
curt
8cf618ea75 Removed derived files "Makefile.in" from version control. 1998-05-23 14:31:48 +00:00
curt
5a81c9ecf0 Derived file "Makefile.in" removed from version control. 1998-05-23 14:18:22 +00:00
curt
4ccc2b3cfc Small tweak for correct win32 compiling. 1998-05-20 20:50:28 +00:00
curt
ff8845de52 Better handling of WIN32 environments. 1998-05-13 18:24:49 +00:00
curt
e4d4a2d8eb Wrapped zlib calls so zlib can be optionally disabled. 1998-05-13 18:24:25 +00:00
curt
5a2a23cc2d Added an "#include <config.h>" and "#include <windows.h>" 1998-05-11 18:04:06 +00:00
curt
8a233ddfbb Moved the extern "C" { } until after all the includes have been done. 1998-05-07 23:20:45 +00:00
curt
2b40dc133d Added a blank formating line! 1998-05-07 23:04:28 +00:00
curt
b26263c62d Added an entry for AUTOPILOT. 1998-05-07 23:03:54 +00:00
curt
2df317eb49 Commented out a debugging printf. 1998-05-03 00:45:49 +00:00
curt
5eef0e61ba polar.[ch] renamed to polar3d.[ch] 1998-05-02 01:50:09 +00:00
curt
021558d6dd Edited cvs log messages in source files ... bad bad bad! 1998-04-25 22:06:22 +00:00
curt
7a6cab8381 Changed "r" to "rb" in gzopen() options. This fixes bad behavior in win32. 1998-04-25 15:05:01 +00:00
curt
1fcb70e553 Wrapped "#include <config.h>" in "#ifdef HAVE_CONFIG_H" 1998-04-24 00:43:12 +00:00
curt
712bbc9085 Removed an extra #ifdef __cplusplus, then "}", #endif 1998-04-22 13:19:00 +00:00
curt
7b2370d608 C++ - ified comments. Make file open errors fatal. 1998-04-22 13:18:10 +00:00
curt
98f398c99a Modified Files:
Makefile.am Makefile.in
Added Files:
    interpolater.cxx interpolater.hxx
1998-04-21 19:14:21 +00:00
curt
e5efd5bf69 Prepairing for C++ integration. 1998-04-21 17:03:45 +00:00
curt
9d504a9e19 Added Debug, Math, and zlib libraries. 1998-04-18 03:54:32 +00:00
curt
e96e09d112 Miscellaneous Tweaks. 1998-04-18 03:53:41 +00:00
curt
28a6ec8065 Moved to Lib directory and created a libDebug. 1998-04-18 03:52:03 +00:00
curt
875560b8dc Initial revision. 1998-04-18 03:48:29 +00:00
curt
fa360360cb Code reorganizations. Added a Lib/ directory for more general libraries. 1998-04-14 02:43:50 +00:00
curt
e543b5228c Code reorganizations. Added a Lib/ directory for more general libraries. 1998-04-14 02:23:15 +00:00
curt
63ea6cd15a Tweaks to Gnu automake/autoconf system. 1998-04-08 23:35:37 +00:00
curt
79a773d25c Adopted Gnu automake/autoconf system. 1998-04-08 23:28:57 +00:00
curt
dcc537e040 Minor cleanups and reorganizations. 1998-04-06 15:56:23 +00:00
curt
37488d0f7e Converting to Gnu autoconf system. 1998-04-03 22:10:27 +00:00
curt
aa645019e9 Incorporated code changes contributed by Charlie Hotchkiss
<chotchkiss@namg.us.anritsu.com>
1998-02-12 21:59:56 +00:00
curt
6179ec5319 Removed "depend" files from cvs control. Other minor make tweaks. 1998-02-09 22:56:59 +00:00
curt
331f91ba43 Lots of little tweaks to fix various consistency problems discovered by
Solaris' CC.  Fixed a bug in fg_debug.c with how the fgPrintf() wrapper
passed arguments along to the real printf().  Also incorporated HUD changes
by Michele America.
1998-02-03 23:20:27 +00:00
curt
a50203dfec Added MetroWorks patches from Carmen Volpe. 1998-01-31 00:43:18 +00:00
curt
b7eab24f14 Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
system and commandline/config file processing code.
1998-01-27 00:47:59 +00:00
curt
d824ffd02b Changed #ifdef FILE_H to #ifdef _FILE_H 1998-01-22 02:59:38 +00:00
curt
238c6f7c88 More misc. tweaks for rpk make merge. 1998-01-19 19:43:07 +00:00
curt
0dd244fb0c Merged in make system changes from Bob Kuehne <rpk@sgi.com>
This should simplify things tremendously.
1998-01-19 19:27:10 +00:00
curt
61a8afa06a Tons of little changes to clean up the code and to remove fatal errors
when building with the c++ compiler.
1998-01-19 18:40:33 +00:00
curt
ed49eadb6a Minor tweaks and fixes for cygwin32. 1998-01-19 18:35:54 +00:00
curt
ecf19f8af4 Beginning to integrate Tile management subsystem. 1998-01-08 02:22:11 +00:00
curt
9d5eb462c9 Miscellaneous tweaks. 1998-01-07 03:31:27 +00:00
curt
1088c5fa57 Tweaks to help building with MSVC++ 1998-01-06 01:20:19 +00:00
curt
ad2bd3db0f Integrated new event manager with subsystem initializations. 1997-12-30 20:47:48 +00:00
curt
abbcf855c4 Merged in Durk's changes ... 1997-12-30 16:36:51 +00:00
curt
83e648b7d6 Aligned sky with sun so dusk/dawn effects can be correct relative to the sun. 1997-12-22 04:14:33 +00:00
curt
89d049ff73 Initial revision. 1997-12-22 04:13:17 +00:00
curt
ac3a2bce72 Working on scene rendering order and options. 1997-12-19 16:45:00 +00:00
curt
ad20c2d242 Initial revision. 1997-12-16 00:49:09 +00:00
curt
6c9aa9527d Add xgl wrappers for debugging.
Generate terrain normals on the fly.
1997-12-15 23:54:53 +00:00
curt
7ad1e2be73 Working on new scenery subsystem. 1997-10-30 12:38:43 +00:00
curt
604f038cfb Continuing to try to align stars correctly. 1997-09-22 14:44:21 +00:00
curt
b185b1a4d9 Changed naming scheme of basic shared structures. 1997-08-27 03:30:20 +00:00
curt
89a65000a5 Merged in initial HUD and Joystick code. 1997-08-25 20:27:23 +00:00
curt
9c83903c2a Initial revision. 1997-07-31 23:13:14 +00:00
curt
68af57b759 Working on redoing internal coordinate systems & scenery transformations. 1997-07-31 22:52:27 +00:00
curt
9c4b4abb50 Moved fg_random routines from Util/ to Math/ 1997-07-30 16:12:41 +00:00
curt
233ffb3b10 Moved random routines from Utils/ to Math/ 1997-07-30 16:04:08 +00:00
curt
34e2bac4d0 Put comments around the text after an #endif for increased portability. 1997-07-23 21:52:21 +00:00
curt
6d4c38a3c8 Eliminated some harmless compiler warnings. 1997-07-21 21:20:28 +00:00
curt
b6ec5707e8 First stab at a system to generate os2 makefiles automatically. 1997-07-20 02:19:11 +00:00
curt
68d3b7b20c Added ranlib. 1997-07-12 02:24:46 +00:00
curt
b84b36d885 Initial revision. 1997-07-07 21:02:36 +00:00
curt
f43e375d62 Working on scenery transformations to enable us to fly fluidly over the
poles with no discontinuity/distortion in scenery.
1997-07-07 20:59:48 +00:00
curt
ab67fa2c15 renamed mat3 directory to Math so we could add other math related routines. 1997-07-05 20:43:31 +00:00
curt
7aff56c284 Working on Makefile structure. 1997-06-27 21:38:14 +00:00
curt
c13dc3a829 Working on Makefile structure. 1997-06-27 20:03:40 +00:00
curt
baf89c9d63 Restructuring make, adding automatic "make dep" support. 1997-06-26 19:08:38 +00:00
curt
a8b4d21a65 Minor changes to compile with rsxnt/win32. 1997-06-25 15:39:49 +00:00
curt
6c20288ff1 The LaRCsim flight model is starting to look like it is working. 1997-05-30 19:30:16 +00:00
curt
935d4f3bda The MAT3 routines from SRGP. 1997-05-30 19:25:54 +00:00
104 changed files with 26178 additions and 103 deletions

0
AUTHORS Normal file
View File

0
ChangeLog Normal file
View File

6
Makefile.am Normal file
View File

@@ -0,0 +1,6 @@
EXTRA_DIST = mksymlinks.sh
dist-hook:
tar cf - src/metar | (cd $(distdir); tar xvf -)
SUBDIRS = src

0
NEWS Normal file
View File

0
README Normal file
View File

1
VERSION.in Normal file
View File

@@ -0,0 +1 @@
@VERSION@

324
acconfig.h Normal file
View File

@@ -0,0 +1,324 @@
/* acconfig.h
This file is in the public domain.
Descriptive text for the C preprocessor macros that
the distributed Autoconf macros can define.
No software package will use all of them; autoheader copies the ones
your configure.in uses into your configuration header file templates.
The entries are in sort -df order: alphabetical, case insensitive,
ignoring punctuation (such as underscores). Although this order
can split up related entries, it makes it easier to check whether
a given entry is in the file.
Leave the following blank line there!! Autoheader needs it. */
/* Define if on AIX 3.
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
#undef _ALL_SOURCE
#endif
/* Define if using alloca.c. */
#undef C_ALLOCA
/* Define if type char is unsigned and you are not using gcc. */
#ifndef __CHAR_UNSIGNED__
#undef __CHAR_UNSIGNED__
#endif
/* Define if the closedir function returns void instead of int. */
#undef CLOSEDIR_VOID
/* Define to empty if the keyword does not work. */
#undef const
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
#undef CRAY_STACKSEG_END
/* Define for DGUX with <sys/dg_sys_info.h>. */
#undef DGUX
/* Define if you have <dirent.h>. */
#undef DIRENT
/* Define to enable audio support */
#undef ENABLE_AUDIO_SUPPORT
/* Define to enable GLUT joystick support (limited to 3 axes) */
#undef ENABLE_GLUT_JOYSTICK
/* Define to enable plib joystick support (recommended) */
#undef ENABLE_PLIB_JOYSTICK
/* Define to eliminate all trace of debugging messages such as for a
release build */
#undef FG_NDEBUG
/* Define to include Oliver's networking support */
#undef FG_NETWORK_OLK
/* Define to avoid Christian's new weather code */
#undef FG_OLD_WEATHER
/* Define if we are building FGFS (should always be defined) */
#undef FGFS
/* Define to enable 3dfx/glide render in a window hack under unix.
This probably won't work under windows. */
#undef XMESA
#undef FX
/* Define to the type of elements in the array set by `getgroups'.
Usually this is either `int' or `gid_t'. */
#undef GETGROUPS_T
/* Define if the `getloadavg' function needs to be run setuid or setgid. */
#undef GETLOADAVG_PRIVILEGED
/* Define if the `getpgrp' function takes no argument. */
#undef GETPGRP_VOID
/* Define to `int' if <sys/types.h> doesn't define. */
#undef gid_t
/* Define if you have alloca, as a function or macro. */
#undef HAVE_ALLOCA
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
#undef HAVE_ALLOCA_H
/* Define if you external variables daylight. */
#undef HAVE_DAYLIGHT
/* Define if you don't have vprintf but do have _doprnt. */
#undef HAVE_DOPRNT
/* Define if your system has a working fnmatch function. */
#undef HAVE_FNMATCH
/* Define if your system has its own `getloadavg' function. */
#undef HAVE_GETLOADAVG
/* Define if you have getrusage() */
#undef HAVE_GETRUSAGE
/* Define if you have the getmntent function. */
#undef HAVE_GETMNTENT
/* Define if you have the gpc library and headers installed. */
#undef HAVE_GPC_H
/* Define if the `long double' type works. */
#undef HAVE_LONG_DOUBLE
/* Define if you support file names longer than 14 characters. */
#undef HAVE_LONG_FILE_NAMES
/* Define if you have a working `mmap' system call. */
#undef HAVE_MMAP
/* Define if system calls automatically restart after interruption
by a signal. */
#undef HAVE_RESTARTABLE_SYSCALLS
/* Define if you have rint() which rounds to closest int but returns
result as a double data type. */
#undef HAVE_RINT
/* Define if your struct stat has st_blksize. */
#undef HAVE_ST_BLKSIZE
/* Define if your struct stat has st_blocks. */
#undef HAVE_ST_BLOCKS
/* Define if you have the strcoll function and it is properly defined. */
#undef HAVE_STRCOLL
/* Define if your struct stat has st_rdev. */
#undef HAVE_ST_RDEV
/* Define if you have the strftime function. */
#undef HAVE_STRFTIME
/* Define if you have <sys/param.h> */
#undef HAVE_SYS_PARAM_H
/* Define if you have <sys/stat.h> that is POSIX.1 compatible. */
#undef HAVE_SYS_STAT_H
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
#undef HAVE_SYS_WAIT_H
/* Define if you have timegm() */
#undef HAVE_TIMEGM
/* Define if you external variables timezone. */
#undef HAVE_TIMEZONE
/* Define if your struct tm has tm_zone. */
#undef HAVE_TM_ZONE
/* Define if you don't have tm_zone but do have the external array
tzname. */
#undef HAVE_TZNAME
/* Define if you have <unistd.h>. */
#undef HAVE_UNISTD_H
/* Define if utime(file, NULL) sets file's timestamp to the present. */
#undef HAVE_UTIME_NULL
/* Define if you have <vfork.h>. */
#undef HAVE_VFORK_H
/* Define if you have the vprintf function. */
#undef HAVE_VPRINTF
/* Define if you have the wait3 system call. */
#undef HAVE_WAIT3
/* Define as __inline if that's what the C compiler calls it. */
#undef inline
/* Define if int is 16 bits instead of 32. */
#undef INT_16_BITS
/* Define if long int is 64 bits. */
#undef LONG_64_BITS
/* Define if major, minor, and makedev are declared in <mkdev.h>. */
#undef MAJOR_IN_MKDEV
/* Define if major, minor, and makedev are declared in <sysmacros.h>. */
#undef MAJOR_IN_SYSMACROS
/* Define if on MINIX. */
#undef _MINIX
/* Define to `int' if <sys/types.h> doesn't define. */
#undef mode_t
/* Define if you don't have <dirent.h>, but have <ndir.h>. */
#undef NDIR
/* Define if you have <memory.h>, and <string.h> doesn't declare the
mem* functions. */
#undef NEED_MEMORY_H
/* Define if your struct nlist has an n_un member. */
#undef NLIST_NAME_UNION
/* Define if you have <nlist.h>. */
#undef NLIST_STRUCT
/* Define if your C compiler doesn't accept -c and -o together. */
#undef NO_MINUS_C_MINUS_O
/* Define to `long' if <sys/types.h> doesn't define. */
#undef off_t
/* Define to package name */
#undef PACKAGE
/* Define to `int' if <sys/types.h> doesn't define. */
#undef pid_t
/* Define if the system does not provide POSIX.1 features except
with this defined. */
#undef _POSIX_1_SOURCE
/* Define if you need to in order for stat and other things to work. */
#undef _POSIX_SOURCE
/* Define as the return type of signal handlers (int or void). */
#undef RETSIGTYPE
/* Define if the `setpgrp' function takes no argument. */
#undef SETPGRP_VOID
/* Define if the setvbuf function takes the buffering type as its second
argument and the buffer pointer as the third, as on System V
before release 3. */
#undef SETVBUF_REVERSED
/* Define to `unsigned' if <sys/types.h> doesn't define. */
#undef size_t
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
#undef STACK_DIRECTION
/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
#undef STAT_MACROS_BROKEN
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define on System V Release 4. */
#undef SVR4
/* Define if you don't have <dirent.h>, but have <sys/dir.h>. */
#undef SYSDIR
/* Define if you don't have <dirent.h>, but have <sys/ndir.h>. */
#undef SYSNDIR
/* Define if `sys_siglist' is declared by <signal.h>. */
#undef SYS_SIGLIST_DECLARED
/* Define if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Define if your <sys/time.h> declares struct tm. */
#undef TM_IN_SYS_TIME
/* Define to `int' if <sys/types.h> doesn't define. */
#undef uid_t
/* Define for Encore UMAX. */
#undef UMAX
/* Define for Encore UMAX 4.3 that has <inq_status/cpustats.h>
instead of <sys/cpustats.h>. */
#undef UMAX4_3
/* Define if you do not have <strings.h>, index, bzero, etc.. */
#undef USG
/* Define to version number */
#undef VERSION
/* Define vfork as fork if vfork does not work. */
#undef vfork
/* Define if the closedir function returns void instead of int. */
#undef VOID_CLOSEDIR
/* Define if compiling on a Winbloze (95, NT, etc.) platform */
#undef WIN32
/* Define if your processor stores words with the most significant
byte first (like Motorola and SPARC, unlike Intel and VAX). */
#undef WORDS_BIGENDIAN
/* Define if the X Window System is missing or not being used. */
#undef X_DISPLAY_MISSING
/* Define if lex declares yytext as a char * by default, not a char[]. */
#undef YYTEXT_POINTER
/* Leave that blank line there!! Autoheader needs it.
If you're adding to this file, keep in mind:
The entries are in sort -df order: alphabetical, case insensitive,
ignoring punctuation (such as underscores). */

149
aclocal.m4 vendored Normal file
View File

@@ -0,0 +1,149 @@
dnl aclocal.m4 generated automatically by aclocal 1.3
dnl Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
dnl This Makefile.in is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl This program is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
dnl PARTICULAR PURPOSE.
# Do all the work for Automake. This macro actually does too much --
# some checks are only needed if your package does certain things.
# But this isn't really a big deal.
# serial 1
dnl Usage:
dnl AM_INIT_AUTOMAKE(package,version, [no-define])
AC_DEFUN(AM_INIT_AUTOMAKE,
[AC_REQUIRE([AM_PROG_INSTALL])
PACKAGE=[$1]
AC_SUBST(PACKAGE)
VERSION=[$2]
AC_SUBST(VERSION)
dnl test to see if srcdir already configured
if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
ifelse([$3],,
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE")
AC_DEFINE_UNQUOTED(VERSION, "$VERSION"))
AC_REQUIRE([AM_SANITY_CHECK])
AC_REQUIRE([AC_ARG_PROGRAM])
dnl FIXME This is truly gross.
missing_dir=`cd $ac_aux_dir && pwd`
AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
AC_REQUIRE([AC_PROG_MAKE_SET])])
# serial 1
AC_DEFUN(AM_PROG_INSTALL,
[AC_REQUIRE([AC_PROG_INSTALL])
test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
AC_SUBST(INSTALL_SCRIPT)dnl
])
#
# Check to make sure that the build environment is sane.
#
AC_DEFUN(AM_SANITY_CHECK,
[AC_MSG_CHECKING([whether build environment is sane])
# Just in case
sleep 1
echo timestamp > conftestfile
# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
if test "[$]*" = "X"; then
# -L didn't work.
set X `ls -t $srcdir/configure conftestfile`
fi
if test "[$]*" != "X $srcdir/configure conftestfile" \
&& test "[$]*" != "X conftestfile $srcdir/configure"; then
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
alias in your environment])
fi
test "[$]2" = conftestfile
)
then
# Ok.
:
else
AC_MSG_ERROR([newly created file is older than distributed files!
Check your system clock])
fi
rm -f conftest*
AC_MSG_RESULT(yes)])
dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
dnl The program must properly implement --version.
AC_DEFUN(AM_MISSING_PROG,
[AC_MSG_CHECKING(for working $2)
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
if ($2 --version) < /dev/null > /dev/null 2>&1; then
$1=$2
AC_MSG_RESULT(found)
else
$1="$3/missing $2"
AC_MSG_RESULT(missing)
fi
AC_SUBST($1)])
# Define a conditional.
AC_DEFUN(AM_CONDITIONAL,
[AC_SUBST($1_TRUE)
AC_SUBST($1_FALSE)
if $2; then
$1_TRUE=
$1_FALSE='#'
else
$1_TRUE='#'
$1_FALSE=
fi])
# Like AC_CONFIG_HEADER, but automatically create stamp file.
AC_DEFUN(AM_CONFIG_HEADER,
[AC_PREREQ([2.12])
AC_CONFIG_HEADER([$1])
dnl When config.status generates a header, we must update the stamp-h file.
dnl This file resides in the same directory as the config header
dnl that is generated. We must strip everything past the first ":",
dnl and everything past the last "/".
AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
<<am_indx=1
for am_file in <<$1>>; do
case " <<$>>CONFIG_HEADERS " in
*" <<$>>am_file "*<<)>>
echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
;;
esac
am_indx=`expr "<<$>>am_indx" + 1`
done<<>>dnl>>)
changequote([,]))])

394
acsite.m4 Normal file
View File

@@ -0,0 +1,394 @@
dnl
dnl originally from ncftp 2.3.0
dnl added wi_EXTRA_PDIR and wi_ANSI_C
dnl $Id$
dnl
AC_DEFUN(wi_EXTRA_IDIR, [
incdir="$1"
if test -r $incdir ; then
case "$CPPFLAGS" in
*-I${incdir}*)
# echo " + already had $incdir" 1>&6
;;
*)
if test "$CPPFLAGS" = "" ; then
CPPFLAGS="-I$incdir"
else
CPPFLAGS="$CPPFLAGS -I$incdir"
fi
echo " + found $incdir" 1>&6
;;
esac
fi
])
dnl
dnl
dnl
dnl
AC_DEFUN(wi_EXTRA_LDIR, [
mylibdir="$1"
if test -r $mylibdir ; then
case "$LDFLAGS" in
*-L${mylibdir}*)
# echo " + already had $mylibdir" 1>&6
;;
*)
if test "$LDFLAGS" = "" ; then
LDFLAGS="-L$mylibdir"
else
LDFLAGS="$LDFLAGS -L$mylibdir"
fi
echo " + found $mylibdir" 1>&6
;;
esac
fi
])
dnl
dnl __FP__
dnl
dnl
AC_DEFUN(wi_EXTRA_PDIR, [
progdir="$1"
if test -r $progdir ; then
case "$PATH" in
*:${progdir}*)
# echo " + already had $progdir" 1>&6
;;
*${progdir}:*)
# echo " + already had $progdir" 1>&6
;;
*)
if test "$PATH" = "" ; then
PATH="$progdir"
else
PATH="$PATH:$progdir"
fi
echo " + found $progdir" 1>&6
;;
esac
fi
])
dnl
dnl
dnl If you want to also look for include and lib subdirectories in the
dnl $HOME tree, you supply "yes" as the first argument to this macro.
dnl
dnl If you want to look for subdirectories in include/lib directories,
dnl you pass the names in argument 3, otherwise pass a dash.
dnl
AC_DEFUN(wi_EXTRA_DIRS, [echo "checking for extra include and lib directories..." 1>&6
ifelse([$1], yes, [dnl
b1=`cd .. ; pwd`
b2=`cd ../.. ; pwd`
exdirs="$HOME $j $b1 $b2 $prefix $2"
],[dnl
exdirs="$prefix $2"
])
subexdirs="$3"
if test "$subexdirs" = "" ; then
subexdirs="-"
fi
for subexdir in $subexdirs ; do
if test "$subexdir" = "-" ; then
subexdir=""
else
subexdir="/$subexdir"
fi
for exdir in $exdirs ; do
if test "$exdir" != "/usr" || test "$subexdir" != ""; then
incdir="${exdir}/include${subexdir}"
wi_EXTRA_IDIR($incdir)
mylibdir="${exdir}/lib${subexdir}"
wi_EXTRA_LDIR($mylibdir)
progdir="${exdir}/bin${subexdirr}"
wi_EXTRA_PDIR($progdir)
fi
done
done
])
dnl
dnl
dnl
AC_DEFUN(wi_HPUX_CFLAGS,
[AC_MSG_CHECKING(if HP-UX ansi C compiler flags are needed)
AC_REQUIRE([AC_PROG_CC])
os=`uname -s | tr '[A-Z]' '[a-z]'`
ac_cv_hpux_flags=no
if test "$os" = hp-ux ; then
if test "$ac_cv_prog_gcc" = yes ; then
if test "$CFLAGS" != "" ; then
# Shouldn't be in there.
CFLAGS=`echo "$CFLAGS" | sed 's/-Aa//g'`
fi
else
# If you're not using gcc, then you better have a cc/c89
# that is usable. If you have the barebones compiler, it
# won't work. The good compiler uses -Aa for the ANSI
# compatible stuff.
x=`echo $CFLAGS | grep 'Aa' 2>/dev/null`
if test "$x" = "" ; then
CFLAGS="$CFLAGS -Aa"
fi
ac_cv_hpux_flags=yes
fi
# Also add _HPUX_SOURCE to get the extended namespace.
x=`echo $CFLAGS | grep '_HPUX_SOURCE' 2>/dev/null`
if test "$x" = "" ; then
CFLAGS="$CFLAGS -D_HPUX_SOURCE"
fi
fi
AC_MSG_RESULT($ac_cv_hpux_flags)
])
dnl
dnl
dnl
AC_DEFUN(wi_CFLAGS, [AC_REQUIRE([AC_PROG_CC])
wi_HPUX_CFLAGS
if test "$CFLAGS" = "" ; then
CFLAGS="-O"
elif test "$ac_cv_prog_gcc" = "yes" ; then
case "$CFLAGS" in
*"-g -O"*)
#echo "using -g as default gcc CFLAGS" 1>&6
CFLAGS=`echo $CFLAGS | sed 's/-g\ -O/-O/'`
;;
*"-O -g"*)
# Leave the -g, but remove all -O options.
#echo "using -g as default gcc CFLAGS" 1>&6
CFLAGS=`echo $CFLAGS | sed 's/-O\ -g/-O/'`
;;
esac
fi
])
dnl
dnl
dnl
AC_DEFUN(wi_PROTOTYPES, [
AC_MSG_CHECKING(if the compiler supports function prototypes)
AC_TRY_COMPILE(,[extern void exit(int status);],[wi_cv_prototypes=yes
AC_DEFINE(PROTOTYPES)],wi_cv_prototypes=no)
AC_MSG_RESULT($wi_cv_prototypes)
])
dnl
dnl
dnl
AC_DEFUN(wi_ANSI_C, [
AC_MSG_CHECKING(ANSI-style function definitions)
AC_TRY_COMPILE(,[int blubb(int x) { return 0; }],[wi_cv_ansi_funcs=yes
AC_DEFINE(ANSI_FUNCS)],wi_cv_ansi_funcs=no)
AC_MSG_RESULT($wi_cv_ansi_funcs)
])
dnl
dnl
dnl
AC_DEFUN(wi_HEADER_SYS_SELECT_H, [
# See if <sys/select.h> is includable after <sys/time.h>
if test "$ac_cv_header_sys_time_h" = no ; then
AC_CHECK_HEADERS(sys/time.h sys/select.h)
else
AC_CHECK_HEADERS(sys/select.h)
fi
if test "$ac_cv_header_sys_select_h" = yes ; then
AC_MSG_CHECKING([if <sys/select.h> is compatible with <sys/time.h>])
selecth=yes
if test "$ac_cv_header_sys_time_h" = yes ; then
AC_TRY_COMPILE([#include <sys/time.h>
#include <sys/select.h>],[
fd_set a;
struct timeval tmval;
tmval.tv_sec = 0;],selecth=yes,selecth=no)
if test "$selecth" = yes ; then
AC_DEFINE(CAN_USE_SYS_SELECT_H)
fi
fi
AC_MSG_RESULT($selecth)
fi
])
dnl
dnl
dnl
AC_DEFUN(wi_LIB_RESOLV, [
# See if we could access two well-known sites without help of any special
# libraries, like resolv.
AC_TRY_RUN([
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
main()
{
struct hostent *hp1, *hp2;
int result;
hp1 = gethostbyname("gatekeeper.dec.com");
hp2 = gethostbyname("ftp.ncsa.uiuc.edu");
result = ((hp1 != (struct hostent *) 0) && (hp2 != (struct hostent *) 0));
exit(! result);
}],look_for_resolv=no,look_for_resolv=yes,look_for_resolv=yes)
AC_MSG_CHECKING([if we need to look for -lresolv])
AC_MSG_RESULT($look_for_resolv)
if test "$look_for_resolv" = yes ; then
AC_CHECK_LIB(resolv,main)
else
ac_cv_lib_resolv=no
fi
])
dnl
dnl
dnl
AC_DEFUN(wi_LIB_NSL, [
AC_MSG_CHECKING(if we can use -lnsl)
ac_save_LIBS="$LIBS";
LIBS="$LIBS -lnsl";
AC_CACHE_VAL(r_cv_use_libnsl, [
AC_TRY_RUN(
main() { if (getpwuid(getuid())) exit(0); exit(-1); },
nc_cv_use_libnsl=yes, nc_cv_use_libnsl=no, nc_cv_use_libnsl=no)
])
if test "$nc_cv_use_libnsl" = "no"; then LIBS="$ac_save_LIBS"; fi
AC_MSG_RESULT($nc_cv_use_libnsl)
])dnl
dnl
dnl
dnl
AC_DEFUN(nc_PATH_PROG_ZCAT, [
AC_PATH_PROG(GZCAT,gzcat)
AC_PATH_PROG(ZCAT,zcat)
if test "x$GZCAT" = x ; then
if test "x$ZCAT" != x ; then
# See if zcat is really gzcat. gzcat has a --version option, regular
# zcat does not.
AC_MSG_CHECKING(if zcat is really gzcat in disguise)
if $ZCAT --version 2> /dev/null ; then
AC_DEFINE_UNQUOTED(GZCAT, "$ZCAT")
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
fi
else
AC_DEFINE_UNQUOTED(GZCAT, "$GZCAT")
fi
if test "x$ZCAT" != x ; then
AC_DEFINE_UNQUOTED(ZCAT, "$ZCAT")
fi
])
dnl
dnl
dnl
AC_DEFUN(wi_SYSV_EXTRA_DIRS, [
# Use System V because their curses extensions are required. This must
# be done early so we use the -I and -L in the library checks also.
# This is mostly a Solaris/SunOS hack. Note that doing this will also
# use all of the other System V libraries and headers.
AC_MSG_CHECKING(for alternative System V libraries)
if test -f /usr/5include/curses.h ; then
CPPFLAGS="$CPPFLAGS -I/usr/5include"
LDFLAGS="$LDFLAGS -L/usr/5lib"
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
])
dnl
dnl
dnl
AC_DEFUN(wi_DEFINE_UNAME, [
# Get first 127 chars of all uname information. Some folks have
# way too much stuff there, so grab only the first 127.
unam=`uname -a 2>/dev/null | cut -c1-127`
if test "$unam" != "" ; then
AC_DEFINE_UNQUOTED(UNAME, "$unam")
fi
])
dnl
dnl
dnl
AC_DEFUN(wi_READLINE_WITH_NCURSES, [
# Readline and Ncurses could both define "backspace".
# Warn about this if we have both things in our definitions list.
if test "$ac_cv_lib_readline" = yes && test "$ac_cv_lib_ncurses" = yes ; then
AC_MSG_CHECKING(if readline and ncurses will link together)
j="$LIBS"
LIBS="-lreadline -lncurses"
AC_TRY_LINK(,[
readline("prompt");
endwin();
],k=yes,k=no)
if test "$k" = no ; then
AC_MSG_RESULT(no)
# Remove '-lreadline' from LIBS.
LIBS=`echo $j | sed s/-lreadline//g`
ac_cv_lib_readline=no
AC_WARN([The versions of GNU readline and ncurses you have installed on this system
can't be used together, because they use the same symbol, backspace. If
possible, recompile one of the libraries with -Dbackspace=back_space, then
re-run configure.])
else
AC_MSG_RESULT(yes)
LIBS="$j"
fi
fi
])
dnl
dnl
dnl
dnl AC_EXT_DAYLIGHT
dnl Check for an external variable daylight. Stolen from w3c-libwww.
AC_DEFUN(AC_EXT_DAYLIGHT,
[ AC_MSG_CHECKING(int daylight variable)
AC_TRY_COMPILE([#include <time.h>], [return daylight;],
have_daylight=yes,
have_daylight=no)
AC_MSG_RESULT($have_daylight)
])dnl
dnl AC_EXT_TIMEZONE
dnl Check for an external variable timezone. Stolen from tcl-8.0.
AC_DEFUN(AC_EXT_TIMEZONE,
[
#
# Its important to include time.h in this check, as some systems (like convex)
# have timezone functions, etc.
#
have_timezone=no
AC_MSG_CHECKING([long timezone variable])
AC_TRY_COMPILE([#include <time.h>],
[extern long timezone;
timezone += 1;
exit (0);],
[have_timezone=yes
AC_MSG_RESULT(yes)],
AC_MSG_RESULT(no))
#
# On some systems (eg IRIX 6.2), timezone is a time_t and not a long.
#
if test "$have_timezone" = no; then
AC_MSG_CHECKING([time_t timezone variable])
AC_TRY_COMPILE([#include <time.h>],
[extern time_t timezone;
timezone += 1;
exit (0);],
[have_timezone=yes
AC_MSG_RESULT(yes)],
AC_MSG_RESULT(no))
fi
])dnl

259
configure.in Normal file
View File

@@ -0,0 +1,259 @@
dnl Process this file with aclocal ; automake -a ; autoconf to produce a
dnl working configure script.
dnl
dnl $Id$
AC_INIT(src/bucket/newbucket.cxx)
dnl Initialize the automake stuff
AM_INIT_AUTOMAKE(SimGear, 0.0.1)
dnl Checks for programs.
AC_PROG_MAKE_SET
AC_PROG_CC
AC_PROG_CXX
AC_PROG_RANLIB
AC_PROG_INSTALL
AC_PROG_LN_S
if echo $includedir | egrep "simgear$" > /dev/null; then
echo "includedir is" $includedir "libdir is" $libdir
else
includedir="${includedir}/simgear"
echo "includedir changed to" $includedir "libdir is" $libdir
fi
dnl Specify if we want logging (testing build) or not (release build)
# set logging default value
# with_logging=yes
AC_ARG_WITH(logging, [ --with-logging Include logging output (default)])
if test "x$with_logging" = "xno" ; then
AC_DEFINE(FG_NDEBUG)
fi
dnl specify if we are building with "checker"
AC_ARG_WITH(efence, [ --with-efence Specify if we are building with "electric-fence"])
if test "x$with_efence" = "xyes" ; then
echo "Building with efence"
LIBS= "$LIBS -lefence"
fi
dnl Check for MS Windows environment
AC_CHECK_HEADER(windows.h)
dnl extra library and include directories
EXTRA_DIRS="/usr/local /usr/local/plib /usr/X11R6"
if test -d /opt/X11R6 ; then
EXTRA_DIRS="$EXTRA_DIRS /opt/X11R6"
fi
if test "x$ac_cv_header_windows_h" = "xyes" ; then
EXTRA_DIRS="${EXTRA_DIRS} `pwd`/Win32"
# elif test `uname -s` = "SunOS" ; then
# EXTRA_DIRS="${EXTRA_DIRS} `pwd`/SunOS"
fi
wi_EXTRA_DIRS(no, ${EXTRA_DIRS})
dnl Using AM_CONDITIONAL is a step out of the protected little
dnl automake fold so it is potentially dangerous. But, we are
dnl beginning to run into cases where the standard checks are not
dnl enough. AM_CONDITIONALS are then referenced to conditionally
dnl build a Makefile.in from a Makefile.am which lets us define custom
dnl includes, compile alternative source files, etc.
dnl Enable serial support on Unix type systems
AM_CONDITIONAL(ENABLE_UNIX_SERIAL, true)
dnl Check for X11 (fancy)
AC_PATH_XTRA
dnl Checks for libraries.
null_LIBS="$LIBS"
AC_CHECK_LIB(m, cos)
base_LIBS="$LIBS"
AC_CHECK_LIB(socket, socket)
AC_CHECK_LIB(X11, XCreateWindow)
AC_CHECK_LIB(Xext, XShmCreateImage)
AC_CHECK_LIB(Xi, XGetExtensionVersion)
AC_CHECK_LIB(ICE, IceOpenConnection)
AC_CHECK_LIB(SM, SmcOpenConnection)
AC_CHECK_LIB(Xt, XtMalloc)
AC_CHECK_LIB(Xmu, XmuLookupStandardColormap)
dnl check for OpenGL related libraries
if test "x$ac_cv_header_windows_h" != "xyes" ; then
dnl Reasonable stuff for non-windoze variants ... :-)
AC_CHECK_LIB(GLcore, glNewList)
if test "x$ac_cv_lib_GLcore_glNewList" = "xno" ; then
dnl if no GLcore, check for GL
AC_CHECK_LIB(GL, glNewList)
if test "x$ac_cv_lib_GL_glNewList" = "xno" ; then
dnl if no GL, check for MesaGL
AC_CHECK_LIB(MesaGL, glNewList)
fi
else
dnl if GLcore found, then also check for GL
AC_CHECK_LIB(GL, glXCreateContext)
fi
dnl if using mesa, check for xmesa.h
if test "x$ac_cv_lib_MesaGL_glNewList" = "xyes" ; then
AC_CHECK_HEADER(GL/xmesa.h)
if test "x$ac_cv_header_GL_xmesa_h" = "xyes"; then
AC_DEFINE( XMESA )
AC_DEFINE( FX )
fi
fi
AC_CHECK_LIB(GLU, gluLookAt)
if test "x$ac_cv_lib_GLU_gluLookAt" = "xno" ; then
dnl if no GLU, check for MesaGLU
AC_CHECK_LIB(MesaGLU, gluLookAt)
fi
dnl check for glut
AC_CHECK_LIB(glut, glutGetModifiers)
dnl test for glutGameModeString, but avoid adding glut a second time into
dnl the list of libraries
save_LIBS="$LIBS"
AC_CHECK_LIB(glut, glutGameModeString)
LIBS="$save_LIBS"
else
dnl Win32 is a little wierd because it has to try to handle the various
dnl winbloze-isms. We'll just do this manually for now.
echo Win32 specific hacks...
AC_DEFINE(WIN32)
dnl force a failed check since we will be building under windoze
AM_CONDITIONAL(ENABLE_XMESA_FX, test "no" = "yes")
dnl just define these to true and hope for the best
ac_cv_lib_glut_glutGetModifiers="yes"
ac_cv_lib_glut_glutGameModeString="yes"
if test "x$with_sgi_opengl" = "xyes" ; then
echo "Building with glut.dll, glu.dll, and opengl.dll"
WIN32_GLUT=glut
WIN32_GLU=glu
WIN32_OPENGL=opengl
else
echo "Building with glut32.dll, glu32.dll, and opengl32.dll"
WIN32_GLUT=glut32
WIN32_GLU=glu32
WIN32_OPENGL=opengl32
fi
LIBS="$LIBS -l${WIN32_GLUT} -l${WIN32_GLU} -l${WIN32_OPENGL}"
LIBS="$LIBS -luser32 -lgdi32"
echo "Will link apps with $LIBS"
fi
if test "x$ac_cv_lib_glut_glutGetModifiers" = "xno"; then
echo
echo "Unable to find the necessary OpenGL or GLUT libraries."
echo "See config.log for automated test details and results ..."
exit 1
fi
if test "x$ac_cv_lib_glut_glutGameModeString" = "xno"; then
echo
echo "Your version of glut doesn't support game mode."
echo "You need to fetch and install the latest version of glut from:"
echo
echo " http://reality.sgi.com/opengl/glut3/glut3.html"
exit 1
fi
opengl_LIBS="$LIBS"
LIBS="$base_LIBS"
AC_SUBST(base_LIBS)
AC_SUBST(opengl_LIBS)
AM_CONDITIONAL(HAVE_XWINDOWS, test "x$ac_cv_lib_X11_XCreateWindow" = "xyes" )
dnl Check for "plib" without which we cannot go on
AC_CHECK_HEADER(plib/pu.h)
if test "x$ac_cv_header_plib_pu_h" != "xyes"; then
echo
echo "You *must* have the plib library installed on your system to build"
echo "the FGFS simulator!"
echo
echo "Please see README.plib for more details."
echo
echo "configure aborted."
exit
fi
dnl Check for system installed zlib
AC_CHECK_HEADER(zlib.h)
if test "x$ac_cv_header_zlib_h" != "xyes"; then
echo "no zlib found, building."
fi
AM_CONDITIONAL(HAVE_ZLIB, test "x$ac_cv_header_zlib_h" = "xyes" )
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS( \
fcntl.h getopt.h malloc.h memory.h stdlib.h sys/param.h sys/stat.h \
sys/time.h sys/timeb.h unistd.h windows.h winbase.h values.h )
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_SIZE_T
AC_HEADER_TIME
AC_STRUCT_TM
dnl Checks for library functions.
AC_TYPE_SIGNAL
AC_FUNC_VPRINTF
AC_CHECK_FUNCS( ftime gettimeofday timegm memcpy bcopy mktime strstr rand \
random setitimer getitimer signal GetLocalTime rint getrusage )
AM_CONFIG_HEADER(src/include/config.h)
AC_OUTPUT( \
VERSION \
Makefile \
src/Makefile \
src/include/Makefile \
src/bucket/Makefile \
src/debug/Makefile \
src/math/Makefile \
src/misc/Makefile \
src/screen/Makefile \
src/serial/Makefile \
src/xgl/Makefile \
src/zlib/Makefile \
)
AC_OUTPUT_COMMANDS([./mksymlinks.sh])
echo ""
echo "Configure Summary"
echo "================="
echo "Prefix: $prefix"
if test "x$with_logging" != "x"; then
echo "Debug messages: $with_logging"
else
echo "Debug messages: yes"
fi
if test "x$with_efence" != "x"; then
echo "Electric fence: $with_efence"
else
echo "Electric fence: no"
fi

39
mksymlinks.sh Executable file
View File

@@ -0,0 +1,39 @@
#! /bin/sh
echo ""
echo "running $0 to rebuild simgear include links"
# toast the old directory
rm -rf src/simgear
mkdir src/simgear
mkdir src/simgear/bucket
mkdir src/simgear/debug
mkdir src/simgear/math
mkdir src/simgear/misc
mkdir src/simgear/screen
mkdir src/simgear/serial
mkdir src/simgear/xgl
mkdir src/simgear/zlib
# build new links
ln -s ../include/compiler.h src/simgear/compiler.h
ln -s ../include/constants.h src/simgear/constants.h
ln -s ../include/fg_traits.hxx src/simgear/fg_traits.hxx
ln -s ../include/fg_zlib.h src/simgear/fg_zlib.h
ln -s ../../bucket/newbucket.hxx src/simgear/bucket/newbucket.hxx
ln -s ../../debug/debug_types.h src/simgear/debug/debug_types.h
ln -s ../../debug/logstream.hxx src/simgear/debug/logstream.hxx
ln -s ../../math/fg_memory.h src/simgear/math/fg_memory.h
ln -s ../../math/fg_types.hxx src/simgear/math/fg_types.hxx
ln -s ../../math/mat3.h src/simgear/math/mat3.h
ln -s ../../math/point3d.hxx src/simgear/math/point3d.hxx
ln -s ../../math/polar3d.hxx src/simgear/math/polar3d.hxx
ln -s ../../misc/fgpath.hxx src/simgear/misc/fgpath.hxx
ln -s ../../misc/fgstream.hxx src/simgear/misc/fgstream.hxx
ln -s ../../misc/zfstream.hxx src/simgear/misc/zfstream.hxx
ln -s ../../xgl/xgl.h src/simgear/xgl/xgl.h

27
simgear/Makefile.am Normal file
View File

@@ -0,0 +1,27 @@
if ENABLE_UNIX_SERIAL
SERIAL_DIRS = serial
else
SERIAL_DIRS =
endif
if HAVE_ZLIB
ZLIB_DIRS =
else
ZLIB_DIRS = zlib
endif
METAR_DIRS =
# METAR_DIRS = metar
SUBDIRS = \
include \
bucket \
debug \
math \
$(METAR_DIRS) \
misc \
screen \
$(SERIAL_DIRS) \
xgl \
$(ZLIB_DIRS)

View File

@@ -0,0 +1,17 @@
includedir = @includedir@/bucket
lib_LIBRARIES = libsgbucket.a
include_HEADERS = newbucket.hxx
libsgbucket_a_SOURCES = newbucket.cxx
# noinst_PROGRAMS = testbucket
# testbucket_SOURCES = testbucket.cxx
# testbucket_LDADD = \
# $(top_builddir)/bucket/libsgbucket.a \
# $(top_builddir)/misc/libsgmisc.a
INCLUDES += -I$(top_builddir)/src

View File

@@ -0,0 +1,155 @@
/**************************************************************************
* newbucket.hxx -- new bucket routines for better world modeling
*
* Written by Curtis L. Olson, started February 1999.
*
* Copyright (C) 1999 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$
**************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <math.h>
#include <simgear/misc/fgpath.hxx>
#include "newbucket.hxx"
// Build the path name for this bucket
string FGBucket::gen_base_path() const {
// long int index;
int top_lon, top_lat, main_lon, main_lat;
char hem, pole;
char raw_path[256];
top_lon = lon / 10;
main_lon = lon;
if ( (lon < 0) && (top_lon * 10 != lon) ) {
top_lon -= 1;
}
top_lon *= 10;
if ( top_lon >= 0 ) {
hem = 'e';
} else {
hem = 'w';
top_lon *= -1;
}
if ( main_lon < 0 ) {
main_lon *= -1;
}
top_lat = lat / 10;
main_lat = lat;
if ( (lat < 0) && (top_lat * 10 != lat) ) {
top_lat -= 1;
}
top_lat *= 10;
if ( top_lat >= 0 ) {
pole = 'n';
} else {
pole = 's';
top_lat *= -1;
}
if ( main_lat < 0 ) {
main_lat *= -1;
}
sprintf(raw_path, "%c%03d%c%02d/%c%03d%c%02d",
hem, top_lon, pole, top_lat,
hem, main_lon, pole, main_lat);
FGPath path( raw_path );
return path.str();
}
// 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;
// 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 );
// walk dx units in the lon direction
double tmp = dlon + dx * span;
while ( tmp < -180.0 ) {
tmp += 360.0;
}
while ( tmp >= 180.0 ) {
tmp -= 360.0;
}
result.set_bucket( tmp, clat );
return result;
}
// calculate the offset between two buckets
void fgBucketDiff( const FGBucket& b1, const FGBucket& b2, int *dx, int *dy ) {
// Latitude difference
double c1_lat = b1.get_center_lat();
double c2_lat = b2.get_center_lat();
double diff_lat = c2_lat - c1_lat;
#ifdef HAVE_RINT
*dy = (int)rint( diff_lat / FG_BUCKET_SPAN );
#else
if ( diff_lat > 0 ) {
*dy = (int)( diff_lat / FG_BUCKET_SPAN + 0.5 );
} else {
*dy = (int)( diff_lat / FG_BUCKET_SPAN - 0.5 );
}
#endif
// longitude difference
double c1_lon = b1.get_center_lon();
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);
} else {
span = bucket_span(c2_lat);
}
#ifdef HAVE_RINT
*dx = (int)rint( diff_lon / span );
#else
if ( diff_lon > 0 ) {
*dx = (int)( diff_lon / span + 0.5 );
} else {
*dx = (int)( diff_lon / span - 0.5 );
}
#endif
}

View File

@@ -0,0 +1,351 @@
/**************************************************************************
* newbucket.hxx -- new bucket routines for better world modeling
*
* Written by Curtis L. Olson, started February 1999.
*
* Copyright (C) 1999 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 _NEWBUCKET_HXX
#define _NEWBUCKET_HXX
#include <simgear/compiler.h>
#include <simgear/constants.h>
#ifdef FG_HAVE_STD_INCLUDES
# include <cmath>
# include <cstdio> // sprintf()
# include <iostream>
#else
# include <math.h>
# include <stdio.h> // sprintf()
# include <iostream.h>
#endif
// 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
#ifdef __MWERKS__
# include <math.h> // needed fabs()
#endif
#include STL_STRING
FG_USING_STD(string);
#if ! defined( FG_HAVE_NATIVE_SGI_COMPILERS )
FG_USING_STD(ostream);
#endif
#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
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 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& );
};
// return the horizontal tile span factor based on latitude
inline double bucket_span( double l ) {
if ( l >= 89.0 ) {
return 360.0;
} else if ( l >= 88.0 ) {
return 8.0;
} else if ( l >= 86.0 ) {
return 4.0;
} else if ( l >= 83.0 ) {
return 2.0;
} else if ( l >= 76.0 ) {
return 1.0;
} else if ( l >= 62.0 ) {
return 0.5;
} else if ( l >= 22.0 ) {
return 0.25;
} else if ( l >= -22.0 ) {
return 0.125;
} else if ( l >= -62.0 ) {
return 0.25;
} else if ( l >= -76.0 ) {
return 0.5;
} else if ( l >= -83.0 ) {
return 1.0;
} else if ( l >= -86.0 ) {
return 2.0;
} else if ( l >= -88.0 ) {
return 4.0;
} else if ( l >= -89.0 ) {
return 8.0;
} else {
return 360.0;
}
}
// 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;
// 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);
}
// default constructor
inline FGBucket::FGBucket() {}
// 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 ) {
lon = -1000;
}
}
// 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;
}
}
// 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 );
// calculate the offset between two buckets
void fgBucketDiff( const FGBucket& b1, const FGBucket& b2, int *dx, int *dy );
/*
// Given a lat/lon, fill in the local tile index array
void fgBucketGenIdxArray(fgBUCKET *p1, fgBUCKET *tiles, int width, int height);
*/
inline ostream&
operator<< ( ostream& out, const FGBucket& b )
{
return out << b.lon << ":" << b.x << ", " << b.lat << ":" << b.y;
}
inline bool
operator== ( const FGBucket& b1, const FGBucket& b2 )
{
return ( b1.lon == b2.lon &&
b1.lat == b2.lat &&
b1.x == b2.x &&
b1.y == b2.y );
}
#endif // _NEWBUCKET_HXX

11
simgear/debug/Makefile.am Normal file
View File

@@ -0,0 +1,11 @@
includedir = @includedir@/debug
EXTRA_DIST = logtest.cxx
lib_LIBRARIES = libsgdebug.a
include_HEADERS = debug_types.h logstream.hxx
libsgdebug_a_SOURCES = logstream.cxx
INCLUDES += -I$(top_builddir)/src

View File

@@ -0,0 +1,38 @@
// NB: To add a dbg_class, add it here, and add it to the structure in
// fg_debug.c
typedef enum {
FG_NONE = 0x00000000,
FG_TERRAIN = 0x00000001,
FG_ASTRO = 0x00000002,
FG_FLIGHT = 0x00000004,
FG_INPUT = 0x00000008,
FG_GL = 0x00000010,
FG_VIEW = 0x00000020,
FG_COCKPIT = 0x00000040,
FG_GENERAL = 0x00000080,
FG_MATH = 0x00000100,
FG_EVENT = 0x00000200,
FG_AIRCRAFT = 0x00000400,
FG_AUTOPILOT = 0x00000800,
FG_IO = 0x00001000,
FG_CLIPPER = 0x00002000,
FG_NETWORK = 0x00004000,
FG_UNDEFD = 0x00008000, // For range checking
FG_ALL = 0xFFFFFFFF
} fgDebugClass;
// NB: To add a priority, add it here.
typedef enum {
FG_BULK, // For frequent messages
FG_DEBUG, // Less frequent debug type messages
FG_INFO, // Informatory messages
FG_WARN, // Possible impending problem
FG_ALERT // Very possible impending problem
// FG_EXIT, // Problem (no core)
// FG_ABORT // Abandon ship (core)
} fgDebugPriority;

View File

@@ -0,0 +1,63 @@
// Stream based logging mechanism.
//
// Written by Bernie Bright, 1998
//
// Copyright (C) 1998 Bernie Bright - bbright@c031.aone.net.au
//
// 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 "logstream.hxx"
bool logbuf::logging_enabled = true;
fgDebugClass logbuf::logClass = FG_NONE;
fgDebugPriority logbuf::logPriority = FG_INFO;
streambuf* logbuf::sbuf = NULL;
logbuf::logbuf()
{
// if ( sbuf == NULL )
// sbuf = cerr.rdbuf();
}
logbuf::~logbuf()
{
if ( sbuf )
sync();
}
void
logbuf::set_sb( streambuf* sb )
{
if ( sbuf )
sync();
sbuf = sb;
}
void
logbuf::set_log_level( fgDebugClass c, fgDebugPriority p )
{
logClass = c;
logPriority = p;
}
void
logstream::setLogLevels( fgDebugClass c, fgDebugPriority p )
{
logbuf::set_log_level( c, p );
}

220
simgear/debug/logstream.hxx Normal file
View File

@@ -0,0 +1,220 @@
// Stream based logging mechanism.
//
// Written by Bernie Bright, 1998
//
// Copyright (C) 1998 Bernie Bright - bbright@c031.aone.net.au
//
// 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 _LOGSTREAM_H
#define _LOGSTREAM_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <simgear/compiler.h>
#ifdef FG_HAVE_STD_INCLUDES
# include <streambuf>
# include <iostream>
#else
# include <iostream.h>
# include <simgear/fg_traits.hxx>
#endif
#include <simgear/debug/debug_types.h>
#ifndef FG_HAVE_NATIVE_SGI_COMPILERS
FG_USING_STD(streambuf);
FG_USING_STD(ostream);
FG_USING_STD(cerr);
FG_USING_STD(endl);
#endif
#ifdef __MWERKS__
# define cerr std::cerr
# define endl std::endl
FG_USING_STD(iostream);
#endif
//
// TODO:
//
// 1. Change output destination. Done.
// 2. Make logbuf thread safe.
// 3. Read environment for default debugClass and debugPriority.
//
//-----------------------------------------------------------------------------
//
// logbuf is an output-only streambuf with the ability to disable sets of
// messages at runtime. Only messages with priority >= logbuf::logPriority
// and debugClass == logbuf::logClass are output.
//
class logbuf : public streambuf
{
public:
#ifndef FG_HAVE_STD_INCLUDES
typedef char_traits<char> traits_type;
typedef char_traits<char>::int_type int_type;
typedef char_traits<char>::pos_type pos_type;
typedef char_traits<char>::off_type off_type;
#endif
// logbuf( streambuf* sb ) : sbuf(sb) {}
logbuf();
~logbuf();
// Is logging enabled?
bool enabled() { return logging_enabled; }
// Set the logging level of subsequent messages.
void set_log_state( fgDebugClass c, fgDebugPriority p );
// Set the global logging level.
static void set_log_level( fgDebugClass c, fgDebugPriority p );
//
void set_sb( streambuf* sb );
protected:
inline virtual int sync();
int_type overflow( int ch );
// int xsputn( const char* s, istreamsize n );
private:
// The streambuf used for actual output. Defaults to cerr.rdbuf().
static streambuf* sbuf;
static bool logging_enabled;
static fgDebugClass logClass;
static fgDebugPriority logPriority;
private:
// Not defined.
logbuf( const logbuf& );
void operator= ( const logbuf& );
};
inline int
logbuf::sync()
{
#ifdef FG_HAVE_STD_INCLUDES
return sbuf->pubsync();
#else
return sbuf->sync();
#endif
}
inline void
logbuf::set_log_state( fgDebugClass c, fgDebugPriority p )
{
logging_enabled = ((c & logClass) != 0 && p >= logPriority);
}
inline logbuf::int_type
logbuf::overflow( int c )
{
return logging_enabled ? sbuf->sputc(c) : (EOF == 0 ? 1: 0);
}
//-----------------------------------------------------------------------------
//
// logstream manipulator for setting the log level of a message.
//
struct loglevel
{
loglevel( fgDebugClass c, fgDebugPriority p )
: logClass(c), logPriority(p) {}
fgDebugClass logClass;
fgDebugPriority logPriority;
};
//-----------------------------------------------------------------------------
//
// A helper class that ensures a streambuf and ostream are constructed and
// destroyed in the correct order. The streambuf must be created before the
// ostream but bases are constructed before members. Thus, making this class
// a private base of logstream, declared to the left of ostream, we ensure the
// correct order of construction and destruction.
//
struct logstream_base
{
// logstream_base( streambuf* sb ) : lbuf(sb) {}
logstream_base() {}
logbuf lbuf;
};
//-----------------------------------------------------------------------------
//
//
//
class logstream : private logstream_base, public ostream
{
public:
// The default is to send messages to cerr.
logstream( ostream& out )
// : logstream_base(out.rdbuf()),
: logstream_base(),
ostream(&lbuf) { lbuf.set_sb(out.rdbuf());}
void set_output( ostream& out ) { lbuf.set_sb( out.rdbuf() ); }
// Set the global log class and priority level.
void setLogLevels( fgDebugClass c, fgDebugPriority p );
// Output operator to capture the debug level and priority of a message.
inline ostream& operator<< ( const loglevel& l );
};
inline ostream&
logstream::operator<< ( const loglevel& l )
{
lbuf.set_log_state( l.logClass, l.logPriority );
return *this;
}
//-----------------------------------------------------------------------------
//
// Return the one and only logstream instance.
// We use a function instead of a global object so we are assured that cerr
// has been initialised.
//
inline logstream&
fglog()
{
static logstream logstrm( cerr );
return logstrm;
}
#ifdef FG_NDEBUG
# define FG_LOG(C,P,M)
#elif defined( __MWERKS__ )
# define FG_LOG(C,P,M) ::fglog() << ::loglevel(C,P) << M << std::endl
#else
# define FG_LOG(C,P,M) fglog() << loglevel(C,P) << M << endl
#endif
#endif // _LOGSTREAM_H

34
simgear/debug/logtest.cxx Normal file
View File

@@ -0,0 +1,34 @@
#include <string>
#include "Debug/logstream.hxx"
int
main( int argc, char* argv[] )
{
fglog().setLogLevels( FG_ALL, FG_INFO );
FG_LOG( FG_TERRAIN, FG_BULK, "terrain::bulk" ); // shouldnt appear
FG_LOG( FG_TERRAIN, FG_DEBUG, "terrain::debug" ); // shouldnt appear
FG_LOG( FG_TERRAIN, FG_INFO, "terrain::info" );
FG_LOG( FG_TERRAIN, FG_WARN, "terrain::warn" );
FG_LOG( FG_TERRAIN, FG_ALERT, "terrain::alert" );
int i = 12345;
long l = 54321L;
double d = 3.14159;
string s = "Hello world!";
FG_LOG( FG_EVENT, FG_INFO, "event::info "
<< "i=" << i
<< ", l=" << l
<< ", d=" << d
<< ", d*l=" << d*l
<< ", s=\"" << s << "\"" );
// This shouldn't appear in log output:
FG_LOG( FG_EVENT, FG_DEBUG, "event::debug "
<< "- this should be seen - "
<< "d=" << d
<< ", s=\"" << s << "\"" );
return 0;
}

View File

@@ -16,4 +16,4 @@ libAstro_a_SOURCES = \
uranus.cxx uranus.hxx \
venus.cxx venus.hxx
INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Simulator
INCLUDES += -I$(top_builddir) -I$(top_builddir)/src

View File

@@ -22,15 +22,17 @@
* $Id$
**************************************************************************/
#include "celestialBody.hxx"
#include "star.hxx"
#include <Debug/logstream.hxx>
#include <simgear/debug/logstream.hxx>
#ifdef FG_MATH_EXCEPTION_CLASH
# define exception c_exception
#endif
#include <math.h>
#include "celestialBody.hxx"
#include "star.hxx"
/**************************************************************************
* void CelestialBody::updatePosition(fgTIME *t, Star *ourSun)
*

View File

@@ -31,8 +31,9 @@
#endif
#include <simgear/constants.h>
#include <Time/fg_time.hxx>
#include <Include/fg_constants.h>
class Star;

View File

@@ -22,14 +22,13 @@
* $Id$
**************************************************************************/
#include <FDM/flight.hxx>
#include <string.h>
#include "moon.hxx"
#include <Debug/logstream.hxx>
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/fgpath.hxx>
#include <Main/options.hxx>
#include <Misc/fgpath.hxx>
#include <Objects/texload.h>
#ifdef __BORLANDC__
@@ -37,6 +36,9 @@
#endif
#include <math.h>
#include <FDM/flight.hxx>
#include "moon.hxx"
/*************************************************************************
* Moon::Moon(FGTime *t)
@@ -156,27 +158,22 @@ void Moon::setHalo()
for (i=0; i < texWidth; i++) {
for (j=0; j < texWidth; j++) {
double x, y, d;
*p = 0xff;
*(p+1) = 0xff;
*(p+2) = 0xff;
x = fabs((double)(i - (texWidth / 2)));
y = fabs((double)(j - (texWidth / 2)));
d = sqrt((x * x) + (y * y));
if (d < radius)
{
if (d < radius) {
double t = 1.0 - (d / radius); // t is 1.0 at center, 0.0 at edge */
// inverse square looks nice
*p = (int)((double)0xff * (t * t));
*(p+1) = (int)((double) 0xff * (t*t));
*(p+2) = (int)((double) 0xff * (t*t));
*(p+3) = 0x11;
}
else
{
*p = 0x00;
*(p+1) = 0x00;
*(p+2) = 0x00;
*(p+3) = 0x11;
}
*(p+3) = (int)((double) 0x20 * (t*t));
} else {
*(p+3) = 0x00;
}
p += 4;
}
}
@@ -353,7 +350,8 @@ void Moon::newImage()
// Draw the halo...
if (current_options.get_textures())
{
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
// glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
glEnable(GL_TEXTURE_2D); // TEXTURE ENABLED
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBindTexture(GL_TEXTURE_2D, moon_halotexid);

View File

@@ -24,8 +24,9 @@
#ifndef _MOON_HXX_
#define _MOON_HXX_
#include <simgear/constants.h>
#include <Aircraft/aircraft.hxx>
#include <Include/fg_constants.h>
#include <Main/views.hxx>
#include <Time/fg_time.hxx>

View File

@@ -32,14 +32,15 @@
#include <math.h>
#include <GL/glut.h>
#include <XGL/xgl.h>
#include <simgear/xgl/xgl.h>
#include <simgear/constants.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/math/fg_random.h>
#include <Aircraft/aircraft.hxx>
#include <Debug/logstream.hxx>
#include <FDM/flight.hxx>
#include <Include/fg_constants.h>
#include <Main/views.hxx>
#include <Math/fg_random.h>
#include <Time/event.hxx>
#include <Time/fg_time.hxx>
@@ -72,9 +73,9 @@ static float middle_vertex[12][3];
static float outer_vertex[12][3];
static float bottom_vertex[12][3];
static float inner_color[12][4];
static float middle_color[12][4];
static float outer_color[12][4];
static GLubyte inner_color[12][4];
static GLubyte middle_color[12][4];
static GLubyte outer_color[12][4];
// Calculate the sky structure vertices
@@ -168,19 +169,21 @@ void fgSkyColorsInit( void ) {
// printf("sky = %.2f fog = %.2f diff = %.2f\n",
// l->sky_color[j], l->fog_color[j], diff);
inner_color[i][j] = l->sky_color[j] - diff * 0.3;
middle_color[i][j] = l->sky_color[j] - diff * 0.9 + middle_amt[j];
outer_color[i][j] = l->fog_color[j] + outer_amt[j];
inner_color[i][j] = (GLubyte)((l->sky_color[j] - diff * 0.3) * 255);
middle_color[i][j] = (GLubyte)((l->sky_color[j] - diff * 0.9
+ middle_amt[j]) * 255);
outer_color[i][j] = (GLubyte)((l->fog_color[j] + outer_amt[j])
* 255);
if ( inner_color[i][j] > 1.00 ) { inner_color[i][j] = 1.00; }
if ( inner_color[i][j] < 0.10 ) { inner_color[i][j] = 0.10; }
if ( middle_color[i][j] > 1.00 ) { middle_color[i][j] = 1.00; }
if ( middle_color[i][j] < 0.10 ) { middle_color[i][j] = 0.10; }
if ( outer_color[i][j] > 1.00 ) { outer_color[i][j] = 1.00; }
if ( outer_color[i][j] < 0.10 ) { outer_color[i][j] = 0.10; }
if ( inner_color[i][j] > 255 ) { inner_color[i][j] = 255; }
if ( inner_color[i][j] < 25 ) { inner_color[i][j] = 25; }
if ( middle_color[i][j] > 255 ) { middle_color[i][j] = 255; }
if ( middle_color[i][j] < 25 ) { middle_color[i][j] = 25; }
if ( outer_color[i][j] > 255 ) { outer_color[i][j] = 255; }
if ( outer_color[i][j] < 25 ) { outer_color[i][j] = 25; }
}
inner_color[i][3] = middle_color[i][3] = outer_color[i][3] =
l->sky_color[3];
(GLubyte)(l->sky_color[3] * 255);
for ( j = 0; j < 3; j++ ) {
outer_amt[j] -= outer_diff[j];
@@ -212,19 +215,21 @@ void fgSkyColorsInit( void ) {
// printf("sky = %.2f fog = %.2f diff = %.2f\n",
// l->sky_color[j], l->fog_color[j], diff);
inner_color[i][j] = l->sky_color[j] - diff * 0.3;
middle_color[i][j] = l->sky_color[j] - diff * 0.9 + middle_amt[j];
outer_color[i][j] = l->fog_color[j] + outer_amt[j];
inner_color[i][j] = (GLubyte)((l->sky_color[j] - diff * 0.3) * 255);
middle_color[i][j] = (GLubyte)((l->sky_color[j] - diff * 0.9
+ middle_amt[j]) * 255);
outer_color[i][j] = (GLubyte)((l->fog_color[j] + outer_amt[j])
* 255);
if ( inner_color[i][j] > 1.00 ) { inner_color[i][j] = 1.00; }
if ( inner_color[i][j] < 0.10 ) { inner_color[i][j] = 0.10; }
if ( middle_color[i][j] > 1.00 ) { middle_color[i][j] = 1.00; }
if ( middle_color[i][j] < 0.10 ) { middle_color[i][j] = 0.10; }
if ( outer_color[i][j] > 1.00 ) { outer_color[i][j] = 1.00; }
if ( outer_color[i][j] < 0.15 ) { outer_color[i][j] = 0.15; }
if ( inner_color[i][j] > 255 ) { inner_color[i][j] = 255; }
if ( inner_color[i][j] < 25 ) { inner_color[i][j] = 25; }
if ( middle_color[i][j] > 255 ) { middle_color[i][j] = 255; }
if ( middle_color[i][j] < 25 ) { middle_color[i][j] = 25; }
if ( outer_color[i][j] > 255 ) { outer_color[i][j] = 255; }
if ( outer_color[i][j] < 35 ) { outer_color[i][j] = 35; }
}
inner_color[i][3] = middle_color[i][3] = outer_color[i][3] =
l->sky_color[3];
(GLubyte)(l->sky_color[3] * 255);
for ( j = 0; j < 3; j++ ) {
outer_amt[j] += outer_diff[j];
@@ -261,9 +266,10 @@ void fgSkyInit( void ) {
void fgSkyRender( void ) {
FGInterface *f;
fgLIGHT *l;
float inner_color[4];
float middle_color[4];
float outer_color[4];
GLubyte sky_color[4];
GLubyte inner_color[4];
GLubyte middle_color[4];
GLubyte outer_color[4];
double diff;
int i;
@@ -279,11 +285,12 @@ void fgSkyRender( void ) {
// printf("sky = %.2f fog = %.2f diff = %.2f\n",
// l->sky_color[j], l->adj_fog_color[j], diff);
inner_color[i] = l->sky_color[i] - diff * 0.3;
middle_color[i] = l->sky_color[i] - diff * 0.9;
outer_color[i] = l->adj_fog_color[i];
inner_color[i] = (GLubyte)((l->sky_color[i] - diff * 0.3) * 255);
middle_color[i] = (GLubyte)((l->sky_color[i] - diff * 0.9) * 255);
outer_color[i] = (GLubyte)(l->adj_fog_color[i] * 255);
}
inner_color[3] = middle_color[3] = outer_color[3] = l->adj_fog_color[3];
inner_color[3] = middle_color[3] = outer_color[3] =
(GLubyte)(l->adj_fog_color[3] * 255);
xglPushMatrix();
@@ -302,36 +309,39 @@ void fgSkyRender( void ) {
// Draw inner/center section of sky*/
xglBegin( GL_TRIANGLE_FAN );
for ( i = 0; i < 4; i++ ) {
sky_color[i] = (GLubyte)(l->sky_color[i] * 255);
}
xglColor4fv(l->sky_color);
xglVertex3f(0.0, 0.0, CENTER_ELEV);
for ( i = 11; i >= 0; i-- ) {
xglColor4fv( inner_color );
xglColor4ubv( inner_color );
xglVertex3fv( inner_vertex[i] );
}
xglColor4fv( inner_color );
xglColor4ubv( inner_color );
xglVertex3fv( inner_vertex[11] );
xglEnd();
// Draw the middle ring
xglBegin( GL_TRIANGLE_STRIP );
for ( i = 0; i < 12; i++ ) {
xglColor4fv( middle_color );
xglColor4ubv( middle_color );
// printf("middle_color[%d] = %.2f %.2f %.2f %.2f\n", i,
// middle_color[i][0], middle_color[i][1], middle_color[i][2],
// middle_color[i][3]);
// xglColor4f(1.0, 0.0, 0.0, 1.0);
xglVertex3fv( middle_vertex[i] );
xglColor4fv( inner_color );
xglColor4ubv( inner_color );
// printf("inner_color[%d] = %.2f %.2f %.2f %.2f\n", i,
// inner_color[i][0], inner_color[i][1], inner_color[i][2],
// inner_color[i][3]);
// xglColor4f(0.0, 0.0, 1.0, 1.0);
xglVertex3fv( inner_vertex[i] );
}
xglColor4fv( middle_color );
xglColor4ubv( middle_color );
// xglColor4f(1.0, 0.0, 0.0, 1.0);
xglVertex3fv( middle_vertex[0] );
xglColor4fv( inner_color );
xglColor4ubv( inner_color );
// xglColor4f(0.0, 0.0, 1.0, 1.0);
xglVertex3fv( inner_vertex[0] );
xglEnd();
@@ -339,20 +349,20 @@ void fgSkyRender( void ) {
// Draw the outer ring
xglBegin( GL_TRIANGLE_STRIP );
for ( i = 0; i < 12; i++ ) {
xglColor4fv( outer_color );
xglColor4ubv( outer_color );
xglVertex3fv( outer_vertex[i] );
xglColor4fv( middle_color );
xglColor4ubv( middle_color );
xglVertex3fv( middle_vertex[i] );
}
xglColor4fv( outer_color );
xglColor4ubv( outer_color );
xglVertex3fv( outer_vertex[0] );
xglColor4fv( middle_color );
xglColor4ubv( middle_color );
xglVertex3fv( middle_vertex[0] );
xglEnd();
// Draw the bottom skirt
xglBegin( GL_TRIANGLE_STRIP );
xglColor4fv( outer_color );
xglColor4ubv( outer_color );
for ( i = 0; i < 12; i++ ) {
xglVertex3fv( bottom_vertex[i] );
xglVertex3fv( outer_vertex[i] );

View File

@@ -30,7 +30,7 @@
#endif
#include <ssg.h> // plib include
#include <plib/ssg.h> // plib include
class fgSky : ssgLeaf

View File

@@ -36,8 +36,10 @@
#include <math.h>
#include <GL/glut.h>
#include <XGL/xgl.h>
#include <Debug/logstream.hxx>
#include <simgear/xgl/xgl.h>
#include <simgear/debug/logstream.hxx>
#include <Time/sunpos.hxx>
#include <Time/moonpos.hxx>
#include "solarsystem.hxx"

View File

@@ -26,10 +26,13 @@
# define exception c_exception
#endif
#include <math.h>
#include <simgear/debug/logstream.hxx>
#include <Time/sunpos.hxx>
#include <Debug/logstream.hxx>
#include <Time/light.hxx>
#include <Main/options.hxx>
#include "star.hxx"
/*************************************************************************
@@ -116,26 +119,21 @@ void Star::setTexture()
for (j=0; j < texWidth; j++) {
double x, y, d;
*p = 0xff;
*(p+1) = 0xff;
*(p+2) = 0xff;
x = fabs((double)(i - (texWidth / 2)));
y = fabs((double)(j - (texWidth / 2)));
d = sqrt((x * x) + (y * y));
if (d < radius)
{
if (d < radius) {
double t = 1.0 - (d / radius); // t is 1.0 at center, 0.0 at edge */
// inverse square looks nice
*p = (int)((double)0xff * (t * t));
*(p+1) = (int)((double) 0xff * (t*t));
*(p+2) = (int)((double) 0xff * (t*t));
*(p+3) = (int)((double) 0xff * (t*t));
}
else
{
*p = 0x00;
*(p+1) = 0x00;
*(p+2) = 0x00;
} else {
*(p+3) = 0x00;
}
}
p += 4;
}
}
@@ -235,10 +233,11 @@ void Star::newImage(void)
xglTranslatef(0,60000,0);
if (current_options.get_textures())
{
glEnable(GL_TEXTURE_2D); // TEXTURE ENABLED
glEnable(GL_BLEND); // BLEND ENABLED
glEnable(GL_TEXTURE_2D); // TEXTURE ENABLED
glEnable(GL_BLEND); // BLEND ENABLED
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
// glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBindTexture(GL_TEXTURE_2D, sun_texid);
@@ -254,8 +253,8 @@ void Star::newImage(void)
}
glPopMatrix();
glDisable(GL_LIGHTING); //LIGHTING DISABLED
glDisable(GL_BLEND); //BLEND DISABLED
glDisable(GL_LIGHTING); // LIGHTING DISABLED
glDisable(GL_BLEND); // BLEND DISABLED
glPushMatrix();
{
xglRotatef(((RAD_TO_DEG * rightAscension)- 90.0), 0.0, 0.0, 1.0);
@@ -265,7 +264,7 @@ void Star::newImage(void)
gluSphere( SunObject, sun_size, 10, 10 );
}
glPopMatrix();
glDisable(GL_TEXTURE_2D); // TEXTURE DISABLED
glDisable(GL_BLEND); // BLEND DISABLED
glDisable(GL_TEXTURE_2D); // TEXTURE DISABLED
glDisable(GL_BLEND); // BLEND DISABLED
}
}

View File

@@ -30,7 +30,8 @@
# include <windows.h>
#endif
#include "Include/compiler.h"
#include <simgear/compiler.h>
#ifdef FG_HAVE_STD_INCLUDES
# include <cmath>
# include <cstdio>
@@ -46,22 +47,22 @@
#include <string>
#include <GL/glut.h>
#include <XGL/xgl.h>
#include <simgear/xgl/xgl.h>
#include <simgear/constants.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/fgpath.hxx>
#include <simgear/misc/fgstream.hxx>
#include <simgear/misc/stopwatch.hxx>
#include <Aircraft/aircraft.hxx>
#include <Debug/logstream.hxx>
#include <Include/fg_constants.h>
#include <Misc/fgpath.hxx>
#include <Misc/fgstream.hxx>
#include <Misc/stopwatch.hxx>
#include <Main/options.hxx>
#include <Main/views.hxx>
#include <Time/fg_time.hxx>
#include "Misc/stopwatch.hxx"
#include "stars.hxx"
FG_USING_STD(getline);
// FG_USING_STD(getline);
#define EpochStart (631065600)
#define DaysSinceEpoch(secs) (((secs)-EpochStart)*(1.0/(24*3600)))

168
simgear/math/MAT3geom.c Normal file
View File

@@ -0,0 +1,168 @@
/* #include "HEADERS.h" */
/* Copyright 1988, Brown Computer Graphics Group. All Rights Reserved. */
/* --------------------------------------------------------------------------
* This file contains routines that perform geometry-related operations
* on matrices.
* -------------------------------------------------------------------------*/
#include "mat3defs.h"
/* -------------------------- Static Routines ---------------------------- */
/* ------------------------- Internal Routines --------------------------- */
/* -------------------------- Public Routines ---------------------------- */
/*
* This takes a matrix used to transform points, and returns a corresponding
* matrix that can be used to transform direction vectors (between points).
*/
void
MAT3direction_matrix(register double (*result_mat)[4], register double (*mat)[4])
{
register int i;
MAT3copy(result_mat, mat);
for (i = 0; i < 4; i++) result_mat[i][3] = result_mat[3][i] = 0.0;
result_mat[3][3] = 1.0;
}
/*
* This takes a matrix used to transform points, and returns a corresponding
* matrix that can be used to transform vectors that must remain perpendicular
* to planes defined by the points. It is useful when you are transforming
* some object that has both points and normals in its definition, and you
* only have the transformation matrix for the points. This routine returns
* FALSE if the normal matrix is uncomputable. Otherwise, it returns TRUE.
*
* Spike sez: "This is the adjoint for the non-homogeneous part of the
* transformation."
*/
int
MAT3normal_matrix(register double (*result_mat)[4], register double (*mat)[4])
{
register int ret;
MAT3mat tmp_mat;
MAT3direction_matrix(result_mat, mat);
if ( (ret = MAT3invert(tmp_mat, tmp_mat)) ) {
MAT3transpose(result_mat, tmp_mat);
}
return(ret);
}
/*
* Sets the given matrix to be a scale matrix for the given vector of
* scale values.
*/
void
MAT3scale(double (*result_mat)[4], double *scale)
{
MAT3identity(result_mat);
result_mat[0][0] = scale[0];
result_mat[1][1] = scale[1];
result_mat[2][2] = scale[2];
}
/*
* Sets up a matrix for a rotation about an axis given by the line from
* (0,0,0) to axis, through an angle (in radians).
* Looking along the axis toward the origin, the rotation is counter-clockwise.
*/
#define SELECT .7071 /* selection constant (roughly .5*sqrt(2) */
void
MAT3rotate(double (*result_mat)[4], double *axis, double angle_in_radians)
{
MAT3vec naxis, /* Axis of rotation, normalized */
base2, /* 2nd unit basis vec, perp to axis */
base3; /* 3rd unit basis vec, perp to axis & base2 */
double dot;
MAT3mat base_mat, /* Change-of-basis matrix */
base_mat_trans; /* Inverse of c-o-b matrix */
register int i;
/* Step 1: extend { axis } to a basis for 3-space: { axis, base2, base3 }
* which is orthonormal (all three have unit length, and all three are
* mutually orthogonal). Also should be oriented, i.e. axis cross base2 =
* base3, rather than -base3.
*
* Method: Find a vector linearly independent from axis. For this we
* either use the y-axis, or, if that is too close to axis, the
* z-axis. 'Too close' means that the dot product is too near to 1.
*/
MAT3_COPY_VEC(naxis, axis);
MAT3_NORMALIZE_VEC(naxis, dot);
if (dot == 0.0) {
/* ERR_ERROR(MAT3_errid, ERR_SEVERE,
(ERR_S, "Zero-length axis vector given to MAT3rotate")); */
return;
}
MAT3perp_vec(base2, naxis, TRUE);
MAT3cross_product(base3, naxis, base2);
/* Set up the change-of-basis matrix, and its inverse */
MAT3identity(base_mat);
MAT3identity(base_mat_trans);
MAT3identity(result_mat);
for (i = 0; i < 3; i++){
base_mat_trans[i][0] = base_mat[0][i] = naxis[i];
base_mat_trans[i][1] = base_mat[1][i] = base2[i];
base_mat_trans[i][2] = base_mat[2][i] = base3[i];
}
/* If T(u) = uR, where R is base_mat, then T(x-axis) = naxis,
* T(y-axis) = base2, and T(z-axis) = base3. The inverse of base_mat is
* its transpose. OK?
*/
result_mat[1][1] = result_mat[2][2] = cos(angle_in_radians);
result_mat[2][1] = -(result_mat[1][2] = sin(angle_in_radians));
MAT3mult(result_mat, base_mat_trans, result_mat);
MAT3mult(result_mat, result_mat, base_mat);
}
/*
* Sets the given matrix to be a translation matrix for the given vector of
* translation values.
*/
void
MAT3translate(double (*result_mat)[4], double *trans)
{
MAT3identity(result_mat);
result_mat[3][0] = trans[0];
result_mat[3][1] = trans[1];
result_mat[3][2] = trans[2];
}
/*
* Sets the given matrix to be a shear matrix for the given x and y shear
* values.
*/
void
MAT3shear(double (*result_mat)[4], double xshear, double yshear)
{
MAT3identity(result_mat);
result_mat[2][0] = xshear;
result_mat[2][1] = yshear;
}

311
simgear/math/MAT3inv.c Normal file
View File

@@ -0,0 +1,311 @@
/* Copyright 1988, Brown Computer Graphics Group. All Rights Reserved. */
/* --------------------------------------------------------------------------
* This file contains routines that operate solely on matrices.
* -------------------------------------------------------------------------*/
#include "mat3defs.h"
/* -------------------------- Static Routines ---------------------------- */
#define SMALL 1e-20 /* Small enough to be considered zero */
/*
* Shuffles rows in inverse of 3x3. See comment in MAT3_inv3_second_col().
*/
static void
MAT3_inv3_swap( register double inv[3][3], int row0, int row1, int row2)
{
register int i, tempi;
double temp;
#define SWAP_ROWS(a, b) \
for (i = 0; i < 3; i++) SWAP(inv[a][i], inv[b][i], temp); \
SWAP(a, b, tempi)
if (row0 != 0){
if (row1 == 0) {
SWAP_ROWS(row0, row1);
}
else {
SWAP_ROWS(row0, row2);
}
}
if (row1 != 1) {
SWAP_ROWS(row1, row2);
}
}
/*
* Does Gaussian elimination on second column.
*/
static int
MAT3_inv3_second_col (register double source[3][3], register double inv[3][3], int row0)
{
register int row1, row2, i1, i2, i;
double temp;
double a, b;
/* Find which row to use */
if (row0 == 0) i1 = 1, i2 = 2;
else if (row0 == 1) i1 = 0, i2 = 2;
else i1 = 0, i2 = 1;
/* Find which is larger in abs. val.:the entry in [i1][1] or [i2][1] */
/* and use that value for pivoting. */
a = source[i1][1]; if (a < 0) a = -a;
b = source[i2][1]; if (b < 0) b = -b;
if (a > b) row1 = i1;
else row1 = i2;
row2 = (row1 == i1 ? i2 : i1);
/* Scale row1 in source */
if ((source[row1][1] < SMALL) && (source[row1][1] > -SMALL)) return(FALSE);
temp = 1.0 / source[row1][1];
source[row1][1] = 1.0;
source[row1][2] *= temp; /* source[row1][0] is zero already */
/* Scale row1 in inv */
inv[row1][row1] = temp; /* it used to be a 1.0 */
inv[row1][row0] *= temp;
/* Clear column one, source, and make corresponding changes in inv */
for (i = 0; i < 3; i++) if (i != row1) { /* for i = all rows but row1 */
temp = -source[i][1];
source[i][1] = 0.0;
source[i][2] += temp * source[row1][2];
inv[i][row1] = temp * inv[row1][row1];
inv[i][row0] += temp * inv[row1][row0];
}
/* Scale row2 in source */
if ((source[row2][2] < SMALL) && (source[row2][2] > -SMALL)) return(FALSE);
temp = 1.0 / source[row2][2];
source[row2][2] = 1.0; /* source[row2][*] is zero already */
/* Scale row2 in inv */
inv[row2][row2] = temp; /* it used to be a 1.0 */
inv[row2][row0] *= temp;
inv[row2][row1] *= temp;
/* Clear column one, source, and make corresponding changes in inv */
for (i = 0; i < 3; i++) if (i != row2) { /* for i = all rows but row2 */
temp = -source[i][2];
source[i][2] = 0.0;
inv[i][row0] += temp * inv[row2][row0];
inv[i][row1] += temp * inv[row2][row1];
inv[i][row2] += temp * inv[row2][row2];
}
/*
* Now all is done except that the inverse needs to have its rows shuffled.
* row0 needs to be moved to inv[0][*], row1 to inv[1][*], etc.
*
* We *didn't* do the swapping before the elimination so that we could more
* easily keep track of what ops are needed to be done in the inverse.
*/
MAT3_inv3_swap(inv, row0, row1, row2);
return(TRUE);
}
/*
* Fast inversion routine for 3 x 3 matrices. - Written by jfh.
*
* This takes 30 multiplies/divides, as opposed to 39 for Cramer's Rule.
* The algorithm consists of performing fast gaussian elimination, by never
* doing any operations where the result is guaranteed to be zero, or where
* one operand is guaranteed to be zero. This is done at the cost of clarity,
* alas.
*
* Returns 1 if the inverse was successful, 0 if it failed.
*/
static int
MAT3_invert3 (register double source[3][3], register double inv[3][3])
{
register int i, row0;
double temp;
double a, b, c;
inv[0][0] = inv[1][1] = inv[2][2] = 1.0;
inv[0][1] = inv[0][2] = inv[1][0] = inv[1][2] = inv[2][0] = inv[2][1] = 0.0;
/* attempt to find the largest entry in first column to use as pivot */
a = source[0][0]; if (a < 0) a = -a;
b = source[1][0]; if (b < 0) b = -b;
c = source[2][0]; if (c < 0) c = -c;
if (a > b) {
if (a > c) row0 = 0;
else row0 = 2;
}
else {
if (b > c) row0 = 1;
else row0 = 2;
}
/* Scale row0 of source */
if ((source[row0][0] < SMALL) && (source[row0][0] > -SMALL)) return(FALSE);
temp = 1.0 / source[row0][0];
source[row0][0] = 1.0;
source[row0][1] *= temp;
source[row0][2] *= temp;
/* Scale row0 of inverse */
inv[row0][row0] = temp; /* other entries are zero -- no effort */
/* Clear column zero of source, and make corresponding changes in inverse */
for (i = 0; i < 3; i++) if (i != row0) { /* for i = all rows but row0 */
temp = -source[i][0];
source[i][0] = 0.0;
source[i][1] += temp * source[row0][1];
source[i][2] += temp * source[row0][2];
inv[i][row0] = temp * inv[row0][row0];
}
/*
* We've now done gaussian elimination so that the source and
* inverse look like this:
*
* 1 * * * 0 0
* 0 * * * 1 0
* 0 * * * 0 1
*
* We now proceed to do elimination on the second column.
*/
if (! MAT3_inv3_second_col(source, inv, row0)) return(FALSE);
return(TRUE);
}
/*
* Finds a new pivot for a non-simple 4x4. See comments in MAT3invert().
*/
static int
MAT3_inv4_pivot (register MAT3mat src, MAT3vec r, double *s, int *swap)
{
register int i, j;
double temp, max;
*swap = -1;
if (MAT3_IS_ZERO(src[3][3])) {
/* Look for a different pivot element: one with largest abs value */
max = 0.0;
for (i = 0; i < 4; i++) {
if (src[i][3] > max) max = src[*swap = i][3];
else if (src[i][3] < -max) max = -src[*swap = i][3];
}
/* No pivot element available ! */
if (*swap < 0) return(FALSE);
else for (j = 0; j < 4; j++) SWAP(src[*swap][j], src[3][j], temp);
}
MAT3_SET_VEC (r, -src[0][3], -src[1][3], -src[2][3]);
*s = 1.0 / src[3][3];
src[0][3] = src[1][3] = src[2][3] = 0.0;
src[3][3] = 1.0;
MAT3_SCALE_VEC(src[3], src[3], *s);
for (i = 0; i < 3; i++) {
src[0][i] += r[0] * src[3][i];
src[1][i] += r[1] * src[3][i];
src[2][i] += r[2] * src[3][i];
}
return(TRUE);
}
/* ------------------------- Internal Routines --------------------------- */
/* -------------------------- Public Routines ---------------------------- */
/*
* This returns the inverse of the given matrix. The result matrix
* may be the same as the one to invert.
*
* Fast inversion routine for 4 x 4 matrices, written by jfh.
*
* Returns 1 if the inverse was successful, 0 if it failed.
*
* This routine has been specially tweaked to notice the following:
* If the matrix has the form
* * * * 0
* * * * 0
* * * * 0
* * * * 1
*
* (as do many matrices in graphics), then we compute the inverse of
* the upper left 3x3 matrix and use this to find the general inverse.
*
* In the event that the right column is not 0-0-0-1, we do gaussian
* elimination to make it so, then use the 3x3 inverse, and then do
* our gaussian elimination.
*/
int
MAT3invert(double (*result_mat)[4], double (*mat)[4])
{
MAT3mat src, inv;
register int i, j, simple;
double m[3][3], inv3[3][3], s, temp;
MAT3vec r, t;
int swap;
MAT3copy(src, mat);
MAT3identity(inv);
/* If last column is not (0,0,0,1), use special code */
simple = (mat[0][3] == 0.0 && mat[1][3] == 0.0 &&
mat[2][3] == 0.0 && mat[3][3] == 1.0);
if (! simple && ! MAT3_inv4_pivot(src, r, &s, &swap)) return(FALSE);
MAT3_COPY_VEC(t, src[3]); /* Translation vector */
/* Copy upper-left 3x3 matrix */
for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) m[i][j] = src[i][j];
if (! MAT3_invert3(m, inv3)) return(FALSE);
for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) inv[i][j] = inv3[i][j];
for (i = 0; i < 3; i++) for (j = 0; j < 3; j++)
inv[3][i] -= t[j] * inv3[j][i];
if (! simple) {
/* We still have to undo our gaussian elimination from earlier on */
/* add r0 * first col to last col */
/* add r1 * 2nd col to last col */
/* add r2 * 3rd col to last col */
for (i = 0; i < 4; i++) {
inv[i][3] += r[0] * inv[i][0] + r[1] * inv[i][1] + r[2] * inv[i][2];
inv[i][3] *= s;
}
if (swap >= 0)
for (i = 0; i < 4; i++) SWAP(inv[i][swap], inv[i][3], temp);
}
MAT3copy(result_mat, inv);
return(TRUE);
}

120
simgear/math/MAT3mat.c Normal file
View File

@@ -0,0 +1,120 @@
/* #include "HEADERS.h" */
/* Copyright 1988, Brown Computer Graphics Group. All Rights Reserved. */
/* --------------------------------------------------------------------------
* This file contains routines that operate solely on matrices.
* -------------------------------------------------------------------------*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef WIN32
# ifndef HAVE_STL_SGI_PORT
# ifdef __BORLANDC__
# include <mem.h>
# else
# include <memory.h> /* required for memset() and memcpy() */
# endif
# endif
#endif
#include <string.h>
#include "mat3defs.h"
MAT3mat identityMatrix = {
{ 1.0, 0.0, 0.0, 0.0 },
{ 0.0, 1.0, 0.0, 0.0 },
{ 0.0, 0.0, 1.0, 0.0 },
{ 0.0, 0.0, 0.0, 1.0 }
};
/* #include "macros.h" */
/* -------------------------- Static Routines ---------------------------- */
/* ------------------------- Internal Routines --------------------------- */
/* -------------------------- Public Routines ---------------------------- */
#if !defined( USE_XTRA_MAT3_INLINES )
/*
* This multiplies two matrices, producing a third, which may the same as
* either of the first two.
*/
void
MAT3mult (double (*result_mat)[4], register double (*mat1)[4], register double (*mat2)[4])
{
register int i, j;
MAT3mat tmp_mat;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
tmp_mat[i][j] = (mat1[i][0] * mat2[0][j] +
mat1[i][1] * mat2[1][j] +
mat1[i][2] * mat2[2][j] +
mat1[i][3] * mat2[3][j]);
MAT3copy (result_mat, tmp_mat);
}
#endif // !defined( USE_XTRA_MAT3_INLINES )
/*
* This returns the transpose of a matrix. The result matrix may be
* the same as the one to transpose.
*/
void
MAT3transpose (double (*result_mat)[4], register double (*mat)[4])
{
register int i, j;
MAT3mat tmp_mat;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
tmp_mat[i][j] = mat[j][i];
MAT3copy (result_mat, tmp_mat);
}
/*
* This prints the given matrix to the given file pointer.
*/
void
MAT3print(double (*mat)[4], FILE *fp)
{
MAT3print_formatted(mat, fp, CNULL, CNULL, CNULL, CNULL);
}
/*
* This prints the given matrix to the given file pointer.
* use the format string to pass to fprintf. head and tail
* are printed at the beginning and end of each line.
*/
void
MAT3print_formatted(double (*mat)[4], FILE *fp, char *title, char *head, char *format, char *tail)
{
register int i, j;
/* This is to allow this to be called easily from a debugger */
if (fp == NULL) fp = stderr;
if (title == NULL) title = "MAT3 matrix:\n";
if (head == NULL) head = " ";
if (format == NULL) format = "%#8.4lf ";
if (tail == NULL) tail = "\n";
(void) fprintf(fp, title);
for (i = 0; i < 4; i++) {
(void) fprintf(fp, head);
for (j = 0; j < 4; j++) (void) fprintf(fp, format, mat[i][j]);
(void) fprintf(fp, tail);
}
}

154
simgear/math/MAT3vec.c Normal file
View File

@@ -0,0 +1,154 @@
/* Copyright 1988, Brown Computer Graphics Group. All Rights Reserved. */
/* --------------------------------------------------------------------------
* This file contains routines that operate on matrices and vectors, or
* vectors and vectors.
* -------------------------------------------------------------------------*/
/* #include "sphigslocal.h" */
/* -------------------------- Static Routines ---------------------------- */
/* ------------------------- Internal Routines --------------------------- */
/* -------------------------- Public Routines ---------------------------- */
/*
* Multiplies a vector by a matrix, setting the result vector.
* It assumes all homogeneous coordinates are 1.
* The two vectors involved may be the same.
*/
#include "mat3.h"
#ifndef TRUE
# define TRUE 1
#endif
#ifndef FALSE
# define FALSE 0
#endif
#if !defined( USE_XTRA_MAT3_INLINES )
void
MAT3mult_vec(double *result_vec, register double *vec, register double (*mat)[4])
{
MAT3vec tempvec;
register double *temp = tempvec;
temp[0] = vec[0] * mat[0][0] + vec[1] * mat[1][0] +
vec[2] * mat[2][0] + mat[3][0];
temp[1] = vec[0] * mat[0][1] + vec[1] * mat[1][1] +
vec[2] * mat[2][1] + mat[3][1];
temp[2] = vec[0] * mat[0][2] + vec[1] * mat[1][2] +
vec[2] * mat[2][2] + mat[3][2];
MAT3_COPY_VEC(result_vec, temp);
}
#endif // !defined( USE_XTRA_MAT3_INLINES )
/*
* Multiplies a vector of size 4 by a matrix, setting the result vector.
* The fourth element of the vector is the homogeneous coordinate, which
* may or may not be 1. If the "normalize" parameter is TRUE, then the
* result vector will be normalized so that the homogeneous coordinate is 1.
* The two vectors involved may be the same.
* This returns zero if the vector was to be normalized, but couldn't be.
*/
int
MAT3mult_hvec(double *result_vec, register double *vec, register double (*mat)[4], int normalize)
{
MAT3hvec tempvec;
double norm_fac;
register double *temp = tempvec;
register int ret = TRUE;
temp[0] = vec[0] * mat[0][0] + vec[1] * mat[1][0] +
vec[2] * mat[2][0] + vec[3] * mat[3][0];
temp[1] = vec[0] * mat[0][1] + vec[1] * mat[1][1] +
vec[2] * mat[2][1] + vec[3] * mat[3][1];
temp[2] = vec[0] * mat[0][2] + vec[1] * mat[1][2] +
vec[2] * mat[2][2] + vec[3] * mat[3][2];
temp[3] = vec[0] * mat[0][3] + vec[1] * mat[1][3] +
vec[2] * mat[2][3] + vec[3] * mat[3][3];
/* Normalize if asked for, possible, and necessary */
if (normalize) {
if (MAT3_IS_ZERO(temp[3])) {
#ifndef THINK_C
fprintf (stderr,
"Can't normalize vector: homogeneous coordinate is 0");
#endif
ret = FALSE;
}
else {
norm_fac = 1.0 / temp[3];
MAT3_SCALE_VEC(result_vec, temp, norm_fac);
result_vec[3] = 1.0;
}
}
else MAT3_COPY_HVEC(result_vec, temp);
return(ret);
}
#if !defined( USE_XTRA_MAT3_INLINES )
/*
* Sets the first vector to be the cross-product of the last two vectors.
*/
void
MAT3cross_product(double *result_vec, register double *vec1, register double *vec2)
{
MAT3vec tempvec;
register double *temp = tempvec;
temp[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
temp[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
temp[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
MAT3_COPY_VEC(result_vec, temp);
}
#endif // !defined( USE_XTRA_MAT3_INLINES )
/*
* Finds a vector perpendicular to vec and stores it in result_vec.
* Method: take any vector (we use <0,1,0>) and subtract the
* portion of it pointing in the vec direction. This doesn't
* work if vec IS <0,1,0> or is very near it. So if this is
* the case, use <0,0,1> instead.
* If "is_unit" is TRUE, the given vector is assumed to be unit length.
*/
#define SELECT .7071 /* selection constant (roughly .5*sqrt(2) */
void
MAT3perp_vec(double *result_vec, double *vec, int is_unit)
{
MAT3vec norm;
double dot;
MAT3_SET_VEC(result_vec, 0.0, 1.0, 0.0);
MAT3_COPY_VEC(norm, vec);
if (! is_unit) MAT3_NORMALIZE_VEC(norm, dot);
/* See if vector is too close to <0,1,0>. If so, use <0,0,1> */
if ((dot = MAT3_DOT_PRODUCT(norm, result_vec)) > SELECT || dot < -SELECT) {
result_vec[1] = 0.0;
result_vec[2] = 1.0;
dot = MAT3_DOT_PRODUCT(norm, result_vec);
}
/* Subtract off non-perpendicular part */
result_vec[0] -= dot * norm[0];
result_vec[1] -= dot * norm[1];
result_vec[2] -= dot * norm[2];
/* Make result unit length */
MAT3_NORMALIZE_VEC(result_vec, dot);
}

32
simgear/math/Makefile.am Normal file
View File

@@ -0,0 +1,32 @@
includedir = @includedir@/math
lib_LIBRARIES = libsgmath.a
include_HEADERS = \
fg_geodesy.hxx \
fg_memory.h \
fg_random.h \
fg_types.hxx \
interpolater.hxx \
leastsqs.hxx \
mat3.h \
point3d.hxx \
polar3d.hxx \
vector.hxx
EXTRA_DIST = linintp2.h linintp2.inl sphrintp.h sphrintp.inl
libsgmath_a_SOURCES = \
MAT3geom.c \
MAT3inv.c \
MAT3mat.c \
MAT3vec.c \
fg_geodesy.cxx \
fg_random.c \
interpolater.cxx \
leastsqs.cxx \
mat3defs.h mat3err.h \
polar3d.cxx \
vector.cxx
INCLUDES += -I$(top_builddir)/src

446
simgear/math/fg_geodesy.cxx Normal file
View File

@@ -0,0 +1,446 @@
// fg_geodesy.cxx -- routines to convert between geodetic and geocentric
// coordinate systems.
//
// Copied and adapted directly from LaRCsim/ls_geodesy.c
//
// See below for the complete original LaRCsim comments.
//
// $Id$
#include <simgear/compiler.h>
#ifdef FG_HAVE_STD_INCLUDES
# include <cmath>
# include <cerrno>
#else
# include <math.h>
# include <errno.h>
#endif
#include <simgear/constants.h>
#include <simgear/debug/logstream.hxx>
#include "point3d.hxx"
#include "fg_geodesy.hxx"
#ifndef FG_HAVE_NATIVE_SGI_COMPILERS
FG_USING_STD(cout);
#endif
// ONE_SECOND is pi/180/60/60, or about 100 feet at earths' equator
#define ONE_SECOND 4.848136811E-6
// fgGeocToGeod(lat_geoc, radius, *lat_geod, *alt, *sea_level_r)
// INPUTS:
// lat_geoc Geocentric latitude, radians, + = North
// radius C.G. radius to earth center (meters)
//
// OUTPUTS:
// lat_geod Geodetic latitude, radians, + = North
// alt C.G. altitude above mean sea level (meters)
// 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
*lat_geod, double *alt, double *sea_level_r )
{
double t_lat, x_alpha, mu_alpha, delt_mu, r_alpha, l_point, rho_alpha;
double sin_mu_a, denom,delt_lambda, lambda_sl, sin_lambda_sl;
if( ( (FG_PI_2 - lat_geoc) < ONE_SECOND ) // near North pole
|| ( (FG_PI_2 + lat_geoc) < ONE_SECOND ) ) // near South pole
{
*lat_geod = lat_geoc;
*sea_level_r = EQUATORIAL_RADIUS_M*E;
*alt = radius - *sea_level_r;
} else {
t_lat = tan(lat_geoc);
x_alpha = E*EQUATORIAL_RADIUS_M/sqrt(t_lat*t_lat + E*E);
double tmp = RESQ_M - x_alpha * x_alpha;
if ( tmp < 0.0 ) { tmp = 0.0; }
mu_alpha = atan2(sqrt(tmp),E*x_alpha);
if (lat_geoc < 0) mu_alpha = - mu_alpha;
sin_mu_a = sin(mu_alpha);
delt_lambda = mu_alpha - lat_geoc;
r_alpha = x_alpha/cos(lat_geoc);
l_point = radius - r_alpha;
*alt = l_point*cos(delt_lambda);
// check for domain error
if ( errno == EDOM ) {
FG_LOG( FG_GENERAL, FG_ALERT, "Domain ERROR in fgGeocToGeod!!!!" );
*alt = 0.0;
}
denom = sqrt(1-EPS*EPS*sin_mu_a*sin_mu_a);
rho_alpha = EQUATORIAL_RADIUS_M*(1-EPS)/
(denom*denom*denom);
delt_mu = atan2(l_point*sin(delt_lambda),rho_alpha + *alt);
*lat_geod = mu_alpha - delt_mu;
lambda_sl = atan( E*E * tan(*lat_geod) ); // SL geoc. latitude
sin_lambda_sl = sin( lambda_sl );
*sea_level_r =
sqrt(RESQ_M / (1 + ((1/(E*E))-1)*sin_lambda_sl*sin_lambda_sl));
// check for domain error
if ( errno == EDOM ) {
FG_LOG( FG_GENERAL, FG_ALERT, "Domain ERROR in fgGeocToGeod!!!!" );
*sea_level_r = 0.0;
}
}
}
// fgGeodToGeoc( lat_geod, alt, *sl_radius, *lat_geoc )
// INPUTS:
// lat_geod Geodetic latitude, radians, + = North
// alt C.G. altitude above mean sea level (meters)
//
// OUTPUTS:
// sl_radius SEA LEVEL radius to earth center (meters)
// (add Altitude to get true distance from earth center.
// lat_geoc Geocentric latitude, radians, + = North
//
void fgGeodToGeoc( 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;
lambda_sl = atan( E*E * tan(lat_geod) ); // sea level geocentric latitude
sin_lambda_sl = sin( lambda_sl );
cos_lambda_sl = cos( lambda_sl );
sin_mu = sin(lat_geod); // Geodetic (map makers') latitude
cos_mu = cos(lat_geod);
*sl_radius =
sqrt(RESQ_M / (1 + ((1/(E*E))-1)*sin_lambda_sl*sin_lambda_sl));
py = *sl_radius*sin_lambda_sl + alt*sin_mu;
px = *sl_radius*cos_lambda_sl + alt*cos_mu;
*lat_geoc = atan2( py, px );
}
// Direct and inverse distance functions
//
// Proceedings of the 7th International Symposium on Geodetic
// Computations, 1985
//
// "The Nested Coefficient Method for Accurate Solutions of Direct and
// Inverse Geodetic Problems With Any Length"
//
// Zhang Xue-Lian
// pp 747-763
//
// modified for FlightGear to use WGS84 only -- Norman Vine
#define GEOD_INV_PI FG_PI
// s == distance
// az = azimuth
// for WGS_84 a = 6378137.000, rf = 298.257223563;
static double M0( double e2 ) {
//double e4 = e2*e2;
return GEOD_INV_PI*(1.0 - e2*( 1.0/4.0 + e2*( 3.0/64.0 +
e2*(5.0/256.0) )))/2.0;
}
// given, alt, lat1, lon1, az1 and distance (s), calculate lat2, lon2
// and az2. Lat, lon, and azimuth are in degrees. distance in meters
int geo_direct_wgs_84 ( double alt, double lat1, double lon1, double az1,
double s, double *lat2, double *lon2, double *az2 )
{
double a = 6378137.000, rf = 298.257223563;
double RADDEG = (GEOD_INV_PI)/180.0, testv = 1.0E-10;
double f = ( rf > 0.0 ? 1.0/rf : 0.0 );
double b = a*(1.0-f);
double e2 = f*(2.0-f);
double phi1 = lat1*RADDEG, lam1 = lon1*RADDEG;
double sinphi1 = sin(phi1), cosphi1 = cos(phi1);
double azm1 = az1*RADDEG;
double sinaz1 = sin(azm1), cosaz1 = cos(azm1);
if( fabs(s) < 0.01 ) { // distance < centimeter => congruency
*lat2 = lat1;
*lon2 = lon1;
*az2 = 180.0 + az1;
if( *az2 > 360.0 ) *az2 -= 360.0;
return 0;
} else if( cosphi1 ) { // non-polar origin
// u1 is reduced latitude
double tanu1 = sqrt(1.0-e2)*sinphi1/cosphi1;
double sig1 = atan2(tanu1,cosaz1);
double cosu1 = 1.0/sqrt( 1.0 + tanu1*tanu1 ), sinu1 = tanu1*cosu1;
double sinaz = cosu1*sinaz1, cos2saz = 1.0-sinaz*sinaz;
double us = cos2saz*e2/(1.0-e2);
// Terms
double ta = 1.0+us*(4096.0+us*(-768.0+us*(320.0-175.0*us)))/16384.0,
tb = us*(256.0+us*(-128.0+us*(74.0-47.0*us)))/1024.0,
tc = 0;
// FIRST ESTIMATE OF SIGMA (SIG)
double first = s/(b*ta); // !!
double sig = first;
double c2sigm, sinsig,cossig, temp,denom,rnumer, dlams, dlam;
do {
c2sigm = cos(2.0*sig1+sig);
sinsig = sin(sig); cossig = cos(sig);
temp = sig;
sig = first +
tb*sinsig*(c2sigm+tb*(cossig*(-1.0+2.0*c2sigm*c2sigm) -
tb*c2sigm*(-3.0+4.0*sinsig*sinsig)
*(-3.0+4.0*c2sigm*c2sigm)/6.0)
/4.0);
} while( fabs(sig-temp) > testv);
// LATITUDE OF POINT 2
// DENOMINATOR IN 2 PARTS (TEMP ALSO USED LATER)
temp = sinu1*sinsig-cosu1*cossig*cosaz1;
denom = (1.0-f)*sqrt(sinaz*sinaz+temp*temp);
// NUMERATOR
rnumer = sinu1*cossig+cosu1*sinsig*cosaz1;
*lat2 = atan2(rnumer,denom)/RADDEG;
// DIFFERENCE IN LONGITUDE ON AUXILARY SPHERE (DLAMS )
rnumer = sinsig*sinaz1;
denom = cosu1*cossig-sinu1*sinsig*cosaz1;
dlams = atan2(rnumer,denom);
// TERM C
tc = f*cos2saz*(4.0+f*(4.0-3.0*cos2saz))/16.0;
// DIFFERENCE IN LONGITUDE
dlam = dlams-(1.0-tc)*f*sinaz*(sig+tc*sinsig*
(c2sigm+
tc*cossig*(-1.0+2.0*
c2sigm*c2sigm)));
*lon2 = (lam1+dlam)/RADDEG;
if (*lon2 > 180.0 ) *lon2 -= 360.0;
if (*lon2 < -180.0 ) *lon2 += 360.0;
// AZIMUTH - FROM NORTH
*az2 = atan2(-sinaz,temp)/RADDEG;
if ( fabs(*az2) < testv ) *az2 = 0.0;
if( *az2 < 0.0) *az2 += 360.0;
return 0;
} else { // phi1 == 90 degrees, polar origin
double dM = a*M0(e2) - s;
double paz = ( phi1 < 0.0 ? 180.0 : 0.0 );
return geo_direct_wgs_84( alt, 0.0, lon1, paz, dM,lat2,lon2,az2 );
}
}
// given alt, lat1, lon1, lat2, lon2, calculate starting and ending
// az1, az2 and distance (s). Lat, lon, and azimuth are in degrees.
// distance in meters
int geo_inverse_wgs_84( double alt, double lat1, double lon1, double lat2,
double lon2, double *az1, double *az2, double *s )
{
double a = 6378137.000, rf = 298.257223563;
int iter=0;
double RADDEG = (GEOD_INV_PI)/180.0, testv = 1.0E-10;
double f = ( rf > 0.0 ? 1.0/rf : 0.0 );
double b = a*(1.0-f);
// double e2 = f*(2.0-f); // unused in this routine
double phi1 = lat1*RADDEG, lam1 = lon1*RADDEG;
double sinphi1 = sin(phi1), cosphi1 = cos(phi1);
double phi2 = lat2*RADDEG, lam2 = lon2*RADDEG;
double sinphi2 = sin(phi2), cosphi2 = cos(phi2);
if( (fabs(lat1-lat2) < testv &&
( fabs(lon1-lon2) < testv) || fabs(lat1-90.0) < testv ) )
{
// TWO STATIONS ARE IDENTICAL : SET DISTANCE & AZIMUTHS TO ZERO */
*az1 = 0.0; *az2 = 0.0; *s = 0.0;
return 0;
} else if( fabs(cosphi1) < testv ) {
// initial point is polar
int k = geo_inverse_wgs_84( alt, lat2,lon2,lat1,lon1, az1,az2,s );
k = k; // avoid compiler error since return result is unused
b = *az1; *az1 = *az2; *az2 = b;
return 0;
} else if( fabs(cosphi2) < testv ) {
// terminal point is polar
int k = geo_inverse_wgs_84( alt, lat1,lon1,lat1,lon1+180.0,
az1,az2,s );
k = k; // avoid compiler error since return result is unused
*s /= 2.0;
*az2 = *az1 + 180.0;
if( *az2 > 360.0 ) *az2 -= 360.0;
return 0;
} else if( (fabs( fabs(lon1-lon2) - 180 ) < testv) &&
(fabs(lat1+lat2) < testv) )
{
// Geodesic passes through the pole (antipodal)
double s1,s2;
geo_inverse_wgs_84( alt, lat1,lon1, lat1,lon2, az1,az2, &s1 );
geo_inverse_wgs_84( alt, lat2,lon2, lat1,lon2, az1,az2, &s2 );
*az2 = *az1;
*s = s1 + s2;
return 0;
} else {
// antipodal and polar points don't get here
double dlam = lam2 - lam1, dlams = dlam;
double sdlams,cdlams, sig,sinsig,cossig, sinaz,
cos2saz, c2sigm;
double tc,temp, us,rnumer,denom, ta,tb;
double cosu1,sinu1, sinu2,cosu2;
// Reduced latitudes
temp = (1.0-f)*sinphi1/cosphi1;
cosu1 = 1.0/sqrt(1.0+temp*temp);
sinu1 = temp*cosu1;
temp = (1.0-f)*sinphi2/cosphi2;
cosu2 = 1.0/sqrt(1.0+temp*temp);
sinu2 = temp*cosu2;
do {
sdlams = sin(dlams), cdlams = cos(dlams);
sinsig = sqrt(cosu2*cosu2*sdlams*sdlams+
(cosu1*sinu2-sinu1*cosu2*cdlams)*
(cosu1*sinu2-sinu1*cosu2*cdlams));
cossig = sinu1*sinu2+cosu1*cosu2*cdlams;
sig = atan2(sinsig,cossig);
sinaz = cosu1*cosu2*sdlams/sinsig;
cos2saz = 1.0-sinaz*sinaz;
c2sigm = (sinu1 == 0.0 || sinu2 == 0.0 ? cossig :
cossig-2.0*sinu1*sinu2/cos2saz);
tc = f*cos2saz*(4.0+f*(4.0-3.0*cos2saz))/16.0;
temp = dlams;
dlams = dlam+(1.0-tc)*f*sinaz*
(sig+tc*sinsig*
(c2sigm+tc*cossig*(-1.0+2.0*c2sigm*c2sigm)));
if (fabs(dlams) > GEOD_INV_PI && iter++ > 50) {
return iter;
}
} while ( fabs(temp-dlams) > testv);
us = cos2saz*(a*a-b*b)/(b*b); // !!
// BACK AZIMUTH FROM NORTH
rnumer = -(cosu1*sdlams);
denom = sinu1*cosu2-cosu1*sinu2*cdlams;
*az2 = atan2(rnumer,denom)/RADDEG;
if( fabs(*az2) < testv ) *az2 = 0.0;
if(*az2 < 0.0) *az2 += 360.0;
// FORWARD AZIMUTH FROM NORTH
rnumer = cosu2*sdlams;
denom = cosu1*sinu2-sinu1*cosu2*cdlams;
*az1 = atan2(rnumer,denom)/RADDEG;
if( fabs(*az1) < testv ) *az1 = 0.0;
if(*az1 < 0.0) *az1 += 360.0;
// Terms a & b
ta = 1.0+us*(4096.0+us*(-768.0+us*(320.0-175.0*us)))/
16384.0;
tb = us*(256.0+us*(-128.0+us*(74.0-47.0*us)))/1024.0;
// GEODETIC DISTANCE
*s = b*ta*(sig-tb*sinsig*
(c2sigm+tb*(cossig*(-1.0+2.0*c2sigm*c2sigm)-tb*
c2sigm*(-3.0+4.0*sinsig*sinsig)*
(-3.0+4.0*c2sigm*c2sigm)/6.0)/
4.0));
return 0;
}
}
/***************************************************************************
TITLE: ls_geodesy
----------------------------------------------------------------------------
FUNCTION: Converts geocentric coordinates to geodetic positions
----------------------------------------------------------------------------
MODULE STATUS: developmental
----------------------------------------------------------------------------
GENEALOGY: Written as part of LaRCSim project by E. B. Jackson
----------------------------------------------------------------------------
DESIGNED BY: E. B. Jackson
CODED BY: E. B. Jackson
MAINTAINED BY: E. B. Jackson
----------------------------------------------------------------------------
MODIFICATION HISTORY:
DATE PURPOSE BY
930208 Modified to avoid singularity near polar region. EBJ
930602 Moved backwards calcs here from ls_step. EBJ
931214 Changed erroneous Latitude and Altitude variables to
*lat_geod and *alt in routine ls_geoc_to_geod. EBJ
940111 Changed header files from old ls_eom.h style to ls_types,
and ls_constants. Also replaced old DATA type with new
SCALAR type. EBJ
CURRENT RCS HEADER:
$Header$
* Revision 1.5 1994/01/11 18:47:05 bjax
* Changed include files to use types and constants, not ls_eom.h
* Also changed DATA type to SCALAR type.
*
* Revision 1.4 1993/12/14 21:06:47 bjax
* Removed global variable references Altitude and Latitude. EBJ
*
* Revision 1.3 1993/06/02 15:03:40 bjax
* Made new subroutine for calculating geodetic to geocentric; changed name
* of forward conversion routine from ls_geodesy to ls_geoc_to_geod.
*
----------------------------------------------------------------------------
REFERENCES:
[ 1] Stevens, Brian L.; and Lewis, Frank L.: "Aircraft
Control and Simulation", Wiley and Sons, 1992.
ISBN 0-471-61397-5
----------------------------------------------------------------------------
CALLED BY: ls_aux
----------------------------------------------------------------------------
CALLS TO:
----------------------------------------------------------------------------
INPUTS:
lat_geoc Geocentric latitude, radians, + = North
radius C.G. radius to earth center, ft
----------------------------------------------------------------------------
OUTPUTS:
lat_geod Geodetic latitude, radians, + = North
alt C.G. altitude above mean sea level, ft
sea_level_r radius from earth center to sea level at
local vertical (surface normal) of C.G.
--------------------------------------------------------------------------*/

175
simgear/math/fg_geodesy.hxx Normal file
View File

@@ -0,0 +1,175 @@
// fg_geodesy.hxx -- routines to convert between geodetic and geocentric
// coordinate systems.
//
// Copied and adapted directly from LaRCsim/ls_geodesy.c
//
// See below for the complete original LaRCsim comments.
//
// $Id$
#ifndef _FG_GEODESY_HXX
#define _FG_GEODESY_HXX
#ifndef __cplusplus
# error This library requires C++
#endif
#include <simgear/math/point3d.hxx>
#include <simgear/math/polar3d.hxx>
// fgGeocToGeod(lat_geoc, radius, *lat_geod, *alt, *sea_level_r)
// INPUTS:
// lat_geoc Geocentric latitude, radians, + = North
// radius C.G. radius to earth center (meters)
//
// OUTPUTS:
// lat_geod Geodetic latitude, radians, + = North
// alt C.G. altitude above mean sea level (meters)
// 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
*lat_geod, double *alt, double *sea_level_r );
// fgGeodToGeoc( lat_geod, alt, *sl_radius, *lat_geoc )
// INPUTS:
// lat_geod Geodetic latitude, radians, + = North
// alt C.G. altitude above mean sea level (meters)
//
// OUTPUTS:
// sl_radius SEA LEVEL radius to earth center (meters)
// (add Altitude to get true distance from earth center.
// lat_geoc Geocentric latitude, radians, + = North
//
void fgGeodToGeoc( 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) {
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);
// 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);
}
// given, alt, lat1, lon1, az1 and distance (s), calculate lat2, lon2
// and az2. Lat, lon, and azimuth are in degrees. distance in meters
int geo_direct_wgs_84 ( double alt, double lat1, double lon1, double az1,
double s, double *lat2, double *lon2, double *az2 );
// given alt, lat1, lon1, lat2, lon2, calculate starting and ending
// az1, az2 and distance (s). Lat, lon, and azimuth are in degrees.
// distance in meters
int geo_inverse_wgs_84( double alt, double lat1, double lon1, double lat2,
double lon2, double *az1, double *az2, double *s );
/***************************************************************************
TITLE: ls_geodesy
----------------------------------------------------------------------------
FUNCTION: Converts geocentric coordinates to geodetic positions
----------------------------------------------------------------------------
MODULE STATUS: developmental
----------------------------------------------------------------------------
GENEALOGY: Written as part of LaRCSim project by E. B. Jackson
----------------------------------------------------------------------------
DESIGNED BY: E. B. Jackson
CODED BY: E. B. Jackson
MAINTAINED BY: E. B. Jackson
----------------------------------------------------------------------------
MODIFICATION HISTORY:
DATE PURPOSE BY
930208 Modified to avoid singularity near polar region. EBJ
930602 Moved backwards calcs here from ls_step. EBJ
931214 Changed erroneous Latitude and Altitude variables to
*lat_geod and *alt in routine ls_geoc_to_geod. EBJ
940111 Changed header files from old ls_eom.h style to ls_types,
and ls_constants. Also replaced old DATA type with new
SCALAR type. EBJ
CURRENT RCS HEADER:
$Header$
* Revision 1.5 1994/01/11 18:47:05 bjax
* Changed include files to use types and constants, not ls_eom.h
* Also changed DATA type to SCALAR type.
*
* Revision 1.4 1993/12/14 21:06:47 bjax
* Removed global variable references Altitude and Latitude. EBJ
*
* Revision 1.3 1993/06/02 15:03:40 bjax
* Made new subroutine for calculating geodetic to geocentric; changed name
* of forward conversion routine from ls_geodesy to ls_geoc_to_geod.
*
----------------------------------------------------------------------------
REFERENCES:
[ 1] Stevens, Brian L.; and Lewis, Frank L.: "Aircraft
Control and Simulation", Wiley and Sons, 1992.
ISBN 0-471-61397-5
----------------------------------------------------------------------------
CALLED BY: ls_aux
----------------------------------------------------------------------------
CALLS TO:
----------------------------------------------------------------------------
INPUTS:
lat_geoc Geocentric latitude, radians, + = North
radius C.G. radius to earth center, ft
----------------------------------------------------------------------------
OUTPUTS:
lat_geod Geodetic latitude, radians, + = North
alt C.G. altitude above mean sea level, ft
sea_level_r radius from earth center to sea level at
local vertical (surface normal) of C.G.
--------------------------------------------------------------------------*/
#endif // _FG_GEODESY_HXX

59
simgear/math/fg_memory.h Normal file
View File

@@ -0,0 +1,59 @@
// fg_memory.h -- memcpy/bcopy portability declarations
//
// 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 _FG_MEMORY_H
#define _FG_MEMORY_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_MEMCPY
# ifdef HAVE_MEMORY_H
# include <memory.h>
# endif
# define fgmemcmp memcmp
# define fgmemcpy memcpy
# define fgmemzero(dest,len) memset(dest,0,len)
#elif defined(HAVE_BCOPY)
# define fgmemcmp bcmp
# define fgmemcpy(dest,src,n) bcopy(src,dest,n)
# define fgmemzero bzero
#else
/*
* Neither memcpy() or bcopy() available.
* Use substitutes provided be zlib.
*/
# include <zutil.h>
# define fgmemcmp zmemcmp
# define fgmemcpy zmemcpy
# define fgmemzero zmemzero
#endif
#endif // _FG_MEMORY_H

71
simgear/math/fg_random.c Normal file
View File

@@ -0,0 +1,71 @@
// fg_random.c -- routines to handle random number generation
//
// Written by Curtis Olson, started July 1997.
//
// Copyright (C) 1997 Curtis L. Olson - curt@infoplane.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.
//
// 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$
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h> // for random(), srandom()
#include <time.h> // for time() to seed srandom()
#include "fg_random.h"
#ifndef HAVE_RAND
# ifdef sgi
# undef RAND_MAX
# define RAND_MAX 2147483647
# endif
#endif
#ifdef __SUNPRO_CC
extern "C" {
long int random(void);
void srandom(unsigned int seed);
}
#endif
// 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");
#ifdef HAVE_RAND
srand(time(NULL));
#else
srandom(time(NULL));
#endif
}
// return a random number between [0.0, 1.0)
double fg_random(void) {
#ifdef HAVE_RAND
return(rand() / (double)RAND_MAX);
#else
return(random() / (double)RAND_MAX);
#endif
}

48
simgear/math/fg_random.h Normal file
View File

@@ -0,0 +1,48 @@
// fg_random.h -- routines to handle random number generation
//
// Written by Curtis Olson, started July 1997.
//
// Copyright (C) 1997 Curtis L. Olson - curt@infoplane.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.
//
// 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 _FG_RANDOM_H
#define _FG_RANDOM_H
#ifdef __cplusplus
extern "C" {
#endif
// Seed the random number generater with time() so we don't see the
// same sequence every time
void fg_srandom(void);
// return a random number between [0.0, 1.0)
double fg_random(void);
#ifdef __cplusplus
}
#endif
#endif // _FG_RANDOM_H

73
simgear/math/fg_types.hxx Normal file
View File

@@ -0,0 +1,73 @@
// fg_types.hxx -- commonly used types I don't want to have to keep redefining
//
// Written by Curtis Olson, started March 1999.
//
// Copyright (C) 1999 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 _FG_TYPES_HXX
#define _FG_TYPES_HXX
#ifndef __cplusplus
# error This library requires C++
#endif
#include <simgear/compiler.h>
#include STL_STRING
#include <vector>
#include <simgear/math/point3d.hxx>
FG_USING_STD(vector);
FG_USING_STD(string);
typedef vector < int > int_list;
typedef int_list::iterator int_list_iterator;
typedef int_list::const_iterator const_int_list_iterator;
typedef vector < Point3D > point_list;
typedef point_list::iterator point_list_iterator;
typedef point_list::const_iterator const_point_list_iterator;
typedef vector < string > string_list;
typedef string_list::iterator string_list_iterator;
typedef string_list::const_iterator const_string_list_iterator;
class point2d {
public:
union {
double x;
double dist;
double lon;
};
union {
double y;
double theta;
double lat;
};
};
#endif // _FG_TYPES_HXX

View File

@@ -0,0 +1,107 @@
//
// interpolater.cxx -- routines to handle linear interpolation from a table of
// x,y The table must be sorted by "x" in ascending order
//
// Written by Curtis Olson, started April 1998.
//
// Copyright (C) 1998 Curtis L. Olson - curt@me.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/compiler.h>
#ifdef __MWERKS__
#include <stdlib.h> // for exit()
#endif
#include STL_STRING
#include <simgear/fg_zlib.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/fgstream.hxx>
#include "interpolater.hxx"
// Constructor -- loads the interpolation table from the specified
// file
fgINTERPTABLE::fgINTERPTABLE( const string& file ) {
FG_LOG( FG_MATH, FG_INFO, "Initializing Interpolator for " << file );
fg_gzifstream in( file );
if ( !in ) {
FG_LOG( FG_GENERAL, FG_ALERT, "Cannot open file: " << file );
exit(-1);
}
size = 0;
in >> skipcomment;
while ( in ) {
if ( size < MAX_TABLE_SIZE ) {
in >> table[size][0] >> table[size][1];
size++;
} else {
FG_LOG( FG_MATH, FG_ALERT,
"fgInterpolateInit(): Exceed max table size = "
<< MAX_TABLE_SIZE );
exit(-1);
}
}
}
// Given an x value, linearly interpolate the y value from the table
double fgINTERPTABLE::interpolate(double x) {
int i;
double y;
i = 0;
while ( (x > table[i][0]) && (i < size) ) {
i++;
}
// printf ("i = %d ", i);
if ( (i == 0) && (x < table[0][0]) ) {
FG_LOG( FG_MATH, FG_ALERT,
"fgInterpolateInit(): lookup error, x to small = " << x );
return(0.0);
}
if ( x > table[i][0] ) {
FG_LOG( FG_MATH, FG_ALERT,
"fgInterpolateInit(): lookup error, x to big = " << x );
return(0.0);
}
// y = y1 + (y0 - y1)(x - x1) / (x0 - x1)
y = table[i][1] +
( (table[i-1][1] - table[i][1]) *
(x - table[i][0]) ) /
(table[i-1][0] - table[i][0]);
return(y);
}
// Destructor
fgINTERPTABLE::~fgINTERPTABLE( void ) {
}

View File

@@ -0,0 +1,62 @@
//
// interpolater.hxx -- routines to handle linear interpolation from a table of
// x,y The table must be sorted by "x" in ascending order
//
// Written by Curtis Olson, started April 1998.
//
// Copyright (C) 1998 Curtis L. Olson - curt@me.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 _INTERPOLATER_H
#define _INTERPOLATER_H
#ifndef __cplusplus
# error This library requires C++
#endif
#include <simgear/compiler.h>
#include STL_STRING
FG_USING_STD(string);
#define MAX_TABLE_SIZE 32
class fgINTERPTABLE {
int size;
double table[MAX_TABLE_SIZE][2];
public:
// Constructor -- loads the interpolation table from the specified
// file
fgINTERPTABLE( const string& file );
// Given an x value, linearly interpolate the y value from the table
double interpolate(double x);
// Destructor
~fgINTERPTABLE( void );
};
#endif // _INTERPOLATER_H

135
simgear/math/leastsqs.cxx Normal file
View File

@@ -0,0 +1,135 @@
// leastsqs.c -- Implements a simple linear least squares best fit routine
//
// Written by Curtis Olson, started September 1997.
//
// Copyright (C) 1997 Curtis L. Olson - curt@infoplane.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.
//
// 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 <stdio.h>
#include "leastsqs.hxx"
/*
Least squares fit:
y = b0 + b1x
n*sum(xi*yi) - (sum(xi)*sum(yi))
b1 = --------------------------------
n*sum(xi^2) - (sum(xi))^2
b0 = sum(yi)/n - b1*(sum(xi)/n)
*/
double sum_xi, sum_yi, sum_xi_2, sum_xi_yi;
int sum_n;
void least_squares(double *x, double *y, int n, double *m, double *b) {
int i;
sum_xi = sum_yi = sum_xi_2 = sum_xi_yi = 0.0;
sum_n = n;
for ( i = 0; i < n; i++ ) {
sum_xi += x[i];
sum_yi += y[i];
sum_xi_2 += x[i] * x[i];
sum_xi_yi += x[i] * y[i];
}
/* printf("sum(xi)=%.2f sum(yi)=%.2f sum(xi^2)=%.2f sum(xi*yi)=%.2f\n",
sum_xi, sum_yi, sum_xi_2, sum_xi_yi); */
*m = ( (double)sum_n * sum_xi_yi - sum_xi * sum_yi ) /
( (double)sum_n * sum_xi_2 - sum_xi * sum_xi );
*b = (sum_yi / (double)sum_n) - (*m) * (sum_xi / (double)sum_n);
/* printf("slope = %.2f intercept = %.2f\n", *m, *b); */
}
/* incrimentally update existing values with a new data point */
void least_squares_update(double x, double y, double *m, double *b) {
++sum_n;
sum_xi += x;
sum_yi += y;
sum_xi_2 += x * x;
sum_xi_yi += x * y;
/* printf("sum(xi)=%.2f sum(yi)=%.2f sum(xi^2)=%.2f sum(xi*yi)=%.2f\n",
sum_xi, sum_yi, sum_xi_2, sum_xi_yi); */
*m = ( (double)sum_n * sum_xi_yi - sum_xi * sum_yi ) /
( (double)sum_n * sum_xi_2 - sum_xi * sum_xi );
*b = (sum_yi / (double)sum_n) - (*m) * (sum_xi / (double)sum_n);
/* printf("slope = %.2f intercept = %.2f\n", *m, *b); */
}
/*
return the least squares error:
(y[i] - y_hat[i])^2
-------------------
n
*/
double least_squares_error(double *x, double *y, int n, double m, double b) {
int i;
double error, sum;
sum = 0.0;
for ( i = 0; i < n; i++ ) {
error = y[i] - (m * x[i] + b);
sum += error * error;
// printf("%.2f %.2f\n", error, sum);
}
return ( sum / (double)n );
}
/*
return the maximum least squares error:
(y[i] - y_hat[i])^2
*/
double least_squares_max_error(double *x, double *y, int n, double m, double b){
int i;
double error, max_error;
max_error = 0.0;
for ( i = 0; i < n; i++ ) {
error = y[i] - (m * x[i] + b);
error = error * error;
if ( error > max_error ) {
max_error = error;
}
}
return ( max_error );
}

73
simgear/math/leastsqs.hxx Normal file
View File

@@ -0,0 +1,73 @@
// leastsqs.h -- Implements a simple linear least squares best fit routine
//
// Written by Curtis Olson, started September 1997.
//
// Copyright (C) 1997 Curtis L. Olson - curt@infoplane.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.
//
// 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 _LEASTSQS_H
#define _LEASTSQS_H
#ifndef __cplusplus
# error This library requires C++
#endif
/*
Least squares fit:
y = b0 + b1x
n*sum(xi*yi) - (sum(xi)*sum(yi))
b1 = --------------------------------
n*sum(xi^2) - (sum(xi))^2
b0 = sum(yi)/n - b1*(sum(xi)/n)
*/
void least_squares(double *x, double *y, int n, double *m, double *b);
/* incrimentally update existing values with a new data point */
void least_squares_update(double x, double y, double *m, double *b);
/*
return the least squares error:
(y[i] - y_hat[i])^2
-------------------
n
*/
double least_squares_error(double *x, double *y, int n, double m, double b);
/*
return the maximum least squares error:
(y[i] - y_hat[i])^2
*/
double least_squares_max_error(double *x, double *y, int n, double m, double b);
#endif // _LEASTSQS_H

110
simgear/math/linintp2.h Normal file
View File

@@ -0,0 +1,110 @@
/*
WARNING - Do not remove this header.
This code is a templated version of the 'magic-software' spherical
interpolation code by Dave Eberly. The original (un-hacked) code can be
obtained from here: http://www.magic-software.com/gr_appr.htm
This code is derived from linintp2.h/cpp and sphrintp.h/cpp.
Dave Eberly says that the conditions for use are:
* You may distribute the original source code to others at no charge.
* You may modify the original source code and distribute it to others at
no charge. The modified code must be documented to indicate that it is
not part of the original package.
* You may use this code for non-commercial purposes. You may also
incorporate this code into commercial packages. However, you may not
sell any of your source code which contains my original and/or modified
source code. In such a case, you need to factor out my code and freely
distribute it.
* The original code comes with absolutely no warranty and no guarantee is
made that the code is bug-free.
This does not seem incompatible with GPL - so this modified version
is hereby placed under GPL along with the rest of FlightGear.
Christian Mayer
*/
#ifndef LININTP2_H
#define LININTP2_H
template<class T>
class mgcLinInterp2D
{
public:
mgcLinInterp2D (int _numPoints, double* x, double* y, T* _f);
~mgcLinInterp2D ();
double XMin () { return xmin; }
double XMax () { return xmax; }
double XRange () { return xmax-xmin; }
double YMin () { return ymin; }
double YMax () { return ymax; }
double YRange () { return ymax-ymin; }
int PointCount () { return numPoints; }
void GetPoint (int i, double& x, double& y);
int EdgeCount () { return numEdges; }
void GetEdge (int i, double& x0, double& y0, double& x1, double& y1);
int TriangleCount () { return numTriangles; }
void GetTriangle (int i, double& x0, double& y0, double& x1, double& y1,
double& x2, double& y2);
int Evaluate (double x, double y, T& F);
private:
typedef struct
{
double x, y;
}
Vertex;
typedef struct
{
int vertex[3]; // listed in counterclockwise order
int adj[3];
// adj[0] points to triangle sharing edge (vertex[0],vertex[1])
// adj[1] points to triangle sharing edge (vertex[1],vertex[2])
// adj[2] points to triangle sharing edge (vertex[2],vertex[0])
}
Triangle;
typedef struct
{
int vertex[2];
int triangle[2];
int index[2];
}
Edge;
int numPoints;
double** point;
double** tmppoint;
T* f;
double xmin, xmax, ymin, ymax;
int numEdges;
Edge* edge;
int numTriangles;
Triangle* triangle;
int Delaunay2D ();
void ComputeBarycenter (Vertex& v0, Vertex& v1, Vertex& v2, Vertex& ver,
double c[3]);
int InTriangle (Vertex& v0, Vertex& v1, Vertex& v2, Vertex& test);
};
#include "linintp2.inl"
#endif

540
simgear/math/linintp2.inl Normal file
View File

@@ -0,0 +1,540 @@
/*
WARNING - Do not remove this header.
This code is a templated version of the 'magic-software' spherical
interpolation code by Dave Eberly. The original (un-hacked) code can be
obtained from here: http://www.magic-software.com/gr_appr.htm
This code is derived from linintp2.h/cpp and sphrintp.h/cpp.
Dave Eberly says that the conditions for use are:
* You may distribute the original source code to others at no charge.
* You may modify the original source code and distribute it to others at
no charge. The modified code must be documented to indicate that it is
not part of the original package.
* You may use this code for non-commercial purposes. You may also
incorporate this code into commercial packages. However, you may not
sell any of your source code which contains my original and/or modified
source code. In such a case, you need to factor out my code and freely
distribute it.
* The original code comes with absolutely no warranty and no guarantee is
made that the code is bug-free.
This does not seem incompatible with GPL - so this modified version
is hereby placed under GPL along with the rest of FlightGear.
Christian Mayer
*/
#include <float.h>
#include <math.h>
#include <stdlib.h>
#include "linintp2.h"
//---------------------------------------------------------------------------
template<class T>
mgcLinInterp2D<T>::mgcLinInterp2D (int _numPoints, double* x, double* y,
T* _f)
{
if ( (numPoints = _numPoints) < 3 )
{
point = 0;
edge = 0;
triangle = 0;
numTriangles = 0;
return;
}
cout << "[ 20%] allocating memory \r";
point = new double*[numPoints];
tmppoint = new double*[numPoints+3];
f = new T[numPoints];
int i;
for (i = 0; i < numPoints; i++)
point[i] = new double[2];
for (i = 0; i < numPoints+3; i++)
tmppoint[i] = new double[2];
for (i = 0; i < numPoints; i++)
{
point[i][0] = tmppoint[i][0] = x[i];
point[i][1] = tmppoint[i][1] = y[i];
f[i] = _f[i];
}
cout << "[ 30%] creating delaunay diagram \r";
Delaunay2D();
}
//---------------------------------------------------------------------------
template<class T>
mgcLinInterp2D<T>::~mgcLinInterp2D ()
{
if ( numPoints < 3 )
return;
int i;
if ( point )
{
for (i = 0; i < numPoints; i++)
delete[] point[i];
delete[] point;
}
if ( tmppoint )
{
for (i = 0; i < numPoints+3; i++)
delete[] tmppoint[i];
delete[] tmppoint;
}
delete[] f;
delete[] edge;
delete[] triangle;
}
//---------------------------------------------------------------------------
template<class T>
void mgcLinInterp2D<T>::ComputeBarycenter (Vertex& v0, Vertex& v1, Vertex& v2,
Vertex& ver, double c[3])
{
double A0 = v0.x-v2.x, B0 = v0.y-v2.y;
double A1 = v1.x-v2.x, B1 = v1.y-v2.y;
double A2 = ver.x-v2.x, B2 = ver.y-v2.y;
double m00 = A0*A0+B0*B0, m01 = A0*A1+B0*B1, m11 = A1*A1+B1*B1;
double r0 = A2*A0+B2*B0, r1 = A2*A1+B2*B1;
double det = m00*m11-m01*m01;
c[0] = (m11*r0-m01*r1)/det;
c[1] = (m00*r1-m01*r0)/det;
c[2] = 1-c[0]-c[1];
}
//---------------------------------------------------------------------------
template<class T>
int mgcLinInterp2D<T>::InTriangle (Vertex& v0, Vertex& v1, Vertex& v2,
Vertex& test)
{
const double eps = 1e-08;
double tx, ty, nx, ny;
// test against normal to first edge
tx = test.x - v0.x;
ty = test.y - v0.y;
nx = v0.y - v1.y;
ny = v1.x - v0.x;
if ( tx*nx + ty*ny < -eps )
return 0;
// test against normal to second edge
tx = test.x - v1.x;
ty = test.y - v1.y;
nx = v1.y - v2.y;
ny = v2.x - v1.x;
if ( tx*nx + ty*ny < -eps )
return 0;
// test against normal to third edge
tx = test.x - v2.x;
ty = test.y - v2.y;
nx = v2.y - v0.y;
ny = v0.x - v2.x;
if ( tx*nx + ty*ny < -eps )
return 0;
return 1;
}
//---------------------------------------------------------------------------
template<class T>
int mgcLinInterp2D<T>::Evaluate (double x, double y, T& F)
{
Vertex ver = { x, y };
// determine which triangle contains the target point
int i;
Vertex v0, v1, v2;
for (i = 0; i < numTriangles; i++)
{
Triangle& t = triangle[i];
v0.x = point[t.vertex[0]][0];
v0.y = point[t.vertex[0]][1];
v1.x = point[t.vertex[1]][0];
v1.y = point[t.vertex[1]][1];
v2.x = point[t.vertex[2]][0];
v2.y = point[t.vertex[2]][1];
if ( InTriangle(v0,v1,v2,ver) )
break;
}
if ( i == numTriangles ) // point is outside interpolation region
{
return 0;
}
Triangle& t = triangle[i]; // (x,y) is in this triangle
// compute barycentric coordinates with respect to subtriangle
double bary[3];
ComputeBarycenter(v0,v1,v2,ver,bary);
// compute barycentric combination of function values at vertices
F = bary[0]*f[t.vertex[0]]+bary[1]*f[t.vertex[1]]+bary[2]*f[t.vertex[2]];
return 1;
}
//---------------------------------------------------------------------------
template<class T>
int mgcLinInterp2D<T>::Delaunay2D ()
{
int result;
const double EPSILON = 1e-12;
const int TSIZE = 75;
const double RANGE = 10.0;
xmin = tmppoint[0][0];
xmax = xmin;
ymin = tmppoint[0][1];
ymax = ymin;
int i;
for (i = 0; i < numPoints; i++)
{
double value = tmppoint[i][0];
if ( xmax < value )
xmax = value;
if ( xmin > value )
xmin = value;
value = tmppoint[i][1];
if ( ymax < value )
ymax = value;
if ( ymin > value )
ymin = value;
}
double xrange = xmax-xmin, yrange = ymax-ymin;
double maxrange = xrange;
if ( maxrange < yrange )
maxrange = yrange;
// need to scale the data later to do a correct triangle count
double maxrange2 = maxrange*maxrange;
// tweak the points by very small random numbers
double bgs = EPSILON*maxrange;
srand(367);
for (i = 0; i < numPoints; i++)
{
tmppoint[i][0] += bgs*(0.5 - rand()/double(RAND_MAX));
tmppoint[i][1] += bgs*(0.5 - rand()/double(RAND_MAX));
}
double wrk[2][3] =
{
{ 5*RANGE, -RANGE, -RANGE },
{ -RANGE, 5*RANGE, -RANGE }
};
for (i = 0; i < 3; i++)
{
tmppoint[numPoints+i][0] = xmin+xrange*wrk[0][i];
tmppoint[numPoints+i][1] = ymin+yrange*wrk[1][i];
}
int i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i11;
int nts, ii[3];
double xx;
int tsz = 2*TSIZE;
int** tmp = new int*[tsz+1];
tmp[0] = new int[2*(tsz+1)];
for (i0 = 1; i0 < tsz+1; i0++)
tmp[i0] = tmp[0] + 2*i0;
i1 = 2*(numPoints + 2);
int* id = new int[i1];
for (i0 = 0; i0 < i1; i0++)
id[i0] = i0;
int** a3s = new int*[i1];
a3s[0] = new int[3*i1];
for (i0 = 1; i0 < i1; i0++)
a3s[i0] = a3s[0] + 3*i0;
a3s[0][0] = numPoints;
a3s[0][1] = numPoints+1;
a3s[0][2] = numPoints+2;
double** ccr = new double*[i1]; // circumscribed centers and radii
ccr[0] = new double[3*i1];
for (i0 = 1; i0 < i1; i0++)
ccr[i0] = ccr[0] + 3*i0;
ccr[0][0] = 0.0;
ccr[0][1] = 0.0;
ccr[0][2] = FLT_MAX;
nts = 1; // number of triangles
i4 = 1;
cout << "[ 40%] create triangulation \r";
// compute triangulation
for (i0 = 0; i0 < numPoints; i0++)
{
i1 = i7 = -1;
i9 = 0;
for (i11 = 0; i11 < nts; i11++)
{
i1++;
while ( a3s[i1][0] < 0 )
i1++;
xx = ccr[i1][2];
for (i2 = 0; i2 < 2; i2++)
{
double z = tmppoint[i0][i2]-ccr[i1][i2];
xx -= z*z;
if ( xx < 0 )
goto Corner3;
}
i9--;
i4--;
id[i4] = i1;
for (i2 = 0; i2 < 3; i2++)
{
ii[0] = 0;
if (ii[0] == i2)
ii[0]++;
for (i3 = 1; i3 < 2; i3++)
{
ii[i3] = ii[i3-1] + 1;
if (ii[i3] == i2)
ii[i3]++;
}
if ( i7 > 1 )
{
i8 = i7;
for (i3 = 0; i3 <= i8; i3++)
{
for (i5 = 0; i5 < 2; i5++)
if ( a3s[i1][ii[i5]] != tmp[i3][i5] )
goto Corner1;
for (i6 = 0; i6 < 2; i6++)
tmp[i3][i6] = tmp[i8][i6];
i7--;
goto Corner2;
Corner1:;
}
}
if ( ++i7 > tsz )
{
// temporary storage exceeded, increase TSIZE
result = 0;
goto ExitDelaunay;
}
for (i3 = 0; i3 < 2; i3++)
tmp[i7][i3] = a3s[i1][ii[i3]];
Corner2:;
}
a3s[i1][0] = -1;
Corner3:;
}
for (i1 = 0; i1 <= i7; i1++)
{
for (i2 = 0; i2 < 2; i2++)
for (wrk[i2][2] = 0, i3 = 0; i3 < 2; i3++)
{
wrk[i2][i3] = tmppoint[tmp[i1][i2]][i3]-tmppoint[i0][i3];
wrk[i2][2] +=
0.5*wrk[i2][i3]*(tmppoint[tmp[i1][i2]][i3]+
tmppoint[i0][i3]);
}
xx = wrk[0][0]*wrk[1][1]-wrk[1][0]*wrk[0][1];
ccr[id[i4]][0] = (wrk[0][2]*wrk[1][1]-wrk[1][2]*wrk[0][1])/xx;
ccr[id[i4]][1] = (wrk[0][0]*wrk[1][2]-wrk[1][0]*wrk[0][2])/xx;
for (ccr[id[i4]][2] = 0, i2 = 0; i2 < 2; i2++)
{
double z = tmppoint[i0][i2]-ccr[id[i4]][i2];
ccr[id[i4]][2] += z*z;
a3s[id[i4]][i2] = tmp[i1][i2];
}
a3s[id[i4]][2] = i0;
i4++;
i9++;
}
nts += i9;
}
// count the number of triangles
cout << "[ 50%] count the number of triangles \r";
numTriangles = 0;
i0 = -1;
for (i11 = 0; i11 < nts; i11++)
{
i0++;
while ( a3s[i0][0] < 0 )
i0++;
if ( a3s[i0][0] < numPoints )
{
for (i1 = 0; i1 < 2; i1++)
for (i2 = 0; i2 < 2; i2++)
wrk[i1][i2] =
tmppoint[a3s[i0][i1]][i2]-tmppoint[a3s[i0][2]][i2];
if ( fabs(wrk[0][0]*wrk[1][1]-wrk[0][1]*wrk[1][0]) > EPSILON*maxrange2 )
numTriangles++;
}
}
// create the triangles
cout << "[ 60%] create the triangles \r";
triangle = new Triangle[numTriangles];
numTriangles = 0;
i0 = -1;
for (i11 = 0; i11 < nts; i11++)
{
i0++;
while ( a3s[i0][0] < 0 )
i0++;
if ( a3s[i0][0] < numPoints )
{
for (i1 = 0; i1 < 2; i1++)
for (i2 = 0; i2 < 2; i2++)
wrk[i1][i2] =
tmppoint[a3s[i0][i1]][i2]-tmppoint[a3s[i0][2]][i2];
xx = wrk[0][0]*wrk[1][1]-wrk[0][1]*wrk[1][0];
if ( fabs(xx) > EPSILON*maxrange2 )
{
int delta = xx < 0 ? 1 : 0;
Triangle& tri = triangle[numTriangles];
tri.vertex[0] = a3s[i0][0];
tri.vertex[1] = a3s[i0][1+delta];
tri.vertex[2] = a3s[i0][2-delta];
tri.adj[0] = -1;
tri.adj[1] = -1;
tri.adj[2] = -1;
numTriangles++;
}
}
}
// build edge table
cout << "[ 70%] build the edge table \r";
numEdges = 0;
edge = new Edge[3*numTriangles];
int j, j0, j1;
for (i = 0; i < numTriangles; i++)
{
if ( (i%500) == 0)
cout << "[ 7" << 10*i/numTriangles << "%] build the edge table \r";
Triangle& t = triangle[i];
for (j0 = 0, j1 = 1; j0 < 3; j0++, j1 = (j1+1)%3)
{
for (j = 0; j < numEdges; j++)
{
Edge& e = edge[j];
if ( (t.vertex[j0] == e.vertex[0]
&& t.vertex[j1] == e.vertex[1])
|| (t.vertex[j0] == e.vertex[1]
&& t.vertex[j1] == e.vertex[0]) )
break;
}
if ( j == numEdges ) // add edge to table
{
edge[j].vertex[0] = t.vertex[j0];
edge[j].vertex[1] = t.vertex[j1];
edge[j].triangle[0] = i;
edge[j].index[0] = j0;
edge[j].triangle[1] = -1;
numEdges++;
}
else // edge already exists, add triangle to table
{
edge[j].triangle[1] = i;
edge[j].index[1] = j0;
}
}
}
// establish links between adjacent triangles
cout << "[ 80%] establishing links between adjacent triangles \r";
for (i = 0; i < numEdges; i++)
{
if ( edge[i].triangle[1] != -1 )
{
j0 = edge[i].triangle[0];
j1 = edge[i].triangle[1];
triangle[j0].adj[edge[i].index[0]] = j1;
triangle[j1].adj[edge[i].index[1]] = j0;
}
}
result = 1;
ExitDelaunay:;
delete[] tmp[0];
delete[] tmp;
delete[] id;
delete[] a3s[0];
delete[] a3s;
delete[] ccr[0];
delete[] ccr;
cout << "[ 90%] finsishes delauney triangulation \r";
return result;
}
//---------------------------------------------------------------------------
template<class T>
void mgcLinInterp2D<T>::GetPoint (int i, double& x, double& y)
{
// assumes i is valid [can use PointCount() before passing i]
x = point[i][0];
y = point[i][1];
}
//---------------------------------------------------------------------------
template<class T>
void mgcLinInterp2D<T>::GetEdge (int i, double& x0, double& y0, double& x1,
double& y1)
{
// assumes i is valid [can use EdgeCount() before passing i]
int v0 = edge[i].vertex[0], v1 = edge[i].vertex[1];
x0 = point[v0][0];
y0 = point[v0][1];
x1 = point[v1][0];
y1 = point[v1][1];
}
//---------------------------------------------------------------------------
template<class T>
void mgcLinInterp2D<T>::GetTriangle (int i, double& x0, double& y0, double& x1,
double& y1, double& x2, double& y2)
{
// assumes i is valid [can use TriangleCount() before passing i]
int v0 = triangle[i].vertex[0];
int v1 = triangle[i].vertex[1];
int v2 = triangle[i].vertex[2];
x0 = point[v0][0];
y0 = point[v0][1];
x1 = point[v1][0];
y1 = point[v1][1];
x2 = point[v2][0];
y2 = point[v2][1];
}
//---------------------------------------------------------------------------

233
simgear/math/mat3.h Normal file
View File

@@ -0,0 +1,233 @@
/* Copyright 1988, Brown Computer Graphics Group. All Rights Reserved. */
/* -------------------------------------------------------------------------
Public MAT3 include file
------------------------------------------------------------------------- */
#ifndef MAT3_HAS_BEEN_INCLUDED
#define MAT3_HAS_BEEN_INCLUDED
/* ----------------------------- Constants ------------------------------ */
/*
* Make sure the math library .h file is included, in case it wasn't.
*/
#ifndef HUGE
#include <math.h>
#endif
#include <stdio.h>
#include <string.h>
#include <simgear/math/fg_memory.h>
#ifdef __cplusplus
extern "C" {
#endif
#define MAT3_DET0 -1 /* Indicates singular mat */
#define MAT3_EPSILON 1e-12 /* Close enough to zero */
#ifdef M_PI
# define MAT3_PI M_PI
#else
# define MAT3_PI 3.14159265358979323846
#endif
#define USE_XTRA_MAT3_INLINES
#if defined(i386)
#define USE_X86_ASM
#endif
#if defined(USE_X86_ASM)
static __inline__ int FloatToInt(float f)
{
int r;
__asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st");
return r;
}
#elif defined(__MSC__) && defined(__WIN32__)
static __inline int FloatToInt(float f)
{
int r;
_asm {
fld f
fistp r
}
return r;
}
#else
#define FloatToInt(F) ((int) ((F) < 0.0f ? (F)-0.5f : (F)+0.5f))
#endif
/* ------------------------------ Types --------------------------------- */
typedef double MAT3mat[4][4]; /* 4x4 matrix */
typedef double MAT3vec[3]; /* Vector */
typedef double MAT3hvec[4]; /* Vector with homogeneous coord */
/* ------------------------------ Macros -------------------------------- */
extern MAT3mat identityMatrix;
/* Tests if a number is within EPSILON of zero */
#define MAT3_IS_ZERO(N) ((N) < MAT3_EPSILON && (N) > -MAT3_EPSILON)
/* Sets a vector to the three given values */
#define MAT3_SET_VEC(V,X,Y,Z) ((V)[0]=(X), (V)[1]=(Y), (V)[2]=(Z))
/* Tests a vector for all components close to zero */
#define MAT3_IS_ZERO_VEC(V) (MAT3_IS_ZERO((V)[0]) && \
MAT3_IS_ZERO((V)[1]) && \
MAT3_IS_ZERO((V)[2]))
/* Dot product of two vectors */
#define MAT3_DOT_PRODUCT(V1,V2) \
((V1)[0]*(V2)[0] + (V1)[1]*(V2)[1] + (V1)[2]*(V2)[2])
/* Copy one vector to other */
#define MAT3_COPY_VEC(TO,FROM) ((TO)[0] = (FROM)[0], \
(TO)[1] = (FROM)[1], \
(TO)[2] = (FROM)[2])
/* Normalize vector to unit length, using TEMP as temporary variable.
* TEMP will be zero if vector has zero length */
#define MAT3_NORMALIZE_VEC(V,TEMP) \
if ((TEMP = sqrt(MAT3_DOT_PRODUCT(V,V))) > MAT3_EPSILON) { \
TEMP = 1.0 / TEMP; \
MAT3_SCALE_VEC(V,V,TEMP); \
} else TEMP = 0.0
/* Scale vector by given factor, storing result vector in RESULT_V */
#define MAT3_SCALE_VEC(RESULT_V,V,SCALE) \
MAT3_SET_VEC(RESULT_V, (V)[0]*(SCALE), (V)[1]*(SCALE), (V)[2]*(SCALE))
/* Adds vectors V1 and V2, storing result in RESULT_V */
#define MAT3_ADD_VEC(RESULT_V,V1,V2) \
MAT3_SET_VEC(RESULT_V, (V1)[0]+(V2)[0], (V1)[1]+(V2)[1], \
(V1)[2]+(V2)[2])
/* Subtracts vector V2 from V1, storing result in RESULT_V */
#define MAT3_SUB_VEC(RESULT_V,V1,V2) \
MAT3_SET_VEC(RESULT_V, (V1)[0]-(V2)[0], (V1)[1]-(V2)[1], \
(V1)[2]-(V2)[2])
/* Multiplies vectors V1 and V2, storing result in RESULT_V */
#define MAT3_MULT_VEC(RESULT_V,V1,V2) \
MAT3_SET_VEC(RESULT_V, (V1)[0]*(V2)[0], (V1)[1]*(V2)[1], \
(V1)[2]*(V2)[2])
/* Sets RESULT_V to the linear combination of V1 and V2, scaled by
* SCALE1 and SCALE2, respectively */
#define MAT3_LINEAR_COMB(RESULT_V,SCALE1,V1,SCALE2,V2) \
MAT3_SET_VEC(RESULT_V, (SCALE1)*(V1)[0] + (SCALE2)*(V2)[0], \
(SCALE1)*(V1)[1] + (SCALE2)*(V2)[1], \
(SCALE1)*(V1)[2] + (SCALE2)*(V2)[2])
/* Several of the vector macros are useful for homogeneous-coord vectors */
#define MAT3_SET_HVEC(V,X,Y,Z,W) ((V)[0]=(X), (V)[1]=(Y), \
(V)[2]=(Z), (V)[3]=(W))
#define MAT3_COPY_HVEC(TO,FROM) ((TO)[0] = (FROM)[0], \
(TO)[1] = (FROM)[1], \
(TO)[2] = (FROM)[2], \
(TO)[3] = (FROM)[3])
#define MAT3_SCALE_HVEC(RESULT_V,V,SCALE) \
MAT3_SET_HVEC(RESULT_V, (V)[0]*(SCALE), (V)[1]*(SCALE), \
(V)[2]*(SCALE), (V)[3]*(SCALE))
#define MAT3_ADD_HVEC(RESULT_V,V1,V2) \
MAT3_SET_HVEC(RESULT_V, (V1)[0]+(V2)[0], (V1)[1]+(V2)[1], \
(V1)[2]+(V2)[2], (V1)[3]+(V2)[3])
#define MAT3_SUB_HVEC(RESULT_V,V1,V2) \
MAT3_SET_HVEC(RESULT_V, (V1)[0]-(V2)[0], (V1)[1]-(V2)[1], \
(V1)[2]-(V2)[2], (V1)[3]-(V2)[3])
#define MAT3_MULT_HVEC(RESULT_V,V1,V2) \
MAT3_SET_HVEC(RESULT_V, (V1)[0]*(V2)[0], (V1)[1]*(V2)[1], \
(V1)[2]*(V2)[2], (V1)[3]*(V2)[3])
/* ------------------------------ Entries ------------------------------- */
#define MAT3identity(mat) fgmemcpy( mat, identityMatrix, sizeof(MAT3mat) )
#define MAT3zero(mat) fgmemzero( mat, sizeof(MAT3mat) )
#define MAT3copy(to, from) fgmemcpy( to, from, sizeof(MAT3mat) )
#if defined( USE_XTRA_MAT3_INLINES )
# define MAT3mult_vec( result_vec, vec, mat) { \
MAT3vec tempvec; \
tempvec[0]=vec[0]*mat[0][0]+vec[1]*mat[1][0]+vec[2]*mat[2][0]+mat[3][0]; \
tempvec[1]=vec[0]*mat[0][1]+vec[1]*mat[1][1]+vec[2]*mat[2][1]+mat[3][1]; \
tempvec[2]=vec[0]*mat[0][2]+vec[1]*mat[1][2]+vec[2]*mat[2][2]+mat[3][2]; \
result_vec[0] = tempvec[0]; \
result_vec[1] = tempvec[1]; \
result_vec[2] = tempvec[2]; \
}
# define MAT3cross_product(result_vec, vec1, vec2) { \
MAT3vec tempvec; \
tempvec[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1]; \
tempvec[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2]; \
tempvec[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0]; \
result_vec[0] = tempvec[0]; \
result_vec[1] = tempvec[1]; \
result_vec[2] = tempvec[2]; \
}
# define MAT3mult( result_mat, mat1, mat2) { \
register int i, j; \
MAT3mat tmp_mat; \
for (i = 0; i < 4; i++) \
for (j = 0; j < 4; j++) \
tmp_mat[i][j] = (mat1[i][0] * mat2[0][j] + \
mat1[i][1] * mat2[1][j] + \
mat1[i][2] * mat2[2][j] + \
mat1[i][3] * mat2[3][j]); \
fgmemcpy(result_mat, tmp_mat, sizeof(MAT3mat)); \
}
#else // !defined( USE_XTRA_MAT3_INLINES )
/* In MAT3mat.c */
void MAT3mult(MAT3mat result, MAT3mat, MAT3mat);
void MAT3mult_vec(MAT3vec result_vec, MAT3vec vec, MAT3mat mat);
void MAT3cross_product(MAT3vec result,MAT3vec,MAT3vec);
#endif // defined( USE_XTRA_MAT3_INLINES )
/* In MAT3geom.c */
void MAT3direction_matrix (MAT3mat result_mat, MAT3mat mat);
int MAT3normal_matrix (MAT3mat result_mat, MAT3mat mat);
void MAT3rotate (MAT3mat result_mat, MAT3vec axis, double angle_in_radians);
void MAT3translate (MAT3mat result_mat, MAT3vec trans);
void MAT3scale (MAT3mat result_mat, MAT3vec scale);
void MAT3shear(MAT3mat result_mat, double xshear, double yshear);
void MAT3transpose (MAT3mat result, MAT3mat);
int MAT3invert (MAT3mat result, MAT3mat);
void MAT3print (MAT3mat, FILE *fp);
void MAT3print_formatted (MAT3mat, FILE *fp,
char *title, char *head, char *format, char *tail);
int MAT3equal( void );
double MAT3trace( void );
int MAT3power( void );
int MAT3column_reduce( void );
int MAT3kernel_basis( void );
/* In MAT3vec.c */
int MAT3mult_hvec (MAT3hvec result_vec, MAT3hvec vec, MAT3mat mat, int normalize);
void MAT3perp_vec(MAT3vec result_vec, MAT3vec vec, int is_unit);
#ifdef __cplusplus
}
#endif
#endif /* MAT3_HAS_BEEN_INCLUDED */

56
simgear/math/mat3defs.h Normal file
View File

@@ -0,0 +1,56 @@
/* Copyright 1988, Brown Computer Graphics Group. All Rights Reserved. */
#ifndef _MAT3DEFS_H
#define _MAT3DEFS_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
/* #include <Math/mat3err.h> */
#include "mat3.h"
/* ----------------------------- Constants ------------------------------ */
#define FALSE 0
#define TRUE 1
#define CNULL ((char *) NULL)
/* ------------------------------ Macros -------------------------------- */
#define ALLOCN(P,T,N,M) \
if ((P = (T *) malloc((unsigned) (N) * sizeof(T))) == NULL) \
ERR_ERROR(MAT3_errid, ERR_FATAL, (ERR_ALLOC1, M)); \
else
#define FREE(P) free((char *) (P))
#define ABS(A) ((A) > 0 ? (A) : -(A))
#define MIN(A,B) ((A) < (B) ? (A) : (B))
#define MAX(A,B) ((A) > (B) ? (A) : (B))
#define SWAP(A,B,T) (T = A, A = B, B = T)
/* Is N within EPS of zero ? */
#define IS_ZERO(N,EPS) ((N) < EPS && (N) > -EPS)
/* Macros for lu routines */
#define LU_PERMUTE(p,i,j) { int LU_T; LU_T = p[i]; p[i] = p[j]; p[j] = LU_T; }
/* ------------------------- Internal Entries ---------------------------- */
/* ------------------------- Global Variables ---------------------------- */
/* extern ERRid *MAT3_errid; */
#ifdef __cplusplus
}
#endif
#endif /* _MAT3DEFS_H */

41
simgear/math/mat3err.h Normal file
View File

@@ -0,0 +1,41 @@
#ifndef _MAT3ERR_H
#define _MAT3ERR_H
#ifdef __cplusplus
extern "C" {
#endif
#include "sph_errtypes.h"
#ifdef THINK_C
/* We hide this from gnu's compiler, which doesn't understand it. */
void SPH__error (int errtype, ...);
#endif
#define ERR_ERROR(A,B,C) \
if (1) {char cstr[256]; sprintf C; SPH__error(ERR_MAT3_PACKAGE, cstr); } else
#define ERR_S cstr,"%s\n"
#define ERR_SI cstr,"%s: %d\n"
#define ERR_SS cstr,"%s: %s\n"
#define ERR_SEVERE 0
#define ERR_FATAL 0
#define ERR_ALLOC1 0
typedef int ERRid;
#define ERRregister_package(S) 100
#ifdef __cplusplus
}
#endif
#endif /* _MAT3ERR_H */

341
simgear/math/point3d.hxx Normal file
View File

@@ -0,0 +1,341 @@
// point3d.hxx -- a 3d point class.
//
// Adapted from algebra3 by Jean-Francois Doue, started October 1998.
//
// Copyright (C) 1998 Curtis L. Olson - curt@me.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 _POINT3D_HXX
#define _POINT3D_HXX
#ifndef __cplusplus
# error This library requires C++
#endif
#include <simgear/compiler.h>
#ifdef FG_MATH_EXCEPTION_CLASH
# define exception c_exception
#endif
#ifdef FG_HAVE_STD_INCLUDES
# include <iostream>
# include <cassert>
# include <cmath>
#else
# include <iostream.h>
# include <assert.h>
# include <math.h>
#endif
// 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
#ifdef __MWERKS__
FG_USING_NAMESPACE(std);
#endif
#ifndef FG_HAVE_NATIVE_SGI_COMPILERS
FG_USING_STD(ostream);
FG_USING_STD(istream);
#endif
const double fgPoint3_Epsilon = 0.0000001;
enum {PX, PY, PZ}; // axes
// Kludge for msvc++ 6.0 - requires forward decls of friend functions.
class Point3D;
istream& operator>> ( istream&, Point3D& );
ostream& operator<< ( ostream&, const Point3D& );
Point3D operator- (const Point3D& p); // -p1
bool operator== (const Point3D& a, const Point3D& b); // p1 == p2?
///////////////////////////
//
// 3D Point
//
///////////////////////////
class Point3D {
protected:
double n[3];
public:
// Constructors
Point3D();
Point3D(const double x, const double y, const double z);
explicit Point3D(const double d);
Point3D(const Point3D &p);
// Assignment operators
Point3D& operator = ( const Point3D& p ); // assignment of a Point3D
Point3D& operator += ( const Point3D& p ); // incrementation by a Point3D
Point3D& operator -= ( const Point3D& p ); // decrementation by a Point3D
Point3D& operator *= ( const double d ); // multiplication by a constant
Point3D& operator /= ( const double d ); // division by a constant
void setx(const double x);
void sety(const double y);
void setz(const double z);
// Queries
double& operator [] ( int i); // indexing
double operator[] (int i) const; // read-only indexing
inline const double *get_n() const { return n; };
double x() const; // cartesian x
double y() const; // cartesian y
double z() const; // cartesian z
double lon() const; // polar longitude
double lat() const; // polar latitude
double radius() const; // polar radius
double elev() const; // geodetic elevation (if specifying a surface point)
// friends
friend Point3D operator - (const Point3D& p); // -p1
friend bool operator == (const Point3D& a, const Point3D& b); // p1 == p2?
friend istream& operator>> ( istream&, Point3D& );
friend ostream& operator<< ( ostream&, const Point3D& );
// Special functions
double distance3D(const Point3D& a) const; // distance between
double distance3Dsquared(const Point3D& a) const; // distance between ^ 2
};
// input from stream
inline istream&
operator >> ( istream& in, Point3D& p)
{
char c;
in >> p.n[PX];
// read past optional comma
while ( in.get(c) ) {
if ( (c != ' ') && (c != ',') ) {
// push back on the stream
in.putback(c);
break;
}
}
in >> p.n[PY];
// read past optional comma
while ( in.get(c) ) {
if ( (c != ' ') && (c != ',') ) {
// push back on the stream
in.putback(c);
break;
}
}
in >> p.n[PZ];
return in;
}
inline ostream&
operator<< ( ostream& out, const Point3D& p )
{
return out << p.n[PX] << ", " << p.n[PY] << ", " << p.n[PZ];
}
///////////////////////////
//
// Point3D Member functions
//
///////////////////////////
// CONSTRUCTORS
inline Point3D::Point3D() {}
inline Point3D::Point3D(const double x, const double y, const double z)
{
n[PX] = x; n[PY] = y; n[PZ] = z;
}
inline Point3D::Point3D(const double d)
{
n[PX] = n[PY] = n[PZ] = d;
}
inline Point3D::Point3D(const Point3D& p)
{
n[PX] = p.n[PX]; n[PY] = p.n[PY]; n[PZ] = p.n[PZ];
}
// ASSIGNMENT OPERATORS
inline Point3D& Point3D::operator = (const Point3D& p)
{
n[PX] = p.n[PX]; n[PY] = p.n[PY]; n[PZ] = p.n[PZ]; return *this;
}
inline Point3D& Point3D::operator += ( const Point3D& p )
{
n[PX] += p.n[PX]; n[PY] += p.n[PY]; n[PZ] += p.n[PZ]; return *this;
}
inline Point3D& Point3D::operator -= ( const Point3D& p )
{
n[PX] -= p.n[PX]; n[PY] -= p.n[PY]; n[PZ] -= p.n[PZ]; return *this;
}
inline Point3D& Point3D::operator *= ( const double d )
{
n[PX] *= d; n[PY] *= d; n[PZ] *= d; return *this;
}
inline Point3D& Point3D::operator /= ( const double d )
{
double d_inv = 1./d; n[PX] *= d_inv; n[PY] *= d_inv; n[PZ] *= d_inv;
return *this;
}
inline void Point3D::setx(const double x) {
n[PX] = x;
}
inline void Point3D::sety(const double y) {
n[PY] = y;
}
inline void Point3D::setz(const double z) {
n[PZ] = z;
}
// QUERIES
inline double& Point3D::operator [] ( int i)
{
assert(! (i < PX || i > PZ));
return n[i];
}
inline double Point3D::operator [] ( int i) const {
assert(! (i < PX || i > PZ));
return n[i];
}
inline double Point3D::x() const { return n[PX]; }
inline double Point3D::y() const { return n[PY]; }
inline double Point3D::z() const { return n[PZ]; }
inline double Point3D::lon() const { return n[PX]; }
inline double Point3D::lat() const { return n[PY]; }
inline double Point3D::radius() const { return n[PZ]; }
inline double Point3D::elev() const { return n[PZ]; }
// FRIENDS
inline Point3D operator - (const Point3D& a)
{
return Point3D(-a.n[PX],-a.n[PY],-a.n[PZ]);
}
inline Point3D operator + (const Point3D& a, const Point3D& b)
{
return Point3D(a) += b;
}
inline Point3D operator - (const Point3D& a, const Point3D& b)
{
return Point3D(a) -= b;
}
inline Point3D operator * (const Point3D& a, const double d)
{
return Point3D(a) *= d;
}
inline Point3D operator * (const double d, const Point3D& a)
{
return a*d;
}
inline Point3D operator / (const Point3D& a, const double d)
{
return Point3D(a) *= (1.0 / d );
}
inline bool operator == (const Point3D& a, const Point3D& b)
{
return
fabs(a.n[PX] - b.n[PX]) < fgPoint3_Epsilon &&
fabs(a.n[PY] - b.n[PY]) < fgPoint3_Epsilon &&
fabs(a.n[PZ] - b.n[PZ]) < fgPoint3_Epsilon;
}
inline bool operator != (const Point3D& a, const Point3D& b)
{
return !(a == b);
}
// Special functions
inline double
Point3D::distance3D(const Point3D& a ) const
{
double x, y, z;
x = n[PX] - a.n[PX];
y = n[PY] - a.n[PY];
z = n[PZ] - a.n[PZ];
return sqrt(x*x + y*y + z*z);
}
inline double
Point3D::distance3Dsquared(const Point3D& a ) const
{
double x, y, z;
x = n[PX] - a.n[PX];
y = n[PY] - a.n[PY];
z = n[PZ] - a.n[PZ];
return(x*x + y*y + z*z);
}
#endif // _POINT3D_HXX

61
simgear/math/polar3d.cxx Normal file
View File

@@ -0,0 +1,61 @@
// polar.cxx -- routines to deal with polar math and transformations
//
// Written by Curtis Olson, started June 1997.
//
// Copyright (C) 1997 Curtis L. Olson - curt@infoplane.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.
//
// 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 <math.h>
#include <stdio.h>
#include <simgear/constants.h>
#include "polar3d.hxx"
// 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 t_lat, x_alpha, mu_alpha;
double lat_geoc, radius;
double result;
lat_geoc = FG_PI_2 - atan2( sqrt(cp.x()*cp.x() + cp.y()*cp.y()), cp.z() );
radius = sqrt( cp.x()*cp.x() + cp.y()*cp.y() + cp.z()*cp.z() );
if( ( (FG_PI_2 - lat_geoc) < ONE_SECOND ) // near North pole
|| ( (FG_PI_2 + lat_geoc) < ONE_SECOND ) ) // near South pole
{
result = radius - EQUATORIAL_RADIUS_M*E;
} else {
t_lat = tan(lat_geoc);
x_alpha = E*EQUATORIAL_RADIUS_M/sqrt(t_lat*t_lat + E*E);
mu_alpha = atan2(sqrt(RESQ_M - x_alpha*x_alpha),E*x_alpha);
if (lat_geoc < 0) {
mu_alpha = - mu_alpha;
}
result = (radius - x_alpha/cos(lat_geoc))*cos(mu_alpha - lat_geoc);
}
return(result);
}

101
simgear/math/polar3d.hxx Normal file
View File

@@ -0,0 +1,101 @@
// polar.hxx -- routines to deal with polar math and transformations
//
// Written by Curtis Olson, started June 1997.
//
// Copyright (C) 1997 Curtis L. Olson - curt@infoplane.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.
//
// 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 _POLAR_HXX
#define _POLAR_HXX
#ifndef __cplusplus
# error This library requires C++
#endif
#include <simgear/constants.h>
#include <simgear/math/point3d.hxx>
// Find the Altitude above the Ellipsoid (WGS84) given the Earth
// Centered Cartesian coordinate vector Distances are specified in
// meters.
double fgGeodAltFromCart(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
// to be specified in meters
inline Point3D fgPolarToCart3d(const Point3D& p) {
double tmp = cos( p.lat() ) * p.radius();
return Point3D( cos( p.lon() ) * tmp,
sin( p.lon() ) * tmp,
sin( p.lat() ) * p.radius() );
}
// Convert a cartesian coordinate to polar coordinates (lon/lat
// specified in radians. Distances are specified in meters.
inline Point3D fgCartToPolar3d(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() ),
sqrt(cp.x()*cp.x() + cp.y()*cp.y() + cp.z()*cp.z()) );
}
// calc new lon/lat given starting lon/lat, and offset radial, and
// distance. NOTE: starting point is specifed in radians, distance is
// specified in meters (and converted internally to radians)
// ... assumes a spherical world
inline Point3D calc_lon_lat( const Point3D& orig, double course, double dist ) {
Point3D result;
// lat=asin(sin(lat1)*cos(d)+cos(lat1)*sin(d)*cos(tc))
// IF (cos(lat)=0)
// lon=lon1 // endpoint a pole
// ELSE
// lon=mod(lon1-asin(sin(tc)*sin(d)/cos(lat))+pi,2*pi)-pi
// ENDIF
// printf("calc_lon_lat() offset.theta = %.2f offset.dist = %.2f\n",
// offset.theta, offset.dist);
dist *= METER_TO_NM * NM_TO_RAD;
result.sety( asin( sin(orig.y()) * cos(dist) +
cos(orig.y()) * sin(dist) * cos(course) ) );
if ( cos(result.y()) < FG_EPSILON ) {
result.setx( orig.x() ); // endpoint a pole
} else {
result.setx(
fmod(orig.x() - asin( sin(course) * sin(dist) /
cos(result.y()) ) + FG_PI, FG_2PI) - FG_PI );
}
return result;
}
#endif // _POLAR_HXX

78
simgear/math/sphrintp.h Normal file
View File

@@ -0,0 +1,78 @@
/*
WARNING - Do not remove this header.
This code is a templated version of the 'magic-software' spherical
interpolation code by Dave Eberly. The original (un-hacked) code can be
obtained from here: http://www.magic-software.com/gr_appr.htm
This code is derived from linintp2.h/cpp and sphrintp.h/cpp.
Dave Eberly says that the conditions for use are:
* You may distribute the original source code to others at no charge.
* You may modify the original source code and distribute it to others at
no charge. The modified code must be documented to indicate that it is
not part of the original package.
* You may use this code for non-commercial purposes. You may also
incorporate this code into commercial packages. However, you may not
sell any of your source code which contains my original and/or modified
source code. In such a case, you need to factor out my code and freely
distribute it.
* The original code comes with absolutely no warranty and no guarantee is
made that the code is bug-free.
This does not seem incompatible with GPL - so this modified version
is hereby placed under GPL along with the rest of FlightGear.
Christian Mayer
*/
#ifndef SPHRINTP_H
#define SPHRINTP_H
#include "linintp2.h"
#include <plib/sg.h>
template<class T>
class SphereInterpolate
{
public:
SphereInterpolate (int n, const double* x, const double* y,
const double* z, const T* f);
SphereInterpolate (int n, const sgVec2* p, const T* f);
~SphereInterpolate ();
void GetSphericalCoords (const double x, const double y, const double z,
double& thetaAngle, double& phiAngle) const;
int Evaluate (const double x, const double y, const double z, T& f) const;
int Evaluate (const double thetaAngle, const double phiAngle, T& f) const;
T Evaluate(const sgVec2& p) const
{
T retval;
Evaluate(p[1], p[0], retval);
return retval;
}
T Evaluate(const sgVec3& p) const
{
T retval;
Evaluate(p[1], p[0], retval);
return retval;
}
protected:
int numPoints;
double* theta;
double* phi;
T* func;
mgcLinInterp2D<T>* pInterp;
};
#include "sphrintp.inl"
#endif

172
simgear/math/sphrintp.inl Normal file
View File

@@ -0,0 +1,172 @@
/*
WARNING - Do not remove this header.
This code is a templated version of the 'magic-software' spherical
interpolation code by Dave Eberly. The original (un-hacked) code can be
obtained from here: http://www.magic-software.com/gr_appr.htm
This code is derived from linintp2.h/cpp and sphrintp.h/cpp.
Dave Eberly says that the conditions for use are:
* You may distribute the original source code to others at no charge.
* You may modify the original source code and distribute it to others at
no charge. The modified code must be documented to indicate that it is
not part of the original package.
* You may use this code for non-commercial purposes. You may also
incorporate this code into commercial packages. However, you may not
sell any of your source code which contains my original and/or modified
source code. In such a case, you need to factor out my code and freely
distribute it.
* The original code comes with absolutely no warranty and no guarantee is
made that the code is bug-free.
This does not seem incompatible with GPL - so this modified version
is hereby placed under GPL along with the rest of FlightGear.
Christian Mayer
*/
#include <math.h>
#include "sphrintp.h"
static const double PI = 4.0*atan(1.0);
static const double TWOPI = 2.0*PI;
//---------------------------------------------------------------------------
template<class T>
SphereInterpolate<T>::SphereInterpolate (int n, const double* x,
const double* y, const double* z,
const T* f)
{
// Assumes (x[i],y[i],z[i]) is unit length for all 0 <= i < n.
// For complete spherical coverage, include the two antipodal points
// (0,0,1,f(0,0,1)) and (0,0,-1,f(0,0,-1)) in the data set.
cout << "Initialising spherical interpolator.\n";
cout << "[ 0%] Allocating memory \r";
theta = new double[3*n];
phi = new double[3*n];
func = new T[3*n];
// convert data to spherical coordinates
int i;
T empty;
for (i = 0; i < n; i++)
{
GetSphericalCoords(x[i],y[i],z[i],theta[i],phi[i]);
func[i] = f[i];
}
// use periodicity to get wrap-around in the Delaunay triangulation
cout << "[ 10%] copying vertices for wrap-around\r";
int j, k;
for (i = 0, j = n, k = 2*n; i < n; i++, j++, k++)
{
theta[j] = theta[i]+TWOPI;
theta[k] = theta[i]-TWOPI;
phi[j] = phi[i];
phi[k] = phi[i];
func[j] = func[i];
func[k] = func[i];
}
pInterp = new mgcLinInterp2D<T>(3*n,theta,phi,func);
cout << "[100%] Finished initialising spherical interpolator. \n";
}
template<class T>
SphereInterpolate<T>::SphereInterpolate (int n, const sgVec2* p, const T* f)
{
// Assumes (x[i],y[i],z[i]) is unit length for all 0 <= i < n.
// For complete spherical coverage, include the two antipodal points
// (0,0,1,f(0,0,1)) and (0,0,-1,f(0,0,-1)) in the data set.
cout << "Initialising spherical interpolator.\n";
cout << "[ 0%] Allocating memory \r";
theta = new double[3*n];
phi = new double[3*n];
func = new T[3*n];
// convert data to spherical coordinates
cout << "[ 10%] copying vertices for wrap-around \r";
int i, j, k;
for (i = 0, j = n, k = 2*n; i < n; i++, j++, k++)
{
phi[i] = p[i][0];
theta[i] = p[i][1];
func[i] = f[i];
// use periodicity to get wrap-around in the Delaunay triangulation
phi[j] = phi[i];
phi[k] = phi[i];
theta[j] = theta[i]+TWOPI;
theta[k] = theta[i]-TWOPI;
func[j] = func[i];
func[k] = func[i];
}
pInterp = new mgcLinInterp2D<T>(3*n,theta,phi,func);
cout << "[100%] Finished initialising spherical interpolator. \n";
}
//---------------------------------------------------------------------------
template<class T>
SphereInterpolate<T>::~SphereInterpolate ()
{
delete pInterp;
delete[] theta;
delete[] phi;
delete[] func;
}
//---------------------------------------------------------------------------
template<class T>
void SphereInterpolate<T>::GetSphericalCoords (const double x, const double y, const double z,
double& thetaAngle,
double& phiAngle) const
{
// Assumes (x,y,z) is unit length. Returns -PI <= thetaAngle <= PI
// and 0 <= phiAngle <= PI.
if ( z < 1.0f )
{
if ( z > -1.0f )
{
thetaAngle = atan2(y,x);
phiAngle = acos(z);
}
else
{
thetaAngle = -PI;
phiAngle = PI;
}
}
else
{
thetaAngle = -PI;
phiAngle = 0.0f;
}
}
//---------------------------------------------------------------------------
template<class T>
int SphereInterpolate<T>::Evaluate (const double x, const double y, const double z, T& f) const
{
// assumes (x,y,z) is unit length
double thetaAngle, phiAngle;
GetSphericalCoords(x,y,z,thetaAngle,phiAngle);
return pInterp->Evaluate(thetaAngle,phiAngle,f);
}
//---------------------------------------------------------------------------
template<class T>
int SphereInterpolate<T>::Evaluate (const double thetaAngle, const double phiAngle, T& f) const
{
return pInterp->Evaluate(thetaAngle,phiAngle,f);
}
//---------------------------------------------------------------------------

179
simgear/math/vector.cxx Normal file
View File

@@ -0,0 +1,179 @@
// vector.cxx -- additional vector routines
//
// Written by Curtis Olson, started December 1997.
//
// Copyright (C) 1997 Curtis L. Olson - curt@infoplane.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.
//
// 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 <math.h>
#include <stdio.h>
// #include <Include/fg_types.h>
#include "vector.hxx"
#include "mat3.h"
// Map a vector onto the plane specified by normal
void map_vec_onto_cur_surface_plane(MAT3vec normal, MAT3vec v0, MAT3vec vec,
MAT3vec result)
{
MAT3vec u1, v, tmp;
// calculate a vector "u1" representing the shortest distance from
// the plane specified by normal and v0 to a point specified by
// "vec". "u1" represents both the direction and magnitude of
// this desired distance.
// u1 = ( (normal <dot> vec) / (normal <dot> normal) ) * normal
MAT3_SCALE_VEC( u1,
normal,
( MAT3_DOT_PRODUCT(normal, vec) /
MAT3_DOT_PRODUCT(normal, normal)
)
);
// printf(" vec = %.2f, %.2f, %.2f\n", vec[0], vec[1], vec[2]);
// printf(" v0 = %.2f, %.2f, %.2f\n", v0[0], v0[1], v0[2]);
// printf(" u1 = %.2f, %.2f, %.2f\n", u1[0], u1[1], u1[2]);
// calculate the vector "v" which is the vector "vec" mapped onto
// the plane specified by "normal" and "v0".
// v = v0 + vec - u1
MAT3_ADD_VEC(tmp, v0, vec);
MAT3_SUB_VEC(v, tmp, u1);
// printf(" v = %.2f, %.2f, %.2f\n", v[0], v[1], v[2]);
// Calculate the vector "result" which is "v" - "v0" which is a
// directional vector pointing from v0 towards v
// result = v - v0
MAT3_SUB_VEC(result, v, v0);
// printf(" result = %.2f, %.2f, %.2f\n",
// result[0], result[1], result[2]);
}
// Given a point p, and a line through p0 with direction vector d,
// find the shortest distance from the point to the line
double fgPointLine(MAT3vec p, MAT3vec p0, MAT3vec d) {
MAT3vec u, u1, v;
double ud, dd, tmp;
// u = p - p0
MAT3_SUB_VEC(u, p, p0);
// calculate the projection, u1, of u along d.
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
ud = MAT3_DOT_PRODUCT(u, d);
dd = MAT3_DOT_PRODUCT(d, d);
tmp = ud / dd;
MAT3_SCALE_VEC(u1, d, tmp);;
// v = u - u1 = vector from closest point on line, p1, to the
// original point, p.
MAT3_SUB_VEC(v, u, u1);
return sqrt(MAT3_DOT_PRODUCT(v, v));
}
// 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 fgPointLineSquared(MAT3vec p, MAT3vec p0, MAT3vec d) {
MAT3vec u, u1, v;
double ud, dd, tmp;
// u = p - p0
MAT3_SUB_VEC(u, p, p0);
// calculate the projection, u1, of u along d.
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
ud = MAT3_DOT_PRODUCT(u, d);
dd = MAT3_DOT_PRODUCT(d, d);
tmp = ud / dd;
MAT3_SCALE_VEC(u1, d, tmp);;
// v = u - u1 = vector from closest point on line, p1, to the
// original point, p.
MAT3_SUB_VEC(v, u, u1);
return ( MAT3_DOT_PRODUCT(v, v) );
}
// 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 ) {
sgVec3 u, u1, v;
double ud, dd, tmp;
// 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;
ud = sgScalarProductVec3(u, d);
dd = sgScalarProductVec3(d, d);
tmp = ud / dd;
sgScaleVec3(u1, d, tmp);;
// v = u - u1 = vector from closest point on line, p1, to the
// original point, p.
sgSubVec3(v, u, u1);
return ( sgScalarProductVec3(v, v) );
}
// 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 ) {
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;
sgdScaleVec3(u1, d, tmp);;
// v = u - u1 = vector from closest point on line, p1, to the
// original point, p.
sgdSubVec3(v, u, u1);
return ( sgdScalarProductVec3(v, v) );
}

118
simgear/math/vector.hxx Normal file
View File

@@ -0,0 +1,118 @@
// vector.hxx -- additional vector routines
//
// Written by Curtis Olson, started December 1997.
//
// Copyright (C) 1997 Curtis L. Olson - curt@infoplane.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.
//
// 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 _VECTOR_HXX
#define _VECTOR_HXX
#ifndef __cplusplus
# error This library requires C++
#endif
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <simgear/compiler.h>
#include <plib/sg.h>
#include <simgear/math/mat3.h>
// Map a vector onto the plane specified by normal
void map_vec_onto_cur_surface_plane( MAT3vec normal,
MAT3vec v0,
MAT3vec vec,
MAT3vec result );
inline void sgmap_vec_onto_cur_surface_plane( sgVec3 normal,
sgVec3 v0,
sgVec3 vec,
sgVec3 result )
{
sgVec3 u1, v, tmp;
// calculate a vector "u1" representing the shortest distance from
// the plane specified by normal and v0 to a point specified by
// "vec". "u1" represents both the direction and magnitude of
// this desired distance.
// u1 = ( (normal <dot> vec) / (normal <dot> normal) ) * normal
sgScaleVec3( u1,
normal,
( sgScalarProductVec3(normal, vec) /
sgScalarProductVec3(normal, normal)
)
);
// printf(" vec = %.2f, %.2f, %.2f\n", vec[0], vec[1], vec[2]);
// printf(" v0 = %.2f, %.2f, %.2f\n", v0[0], v0[1], v0[2]);
// printf(" u1 = %.2f, %.2f, %.2f\n", u1[0], u1[1], u1[2]);
// calculate the vector "v" which is the vector "vec" mapped onto
// the plane specified by "normal" and "v0".
// v = v0 + vec - u1
sgAddVec3(tmp, v0, vec);
sgSubVec3(v, tmp, u1);
// printf(" v = %.2f, %.2f, %.2f\n", v[0], v[1], v[2]);
// Calculate the vector "result" which is "v" - "v0" which is a
// directional vector pointing from v0 towards v
// result = v - v0
sgSubVec3(result, v, v0);
// printf(" result = %.2f, %.2f, %.2f\n",
// result[0], result[1], result[2]);
}
// Given a point p, and a line through p0 with direction vector d,
// find the shortest distance from the point to the line
double fgPointLine(MAT3vec p, MAT3vec p0, MAT3vec 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 fgPointLineSquared(MAT3vec p, MAT3vec p0, MAT3vec 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 sgPointLineDistSquared( 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 sgdPointLineDistSquared( const sgdVec3 p, const sgdVec3 p0,
const sgdVec3 d );
#endif // _VECTOR_HXX

73
simgear/metar/Antoi.cpp Normal file
View File

@@ -0,0 +1,73 @@
#pragma comment(compiler)
#pragma comment(date)
#pragma comment(timestamp)
#include <stdlib.h>
#pragma title("antoi - char array to integer")
#pragma pagesize (80)
#pragma page(1)
/********************************************************************/
/* */
/* Title: antoi */
/* Date: Jan 28, 1991 */
/* Organization: W/OSO242 - Graphics and Display Section */
/* Programmer: Allan Darling */
/* Language: C/370 */
/* */
/* Abstract: This function will convert a character array */
/* (string) of length (len) into an integer. */
/* The integer is created via a call to the */
/* function atoi. This function extends the */
/* functionality of atoi by removing the */
/* requirement for a sentinal delimited string */
/* as input. */
/* */
/* Input: - Pointer to an array of characters. */
/* - Integer indicating the number of character to include */
/* in the conversion. */
/* */
/* Output:- An integer corresponding to the value in the character */
/* array or MAXNEG (-2147483648) if the function is */
/* unable to acquire system storage. */
/* */
/* Modification History: */
/* None */
/* */
/********************************************************************/
int antoi(char * string, int len)
{
/*******************/
/* local variables */
/*******************/
char * tmpstr;
int i,
retval;
/*****************/
/* function body */
/*****************/
tmpstr = (char *)malloc((len+1) * sizeof(char));
if (tmpstr == NULL) return (-2147483648);
for (i = 0; i < len; i++)
tmpstr[i] = string[i];
tmpstr[len] = '\0';
retval = atoi(tmpstr);
free(tmpstr);
return(retval);
} /* end antoi */
#pragma page(1)

172
simgear/metar/Charcmp.cpp Normal file
View File

@@ -0,0 +1,172 @@
#pragma comment (compiler)
//#pragma comment (date)
//#pragma comment (timestamp)
#pragma pagesize(80)
#include "Local.h" /* standard header file */
#pragma subtitle(" ")
#pragma page(1)
#pragma subtitle("charcmp - characters compare with patterns ")
/********************************************************************/
/* */
/* Title: charcmp */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 12 Dec 1995 */
/* Programmer: CINDY L. CHONG */
/* Language: C/370 */
/* */
/* Abstract: This function will compare each character in the */
/* string match with each character in the pattern */
/* which is made up of characters. The str can */
/* be longer than the pattern. */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: str is a pointer to char */
/* pattern is a pointer to char */
/* */
/* Output: Return true if str matches pattern, */
/* otherwise, return false */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
#pragma page(1)
bool charcmp(char *str, char *pattern)
{
/**********************************************************/
/* Loop while str and pattern is not equal to null, then */
/* inscreases str and pattern by one */
/**********************************************************/
for (; *pattern != '\0'; pattern++)
{
if (*str == '\0')
return FALSE;
/************************************************************/
/* If pattern match str, then increase str and jump out the */
/* case and read next char of the str and pattern */
/************************************************************/
if ( isspace(*pattern) )
pattern = nxtalpha(pattern);
switch( *pattern )
{
case 'c':
if ( !isalnum(*str++) )
{
return FALSE;
}
break;
case 'a':
if ( !isalpha(*str) )
{
return FALSE;
}
str++;
break;
case 'n':
if ( !iscntrl(*str++) )
{
return FALSE;
}
break;
case 'd':
if ( !isdigit(*str) )
{
return FALSE;
}
str++;
break;
case 'g':
if ( !isgraph(*str++) )
{
return FALSE;
}
break;
case 'i':
if ( !islower(*str++) )
{
return FALSE;
}
break;
case 'p':
if ( !isprint(*str++) )
{
return FALSE;
}
break;
case 't':
if ( !ispunct(*str++) )
{
return FALSE;
}
break;
case 'w':
if ( !isspace(*str++) )
{
return FALSE;
}
break;
case 'u':
if ( !isupper(*str++) )
{
return FALSE;
}
break;
case 's':
if (*str++ != ' ')
{
return FALSE;
}
break;
case 'm':
if ( !isspace(*str) )
{
return FALSE;
}
else
{
while ( isspace(*str) )
str++;
}
break;
case '\'':
pattern++;
if (*pattern != *str)
{
return FALSE;
}
pattern++;
str++;
break;
default:
return FALSE;
} /* end switch */
} /* end for */
return (TRUE);
}

2619
simgear/metar/Dcdmetar.cpp Normal file

File diff suppressed because it is too large Load Diff

5210
simgear/metar/Dcdmtrmk.cpp Normal file

File diff suppressed because it is too large Load Diff

544
simgear/metar/Drvmetar.c Normal file
View File

@@ -0,0 +1,544 @@
#include "Metar.h"
#pragma page(1)
#pragma subtitle(" ")
#pragma subtitle("subtitle - description ")
/********************************************************************/
/* */
/* Title: dRVMETAR */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 28 Oct 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: DRVMETAR is a main routine that acts a driver */
/* for testing the METAR Decoder function. */
/* */
/* External Functions Called: */
/* None. */
/* DcdMETAR */
/* prtDcdMetar */
/* Sec0MTSm */
/* Sec1MTSm */
/* */
/* Input: None */
/* */
/* Output: None */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
#pragma page(1)
main()
{
char bltn_prefix[20];
static char *string[] =
{
"KAST 221156Z COR 09005KT 7SM -RA OVC026 09/08 A2996 RMK "
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005",
"KAST COR 221156Z 09005KT 7SM -RA OVC026 09/08 A2996 RMK "
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005",
"KAST COR 221156Z 09005KT 1/SM -RA OVC026 09/08 A2996 RMK "
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005",
"KP88 COR 221156 09005KT 1/SM -RA OVC026 09/08 A2996 RMK "
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005",
"KP88 COR 221156 09005KT 1/SM -RA OVC026 09/08 A2996 RMK "
"AO2 TNO SLP143 P0007 6//// 70109 T00890084 10100 20089 55005",
NULL,
"EPIT 1755 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1/2V3/4",
"KFAR 181154Z 10003KT 1/4SM HZ CLR 16/13 A2988 RMK AO2 "
"SLP117 56012 10345 20226 T01610133 $",
"KFAR 181154Z 10003KT 1/SM HZ CLR 16/13 A2988 RMK AO2 "
"SLP117 56012 10345 20226 T01610133 $",
"RKSS 21009KT 1400 RP2000 // ////// 21/20 1006/2972 NOSIG",
"RKSS 1200 21009KT 1400 RP2000 // ////// 21/20 1006/2972 NOSIG",
"RKSS 1130Z 23011KT 1100 R14R/P1500N R14L/P1500N BR SCT010 BKN030 "
"BKN080 21/21 Q1006 NOSIG",
"RKSS 1130Z 23011KT 1100 R14R/P1500 R14L/P1500 BR SCT010 BKN030 "
"BKN080 21/21 Q1006 NOSIG",
NULL,
"KFAR 181154Z 10003KT 4SM HZ CLR 16/13 A2988 RMK AO2 "
"SLP117 56012 1//// 2//// T01610133 $",
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
"SF6SC1 VSBY RDCE DUE LO CLD SLP186",
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
"SF6SC1 VSBY RDCE DUE10 LO CLD SLP186",
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
"SF6SC1 VSBY RDCE DUE9 LO CLD SLP186",
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
"SF6SC1 VSBY RDCE FZDZE10 LO CLD SLP186",
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
"SF6SC1 VSBY RDCE FZDZE9 LO CLD SLP186",
"MKJP 1400Z 13011KT 9999 FEW022 30/XX Q1015",
"MKJP 1400Z 13011KT 9999 FEW022 M30/XX Q1015",
"MKJP 1400Z 13011KT 9999 FEW022 MM/XX Q1015",
"MKJP 1400Z 13011KT 9999 FEW022 MM/30 Q1015",
"MKJP 1400Z 13011KT 9999 FEW022 MM/M30 Q1015",
"EGPD 36016G26KT 320V030 9999 FEW015TCU SCT026 BKN045 OVC090 "
"SCT120 FEW250 RMK OCNL LTGICCG OHD",
"EGPD 36016G26KT 320V030 9999 FEW015TCU SCT026 07/01 Q1011 "
"RMK TEMPO 8000 -SHRA BKN015 FRQ LTG VC",
"EGPD 36016G26KT 320V030 9999 FEW015TCU SCT026 07/01 Q1011 "
"RMK TEMPO 8000 -SHRA BKN015 LTG DSNT W",
"METAR KLAX 281156Z AUTO VRB100G135KT 130V210 3 1/2SM "
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT FC "
"+TS BLPY FEW/// SCT000 BKN050 SCT150 OVC250 3/M1 A2991 RMK "
"TORNADO B13E45 6 NE MOV E A02 PK WND 18515/45 "
"WSHFT 1350 FROPA TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
"VIS 2 1/2 RY11 "
"DVR/1000V1600FT "
"OCNL LTG VCY STN "
"RAB1030E1145 FZDZE56 BLPYE57 CIG 1000V1500 CIG 020 RY11 "
"PRESFR PRESRR SLP013 FG FEW/// HZ SCT000 VIS NW 2 1/2 GR 3/4 "
"VIRGA SE -XRAFG3 CIGE005 BKN014 V OVC "
"FU BKN020 NOSPECI LAST 8/365 SNINCR 2/10 4/178 "
"933125 98096 P 0125 60225 70565 "
"T00261015 10369 21026 "
"404800360 52101 VISNO RY05 CHINO RY27 PNO RVRNO "
"PWINO FZRANO TSNO $",
"KBOS 251356Z 26011KT 10SM CLR 12/02 A2995 RMK AO2 SC VCNTY "
"STN SSE-NNW SCT CI ABV SLP141 T01220023",
"EFHK 36009KT 340V060 CAVOK 12/M02 Q1013 NOSIG",
"EGKK 24011KT 210V300 9999 SCT020 BKN045 12/06 Q1007 NOSIG",
"EGPD 31018KT 8000 RA FEW013 BKN021 OVC045 06/04 Q0994 NOSIG",
"EKCH 16012KT CAVOK 20/07 Q1006 NOSIG",
"ESKN 10014KT 9000 BR SCT100 14/04 Q1010",
"LOWW 231450Z 14017KT CAVOK 23/07 Q1010 NOSIG",
"METAR CYCH 171500Z CCA 30017KT 2SM -SN BKN006",
"METAR CYOW 171500Z CCA 30017KT 2SM -SN BKN006 OVC020 00/M02 "
"A2957 RMK S35F4NS1 /S01/ SNW WET SNW MELTG ON GRND CIG 5-7 "
"SLP018",
"KAST 221156Z AUTO 09005KT 7SM -RA OVC026 09/08 A2996 RMK "
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005"
" TSB0159E30 TS SE MOV NE",
"KAST 221156Z AUTO 09005KT 7SM -RA OVC026 09/08 A2996 RMK "
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005"
" TSE0159 TS SE",
"KHVR 1756Z 31007KT 5SM -SN SCT011 BKN024 OVC030 M05/M08 A3056 "
"RMK AOA 933004 "
"BKN V SCT TNO PCPN 000 $ SLP389 4/015 60002 "
"T10501077 11050 21078 51010",
"SPECI KGFI 041420Z AUTO 18030KT 3 1/2SM RVRNO TS -RA BKN008 OVC060 "
"26/22 A2991 RMK A02 RA15TSB20 PRESFR SLP 101 P 0000 T02640218",
"METAR KCLE 281156Z 170100G135KT 110V180 M1/4SM "
"R01L/P6000FT +TSSHRA VCFG "
"BKN025 SCT100 OVC200 M26/ A2991 RMK PK WND 18515/45 A02 "
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
"CIG 1000V1500 PRESFR FRQ LTG CG NW "
"RAB1030E1145 FZDZE56 PRESRR SLP135 GS "
"T1263 "
"VIRGA NW 8/365 4/178 P 0125 60225 7//// 70565 10369 21026 "
"404800360 52101 PWINO FZRANO TSNO $",
"CYQR 161700Z 15015KT 15SM SCT045 SCT090 BKN250 10/03 A2955 "
"RMK SC1AC2C11 OB TAKEN H+ 5 DUE AWOS FAILURE SLP027",
"KPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1V2",
"SPECI KGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
"A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
"SLP 701 P 0254 199/182",
"SPECI KGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
"A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
"SLP701 P0254 199/182",
"KHLN 281156Z AUTO 27005KT 10SM OVC023 07/05 A3011 RMK AOA OVC V "
"BKN $ SLP202 60000 70001 T00670050 10122 20061 53003",
"KPHX 281156Z 12004KT 10SM CLR 15/05 A2996 RMK AOA SLP135 T01500050 "
"10250 20150 53006",
"KFCA 281156Z 30003KT 10SM CLR 06/02 A3009 RMK AO TNO $ SLP191 "
"T00610023 10167 20056 53003",
"KAST 281156Z 00000KT 10SM BKN095 09/08 A2997 RMK AOA SLP150 "
"T00940084 10161 20094 52005 ",
"KHVR 281156Z 03003KT 10SM OVC020 09/07 A3010 RMK AO TNO ZRNO "
"$ SLP194 T00940073 10156 20089 51005",
"KGGW 281156Z 35006KT 5SM BR OVC010 10/09 A3003 RMK AOA $ SLP177 "
"70003 T01000095 10156 20110 53008",
"KELY 1153Z AUTO 14004KT 10SM SCT075 01/M01 A3011 RMK AOA TNO ZRNO "
"SLP171 70001 T00061011 10139 21006 51005",
"KFLG 281156Z 29006KT 10SM CLR 04/M01 A3012 RMK AO TNO SLP147 "
"T00391011 21006 51004",
"KGTF 281156Z 27005KT 7SM BKN080 04/04 A3010 RMK AOA SLP205 "
"T00440045 10117 20039 51006",
"K13A 1918Z 20011KT 26/M06 RMK AO PKWND 020/RNO 644V264 T02611061",
"KP88 1919Z 09001KT 14/03 RMK AO / PKWND 002/RNO 158 Z T01440034",
"K40B 1924Z 29004KT 15/M07 RMK AO PKWND 011/RM MV263 T01501072",
"KGGW 1756Z 33018KT 10SM OVC015 M03/M06 A3041 RMK AOA SLP338 "
"4/007 60002 T10281055 11028 21072 51009",
"KPHX 1756Z 130004KT 10SM CLR 18/M03 A3001 RMK AOA SLP154 "
"T01781033 10178 20067 58007",
"KFCA 1756Z 29005KT 10SM CLR 05/M11 A3049 RMK AOA TNO SLP352 "
"T00501111 10050 21044 50004",
"KAST 1756Z 01006KT 10SM CLR 11/04 A3047 RMK AOA SLP316 "
"T01110045 10111 20000 50002",
"KELY 1753Z 34010KT 10SM CLR 01/M07 A3022 RMK AOA TNO ZRNO "
"SLP240 T00111066 10011 21078 58007",
"KFLG 1756Z 07006KT 10SM CLR 06/M12 A3009 RMK AO TNO ZRNO "
"SLP178 T00561122 10061 21100 58005",
"KGTF 1756Z 35010KT 1/2SM -SN FG VV09 M06/M08 A3051 RMK AOA "
"933004 SFC VSBY 3/4 "
"PCPN M SLP393 60010 T10611077 11044 21067 53013",
"KHLN 1756Z 35012KT 10SM SCT032 OVC060 M02/M09 A3048 RMK AOA "
"SLP369 60000 T10171094 11017 21061 53006",
"KAST 1756Z 01006KT 10SM CLR 11/04 A3047 RMK AOA SLP316 61104 "
"71235 T01110045 10111 20000 401720056 58002",
"METAR KLAX 04281156Z AUTO VRB100G135KT 130V210 3 1/2SM "
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT FC "
"+TS BLPY FEW000 BKN050 SCT150 OVC250 3/M1 A2991 RMK "
"TORNADO B13 DSNT NE A02 PK WND 18515/45 "
"WSHFT 1350 FROPA TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
"VIS 2 1/2 RY11 OCNL LTG VCY STN "
"RAB1030E1145 FZDZE56 BLPYE57 CIG 1000V1500 CIG 020 RY11 "
"PRESFR PRESRR SLP013 FG FEW000 VIS NW2 1/2 GR 3/4 "
"VIRGA SE -XRAFG3 CIGE005 BKN014 V OVC "
"FU BKN020 NOSPECI LAST 8/365 SNINCR 2/10 4/178 "
"933125 98096 P 0125 60225 70565 "
"T00261015 10369 21026 "
"404800360 52101 PWINO FZRANO TSNO $",
"METAR KGFI 041356Z AUTO 17012KT 130V210 3 1/2SM R15L/0500FT -RA "
"SCT050 OVC110 26/18 A2991 RMK FUNNEL CLOUDS A02 RAB30 "
"SLP 101 GR M1/4 VIRGA SCT V BKN P 0010 T02640178",
"METAR KGFI 041356Z AUTO 05008KT 10SM R15L/P6000FT CLR A2991 "
"RMK WATERSPOUTS VCY STN NW A02 SLP 101 10288 20243 52021 $ ",
"SPECI KGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
"A2900 RMK A02A PK WND 18056/28 OCNL LTG AP "
"RAB15E25TSB20 FCB1430 PRESFR "
"SLP 701 P 0254 T01990182",
"KABE 281900Z NIL",
"METAR KPIT NIL",
"METAR KCLE 04281156Z 170100G135KT 110V180 M1/4SM "
"R01L/P6000FT +TSSHRA VCFG "
"BKN025 SCT100 OVC200 M26/ A2991 RMK PK WND 18515/45 A02 "
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
"CIG 1000V1500 PRESFR FRQ LTG CG NW "
"RAB1030E1145 FZDZE56 PRESRR SLP135 GS "
"T1263 "
"VIRGA NW 8/365 4/178 P 0125 60225 7//// 70565 10369 21026 "
"404800360 52101 PWINO FZRANO TSNO $",
"METAR KPHL 040256Z AUTO 170100G135KT 130V210 1/2SM "
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
"FC +TS BKN050 SCT150 OVC250 M26/ A2991 RMK A02 PK WND 185150/1345 "
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 LTG DSNT "
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP037 GR 2 3/4 "
"VIRGA E 8/365 4/178 P 0125 70565 21026 T0263 10369 60225 "
"404800360 52101 PWINO FZRANO TSNO $",
"SPECI KGFI 041420Z AUTO 18030KT 2 1/2SM RVRNO TS -RA BKN008 "
"OVC060 25/22 A2991 RMK A02 LTG DSNT W "
"RAB15TSB20 PRESFR SLP101 P 0000 "
"254/218",
"METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM "
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
"FC +TS BKN050 SCT150 OVC250 M26/ A2991 RMK A02 PK WND 185150/1345 "
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR M1/4 "
"VIRGA SE 8/365 4/178 P 0125 6//// 60225 70565 T0263 10369 21026 "
"404800360 52101 PWINO FZRANO TSNO $",
"METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM "
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
"FC +TS BKN050 SCT150 OVC250 M26/ A2991 RMK A02 PK WND 185150/1345 "
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR 25 "
"VIRGA 35 8/365 4/178 P 0125 6//// 60225 70565 T0263 10369 21026 "
"VIRGA 35 8/365 4/178 P 0125 21026 70565 10369 60225 T0263 21026 "
"404800360 52101 PWINO FZRANO TSNO $",
"METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM "
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
"FC +TS BKN050 SCT150 OVC250 3/M1 A2991 RMK A02 PK WND 18515/45 "
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR 25 "
"VIRGA 35 8/365 4/178 P 0125 60225 70565 T00261015 10369 21026 "
"404800360 52101 PWINO FZRANO TSNO $",
"METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM "
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
"FC +TS BKN050 SCT150 OVC250 3/M1 A2991 RMK A02 PK WND 185150/1345 "
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR 25 "
"VIRGA 35 8/365 4/178 P 0125 60225 70565 T00261015 10369 21026 "
"404800360 52101 PWINO FZRANO TSNO",
"METAR KGFI 041356Z AUTO 05008KT 10SM R15L/P6000FT CLR A2991 RMK "
"A02 SLP 101 10288 20243 52021",
"SPECI DGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
"M20/M18 A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
"SLP 701 P 0254 M199/M182",
"SPECI DGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
"M20/M18 A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
"SLP 701 P 0254 M199/182",
"SPECI DGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
"M20/M18 A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
"SLP 701 P 0254 199/M182",
"METAR APIT 171755Z AUTO 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 4/369 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 8/563 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1 1/2V2 SLP875 SGB1213E1225",
"NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 "
" Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK SLP056 "
"RAE0123",
"SPECI APIT 171755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 8/321 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1 SLP875 FGB1713",
"APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1V2 SLP875",
"APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1 1/2V2 1/2 SLP875",
"APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1V2 1/2 SLP875",
"EGPF 1720Z 00000KT 9999 -SHRA STC014 SCT020CB BNK024 12/09 "
"Q1003 NOSIG",
"NZAA 1700Z 03010KT 30KM 03 5CU022 7SC035 11/07 Q1006.5 NOSIG",
"NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 "
" Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK KAUKAU 30050KT",
"DGAA 1800Z 22012KT 9999 SCT009 BKN120 25/21 Q1015",
"DAAT 1830Z 30010KT CAVOK 29/06 Q1019",
"GQPP 1800Z 34023KT 3000 DRSA SKC 24/20 Q1011 NSG",
"DAAG 1830Z 06006KT 9999 SCT020 25/22 Q1015",
"DABB 1830Z 04010KT 9999 SCT030TCU SCT033CB 27/18 Q1017",
"DABC 1830Z 00000KT 9999 SCT026TCU SCT036CB 22/18 Q1020 RETS",
"NZAA 1700Z 03010KT 30KM 03 5CU022 7SC035 11/07 Q1006.5 NOSIG",
"NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 "
" Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK K",
"NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 "
" Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK KAUKAU 30050KT",
"DGAA 1800Z 22012KT 9999 SCT009 BKN120 25/21 Q1015",
"GFLL 1900Z NIL",
"GOOY 1800Z 03006G17KT 340V080 6000 TSRA BKN016 BKN030CB "
"BKN133 26/23 Q1013 NOSIG",
"GCXO 1930Z 32018KT 8000 SCT003 SCT007 18/16 Q1019",
"APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1 1/2V2",
"BPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1V2",
"CPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1V2 1/2",
"DPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1 1/2V2 1/2",
"FPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 3/4V2 1/2",
"GPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 3/4V3",
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB M18/M16 A2992",
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB M18/16 A2992",
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/M16 A2992",
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB MM/M16 A2992",
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB MM/16 A2992",
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB M18/MM A2992",
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/MM A2992",
NULL};
/***************************/
/* DECLARE LOCAL VARIABLES */
/***************************/
Decoded_METAR Metar;
Decoded_METAR *Mptr = &Metar;
int j,
ErReturn;
static char *synopRTRN = NULL;
/***************************************************/
/* START BODY OF MAIN ROUTINE FOR CALLING DcdMETAR */
/***************************************************/
j = 0;
while( string[j] != NULL)
{
/*-- PRINT INPUT METAR REPORT ----------------------------*/
printf("INPUT METAR REPORT: %s\n",string[j] );
/*-- DECODE INPUT REPORT ---------------------------------*/
if ( (ErReturn = DcdMETAR( string[ j ], Mptr )) != 0 )
printf("DcdMETAR: Error Return Number: %d\n",ErReturn);
/*-- PRINT DECODED METAR REPORT ELEMENTS -----------------*/
prtDMETR( Mptr );
j++;
}
}

View File

@@ -0,0 +1,63 @@
#include "Local.h" /* standard header file */
#include "Metar.h"
#pragma subtitle(" ")
#pragma page(1)
#pragma subtitle("subtitle - description ")
/********************************************************************/
/* */
/* Title: fracPart */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 13 Jun 1995 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: Convert a character string fraction into a */
/* decimal (floating point) number. */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: string - a pointer to a character string frac- */
/* tion. */
/* Output: A decimal (floating point) number. */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
#pragma page(1)
float fracPart( char *string )
{
/***************************/
/* DECLARE LOCAL VARIABLES */
/***************************/
char buf[ 6 ],
*slash;
float numerator,
denominator;
/*************************/
/* START BODY OF ROUTINE */
/*************************/
slash = strchr(string, '/');
memset(buf , '\0', 6);
strncpy( buf, string, slash-string);
numerator = (float) atoi(buf);
memset(buf , '\0', 6);
strcpy( buf, slash+1);
denominator = (float) atoi(buf);
return (numerator/denominator);
}

1171
simgear/metar/Local.h Normal file

File diff suppressed because it is too large Load Diff

12
simgear/metar/Makefile.am Normal file
View File

@@ -0,0 +1,12 @@
includedir = @includedir@/metar
lib_LIBRARIES = libsgmetar.a
libsgmetar_a_SOURCES = \
Antoi.cpp Charcmp.cpp Dcdmetar.cpp Dcdmtrmk.cpp Drvmetar.c \
Fracpart.cpp Local.h Metar.h \
MetarReport.cpp MetarReport.h \
MetarStation.cpp MetarStation.h \
Prtdmetr.cpp Stspack2.cpp Stspack3.cpp
INCLUDES += -I$(top_builddir)

149
simgear/metar/Metar.dsp Normal file
View File

@@ -0,0 +1,149 @@
# Microsoft Developer Studio Project File - Name="Metar" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=Metar - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "Metar.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "Metar.mak" CFG="Metar - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Metar - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "Metar - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "Metar - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /G6 /W3 /GX /Zi /O2 /I "..\..\..\lib" /I "..\lib" /I "..\..\lib" /I "..\..\..\..\lib" /I ".." /I "..\.." /I "..\..\.." /I "..\..\..\.." /I "..\include" /I "..\..\include" /I "..\..\..\include" /I "..\..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "Metar - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /G6 /W3 /Gm /GX /Zi /Od /I "..\..\..\lib" /I "..\lib" /I "..\..\lib" /I "..\..\..\..\lib" /I ".." /I "..\.." /I "..\..\.." /I "..\..\..\.." /I "..\include" /I "..\..\include" /I "..\..\..\include" /I "..\..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ENDIF
# Begin Target
# Name "Metar - Win32 Release"
# Name "Metar - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\Antoi.cpp
# End Source File
# Begin Source File
SOURCE=.\Charcmp.cpp
# End Source File
# Begin Source File
SOURCE=.\Dcdmetar.cpp
# End Source File
# Begin Source File
SOURCE=.\Dcdmtrmk.cpp
# End Source File
# Begin Source File
SOURCE=.\Fracpart.cpp
# End Source File
# Begin Source File
SOURCE=.\MetarReport.cpp
# End Source File
# Begin Source File
SOURCE=.\MetarStation.cpp
# End Source File
# Begin Source File
SOURCE=.\Prtdmetr.cpp
# End Source File
# Begin Source File
SOURCE=.\Stspack2.cpp
# End Source File
# Begin Source File
SOURCE=.\Stspack3.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\LOCAL.H
# End Source File
# Begin Source File
SOURCE=.\METAR.H
# End Source File
# Begin Source File
SOURCE=.\MetarReport.h
# End Source File
# Begin Source File
SOURCE=.\MetarStation.h
# End Source File
# End Group
# End Target
# End Project

265
simgear/metar/Metar.h Normal file
View File

@@ -0,0 +1,265 @@
#ifndef METARX
#define METARX
/********************************************************************/
/* */
/* Title: METAR H */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 19 Jan 1996 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: METAR Decoder Header File. */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
#include "Local.h" /* standard header file */
/*********************************************/
/* */
/* RUNWAY VISUAL RANGE STRUCTURE DECLARATION */
/* AND VARIABLE TYPE DEFINITION */
/* */
/*********************************************/
typedef struct runway_VisRange {
char runway_designator[6];
bool vrbl_visRange;
bool below_min_RVR;
bool above_max_RVR;
int visRange;
int Max_visRange;
int Min_visRange;
} Runway_VisRange;
/***********************************************/
/* */
/* DISPATCH VISUAL RANGE STRUCTURE DECLARATION */
/* AND VARIABLE TYPE DEFINITION */
/* */
/***********************************************/
typedef struct dispatch_VisRange {
bool vrbl_visRange;
bool below_min_DVR;
bool above_max_DVR;
int visRange;
int Max_visRange;
int Min_visRange;
} Dispatch_VisRange;
/*****************************************/
/* */
/* CLOUD CONDITION STRUCTURE DECLARATION */
/* AND VARIABLE TYPE DEFINITION */
/* */
/*****************************************/
typedef struct cloud_Conditions {
char cloud_type[5];
char cloud_hgt_char[4];
char other_cld_phenom[4];
int cloud_hgt_meters;
} Cloud_Conditions;
/*****************************************/
/* */
/* WIND GROUP DATA STRUCTURE DECLARATION */
/* AND VARIABLE TYPE DEFINITION */
/* */
/*****************************************/
typedef struct windstruct {
char windUnits[ 4 ];
bool windVRB;
int windDir;
int windSpeed;
int windGust;
} WindStruct;
/*****************************************/
/* */
/* RECENT WX GROUP STRUCTURE DECLARATION */
/* AND VARIABLE TYPE DEFINITION */
/* */
/*****************************************/
typedef struct recent_wx {
char Recent_weather[ 5 ];
int Bhh;
int Bmm;
int Ehh;
int Emm;
} Recent_Wx;
/***************************************/
/* */
/* DECODED METAR STRUCTURE DECLARATION */
/* AND VARIABLE TYPE DEFINITION */
/* */
/***************************************/
typedef struct decoded_METAR {
char synoptic_cloud_type[ 6 ];
char snow_depth_group[ 6 ];
char codeName[ 6 ];
char stnid[5];
char horiz_vsby[5];
char dir_min_horiz_vsby[3];
char vsby_Dir[ 3 ];
char WxObstruct[10][8];
char autoIndicator[5];
char VSBY_2ndSite_LOC[10];
char SKY_2ndSite_LOC[10];
char SKY_2ndSite[10];
char SectorVsby_Dir[ 3 ];
char ObscurAloft[ 12 ];
char ObscurAloftSkyCond[ 12 ];
char VrbSkyBelow[ 4 ];
char VrbSkyAbove[ 4 ];
char LTG_DIR[ 3 ];
char CloudLow;
char CloudMedium;
char CloudHigh;
char CIG_2ndSite_LOC[10];
char VIRGA_DIR[3];
char TornadicType[15];
char TornadicLOC[10];
char TornadicDIR[4];
char TornadicMovDir[3];
char CHINO_LOC[6];
char VISNO_LOC[6];
char PartialObscurationAmt[2][7];
char PartialObscurationPhenom[2][12];
char SfcObscuration[6][10];
char charPrevailVsby[12];
char charVertVsby[10];
char TS_LOC[3];
char TS_MOVMNT[3];
bool Indeterminant3_6HrPrecip;
bool CIGNO;
bool SLPNO;
bool ACFTMSHP;
bool NOSPECI;
bool FIRST;
bool LAST;
bool SunSensorOut;
bool AUTO;
bool COR;
bool NIL_rpt;
bool CAVOK;
bool RVRNO;
bool A_altstng;
bool Q_altstng;
bool VIRGA;
bool VOLCASH;
bool GR;
bool CHINO;
bool VISNO;
bool PNO;
bool PWINO;
bool FZRANO;
bool TSNO;
bool DollarSign;
bool PRESRR;
bool PRESFR;
bool Wshft_FROPA;
bool OCNL_LTG;
bool FRQ_LTG;
bool CNS_LTG;
bool CG_LTG;
bool IC_LTG;
bool CC_LTG;
bool CA_LTG;
bool DSNT_LTG;
bool AP_LTG;
bool VcyStn_LTG;
bool OVHD_LTG;
bool LightningVCTS;
bool LightningTS;
int TornadicDistance;
int ob_hour;
int ob_minute;
int ob_date;
int minWnDir;
int maxWnDir;
int VertVsby;
int temp;
int dew_pt_temp;
int QFE;
int hectoPasc_altstng;
int char_prestndcy;
int minCeiling;
int maxCeiling;
int WshfTime_hour;
int WshfTime_minute;
int min_vrbl_wind_dir;
int max_vrbl_wind_dir;
int PKWND_dir;
int PKWND_speed;
int PKWND_hour;
int PKWND_minute;
int SKY_2ndSite_Meters;
int Ceiling;
int Estimated_Ceiling;
int SNINCR;
int SNINCR_TotalDepth;
int SunshineDur;
int ObscurAloftHgt;
int VrbSkyLayerHgt;
int Num8thsSkyObscured;
int CIG_2ndSite_Meters;
int snow_depth;
int BTornadicHour;
int BTornadicMinute;
int ETornadicHour;
int ETornadicMinute;
float SectorVsby;
float WaterEquivSnow;
float VSBY_2ndSite;
float prevail_vsbySM;
float prevail_vsbyM;
float prevail_vsbyKM;
float prestndcy;
float precip_amt;
float precip_24_amt;
float maxtemp;
float mintemp;
float max24temp;
float min24temp;
float minVsby;
float maxVsby;
float hourlyPrecip;
float TWR_VSBY;
float SFC_VSBY;
float Temp_2_tenths;
float DP_Temp_2_tenths;
float SLP;
float GR_Size;
double inches_altstng;
Runway_VisRange RRVR[12];
Dispatch_VisRange DVR;
Recent_Wx ReWx[3];
WindStruct winData;
Cloud_Conditions cldTypHgt[6];
} Decoded_METAR;
#define MAXWXSYMBOLS 10 /*-- NOT TO EXCEED 10 PRES. WX GRPS --*/
#define MAXTOKENS 500 /*-- RPT NOT TO EXCEED 500 GRPS --*/
void prtDMETR( Decoded_METAR *Mptr );
int DcdMETAR( char *string, Decoded_METAR *Mptr );
#endif

View File

@@ -0,0 +1,259 @@
// Metar report implementation class code
#include "MetarReport.h"
#include "Metar.h"
CMetarReport::CMetarReport(
char *s ) :
m_DecodedReport( 0 )
{
m_DecodedReport = new Decoded_METAR;
DcdMETAR( s, (Decoded_METAR *)m_DecodedReport );
}
CMetarReport::~CMetarReport()
{
}
static int DecodeDirChars( char* c )
{
int r = 0;
if ( c[0] )
{
if ( c[0] == 'E' ) r = 90;
else if ( c[0] == 'S' ) r = 180;
else if ( c[0] == 'W' ) r = 270;
if ( r == 0 )
{
if ( c[1] == 'E' ) r = 45;
else if ( c[1] == 'W' ) r = 315;
}
else if ( r = 180 )
{
if ( c[1] == 'E' ) r = 135;
else if ( c[1] == 'W' ) r = 225;
}
}
return r;
}
char *CMetarReport::StationID()
{
return ((Decoded_METAR *)m_DecodedReport)->stnid;
}
int CMetarReport::WindDirection()
{
return ((Decoded_METAR *)m_DecodedReport)->winData.windDir;
}
int CMetarReport::WindSpeed()
{
return ((Decoded_METAR *)m_DecodedReport)->winData.windSpeed;
}
int CMetarReport::WindGustSpeed()
{
return ((Decoded_METAR *)m_DecodedReport)->winData.windGust;
}
int CMetarReport::LightningDirection()
{
return DecodeDirChars( ((Decoded_METAR *)m_DecodedReport)->LTG_DIR );
}
char CMetarReport::CloudLow()
{
return ((Decoded_METAR *)m_DecodedReport)->CloudLow;
}
char CMetarReport::CloudMedium()
{
return ((Decoded_METAR *)m_DecodedReport)->CloudMedium;
}
char CMetarReport::CloudHigh()
{
return ((Decoded_METAR *)m_DecodedReport)->CloudHigh;
}
int CMetarReport::VirgaDirection()
{
return DecodeDirChars( ((Decoded_METAR *)m_DecodedReport)->VIRGA_DIR );
}
int CMetarReport::TornadicDirection()
{
return DecodeDirChars( ((Decoded_METAR *)m_DecodedReport)->TornadicDIR );
}
int CMetarReport::TornadicMovementDirection()
{
return DecodeDirChars( ((Decoded_METAR *)m_DecodedReport)->TornadicMovDir );
}
int CMetarReport::ThunderStormDirection()
{
return DecodeDirChars( ((Decoded_METAR *)m_DecodedReport)->TS_LOC );
}
int CMetarReport::ThunderStormMovementDirection()
{
return DecodeDirChars( ((Decoded_METAR *)m_DecodedReport)->TS_MOVMNT );
}
bool CMetarReport::Virga()
{
return ((Decoded_METAR *)m_DecodedReport)->VIRGA;
}
bool CMetarReport::VolcanicAsh()
{
return ((Decoded_METAR *)m_DecodedReport)->VOLCASH;
}
bool CMetarReport::Hail()
{
return ((Decoded_METAR *)m_DecodedReport)->GR;
}
bool CMetarReport::OccationalLightning()
{
return ((Decoded_METAR *)m_DecodedReport)->OCNL_LTG;
}
bool CMetarReport::FrequentLightning()
{
return ((Decoded_METAR *)m_DecodedReport)->FRQ_LTG;
}
bool CMetarReport::ContinuousLightning()
{
return ((Decoded_METAR *)m_DecodedReport)->CNS_LTG;
}
bool CMetarReport::CloudToGroundLightning()
{
return ((Decoded_METAR *)m_DecodedReport)->CG_LTG;
}
bool CMetarReport::InterCloudLightning()
{
return ((Decoded_METAR *)m_DecodedReport)->IC_LTG;
}
bool CMetarReport::CloudToCloudLightning()
{
return ((Decoded_METAR *)m_DecodedReport)->CC_LTG;
}
bool CMetarReport::CloudToAirLightning()
{
return ((Decoded_METAR *)m_DecodedReport)->CA_LTG;
}
bool CMetarReport::DistantLightning()
{
return ((Decoded_METAR *)m_DecodedReport)->DSNT_LTG;
}
bool CMetarReport::AirportLightning()
{
return ((Decoded_METAR *)m_DecodedReport)->AP_LTG;
}
bool CMetarReport::VicinityLightning()
{
return ((Decoded_METAR *)m_DecodedReport)->VcyStn_LTG;
}
bool CMetarReport::OverheadLightning()
{
return ((Decoded_METAR *)m_DecodedReport)->OVHD_LTG;
}
int CMetarReport::Temperature()
{
return ((Decoded_METAR *)m_DecodedReport)->temp;
}
int CMetarReport::DewpointTemperature()
{
return ((Decoded_METAR *)m_DecodedReport)->dew_pt_temp;
}
int CMetarReport::VerticalVisibility() // Meters
{
return ((Decoded_METAR *)m_DecodedReport)->VertVsby;
}
int CMetarReport::Ceiling()
{
return FEET_TO_METER * ((Decoded_METAR *)m_DecodedReport)->Ceiling;
}
int CMetarReport::EstimatedCeiling()
{
return FEET_TO_METER * ((Decoded_METAR *)m_DecodedReport)->Estimated_Ceiling;
}
int CMetarReport::VariableSkyLayerHeight()
{
return FEET_TO_METER * ((Decoded_METAR *)m_DecodedReport)->VrbSkyLayerHgt;
}
int CMetarReport::SnowDepthInches()
{
return ((Decoded_METAR *)m_DecodedReport)->snow_depth;
}
std::ostream&
operator << ( ostream& out, CMetarReport& p )
{
return out
<< "StationID " << p.StationID()
<< " WindDirection " << p.WindDirection()
<< " WindSpeed " << p.WindSpeed()
<< " WindGustSpeed " << p.WindGustSpeed() << std::endl
<< "CloudLow " << p.CloudLow()
<< " CloudMedium " << p.CloudMedium()
<< " CloudHigh " << p.CloudHigh() << std::endl
<< "TornadicDirection " << p.TornadicDirection()
<< " TornadicMovementDirection " << p.TornadicMovementDirection() << std::endl
<< "ThunderStormDirection " << p.ThunderStormDirection()
<< " ThunderStormMovementDirection " << p.ThunderStormMovementDirection() << std::endl
<< "Virga " << p.Virga()
<< " VirgaDirection " << p.VirgaDirection() << std::endl
<< "VolcanicAsh " << p.VolcanicAsh() << std::endl
<< "Hail " << p.Hail() << std::endl
<< "LightningDirection " << p.LightningDirection()
<< " OccationalLightning " << p.OccationalLightning()
<< " FrequentLightning " << p.FrequentLightning()
<< " ContinuousLightning " << p.ContinuousLightning() << std::endl
<< "CloudToGroundLightning " << p.CloudToGroundLightning()
<< " InterCloudLightning " << p.InterCloudLightning()
<< " CloudToCloudLightning " << p.CloudToCloudLightning()
<< " CloudToAirLightning " << p.CloudToAirLightning() << std::endl
<< "DistantLightning " << p.DistantLightning()
<< " AirportLightning " << p.AirportLightning()
<< " VicinityLightning " << p.VicinityLightning()
<< " OverheadLightning " << p.OverheadLightning() << std::endl
<< "VerticalVisibility " << p.VerticalVisibility() << std::endl // Meters
<< "Temperature " << p.Temperature()
<< " DewpointTemperature " << p.DewpointTemperature() << std::endl
<< "Ceiling " << p.Ceiling()
<< " EstimatedCeiling " << p.EstimatedCeiling()
<< " VariableSkyLayerHeight " << p.VariableSkyLayerHeight() << std::endl
<< "SnowDepthInches " << p.SnowDepthInches() << std::endl
;
}
void CMetarReport::dump()
{
prtDMETR( (Decoded_METAR *)m_DecodedReport );
}

111
simgear/metar/MetarReport.h Normal file
View File

@@ -0,0 +1,111 @@
// Class encapulating the metar report information
//
// Individual METAR reports are found in this directory:
// ftp://weather.noaa.gov/data/observations/metar/stations
//
#ifndef _MetarReport_
#define _MetarReport_
#include <iostream>
#include <string>
#include <vector>
#include <Math/point3d.hxx>
#include <Math/polar3d.hxx>
class CMetarReport
{
// Typedefs, enumerations
// Attributes
private:
void *m_DecodedReport;
// A void pointer which is cast to the correct type in the cpp file.
// I don't want the ugly metar structure and header files dragged into
// every report user program file.
// Probably should be a smart pointer if copy constructor and assignment
// is allowed.
// Operations
public:
CMetarReport(
char *s );
// Constructor
~CMetarReport();
// Destructor
char *StationID();
// Directions in degrees
// Speed in knots
// Altitude in meters
// Temperature in centigrade
int WindDirection();
int WindSpeed();
int WindGustSpeed();
// Add cloud more cloud info...
// Cloud code characters...
char CloudLow();
char CloudMedium();
char CloudHigh();
bool Virga();
int VirgaDirection();
int TornadicDirection();
int TornadicMovementDirection();
int ThunderStormDirection();
int ThunderStormMovementDirection();
bool VolcanicAsh();
bool Hail();
int LightningDirection();
bool OccationalLightning();
bool FrequentLightning();
bool ContinuousLightning();
bool Lightning()
{
return OccationalLightning() || FrequentLightning() || ContinuousLightning();
}
bool CloudToGroundLightning();
bool InterCloudLightning();
bool CloudToCloudLightning();
bool CloudToAirLightning();
bool DistantLightning();
bool AirportLightning();
bool OverheadLightning();
bool VicinityLightning();
int Temperature();
int DewpointTemperature();
int VerticalVisibility();
int Ceiling();
int EstimatedCeiling();
int VariableSkyLayerHeight();
int SnowDepthInches();
void dump();
private:
CMetarReport(
const CMetarReport &rNewObj );
// Copy constructor. Not implemented.
CMetarReport &operator =(
const CMetarReport &rObj );
// Assignment operator. Not implemented.
};
std::ostream& operator << ( std::ostream&, CMetarReport& );
#endif

View File

@@ -0,0 +1,231 @@
// Metar station implementation code
#include <stdio.h>
#include "MetarStation.h"
#include <algorithm>
#define TESTPROG
#ifndef TESTPROG
// options is too tightly integrated into FlightGear to use in a test program
#include <Main/options.hxx>
#endif
#include <Misc/fgpath.hxx>
std::vector< CMetarStation *> METAR_Stations;
int CMetarStation::initialized( CMetarStation::initialize() );
std::string CMetarStation::tempName;
double CMetarStation::decodeDMS( char *b )
{
double r = 0;
double m = 0;
double s = 0;
if ( *b )
{
// Degrees
r = (*b - '0') * 10.0; b++;
r += (*b - '0'); b++;
if ( *b != '-' )
{
r *= 10;
r += (*b - '0'); b++;
}
b++;
// Minutes
m = (*b - '0') * 10.0; b++;
m += (*b - '0'); b++;
r += m/60.0;
if ( *b == '-' )
{
// Seconds
b++;
s = (*b - '0') * 10.0; b++;
s += (*b - '0'); b++;
}
r += s/3600.0;
// Direction (E W N S)
if ( *b == 'W' || *b == 'S' ) r = -r;
}
return r * DEG_TO_RAD;
}
CMetarStation::CMetarStation(
char *s )
{
char *t;
t = strchr( s, ';' ); *t = 0; t++;
m_ID = s;
s = t; t = strchr( s, ';' ); *t = 0; t++;
m_number = atoi( s ) * 1000;
s = t; t = strchr( s, ';' ); *t = 0; t++;
m_number += atoi( s );
s = t; t = strchr( s, ';' ); *t = 0; t++;
m_name = s;
s = t; t = strchr( s, ';' ); *t = 0; t++;
m_state = s;
s = t; t = strchr( s, ';' ); *t = 0; t++;
m_country = s;
s = t; t = strchr( s, ';' ); *t = 0; t++;
m_region = atoi( s );
s = t; t = strchr( s, ';' ); *t = 0; t++;
double latitude = decodeDMS( s );
s = t; t = strchr( s, ';' ); *t = 0; t++;
double longitude = decodeDMS( s );
s = t; t = strchr( s, ';' ); *t = 0; t++;
double ulatitude = decodeDMS( s );
s = t; t = strchr( s, ';' ); *t = 0; t++;
double ulongitude = decodeDMS( s );
s = t; t = strchr( s, ';' ); *t = 0; t++;
double altitude = atoi( s ) * FEET_TO_METER;
s = t; t = strchr( s, ';' ); *t = 0; t++;
double ualtitude = atoi( s ) * FEET_TO_METER;
Point3D p( longitude, latitude, altitude+EQUATORIAL_RADIUS_M );
m_locationPolar = p;
m_locationCart = fgPolarToCart3d( p );
Point3D up( ulongitude, ulatitude, ualtitude+EQUATORIAL_RADIUS_M );
m_upperLocationPolar = up;
m_upperLocationCart = fgPolarToCart3d( up );
s = t;
m_pFlag = s[0];
}
// Constructor
// Decodes METAR station string of this format:
// KPUB;72;464;Pueblo, Pueblo Memorial Airport;CO;United States;4;38-17-24N;104-29-54W;38-17-03N;104-29-43W;1440;1420;P
int CMetarStation::initialize()
{
// Read the list of metar stations, decoding and adding to global list.
CMetarStation *m;
char buf[256];
// Goto the Flight Gear installation directory
#ifdef TESTPROG
FGPath weatherPath( "/mkv/Build/FlightGear" );
#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" );
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;
}
}
int CMetarStation::sameName( CMetarStation *m )
{
return m->m_ID == tempName;
}
CMetarStation *CMetarStation::find( std::string stationID )
{
tempName = stationID;
CMetarStation **m = std::find_if( METAR_Stations.begin(), METAR_Stations.end(), sameName );
if ( m != METAR_Stations.end() ) return *m;
return 0;
}
double bestDist;
CMetarStation *bestStation;
Point3D curLocation;
void findHelper( CMetarStation *s )
{
double dist = s->locationCart().distance3Dsquared( curLocation );
if (dist < bestDist )
{
bestDist = dist;
bestStation = s;
}
}
CMetarStation *CMetarStation::find( Point3D locationCart )
{
bestDist = 99999999;
bestStation = 0;
curLocation = locationCart;
for_each( findHelper );
return bestStation;
}
void CMetarStation::for_each( void f( CMetarStation *s ) )
{
std::for_each( METAR_Stations.begin(), METAR_Stations.end(), f );
}
void CMetarStation::dump()
{
std::cout << "ID:" << ID();
std::cout << std::endl;
std::cout << "number:" << number();
std::cout << std::endl;
std::cout << "name:" << name();
std::cout << std::endl;
std::cout << "state:" << state();
std::cout << std::endl;
std::cout << "country:" << country();
std::cout << std::endl;
std::cout << "region:" << region();
std::cout << std::endl;
std::cout << "Location (cart):" << locationCart();
std::cout << std::endl;
std::cout << "Location (polar):" << locationPolar();
std::cout << std::endl;
std::cout << "Upper Location (cart):" << upperLocationCart();
std::cout << std::endl;
std::cout << "Upper Location (polar):" << upperLocationPolar();
std::cout << std::endl;
std::cout << "P flag:" << pFlag();
std::cout << std::endl;
}
std::ostream&
operator << ( ostream& out, const CMetarStation& p )
{
return out
<< "ID:" << p.m_ID << std::endl
<< "number:" << p.m_number << std::endl
<< "name:" << p.m_name << std::endl
<< "state:" << p.m_state << std::endl
<< "country:" << p.m_country << std::endl
<< "region:" << p.m_region << std::endl
<< "Location (cart):" << p.m_locationCart << std::endl
<< "Location (polar):" << p.m_locationCart << std::endl
<< "Upper Location (cart):" << p.m_upperLocationCart << std::endl
<< "Upper Location (polar):" << p.m_upperLocationPolar << std::endl
<< "P flag:" << p.m_pFlag << std::endl;
}

View File

@@ -0,0 +1,87 @@
// Class encapulating the metar station information
//
// METAR station information is kept in this file:
// http://www.nws.noaa.gov/pub/stninfo/nsd_cccc.gz
// http://www.nws.noaa.gov/pub/stninfo/nsd_cccc.txt
// This class looks for the file FG_ROOT/Weather/MetarStations instread of nsd_cccc.
#ifndef _MetarStation_
#define _MetarStation_
#include <iostream>
#include <string>
#include <vector>
#include <Math/point3d.hxx>
#include <Math/polar3d.hxx>
//using namespace std;
class CMetarStation
{
// Attributes
private:
std::string m_ID;
unsigned long m_number;
std::string m_name;
std::string m_state;
std::string m_country;
int m_region;
Point3D m_locationPolar;
Point3D m_upperLocationPolar;
Point3D m_locationCart;
Point3D m_upperLocationCart;
int m_altitude;
int m_upperAltitude;
char m_pFlag;
static int initialized;
static std::string tempName;
// Operations
private:
double decodeDMS( char *b );
static int sameName( CMetarStation *m );
CMetarStation(
char *s );
// Constructor
~CMetarStation()
{
}
// Destructor
public:
std::string &ID() { return m_ID; }
unsigned long number() { return m_number; }
std::string &name() { return m_name; }
std::string &state() { return m_state; }
std::string &country() { return m_country; }
int region() { return m_region; }
Point3D &locationPolar() { return m_locationPolar; }
Point3D &upperLocationPolar() { return m_upperLocationPolar; }
Point3D &locationCart() { return m_locationCart; }
Point3D &upperLocationCart() { return m_upperLocationCart; }
char pFlag() { return m_pFlag; }
// Get attributes
friend std::ostream& operator << ( std::ostream&, const CMetarStation& );
void dump();
static CMetarStation *find( std::string stationID );
static CMetarStation *find( Point3D locationCart );
static void for_each( void f( CMetarStation *s ) );
private:
CMetarStation(
const CMetarStation &rNewObj );
// Copy constructor. Not implemented.
CMetarStation &operator =(
const CMetarStation &rObj );
// Assignment operator. Not implemented.
static int initialize();
};
#endif

View File

@@ -0,0 +1,549 @@
// Metar Library test
#include <iostream>
#include "../MetarReport.h"
#include "../MetarStation.h"
#include <GL/glut.h>
static char *report[] =
{
"KAST 221156Z COR 09005KT 7SM -RA OVC026 09/08 A2996 RMK "
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005",
"KAST COR 221156Z 09005KT 7SM -RA OVC026 09/08 A2996 RMK "
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005",
"KAST COR 221156Z 09005KT 1/SM -RA OVC026 09/08 A2996 RMK "
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005",
"KP88 COR 221156 09005KT 1/SM -RA OVC026 09/08 A2996 RMK "
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005",
"KP88 COR 221156 09005KT 1/SM -RA OVC026 09/08 A2996 RMK "
"AO2 TNO SLP143 P0007 6//// 70109 T00890084 10100 20089 55005",
"EPIT 1755 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1/2V3/4",
"KFAR 181154Z 10003KT 1/4SM HZ CLR 16/13 A2988 RMK AO2 "
"SLP117 56012 10345 20226 T01610133 $",
"KFAR 181154Z 10003KT 1/SM HZ CLR 16/13 A2988 RMK AO2 "
"SLP117 56012 10345 20226 T01610133 $",
"RKSS 21009KT 1400 RP2000 // ////// 21/20 1006/2972 NOSIG",
"RKSS 1200 21009KT 1400 RP2000 // ////// 21/20 1006/2972 NOSIG",
"RKSS 1130Z 23011KT 1100 R14R/P1500N R14L/P1500N BR SCT010 BKN030 "
"BKN080 21/21 Q1006 NOSIG",
"RKSS 1130Z 23011KT 1100 R14R/P1500 R14L/P1500 BR SCT010 BKN030 "
"BKN080 21/21 Q1006 NOSIG",
"KFAR 181154Z 10003KT 4SM HZ CLR 16/13 A2988 RMK AO2 "
"SLP117 56012 1//// 2//// T01610133 $",
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
"SF6SC1 VSBY RDCE DUE LO CLD SLP186",
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
"SF6SC1 VSBY RDCE DUE10 LO CLD SLP186",
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
"SF6SC1 VSBY RDCE DUE9 LO CLD SLP186",
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
"SF6SC1 VSBY RDCE FZDZE10 LO CLD SLP186",
"CYYE 061300Z 3500KT 15SM BKN005 OVC040 08/08 A3004 RMK "
"SF6SC1 VSBY RDCE FZDZE9 LO CLD SLP186",
"MKJP 1400Z 13011KT 9999 FEW022 30/XX Q1015",
"MKJP 1400Z 13011KT 9999 FEW022 M30/XX Q1015",
"MKJP 1400Z 13011KT 9999 FEW022 MM/XX Q1015",
"MKJP 1400Z 13011KT 9999 FEW022 MM/30 Q1015",
"MKJP 1400Z 13011KT 9999 FEW022 MM/M30 Q1015",
"EGPD 36016G26KT 320V030 9999 FEW015TCU SCT026 BKN045 OVC090 "
"SCT120 FEW250 RMK OCNL LTGICCG OHD",
"EGPD 36016G26KT 320V030 9999 FEW015TCU SCT026 07/01 Q1011 "
"RMK TEMPO 8000 -SHRA BKN015 FRQ LTG VC",
"EGPD 36016G26KT 320V030 9999 FEW015TCU SCT026 07/01 Q1011 "
"RMK TEMPO 8000 -SHRA BKN015 LTG DSNT W",
"METAR KLAX 281156Z AUTO VRB100G135KT 130V210 3 1/2SM "
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT FC "
"+TS BLPY FEW/// SCT000 BKN050 SCT150 OVC250 3/M1 A2991 RMK "
"TORNADO B13E45 6 NE MOV E A02 PK WND 18515/45 "
"WSHFT 1350 FROPA TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
"VIS 2 1/2 RY11 "
"DVR/1000V1600FT "
"OCNL LTG VCY STN "
"RAB1030E1145 FZDZE56 BLPYE57 CIG 1000V1500 CIG 020 RY11 "
"PRESFR PRESRR SLP013 FG FEW/// HZ SCT000 VIS NW 2 1/2 GR 3/4 "
"VIRGA SE -XRAFG3 CIGE005 BKN014 V OVC "
"FU BKN020 NOSPECI LAST 8/365 SNINCR 2/10 4/178 "
"933125 98096 P 0125 60225 70565 "
"T00261015 10369 21026 "
"404800360 52101 VISNO RY05 CHINO RY27 PNO RVRNO "
"PWINO FZRANO TSNO $",
"KBOS 251356Z 26011KT 10SM CLR 12/02 A2995 RMK AO2 SC VCNTY "
"STN SSE-NNW SCT CI ABV SLP141 T01220023",
"EFHK 36009KT 340V060 CAVOK 12/M02 Q1013 NOSIG",
"EGKK 24011KT 210V300 9999 SCT020 BKN045 12/06 Q1007 NOSIG",
"EGPD 31018KT 8000 RA FEW013 BKN021 OVC045 06/04 Q0994 NOSIG",
"EKCH 16012KT CAVOK 20/07 Q1006 NOSIG",
"ESKN 10014KT 9000 BR SCT100 14/04 Q1010",
"LOWW 231450Z 14017KT CAVOK 23/07 Q1010 NOSIG",
"METAR CYCH 171500Z CCA 30017KT 2SM -SN BKN006",
"METAR CYOW 171500Z CCA 30017KT 2SM -SN BKN006 OVC020 00/M02 "
"A2957 RMK S35F4NS1 /S01/ SNW WET SNW MELTG ON GRND CIG 5-7 "
"SLP018",
"KAST 221156Z AUTO 09005KT 7SM -RA OVC026 09/08 A2996 RMK "
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005"
" TSB0159E30 TS SE MOV NE",
"KAST 221156Z AUTO 09005KT 7SM -RA OVC026 09/08 A2996 RMK "
"AO2 TNO SLP143 P0007 60047 70109 T00890084 10100 20089 55005"
" TSE0159 TS SE",
"KHVR 1756Z 31007KT 5SM -SN SCT011 BKN024 OVC030 M05/M08 A3056 "
"RMK AOA 933004 "
"BKN V SCT TNO PCPN 000 $ SLP389 4/015 60002 "
"T10501077 11050 21078 51010",
"SPECI KGFI 041420Z AUTO 18030KT 3 1/2SM RVRNO TS -RA BKN008 OVC060 "
"26/22 A2991 RMK A02 RA15TSB20 PRESFR SLP 101 P 0000 T02640218",
"METAR KCLE 281156Z 170100G135KT 110V180 M1/4SM "
"R01L/P6000FT +TSSHRA VCFG "
"BKN025 SCT100 OVC200 M26/ A2991 RMK PK WND 18515/45 A02 "
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
"CIG 1000V1500 PRESFR FRQ LTG CG NW "
"RAB1030E1145 FZDZE56 PRESRR SLP135 GS "
"T1263 "
"VIRGA NW 8/365 4/178 P 0125 60225 7//// 70565 10369 21026 "
"404800360 52101 PWINO FZRANO TSNO $",
"CYQR 161700Z 15015KT 15SM SCT045 SCT090 BKN250 10/03 A2955 "
"RMK SC1AC2C11 OB TAKEN H+ 5 DUE AWOS FAILURE SLP027",
"KPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1V2",
"SPECI KGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
"A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
"SLP 701 P 0254 199/182",
"SPECI KGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
"A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
"SLP701 P0254 199/182",
"KHLN 281156Z AUTO 27005KT 10SM OVC023 07/05 A3011 RMK AOA OVC V "
"BKN $ SLP202 60000 70001 T00670050 10122 20061 53003",
"KPHX 281156Z 12004KT 10SM CLR 15/05 A2996 RMK AOA SLP135 T01500050 "
"10250 20150 53006",
"KFCA 281156Z 30003KT 10SM CLR 06/02 A3009 RMK AO TNO $ SLP191 "
"T00610023 10167 20056 53003",
"KAST 281156Z 00000KT 10SM BKN095 09/08 A2997 RMK AOA SLP150 "
"T00940084 10161 20094 52005 ",
"KHVR 281156Z 03003KT 10SM OVC020 09/07 A3010 RMK AO TNO ZRNO "
"$ SLP194 T00940073 10156 20089 51005",
"KGGW 281156Z 35006KT 5SM BR OVC010 10/09 A3003 RMK AOA $ SLP177 "
"70003 T01000095 10156 20110 53008",
"KELY 1153Z AUTO 14004KT 10SM SCT075 01/M01 A3011 RMK AOA TNO ZRNO "
"SLP171 70001 T00061011 10139 21006 51005",
"KFLG 281156Z 29006KT 10SM CLR 04/M01 A3012 RMK AO TNO SLP147 "
"T00391011 21006 51004",
"KGTF 281156Z 27005KT 7SM BKN080 04/04 A3010 RMK AOA SLP205 "
"T00440045 10117 20039 51006",
"K13A 1918Z 20011KT 26/M06 RMK AO PKWND 020/RNO 644V264 T02611061",
"KP88 1919Z 09001KT 14/03 RMK AO / PKWND 002/RNO 158 Z T01440034",
"K40B 1924Z 29004KT 15/M07 RMK AO PKWND 011/RM MV263 T01501072",
"KGGW 1756Z 33018KT 10SM OVC015 M03/M06 A3041 RMK AOA SLP338 "
"4/007 60002 T10281055 11028 21072 51009",
"KPHX 1756Z 130004KT 10SM CLR 18/M03 A3001 RMK AOA SLP154 "
"T01781033 10178 20067 58007",
"KFCA 1756Z 29005KT 10SM CLR 05/M11 A3049 RMK AOA TNO SLP352 "
"T00501111 10050 21044 50004",
"KAST 1756Z 01006KT 10SM CLR 11/04 A3047 RMK AOA SLP316 "
"T01110045 10111 20000 50002",
"KELY 1753Z 34010KT 10SM CLR 01/M07 A3022 RMK AOA TNO ZRNO "
"SLP240 T00111066 10011 21078 58007",
"KFLG 1756Z 07006KT 10SM CLR 06/M12 A3009 RMK AO TNO ZRNO "
"SLP178 T00561122 10061 21100 58005",
"KGTF 1756Z 35010KT 1/2SM -SN FG VV09 M06/M08 A3051 RMK AOA "
"933004 SFC VSBY 3/4 "
"PCPN M SLP393 60010 T10611077 11044 21067 53013",
"KHLN 1756Z 35012KT 10SM SCT032 OVC060 M02/M09 A3048 RMK AOA "
"SLP369 60000 T10171094 11017 21061 53006",
"KAST 1756Z 01006KT 10SM CLR 11/04 A3047 RMK AOA SLP316 61104 "
"71235 T01110045 10111 20000 401720056 58002",
"METAR KLAX 04281156Z AUTO VRB100G135KT 130V210 3 1/2SM "
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT FC "
"+TS BLPY FEW000 BKN050 SCT150 OVC250 3/M1 A2991 RMK "
"TORNADO B13 DSNT NE A02 PK WND 18515/45 "
"WSHFT 1350 FROPA TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
"VIS 2 1/2 RY11 OCNL LTG VCY STN "
"RAB1030E1145 FZDZE56 BLPYE57 CIG 1000V1500 CIG 020 RY11 "
"PRESFR PRESRR SLP013 FG FEW000 VIS NW2 1/2 GR 3/4 "
"VIRGA SE -XRAFG3 CIGE005 BKN014 V OVC "
"FU BKN020 NOSPECI LAST 8/365 SNINCR 2/10 4/178 "
"933125 98096 P 0125 60225 70565 "
"T00261015 10369 21026 "
"404800360 52101 PWINO FZRANO TSNO $",
"METAR KGFI 041356Z AUTO 17012KT 130V210 3 1/2SM R15L/0500FT -RA "
"SCT050 OVC110 26/18 A2991 RMK FUNNEL CLOUDS A02 RAB30 "
"SLP 101 GR M1/4 VIRGA SCT V BKN P 0010 T02640178",
"METAR KGFI 041356Z AUTO 05008KT 10SM R15L/P6000FT CLR A2991 "
"RMK WATERSPOUTS VCY STN NW A02 SLP 101 10288 20243 52021 $ ",
"SPECI KGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
"A2900 RMK A02A PK WND 18056/28 OCNL LTG AP "
"RAB15E25TSB20 FCB1430 PRESFR "
"SLP 701 P 0254 T01990182",
"KABE 281900Z NIL",
"METAR KPIT NIL",
"METAR KCLE 04281156Z 170100G135KT 110V180 M1/4SM "
"R01L/P6000FT +TSSHRA VCFG "
"BKN025 SCT100 OVC200 M26/ A2991 RMK PK WND 18515/45 A02 "
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
"CIG 1000V1500 PRESFR FRQ LTG CG NW "
"RAB1030E1145 FZDZE56 PRESRR SLP135 GS "
"T1263 "
"VIRGA NW 8/365 4/178 P 0125 60225 7//// 70565 10369 21026 "
"404800360 52101 PWINO FZRANO TSNO $",
"METAR KPHL 040256Z AUTO 170100G135KT 130V210 1/2SM "
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
"FC +TS BKN050 SCT150 OVC250 M26/ A2991 RMK A02 PK WND 185150/1345 "
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 LTG DSNT "
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP037 GR 2 3/4 "
"VIRGA E 8/365 4/178 P 0125 70565 21026 T0263 10369 60225 "
"404800360 52101 PWINO FZRANO TSNO $",
"SPECI KGFI 041420Z AUTO 18030KT 2 1/2SM RVRNO TS -RA BKN008 "
"OVC060 25/22 A2991 RMK A02 LTG DSNT W "
"RAB15TSB20 PRESFR SLP101 P 0000 "
"254/218",
"METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM "
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
"FC +TS BKN050 SCT150 OVC250 M26/ A2991 RMK A02 PK WND 185150/1345 "
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR M1/4 "
"VIRGA SE 8/365 4/178 P 0125 6//// 60225 70565 T0263 10369 21026 "
"404800360 52101 PWINO FZRANO TSNO $",
"METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM "
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
"FC +TS BKN050 SCT150 OVC250 M26/ A2991 RMK A02 PK WND 185150/1345 "
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR 25 "
"VIRGA 35 8/365 4/178 P 0125 6//// 60225 70565 T0263 10369 21026 "
"VIRGA 35 8/365 4/178 P 0125 21026 70565 10369 60225 T0263 21026 "
"404800360 52101 PWINO FZRANO TSNO $",
"METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM "
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
"FC +TS BKN050 SCT150 OVC250 3/M1 A2991 RMK A02 PK WND 18515/45 "
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR 25 "
"VIRGA 35 8/365 4/178 P 0125 60225 70565 T00261015 10369 21026 "
"404800360 52101 PWINO FZRANO TSNO $",
"METAR KGFI 041356Z AUTO 170100G135KT 130V210 3 1/2SM "
"R15L/0500FT R22L/2700FT R16/1200FT R34/1000V1600FT R01L/P6000FT "
"FC +TS BKN050 SCT150 OVC250 3/M1 A2991 RMK A02 PK WND 185150/1345 "
"WSHFT 1350 TWR VIS 1 1/2 SFC VIS 1/4 VIS 1/4V1 1/4 "
"RAB1030E1145 FZDZE56 CIG 1000V1500 PRESFR PRESRR SLP997 GR 25 "
"VIRGA 35 8/365 4/178 P 0125 60225 70565 T00261015 10369 21026 "
"404800360 52101 PWINO FZRANO TSNO",
"METAR KGFI 041356Z AUTO 05008KT 10SM R15L/P6000FT CLR A2991 RMK "
"A02 SLP 101 10288 20243 52021",
"SPECI DGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
"M20/M18 A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
"SLP 701 P 0254 M199/M182",
"SPECI DGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
"M20/M18 A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
"SLP 701 P 0254 M199/182",
"SPECI DGFI 041430Z 18045G56KT M1/4SM R15/0200FT FC +TS VV010 20/18 "
"M20/M18 A2900 RMK A02A PK WND 18056/28 RAB15E25TSB20 FCB1430 PRESFR "
"SLP 701 P 0254 199/M182",
"METAR APIT 171755Z AUTO 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 4/369 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 8/563 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1 1/2V2 SLP875 SGB1213E1225",
"NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 "
" Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK SLP056 "
"RAE0123",
"SPECI APIT 171755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 8/321 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1 SLP875 FGB1713",
"APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1V2 SLP875",
"APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1 1/2V2 1/2 SLP875",
"APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1V2 1/2 SLP875",
"EGPF 1720Z 00000KT 9999 -SHRA STC014 SCT020CB BNK024 12/09 "
"Q1003 NOSIG",
"NZAA 1700Z 03010KT 30KM 03 5CU022 7SC035 11/07 Q1006.5 NOSIG",
"NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 "
" Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK KAUKAU 30050KT",
"DGAA 1800Z 22012KT 9999 SCT009 BKN120 25/21 Q1015",
"DAAT 1830Z 30010KT CAVOK 29/06 Q1019",
"GQPP 1800Z 34023KT 3000 DRSA SKC 24/20 Q1011 NSG",
"DAAG 1830Z 06006KT 9999 SCT020 25/22 Q1015",
"DABB 1830Z 04010KT 9999 SCT030TCU SCT033CB 27/18 Q1017",
"DABC 1830Z 00000KT 9999 SCT026TCU SCT036CB 22/18 Q1020 RETS",
"NZAA 1700Z 03010KT 30KM 03 5CU022 7SC035 11/07 Q1006.5 NOSIG",
"NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 "
" Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK K",
"NZWN 1700Z 35030G49KT 320V030 20KM 02 5SC021 7SC046 12/08 "
" Q0994.2 TEMPO 6000 RA 5ST012 2CB015 RMK KAUKAU 30050KT",
"DGAA 1800Z 22012KT 9999 SCT009 BKN120 25/21 Q1015",
"GFLL 1900Z NIL",
"GOOY 1800Z 03006G17KT 340V080 6000 TSRA BKN016 BKN030CB "
"BKN133 26/23 Q1013 NOSIG",
"GCXO 1930Z 32018KT 8000 SCT003 SCT007 18/16 Q1019",
"APIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1 1/2V2",
"BPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1V2",
"CPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1V2 1/2",
"DPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 1 1/2V2 1/2",
"FPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 3/4V2 1/2",
"GPIT 1755Z 22015G25KT 1 3/4SM R22L/2700FT R16/1200FT "
"R34/1000V1600FT R01L/P6000FT R04RR/900FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/16 A2992 "
"RMK 58033 6003/ TWELVE 70125 10039 20029 410840112 "
"PCPN 0009 WSHFT 1715 PK WND 2032/1725 "
"CIG 20V25 WND 12V25 TWR VIS 2 1/2 "
"SFC VIS 1 1/2 VIS 3/4V3",
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB M18/M16 A2992",
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB M18/16 A2992",
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/M16 A2992",
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB MM/M16 A2992",
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB MM/16 A2992",
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB M18/MM A2992",
"KPIT 1935Z 22015G25KT 1 3/4SM R22L/2700FT "
"TSRA -DZ FG +SNPE SCT005 BKN010 OVC250CB 18/MM A2992",
NULL};
void dispMetarStation( CMetarStation *s )
{
glPointSize( 2.0 );
glColor3d(1.0,1.0,0.0);
glVertex3d( s->locationCart().x()/1000.0, s->locationCart().y()/1000.0, s->locationCart().z()/1000.0 );
}
static int ii = 0;
void
display(void)
{
glPushMatrix();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glRotatef((ii%360), 1.0, 0.0, 0.0);
glRotatef((ii%360), 0.0, 1.0, 0.0);
glRotatef((ii%360), 0.0, 0.0, 1.0);
glBegin( GL_POINTS );
CMetarStation::for_each( dispMetarStation );
glEnd();
glColor3d(0.0, 0.0, 1.0);
glutWireSphere(EARTH_RAD,32,16);
glutSwapBuffers();
ii++;
glPopMatrix();
}
void
idle(void)
{
// std::cout << "Idle" << std::endl;
glutPostRedisplay();
}
void
init(void)
{
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
gluPerspective( 50.0, 1.0, 1.0, 40000.0);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0.0, -19000.0, 0.0,
0.0, 0.0, 0.0,
0.0, 0.0, 1.0);
}
void testMetarStation(int argc,
char **argv )
{
std::cout << "Display all Metar Stations" << std::endl;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutCreateWindow("Metar Stations");
glutDisplayFunc(display);
glutIdleFunc(idle);
init();
glutMainLoop();
}
void testMetarReport()
{
std::cout << "Decode some Metar reports" << std::endl;
int i = 0;
while ( report[i] )
{
std::cout << i << ": " << report[i] << std::endl;
CMetarReport dr( report[i] );
//dr.dump();
std::cout << dr << std::endl;
CMetarStation *ms = CMetarStation::find( dr.StationID() );
if ( ms )
{
std::cout << *ms << std::endl;
}
else
{
std::cout << "No corresponding METAR station found" << std::endl;
}
i++;
}
}
int
main(
int argc,
char **argv )
{
std::cout << "Metar subsystem test" << std::endl;
testMetarReport();
testMetarStation( argc, argv );
return 0;
}

View File

@@ -0,0 +1,100 @@
# Microsoft Developer Studio Project File - Name="MetarLibTest" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=MetarLibTest - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "MetarLibTest.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "MetarLibTest.mak" CFG="MetarLibTest - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "MetarLibTest - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "MetarLibTest - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "MetarLibTest - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /Zi /O2 /I "..\..\..\lib" /I "..\lib" /I "..\..\lib" /I "..\..\..\..\lib" /I ".." /I "..\.." /I "..\..\.." /I "..\..\..\.." /I "..\include" /I "..\..\include" /I "..\..\..\include" /I "..\..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "MetarLibTest - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /GX /Zi /Od /I "..\..\..\lib" /I "..\lib" /I "..\..\lib" /I "..\..\..\..\lib" /I ".." /I "..\.." /I "..\..\.." /I "..\..\..\.." /I "..\include" /I "..\..\include" /I "..\..\..\include" /I "..\..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "MetarLibTest - Win32 Release"
# Name "MetarLibTest - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\MetarLibTest.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View File

@@ -0,0 +1,95 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "LibMisc"=..\..\..\..\Win32\Workspace\LibMisc\LibMisc.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "Metar"=..\Metar.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "MetarLibTest"=.\MetarLibTest.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name Metar
End Project Dependency
Begin Project Dependency
Project_Dep_Name MetarLib
End Project Dependency
Begin Project Dependency
Project_Dep_Name glut
End Project Dependency
Begin Project Dependency
Project_Dep_Name LibMisc
End Project Dependency
}}}
###############################################################################
Project: "MetarTest"=.\MetarTest.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name Metar
End Project Dependency
Begin Project Dependency
Project_Dep_Name MetarLib
End Project Dependency
}}}
###############################################################################
Project: "glut"=..\..\..\..\..\glut\glut.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

590
simgear/metar/Prtdmetr.cpp Normal file
View File

@@ -0,0 +1,590 @@
#include "Local.h" /* standard header file */
#include "Metar.h"
#pragma page(1)
#pragma subtitle("subtitle - description ")
/********************************************************************/
/* */
/* Title: prtDMETR */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: prtDMETR prints, in order of the ASOS METAR */
/* format, all non-initialized members of the structure */
/* addressed by the Decoded_METAR pointer. */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: Mptr - ptr to a decoded_METAR structure. */
/* */
/* Output: NONE */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
#pragma page(1)
void prtDMETR( Decoded_METAR *Mptr )
{
/***************************/
/* DECLARE LOCAL VARIABLES */
/***************************/
int i;
/*************************/
/* START BODY OF ROUTINE */
/*************************/
printf("\n\n\n/*******************************************/\n");
printf("/* THE DECODED METAR REPORT FOLLOWS */\n");
printf("/*******************************************/\n\n");
if( Mptr->codeName[ 0 ] != '\0' )
printf("REPORT CODE NAME : %s\n",Mptr->codeName);
if( Mptr->stnid[ 0 ] != '\0' )
printf("STATION ID : %s\n",Mptr->stnid);
if( Mptr->ob_date != MAXINT )
printf("OBSERVATION DAY : %d\n",Mptr->ob_date);
if( Mptr->ob_hour != MAXINT )
printf("OBSERVATION HOUR : %d\n",Mptr->ob_hour);
if( Mptr->ob_minute != MAXINT )
printf("OBSERVATION MINUTE : %d\n",Mptr->ob_minute);
if( Mptr->NIL_rpt )
printf("NIL REPORT : TRUE\n");
if( Mptr->AUTO )
printf("AUTO REPORT : TRUE\n");
if( Mptr->COR )
printf("CORRECTED REPORT : TRUE\n");
if( Mptr->winData.windVRB )
printf("WIND DIRECTION VRB : TRUE\n");
if( Mptr->winData.windDir != MAXINT )
printf("WIND DIRECTION : %d\n",Mptr->winData.windDir);
if( Mptr->winData.windSpeed != MAXINT )
printf("WIND SPEED : %d\n",Mptr->winData.windSpeed);
if( Mptr->winData.windGust != MAXINT )
printf("WIND GUST : %d\n",Mptr->winData.windGust);
if( Mptr->winData.windUnits[ 0 ] != '\0' )
printf("WIND UNITS : %s\n",Mptr->winData.windUnits);
if( Mptr->minWnDir != MAXINT )
printf("MIN WIND DIRECTION : %d\n",Mptr->minWnDir);
if( Mptr->maxWnDir != MAXINT )
printf("MAX WIND DIRECTION : %d\n",Mptr->maxWnDir);
if( Mptr->prevail_vsbyM != (float) MAXINT )
printf("PREVAIL VSBY (M) : %f\n",Mptr->prevail_vsbyM);
if( Mptr->prevail_vsbyKM != (float) MAXINT )
printf("PREVAIL VSBY (KM) : %f\n",Mptr->prevail_vsbyKM);
if( Mptr->prevail_vsbySM != (float) MAXINT )
printf("PREVAIL VSBY (SM) : %.3f\n",Mptr->prevail_vsbySM);
if( Mptr->charPrevailVsby[0] != '\0' )
printf("PREVAIL VSBY (CHAR) : %s\n",Mptr->charPrevailVsby);
if( Mptr->vsby_Dir[ 0 ] != '\0' )
printf("VISIBILITY DIRECTION: %s\n",Mptr->vsby_Dir);
if( Mptr->RVRNO )
printf("RVRNO : TRUE\n");
for ( i = 0; i < 12; i++ )
{
if( Mptr->RRVR[i].runway_designator[0] != '\0' )
printf("RUNWAY DESIGNATOR : %s\n",
Mptr->RRVR[i].runway_designator);
if( Mptr->RRVR[i].visRange != MAXINT )
printf("R_WAY VIS RANGE (FT): %d\n",
Mptr->RRVR[i].visRange);
if( Mptr->RRVR[i].vrbl_visRange )
printf("VRBL VISUAL RANGE : TRUE\n");
if( Mptr->RRVR[i].below_min_RVR )
printf("BELOW MIN RVR : TRUE\n");
if( Mptr->RRVR[i].above_max_RVR )
printf("ABOVE MAX RVR : TRUE\n");
if( Mptr->RRVR[i].Max_visRange != MAXINT )
printf("MX R_WAY VISRNG (FT): %d\n",
Mptr->RRVR[i].Max_visRange);
if( Mptr->RRVR[i].Min_visRange != MAXINT )
printf("MN R_WAY VISRNG (FT): %d\n",
Mptr->RRVR[i].Min_visRange);
}
if( Mptr->DVR.visRange != MAXINT )
printf("DISPATCH VIS RANGE : %d\n",
Mptr->DVR.visRange);
if( Mptr->DVR.vrbl_visRange )
printf("VRBL DISPATCH VISRNG: TRUE\n");
if( Mptr->DVR.below_min_DVR )
printf("BELOW MIN DVR : TRUE\n");
if( Mptr->DVR.above_max_DVR )
printf("ABOVE MAX DVR : TRUE\n");
if( Mptr->DVR.Max_visRange != MAXINT )
printf("MX DSPAT VISRNG (FT): %d\n",
Mptr->DVR.Max_visRange);
if( Mptr->DVR.Min_visRange != MAXINT )
printf("MN DSPAT VISRNG (FT): %d\n",
Mptr->DVR.Min_visRange);
i = 0;
while ( Mptr->WxObstruct[i][0] != '\0' && i < MAXWXSYMBOLS )
{
printf("WX/OBSTRUCT VISION : %s\n",
Mptr->WxObstruct[i] );
i++;
}
if( Mptr->PartialObscurationAmt[0][0] != '\0' )
printf("OBSCURATION AMOUNT : %s\n",
&(Mptr->PartialObscurationAmt[0][0]));
if( Mptr->PartialObscurationPhenom[0][0] != '\0' )
printf("OBSCURATION PHENOM : %s\n",
&(Mptr->PartialObscurationPhenom[0][0]));
if( Mptr->PartialObscurationAmt[1][0] != '\0' )
printf("OBSCURATION AMOUNT : %s\n",
&(Mptr->PartialObscurationAmt[1][0]));
if( Mptr->PartialObscurationPhenom[1][0] != '\0' )
printf("OBSCURATION PHENOM : %s\n",
&(Mptr->PartialObscurationPhenom[1][0]));
i = 0;
while ( Mptr->cldTypHgt[ i ].cloud_type[0] != '\0' &&
i < 6 )
{
if( Mptr->cldTypHgt[ i ].cloud_type[0] != '\0' )
printf("CLOUD COVER : %s\n",
Mptr->cldTypHgt[ i ].cloud_type);
if( Mptr->cldTypHgt[ i ].cloud_hgt_char[0] != '\0' )
printf("CLOUD HGT (CHARAC.) : %s\n",
Mptr->cldTypHgt[ i ].cloud_hgt_char);
if( Mptr->cldTypHgt[ i ].cloud_hgt_meters != MAXINT)
printf("CLOUD HGT (METERS) : %d\n",
Mptr->cldTypHgt[ i ].cloud_hgt_meters);
if( Mptr->cldTypHgt[ i ].other_cld_phenom[0] != '\0' )
printf("OTHER CLOUD PHENOM : %s\n",
Mptr->cldTypHgt[ i ].other_cld_phenom);
i++;
}
if( Mptr->temp != MAXINT )
printf("TEMP. (CELSIUS) : %d\n", Mptr->temp);
if( Mptr->dew_pt_temp != MAXINT )
printf("D.P. TEMP. (CELSIUS): %d\n", Mptr->dew_pt_temp);
if( Mptr->A_altstng )
printf("ALTIMETER (INCHES) : %.2f\n",
Mptr->inches_altstng );
if( Mptr->Q_altstng )
printf("ALTIMETER (PASCALS) : %d\n",
Mptr->hectoPasc_altstng );
if( Mptr->TornadicType[0] != '\0' )
printf("TORNADIC ACTVTY TYPE: %s\n",
Mptr->TornadicType );
if( Mptr->BTornadicHour != MAXINT )
printf("TORN. ACTVTY BEGHOUR: %d\n",
Mptr->BTornadicHour );
if( Mptr->BTornadicMinute != MAXINT )
printf("TORN. ACTVTY BEGMIN : %d\n",
Mptr->BTornadicMinute );
if( Mptr->ETornadicHour != MAXINT )
printf("TORN. ACTVTY ENDHOUR: %d\n",
Mptr->ETornadicHour );
if( Mptr->ETornadicMinute != MAXINT )
printf("TORN. ACTVTY ENDMIN : %d\n",
Mptr->ETornadicMinute );
if( Mptr->TornadicDistance != MAXINT )
printf("TORN. DIST. FROM STN: %d\n",
Mptr->TornadicDistance );
if( Mptr->TornadicLOC[0] != '\0' )
printf("TORNADIC LOCATION : %s\n",
Mptr->TornadicLOC );
if( Mptr->TornadicDIR[0] != '\0' )
printf("TORNAD. DIR FROM STN: %s\n",
Mptr->TornadicDIR );
if( Mptr->TornadicMovDir[0] != '\0' )
printf("TORNADO DIR OF MOVM.: %s\n",
Mptr->TornadicMovDir );
if( Mptr->autoIndicator[0] != '\0' )
printf("AUTO INDICATOR : %s\n",
Mptr->autoIndicator);
if( Mptr->PKWND_dir != MAXINT )
printf("PEAK WIND DIRECTION : %d\n",Mptr->PKWND_dir);
if( Mptr->PKWND_speed != MAXINT )
printf("PEAK WIND SPEED : %d\n",Mptr->PKWND_speed);
if( Mptr->PKWND_hour != MAXINT )
printf("PEAK WIND HOUR : %d\n",Mptr->PKWND_hour);
if( Mptr->PKWND_minute != MAXINT )
printf("PEAK WIND MINUTE : %d\n",Mptr->PKWND_minute);
if( Mptr->WshfTime_hour != MAXINT )
printf("HOUR OF WIND SHIFT : %d\n",Mptr->WshfTime_hour);
if( Mptr->WshfTime_minute != MAXINT )
printf("MINUTE OF WIND SHIFT: %d\n",Mptr->WshfTime_minute);
if( Mptr->Wshft_FROPA != FALSE )
printf("FROPA ASSOC. W/WSHFT: TRUE\n");
if( Mptr->TWR_VSBY != (float) MAXINT )
printf("TOWER VISIBILITY : %.2f\n",Mptr->TWR_VSBY);
if( Mptr->SFC_VSBY != (float) MAXINT )
printf("SURFACE VISIBILITY : %.2f\n",Mptr->SFC_VSBY);
if( Mptr->minVsby != (float) MAXINT )
printf("MIN VRBL_VIS (SM) : %.4f\n",Mptr->minVsby);
if( Mptr->maxVsby != (float) MAXINT )
printf("MAX VRBL_VIS (SM) : %.4f\n",Mptr->maxVsby);
if( Mptr->VSBY_2ndSite != (float) MAXINT )
printf("VSBY_2ndSite (SM) : %.4f\n",Mptr->VSBY_2ndSite);
if( Mptr->VSBY_2ndSite_LOC[0] != '\0' )
printf("VSBY_2ndSite LOC. : %s\n",
Mptr->VSBY_2ndSite_LOC);
if( Mptr->OCNL_LTG )
printf("OCCASSIONAL LTG : TRUE\n");
if( Mptr->FRQ_LTG )
printf("FREQUENT LIGHTNING : TRUE\n");
if( Mptr->CNS_LTG )
printf("CONTINUOUS LTG : TRUE\n");
if( Mptr->CG_LTG )
printf("CLOUD-GROUND LTG : TRUE\n");
if( Mptr->IC_LTG )
printf("IN-CLOUD LIGHTNING : TRUE\n");
if( Mptr->CC_LTG )
printf("CLD-CLD LIGHTNING : TRUE\n");
if( Mptr->CA_LTG )
printf("CLOUD-AIR LIGHTNING : TRUE\n");
if( Mptr->AP_LTG )
printf("LIGHTNING AT AIRPORT: TRUE\n");
if( Mptr->OVHD_LTG )
printf("LIGHTNING OVERHEAD : TRUE\n");
if( Mptr->DSNT_LTG )
printf("DISTANT LIGHTNING : TRUE\n");
if( Mptr->LightningVCTS )
printf("L'NING W/I 5-10(ALP): TRUE\n");
if( Mptr->LightningTS )
printf("L'NING W/I 5 (ALP) : TRUE\n");
if( Mptr->VcyStn_LTG )
printf("VCY STN LIGHTNING : TRUE\n");
if( Mptr->LTG_DIR[0] != '\0' )
printf("DIREC. OF LIGHTNING : %s\n", Mptr->LTG_DIR);
i = 0;
while( i < 3 && Mptr->ReWx[ i ].Recent_weather[0] != '\0' )
{
printf("RECENT WEATHER : %s",
Mptr->ReWx[i].Recent_weather);
if( Mptr->ReWx[i].Bhh != MAXINT )
printf(" BEG_hh = %d",Mptr->ReWx[i].Bhh);
if( Mptr->ReWx[i].Bmm != MAXINT )
printf(" BEG_mm = %d",Mptr->ReWx[i].Bmm);
if( Mptr->ReWx[i].Ehh != MAXINT )
printf(" END_hh = %d",Mptr->ReWx[i].Ehh);
if( Mptr->ReWx[i].Emm != MAXINT )
printf(" END_mm = %d",Mptr->ReWx[i].Emm);
printf("\n");
i++;
}
if( Mptr->minCeiling != MAXINT )
printf("MIN VRBL_CIG (FT) : %d\n",Mptr->minCeiling);
if( Mptr->maxCeiling != MAXINT )
printf("MAX VRBL_CIG (FT)) : %d\n",Mptr->maxCeiling);
if( Mptr->CIG_2ndSite_Meters != MAXINT )
printf("CIG2ndSite (FT) : %d\n",Mptr->CIG_2ndSite_Meters);
if( Mptr->CIG_2ndSite_LOC[0] != '\0' )
printf("CIG @ 2nd Site LOC. : %s\n",Mptr->CIG_2ndSite_LOC);
if( Mptr->PRESFR )
printf("PRESFR : TRUE\n");
if( Mptr->PRESRR )
printf("PRESRR : TRUE\n");
if( Mptr->SLPNO )
printf("SLPNO : TRUE\n");
if( Mptr->SLP != (float) MAXINT )
printf("SLP (hPa) : %.1f\n", Mptr->SLP);
if( Mptr->SectorVsby != (float) MAXINT )
printf("SECTOR VSBY (MILES) : %.2f\n", Mptr->SectorVsby );
if( Mptr->SectorVsby_Dir[ 0 ] != '\0' )
printf("SECTOR VSBY OCTANT : %s\n", Mptr->SectorVsby_Dir );
if( Mptr->TS_LOC[ 0 ] != '\0' )
printf("THUNDERSTORM LOCAT. : %s\n", Mptr->TS_LOC );
if( Mptr->TS_MOVMNT[ 0 ] != '\0' )
printf("THUNDERSTORM MOVMNT.: %s\n", Mptr->TS_MOVMNT);
if( Mptr->GR )
printf("GR (HAILSTONES) : TRUE\n");
if( Mptr->GR_Size != (float) MAXINT )
printf("HLSTO SIZE (INCHES) : %.3f\n",Mptr->GR_Size);
if( Mptr->VIRGA )
printf("VIRGA : TRUE\n");
if( Mptr->VIRGA_DIR[0] != '\0' )
printf("DIR OF VIRGA FRM STN: %s\n", Mptr->VIRGA_DIR);
for( i = 0; i < 6; i++ ) {
if( Mptr->SfcObscuration[i][0] != '\0' )
printf("SfcObscuration : %s\n",
&(Mptr->SfcObscuration[i][0]) );
}
if( Mptr->Num8thsSkyObscured != MAXINT )
printf("8ths of SkyObscured : %d\n",Mptr->Num8thsSkyObscured);
if( Mptr->CIGNO )
printf("CIGNO : TRUE\n");
if( Mptr->Ceiling != MAXINT )
printf("Ceiling (ft) : %d\n",Mptr->Ceiling);
if( Mptr->Estimated_Ceiling != MAXINT )
printf("Estimated CIG (ft) : %d\n",Mptr->Estimated_Ceiling);
if( Mptr->VrbSkyBelow[0] != '\0' )
printf("VRB SKY COND BELOW : %s\n",Mptr->VrbSkyBelow);
if( Mptr->VrbSkyAbove[0] != '\0' )
printf("VRB SKY COND ABOVE : %s\n",Mptr->VrbSkyAbove);
if( Mptr->VrbSkyLayerHgt != MAXINT )
printf("VRBSKY COND HGT (FT): %d\n",Mptr->VrbSkyLayerHgt);
if( Mptr->ObscurAloftHgt != MAXINT )
printf("Hgt Obscur Aloft(ft): %d\n",Mptr->ObscurAloftHgt);
if( Mptr->ObscurAloft[0] != '\0' )
printf("Obscur Phenom Aloft : %s\n",Mptr->ObscurAloft);
if( Mptr->ObscurAloftSkyCond[0] != '\0' )
printf("Obscur ALOFT SKYCOND: %s\n",Mptr->ObscurAloftSkyCond);
if( Mptr->NOSPECI )
printf("NOSPECI : TRUE\n");
if( Mptr->LAST )
printf("LAST : TRUE\n");
if( Mptr->synoptic_cloud_type[ 0 ] != '\0' )
printf("SYNOPTIC CLOUD GROUP: %s\n",Mptr->synoptic_cloud_type);
if( Mptr->CloudLow != '\0' )
printf("LOW CLOUD CODE : %c\n",Mptr->CloudLow);
if( Mptr->CloudMedium != '\0' )
printf("MEDIUM CLOUD CODE : %c\n",Mptr->CloudMedium);
if( Mptr->CloudHigh != '\0' )
printf("HIGH CLOUD CODE : %c\n",Mptr->CloudHigh);
if( Mptr->SNINCR != MAXINT )
printf("SNINCR (INCHES) : %d\n",Mptr->SNINCR);
if( Mptr->SNINCR_TotalDepth != MAXINT )
printf("SNINCR(TOT. INCHES) : %d\n",Mptr->SNINCR_TotalDepth);
if( Mptr->snow_depth_group[ 0 ] != '\0' )
printf("SNOW DEPTH GROUP : %s\n",Mptr->snow_depth_group);
if( Mptr->snow_depth != MAXINT )
printf("SNOW DEPTH (INCHES) : %d\n",Mptr->snow_depth);
if( Mptr->WaterEquivSnow != (float) MAXINT )
printf("H2O EquivSno(inches): %.2f\n",Mptr->WaterEquivSnow);
if( Mptr->SunshineDur != MAXINT )
printf("SUNSHINE (MINUTES) : %d\n",Mptr->SunshineDur);
if( Mptr->SunSensorOut )
printf("SUN SENSOR OUT : TRUE\n");
if( Mptr->hourlyPrecip != (float) MAXINT )
printf("HRLY PRECIP (INCHES): %.2f\n",Mptr->hourlyPrecip);
if( Mptr->precip_amt != (float) MAXINT)
printf("3/6HR PRCIP (INCHES): %.2f\n",
Mptr->precip_amt);
if( Mptr->Indeterminant3_6HrPrecip )
printf("INDTRMN 3/6HR PRECIP: TRUE\n");
if( Mptr->precip_24_amt != (float) MAXINT)
printf("24HR PRECIP (INCHES): %.2f\n",
Mptr->precip_24_amt);
if( Mptr->Temp_2_tenths != (float) MAXINT )
printf("TMP2TENTHS (CELSIUS): %.1f\n",Mptr->Temp_2_tenths);
if( Mptr->DP_Temp_2_tenths != (float) MAXINT )
printf("DPT2TENTHS (CELSIUS): %.1f\n",Mptr->DP_Temp_2_tenths);
if( Mptr->maxtemp != (float) MAXINT)
printf("MAX TEMP (CELSIUS) : %.1f\n",
Mptr->maxtemp);
if( Mptr->mintemp != (float) MAXINT)
printf("MIN TEMP (CELSIUS) : %.1f\n",
Mptr->mintemp);
if( Mptr->max24temp != (float) MAXINT)
printf("24HrMAXTMP (CELSIUS): %.1f\n",
Mptr->max24temp);
if( Mptr->min24temp != (float) MAXINT)
printf("24HrMINTMP (CELSIUS): %.1f\n",
Mptr->min24temp);
if( Mptr->char_prestndcy != MAXINT)
printf("CHAR PRESS TENDENCY : %d\n",
Mptr->char_prestndcy );
if( Mptr->prestndcy != (float) MAXINT)
printf("PRES. TENDENCY (hPa): %.1f\n",
Mptr->prestndcy );
if( Mptr->PWINO )
printf("PWINO : TRUE\n");
if( Mptr->PNO )
printf("PNO : TRUE\n");
if( Mptr->CHINO )
printf("CHINO : TRUE\n");
if( Mptr->CHINO_LOC[0] != '\0' )
printf("CHINO_LOC : %s\n",Mptr->CHINO_LOC);
if( Mptr->VISNO )
printf("VISNO : TRUE\n");
if( Mptr->VISNO_LOC[0] != '\0' )
printf("VISNO_LOC : %s\n",Mptr->VISNO_LOC);
if( Mptr->FZRANO )
printf("FZRANO : TRUE\n");
if( Mptr->TSNO )
printf("TSNO : TRUE\n");
if( Mptr->DollarSign)
printf("DOLLAR $IGN INDCATR : TRUE\n");
if( Mptr->horiz_vsby[ 0 ] != '\0' )
printf("HORIZ VISIBILITY : %s\n",Mptr->horiz_vsby);
if( Mptr->dir_min_horiz_vsby[ 0 ] != '\0' )
printf("DIR MIN HORIZ VSBY : %s\n",Mptr->dir_min_horiz_vsby);
if( Mptr->CAVOK )
printf("CAVOK : TRUE\n");
if( Mptr->VertVsby != MAXINT )
printf("Vert. Vsby (meters) : %d\n",
Mptr->VertVsby );
if( Mptr->charVertVsby[0] != '\0' )
printf("Vert. Vsby (CHAR) : %s\n",
Mptr->charVertVsby );
if( Mptr->QFE != MAXINT )
printf("QFE : %d\n", Mptr->QFE);
if( Mptr->VOLCASH )
printf("VOLCANIC ASH : TRUE\n");
if( Mptr->min_vrbl_wind_dir != MAXINT )
printf("MIN VRBL WIND DIR : %d\n",Mptr->min_vrbl_wind_dir);
if( Mptr->max_vrbl_wind_dir != MAXINT )
printf("MAX VRBL WIND DIR : %d\n",Mptr->max_vrbl_wind_dir);
printf("\n\n\n");
return;
}

View File

@@ -0,0 +1,69 @@
There are 2 classes: CMetarStation (MetarStation.h) and CMetarReport
(MetarReport.h). These classes provide mechanisms to get information
about meteorological data reporting stations and about the reports
themselves. These stations and reports are known as METAR. See
http://tgsv5.nws.noaa.gov/oso/oso1/oso12/metar.htm for information
from the USA perspective. Quoting from that site:
On 1 July 1996, the international standard code for hourly and special
surface weather observations, METAR/SPECI, took effect.
The METAR acronym roughly translates from the French as Aviation
Routine Weather Report . A special report, SPECI, is merely a METAR
formatted report which is issued on a non-routine basis as dictated by
changing meteorological conditions. The SPECI acronym roughly translates as
Aviation Selected Special Weather Report . Meanwhile, the international
standard code format for terminal forecasts issued for airports, TAF,
also took effect. The acronym translates to Aerodrome Forecast.
This implementation ignores the SPECI and TAF acronyms, calling the
entire system METAR.
The class CMetarStation is implemented by MetarStation.h and
MetarStation.cpp. It decodes a text file containing information about
individual METAR reporting stations and builds a static database of that
information during static construction of the class. There are static
member methods to find individual stations, and member functions to
extract individual station attributes. The information about METAR
stations probably has some overlap with FGFS airport information. That
needs to be investigated. The METAR station information is kept in this
file:
http://www.nws.noaa.gov/pub/stninfo/nsd_cccc.gz
http://www.nws.noaa.gov/pub/stninfo/nsd_cccc.txt
This class looks for the file FG_ROOT/Weather/MetarStations instead of
nsd_cccc.
The current implementation does not look for updates to this file on the
internet.
The class CMetarReport is implemented by MetarReport.h and MetarReport.cpp.
It encapsulates the decoding software written by Carl McCalla at -
NOAA/National Weather Service
1325 East-West Highway
SSMC2, W/OSO242, Station 5114
Silver Spring, Maryland 20910
Work: (301) 713-0882, Ext 115
FAX: (301) 608-0911
E-Mail Address: cmccalla@smtpgate.ssmc.noaa.gov
http://www.nws.noaa.gov/software/
This software generally sucks and the CMetarReport class attempts to clean
up some of that suckiness. A CMetarReport object is created with an ASCII
string as a construction parameter. The string contains a METAR report.
There
are member methods to extract selected information from a report by calling
the McCalla software. Additional information can be selected by adding new
member methods as needed. Certainly the methods currently implemented are
not sufficient. METAR reports are available via the internet. In the USA,
NOAA provides individual METAR reports in this directory:
ftp://weather.noaa.gov/data/observations/metar/stations
Other sources are available as well. The current implementation does not
look for reports on the internet.
There is a test program in the MetarTest subdirectory. It requires that a
#define be changed in the MetarStation.cpp file. Add #define TESTPROG to
the code or -D TESTPROG to the compilation. This is necessary because the
FGFS options class is coupled tightly to code that shouldn't be pulled into
the test program. The test program will decode many METAR reports and
display
them to the screen, then it will plot all the METAR reporting stations on a
tumbling globe.

211
simgear/metar/Stspack2.cpp Normal file
View File

@@ -0,0 +1,211 @@
#pragma comment (compiler)
//#pragma comment (date)
//#pragma comment (timestamp)
#pragma pagesize(80)
#include "Local.h" /* standard header file */
#pragma page(1)
#pragma subtitle(" ")
#pragma subtitle("stspack2 - Local string test functions ")
/********************************************************************/
/* */
/* Title: stspack2 */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 05 Oct 1992 */
/* Programmer: ALLAN DARLING */
/* Language: C/2 */
/* */
/* Abstract: The stspack2 package contains functions to */
/* perform the isalnum through isxdigit functions */
/* on strings. The functions come in four forms: */
/* those that test NULL delimited strings and are */
/* named in the form sxxxxxxx, those that test at */
/* most n characters and are named in the form */
/* nxxxxxxx, those that search forward in a string */
/* and are named in the form nxtyyyyy, and those */
/* that search backward in a string and are named */
/* in the form lstyyyyy. */
/* */
/* The xxxxxxx is the name of the test applied to */
/* each character in the string, such as isalpha, */
/* thus a function to test a NULL delimited string */
/* an return a nonzero value if all characters in */
/* the string are digits is named sisdigit. */
/* */
/* The yyyyy is the name of the test applied to */
/* characters in a string, minus the 'is' prefix. */
/* Thus a function to find the next digit in a NULL */
/* delimited string and return a pointer to it is */
/* named nxtdigit. */
/* */
/* The only exception to the naming rule is for the */
/* functions that test for hexadecimal digits. */
/* These are named sisxdigi, nisxdigi, nxtxdigi, */
/* and lstxdigi because of the eight character */
/* function name limitation. */
/* */
/* The nxxxxxxx class of functions will test up to */
/* n characters or the first NULL character */
/* encountered, whichever comes first. For all */
/* classes of functions, the string sentinal is */
/* not included in the test. */
/* */
/* External Functions Called: */
/* isalnum, isalpha, iscntrl, isdigit, isgraph, */
/* islower, isprint, ispunct, isspace, isupper, */
/* isxdigit. */
/* */
/* Input: For sxxxxxxx class functions, a pointer to a */
/* NULL delimited character string. */
/* */
/* For nxtyyyyy class functions, a pointer to a */
/* NULL delimited character string. */
/* */
/* for nxxxxxxx class functions, a pointer to a */
/* character array, and a positive, nonzero integer.*/
/* */
/* for lstyyyyy class functions, a pointer to a */
/* character array, and a positive, nonzero integer.*/
/* */
/* Output: A nonzero value if the test is true for all */
/* characters in the string, a zero value otherwise.*/
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
#pragma page(1)
int nisalnum(char *s, int n) {
for (; *s && n; s++, n--)
if (!isalnum(*s))
return (0);
return (1);
} /* end nisalnum */
int nisalpha(char *s, int n) {
for (; *s && n; s++, n--)
if (!isalpha(*s))
return (0);
return (1);
} /* end nisalpha */
int niscntrl(char *s, int n) {
for (; *s && n; s++, n--)
if (!iscntrl(*s))
return (0);
return (1);
} /* end niscntrl */
int nisdigit(char *s, int n) {
for (; *s && n; s++, n--)
if (!isdigit(*s))
return (0);
return (1);
} /* end nisdigit */
int nisgraph(char *s, int n) {
for (; *s && n; s++, n--)
if (!isgraph(*s))
return (0);
return (1);
} /* end nisgraph */
int nislower(char *s, int n) {
for (; *s && n; s++, n--)
if (!islower(*s))
return (0);
return (1);
} /* end nislower */
int nisprint(char *s, int n) {
for (; *s && n; s++, n--)
if (!isprint(*s))
return (0);
return (1);
} /* end nisprint */
int nispunct(char *s, int n) {
for (; *s && n; s++, n--)
if (!ispunct(*s))
return (0);
return (1);
} /* end nispunct */
int nisspace(char *s, int n) {
for (; *s && n; s++, n--)
if (!isspace(*s))
return (0);
return (1);
} /* end nisspace */
int nisupper(char *s, int n) {
for (; *s && n; s++, n--)
if (!isupper(*s))
return (0);
return (1);
} /* end nisupper */
int nisxdigi(char *s, int n) {
for (; *s && n; s++, n--)
if (!isxdigit(*s))
return (0);
return (1);
} /* end nisxdigi */
#pragma page(1)

211
simgear/metar/Stspack3.cpp Normal file
View File

@@ -0,0 +1,211 @@
#pragma comment (compiler)
//#pragma comment (date)
//#pragma comment (timestamp)
#pragma pagesize(80)
#include "Local.h" /* standard header file */
#pragma page(1)
#pragma subtitle(" ")
#pragma subtitle("stspack3 - Local string test functions ")
/********************************************************************/
/* */
/* Title: stspack3 */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 05 Oct 1992 */
/* Programmer: ALLAN DARLING */
/* Language: C/2 */
/* */
/* Abstract: The stspack3 package contains functions to */
/* perform the isalnum through isxdigit functions */
/* on strings. The functions come in four forms: */
/* those that test NULL delimited strings and are */
/* named in the form sxxxxxxx, those that test at */
/* most n characters and are named in the form */
/* nxxxxxxx, those that search forward in a string */
/* and are named in the form nxtyyyyy, and those */
/* that search backward in a string and are named */
/* in the form lstyyyyy. */
/* */
/* The xxxxxxx is the name of the test applied to */
/* each character in the string, such as isalpha, */
/* thus a function to test a NULL delimited string */
/* an return a nonzero value if all characters in */
/* the string are digits is named sisdigit. */
/* */
/* The yyyyy is the name of the test applied to */
/* characters in a string, minus the 'is' prefix. */
/* Thus a function to find the next digit in a NULL */
/* delimited string and return a pointer to it is */
/* named nxtdigit. */
/* */
/* The only exception to the naming rule is for the */
/* functions that test for hexadecimal digits. */
/* These are named sisxdigi, nisxdigi, nxtxdigi, */
/* and lstxdigi because of the eight character */
/* function name limitation. */
/* */
/* The nxxxxxxx class of functions will test up to */
/* n characters or the first NULL character */
/* encountered, whichever comes first. For all */
/* classes of functions, the string sentinal is */
/* not included in the test. */
/* */
/* External Functions Called: */
/* isalnum, isalpha, iscntrl, isdigit, isgraph, */
/* islower, isprint, ispunct, isspace, isupper, */
/* isxdigit. */
/* */
/* Input: For sxxxxxxx class functions, a pointer to a */
/* NULL delimited character string. */
/* */
/* For nxtyyyyy class functions, a pointer to a */
/* NULL delimited character string. */
/* */
/* for nxxxxxxx class functions, a pointer to a */
/* character array, and a positive, nonzero integer.*/
/* */
/* for lstyyyyy class functions, a pointer to a */
/* character array, and a positive, nonzero integer.*/
/* */
/* Output: A nonzero value if the test is true for all */
/* characters in the string, a zero value otherwise.*/
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
#pragma page(1)
char *nxtalnum(char *s) {
for (; !isalnum(*s) && *s; s++) ;
if (*s)
return (s);
else
return (NULL);
} /* end nxtalnum */
char *nxtalpha(char *s) {
for (; !isalpha(*s) && *s; s++) ;
if (*s)
return (s);
else
return (NULL);
} /* end nxtalpha */
char *nxtcntrl(char *s) {
for (; !iscntrl(*s) && *s; s++) ;
if (*s)
return (s);
else
return (NULL);
} /* end nxtcntrl */
char *nxtdigit(char *s) {
for (; !isdigit(*s) && *s; s++) ;
if (*s)
return (s);
else
return (NULL);
} /* end nxtdigit */
char *nxtgraph(char *s) {
for (; !isgraph(*s) && *s; s++) ;
if (*s)
return (s);
else
return (NULL);
} /* end nxtgraph */
char *nxtlower(char *s) {
for (; !islower(*s) && *s; s++) ;
if (*s)
return (s);
else
return (NULL);
} /* end nxtlower */
char *nxtprint(char *s) {
for (; !isprint(*s) && *s; s++) ;
if (*s)
return (s);
else
return (NULL);
} /* end nxtprint */
char *nxtpunct(char *s) {
for (; !ispunct(*s) && *s; s++) ;
if (*s)
return (s);
else
return (NULL);
} /* end nxtpunct */
char *nxtspace(char *s) {
for (; !isspace(*s) && *s; s++) ;
if (*s)
return (s);
else
return (NULL);
} /* end nxtspace */
char *nxtupper(char *s) {
for (; !isupper(*s) && *s; s++) ;
if (*s)
return (s);
else
return (NULL);
} /* end nxtupper */
char *nxtxdigi(char *s) {
for (; !isxdigit(*s) && *s; s++) ;
if (*s)
return (s);
else
return (NULL);
} /* end nxtxdigi */
#pragma page(1)

26
simgear/misc/Makefile.am Normal file
View File

@@ -0,0 +1,26 @@
includedir = @includedir@/misc
if HAVE_ZLIB
ZLIB_INCL =
else
ZLIB_INCL = -I$(top_builddir)/zlib
endif
lib_LIBRARIES = libsgmisc.a
include_HEADERS = \
fgpath.hxx \
fgstream.hxx \
stopwatch.hxx \
strutils.hxx \
texcoord.hxx \
zfstream.hxx
libsgmisc_a_SOURCES = \
fgpath.cxx \
fgstream.cxx \
strutils.cxx \
texcoord.cxx \
zfstream.cxx
INCLUDES += -I$(top_builddir)/src

101
simgear/misc/fgpath.cxx Normal file
View File

@@ -0,0 +1,101 @@
//
// fgpath.cxx -- routines to abstract out path separator differences
// between MacOS and the rest of the world
//
// Written by Curtis L. Olson, started April 1999.
//
// Copyright (C) 1999 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$
#include "fgpath.hxx"
// If Unix, replace all ":" with "/". If MacOS, replace all "/" with
// ":" it should go without saying that neither of these characters
// should be used in file or directory names. In windoze, allow the
// second character to be a ":" for things like c:\foo\bar
static string fix_path( const string path ) {
string result = path;
for ( int i = 0; i < (int)path.size(); ++i ) {
#if defined( WIN32 )
// for windoze, don't replace the ":" for the second character
if ( i == 1 ) {
continue;
}
#endif
if ( result[i] == FG_BAD_PATH_SEP ) {
result[i] = FG_PATH_SEP;
}
}
return result;
}
// default constructor
FGPath::FGPath() {
path = "";
}
// create a path based on "path"
FGPath::FGPath( const string p ) {
set( p );
}
// destructor
FGPath::~FGPath() {
}
// set path
void FGPath::set( const string p ) {
path = fix_path( p );
}
// append another piece to the existing path
void FGPath::append( const string p ) {
string part = fix_path( p );
if ( path.size() == 0 ) {
path = part;
} else {
if ( part[0] != FG_PATH_SEP ) {
path += FG_PATH_SEP;
}
path += part;
}
}
// concatenate a string to the end of the path without inserting a
// path separator
void FGPath::concat( const string p ) {
string part = fix_path( p );
if ( path.size() == 0 ) {
path = part;
} else {
path += part;
}
}

85
simgear/misc/fgpath.hxx Normal file
View File

@@ -0,0 +1,85 @@
//
// fgpath.hxx -- routines to abstract out path separator differences
// between MacOS and the rest of the world
//
// Written by Curtis L. Olson, started April 1999.
//
// Copyright (C) 1999 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 _FGPATH_HXX
#define _FGPATH_HXX
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <simgear/compiler.h>
#include STL_STRING
FG_USING_STD(string);
#ifdef MACOS
# define FG_PATH_SEP ':'
# define FG_BAD_PATH_SEP '/'
#else
# define FG_PATH_SEP '/'
# define FG_BAD_PATH_SEP ':'
#endif
class FGPath {
private:
string path;
public:
// default constructor
FGPath();
// create a path based on "path"
FGPath( const string p );
// destructor
~FGPath();
// set path
void set( const string p );
// append another piece to the existing path
void append( const string p );
// concatenate a string to the end of the path without inserting a
// path separator
void concat( const string p );
// get the path string
inline string str() const { return path; }
inline const char *c_str() { return path.c_str(); }
};
#endif // _FGPATH_HXX

158
simgear/misc/fgstream.cxx Normal file
View File

@@ -0,0 +1,158 @@
// zlib input file stream wrapper.
//
// Written by Bernie Bright, 1998
//
// Copyright (C) 1998 Bernie Bright - bbright@c031.aone.net.au
//
// 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 <ctype.h> // isspace()
#include "fgstream.hxx"
fg_gzifstream::fg_gzifstream()
: istream(&gzbuf)
{
}
//-----------------------------------------------------------------------------
//
// Open a possibly gzipped file for reading.
//
fg_gzifstream::fg_gzifstream( const string& name, ios_openmode io_mode )
: istream(&gzbuf)
{
this->open( name, io_mode );
}
//-----------------------------------------------------------------------------
//
// Attach a stream to an already opened file descriptor.
//
fg_gzifstream::fg_gzifstream( int fd, ios_openmode io_mode )
: istream(&gzbuf)
{
gzbuf.attach( fd, io_mode );
}
//-----------------------------------------------------------------------------
//
// Open a possibly gzipped file for reading.
// If the initial open fails and the filename has a ".gz" extension then
// remove the extension and try again.
// If the initial open fails and the filename doesn't have a ".gz" extension
// then append ".gz" and try again.
//
void
fg_gzifstream::open( const string& name, ios_openmode io_mode )
{
gzbuf.open( name.c_str(), io_mode );
if ( ! gzbuf.is_open() )
{
string s = name;
if ( s.substr( s.length() - 3, 3 ) == ".gz" )
{
// remove ".gz" suffix
s.replace( s.length() - 3, 3, "" );
// s.erase( s.length() - 3, 3 );
}
else
{
// Append ".gz" suffix
s += ".gz";
}
// Try again.
gzbuf.open( s.c_str(), io_mode );
}
}
void
fg_gzifstream::attach( int fd, ios_openmode io_mode )
{
gzbuf.attach( fd, io_mode );
}
//
// Manipulators
//
istream&
skipeol( istream& in )
{
char c = '\0';
// skip to end of line.
#ifdef __MWERKS__
while ( in.get(c) && c != '\0' ) {
#else
while ( in.get(c) ) {
#endif
if ( (c == '\n') || (c == '\r') ) {
break;
}
}
return in;
}
istream&
skipws( istream& in ) {
char c;
#ifdef __MWERKS__
while ( in.get(c) && c != '\0' ) {
#else
while ( in.get(c) ) {
#endif
#ifdef __MWERKS__
if ( ! isspace( c ) && c != '\n' ) {
#else
if ( ! isspace( c ) ) {
#endif
// put pack the non-space character
in.putback(c);
break;
}
}
return in;
}
istream&
skipcomment( istream& in )
{
while ( in )
{
// skip whitespace
#ifdef __MWERKS__
in >> ::skipws;
#else
in >> skipws;
#endif
char c;
if ( in.get( c ) && c != '#' )
{
// not a comment
in.putback(c);
break;
}
in >> skipeol;
}
return in;
}

102
simgear/misc/fgstream.hxx Normal file
View File

@@ -0,0 +1,102 @@
// zlib input file stream wrapper.
//
// Written by Bernie Bright, 1998
//
// Copyright (C) 1998 Bernie Bright - bbright@c031.aone.net.au
//
// 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 _FGSTREAM_HXX
#define _FGSTREAM_HXX
#ifndef __cplusplus
# error This library requires C++
#endif
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <simgear/compiler.h>
#if defined( FG_HAVE_STD_INCLUDES )
# include <istream>
#elif defined ( FG_HAVE_NATIVE_SGI_COMPILERS )
# include <CC/stream.h>
#elif defined ( __BORLANDC__ )
# include <iostream>
#else
# include <istream.h>
#endif
#include STL_STRING
#include <simgear/misc/zfstream.hxx>
FG_USING_STD(string);
#ifndef FG_HAVE_NATIVE_SGI_COMPILERS
FG_USING_STD(istream);
#endif
//-----------------------------------------------------------------------------
//
// Envelope class for gzifstream.
//
class fg_gzifstream : private gzifstream_base, public istream
{
public:
//
fg_gzifstream();
// Attempt to open a file with and without ".gz" extension.
fg_gzifstream( const string& name,
ios_openmode io_mode = ios_in | ios_binary );
//
fg_gzifstream( int fd, ios_openmode io_mode = ios_in|ios_binary );
// Attempt to open a file with and without ".gz" extension.
void open( const string& name,
ios_openmode io_mode = ios_in|ios_binary );
void attach( int fd, ios_openmode io_mode = ios_in|ios_binary );
void close() { gzbuf.close(); }
bool is_open() { return gzbuf.is_open(); }
private:
// Not defined!
fg_gzifstream( const fg_gzifstream& );
void operator= ( const fg_gzifstream& );
};
// istream manipulator that skips to end of line.
istream& skipeol( istream& in );
// istream manipulator that skips over white space.
istream& skipws( istream& in );
// istream manipulator that skips comments and white space.
// A comment starts with '#'.
istream& skipcomment( istream& in );
#endif /* _FGSTREAM_HXX */

121
simgear/misc/stopwatch.hxx Normal file
View File

@@ -0,0 +1,121 @@
/***************************************************************************
* stopwatch.hxx Timer class, for use in benchmarking
*
* Based on blitz/Timer.h
*
* $Id$
*
* Copyright (C) 1997,1998 Todd Veldhuizen <tveldhui@seurat.uwaterloo.ca>
*
* 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.
*
* Suggestions: blitz-suggest@cybervision.com
* Bugs: blitz-bugs@cybervision.com
*
* For more information, please see the Blitz++ Home Page:
* http://seurat.uwaterloo.ca/blitz/
*
*/
// This class is not portable to non System V platforms.
// It will need to be rewritten for Windows, NT, Mac.
// NEEDS_WORK
#ifndef _STOPWATCH_HXX
#define _STOPWATCH_HXX
#ifndef __cplusplus
# error This library requires C++
#endif
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#if defined(__linux__) && ! defined(HAVE_GETRUSAGE)
# define HAVE_GETRUSAGE
#endif
#if defined( WIN32 ) && defined( HAVE_GETRUSAGE )
# undef HAVE_GETRUSAGE
#endif // WIN32
#if defined( HAVE_GETRUSAGE )
# if defined( __FreeBSD__ )
# include <sys/types.h>
# endif
# include <sys/time.h>
# include <sys/resource.h>
# include <unistd.h>
#elif defined( WIN32 )
# include <windows.h>
#else
# include <time.h>
#endif
class StopWatch {
public:
StopWatch()
{
// state_ = uninitialized;
}
void start()
{
// state_ = running;
t1_ = systemTime();
}
void stop()
{
t2_ = systemTime();
// BZPRECONDITION(state_ == running);
// state_ = stopped;
}
double elapsedSeconds()
{
// BZPRECONDITION(state_ == stopped);
return t2_ - t1_;
}
private:
StopWatch(StopWatch&) { }
void operator=(StopWatch&) { }
double systemTime()
{
#if defined( HAVE_GETRUSAGE )
getrusage(RUSAGE_SELF, &resourceUsage_);
double seconds = resourceUsage_.ru_utime.tv_sec
+ resourceUsage_.ru_stime.tv_sec;
double micros = resourceUsage_.ru_utime.tv_usec
+ resourceUsage_.ru_stime.tv_usec;
return seconds + micros/1.0e6;
#elif defined( WIN32 )
return double(GetTickCount()) * double(1e-3);
#else
return clock() / (double) CLOCKS_PER_SEC;
#endif
}
// enum { uninitialized, running, stopped } state_;
#if defined( HAVE_GETRUSAGE )
struct rusage resourceUsage_;
#endif
double t1_, t2_;
};
#endif // _STOPWATCH_HXX

71
simgear/misc/strutils.cxx Normal file
View File

@@ -0,0 +1,71 @@
// String utilities.
//
// Written by Bernie Bright, 1998
//
// Copyright (C) 1998 Bernie Bright - bbright@c031.aone.net.au
//
// 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$
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "strutils.hxx"
const string whitespace = " \n\r\t";
//
string
trimleft( const string& s, const string& trimmings )
{
string result;
string::size_type pos = s.find_first_not_of( trimmings );
if ( pos != string::npos )
{
result.assign( s.substr( pos ) );
}
return result;
}
//
string
trimright( const string& s, const string& trimmings )
{
string result;
string::size_type pos = s.find_last_not_of( trimmings );
if ( pos == string::npos )
{
// Not found, return the original string.
result = s;
}
else
{
result.assign( s.substr( 0, pos+1 ) );
}
return result;
}
//
string
trim( const string& s, const string& trimmings )
{
return trimright( trimleft( s, trimmings ), trimmings );
}

65
simgear/misc/strutils.hxx Normal file
View File

@@ -0,0 +1,65 @@
// String utilities.
//
// Written by Bernie Bright, 1998
//
// Copyright (C) 1998 Bernie Bright - bbright@c031.aone.net.au
//
// 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 STRUTILS_H
#define STRUTILS_H
#include <simgear/compiler.h>
#include STL_STRING
#ifdef FG_HAVE_STD_INCLUDES
# include <cstdlib>
#else
# include <stdlib.h>
#endif
FG_USING_STD(string);
// Default characters to remove.
extern const string whitespace;
// Returns a string with trailing characters removed.
string trimleft( const string& s, const string& trimmings = whitespace );
// Returns a string with leading characters removed.
string trimright( const string& s, const string& trimmings = whitespace );
// Returns a string with leading and trailing characters removed.
string trim( const string& s, const string& trimmings = whitespace );
//-----------------------------------------------------------------------------
inline double
atof( const string& str )
{
return ::atof( str.c_str() );
}
inline int
atoi( const string& str )
{
return ::atoi( str.c_str() );
}
#endif // STRUTILS_H

197
simgear/misc/texcoord.cxx Normal file
View File

@@ -0,0 +1,197 @@
// texcoord.hxx -- routine(s) to handle texture coordinate generation
//
// Written by Curtis Olson, started March 1999.
//
// Copyright (C) 1999 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$
#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 )
// return the basic unshifted/unmoded texture coordinate for a lat/lon
inline Point3D basic_tex_coord( const Point3D& p,
double degree_width, double degree_height,
double scale )
{
return Point3D( p.x() * ( degree_width * scale /
FG_STANDARD_TEXTURE_DIMENSION ),
p.y() * ( degree_width * scale /
FG_STANDARD_TEXTURE_DIMENSION ),
0.0 );
}
// 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,
const int_list& fan, double scale )
{
// cout << "calculating texture coordinates for a specific fan of size = "
// << fan.size() << endl;
// calculate perimeter based on center of this degree (not center
// of bucket)
double clat = (int)b.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;
// cout << "clat = " << clat << endl;
// cout << "clat (radians) = " << clat_rad << endl;
// cout << "cos(lat) = " << cos_lat << endl;
// cout << "local_radius = " << local_radius << endl;
// cout << "local_perimeter = " << local_perimeter << endl;
// cout << "degree_width = " << degree_width << endl;
double perimeter = 2.0 * EQUATORIAL_RADIUS_M * FG_PI;
double degree_height = perimeter / 360.0;
// cout << "degree_height = " << degree_height << endl;
// find min/max of fan
Point3D tmin, tmax, p, t;
bool first = true;
for ( int i = 0; i < (int)fan.size(); ++i ) {
p = geod_nodes[ fan[i] ];
// cout << "point p = " << p << endl;
t = basic_tex_coord( p, degree_width, degree_height, scale );
// cout << "basic_tex_coord = " << t << endl;
if ( first ) {
tmin = tmax = t;
first = false;
} else {
if ( t.x() < tmin.x() ) {
tmin.setx( t.x() );
}
if ( t.y() < tmin.y() ) {
tmin.sety( t.y() );
}
if ( t.x() > tmax.x() ) {
tmax.setx( t.x() );
}
if ( t.y() > tmax.y() ) {
tmax.sety( t.y() );
}
}
}
double dx = fabs( tmax.x() - tmin.x() );
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;
tmin.setx( (double)( (int)tmin.x() + 1 ) );
tmin.sety( (double)( (int)tmin.y() + 1 ) );
// cout << "found tmin = " << tmin << endl;
} else {
// structure is small enough ... we can mod it so we can
// properly scale the texture coordinates later.
// cout << "MODDING" << endl;
double x1 = fmod(tmin.x(), MAX_TEX_COORD);
while ( x1 < 0 ) { x1 += MAX_TEX_COORD; }
double y1 = fmod(tmin.y(), MAX_TEX_COORD);
while ( y1 < 0 ) { y1 += MAX_TEX_COORD; }
double x2 = fmod(tmax.x(), MAX_TEX_COORD);
while ( x2 < 0 ) { x2 += MAX_TEX_COORD; }
double y2 = fmod(tmax.y(), MAX_TEX_COORD);
while ( y2 < 0 ) { y2 += MAX_TEX_COORD; }
// At this point we know that the object is < 16 wide in
// texture coordinate space. If the modulo of the tmin is >
// the mod of the tmax at this point, then we know that the
// starting tex coordinate for the tmin > 16 so we can shift
// everything down by 16 and get it within the 0-32 range.
if ( x1 > x2 ) {
mod_shift.setx( HALF_MAX_TEX_COORD );
} else {
mod_shift.setx( 0.0 );
}
if ( y1 > y2 ) {
mod_shift.sety( HALF_MAX_TEX_COORD );
} else {
mod_shift.sety( 0.0 );
}
// cout << "mod_shift = " << mod_shift << endl;
}
// generate tex_list
Point3D adjusted_t;
point_list tex;
tex.clear();
for ( int i = 0; i < (int)fan.size(); ++i ) {
p = geod_nodes[ fan[i] ];
t = basic_tex_coord( p, degree_width, degree_height, scale );
// cout << "second t = " << t << endl;
if ( do_shift ) {
adjusted_t = t - tmin;
} else {
adjusted_t.setx( fmod(t.x() + mod_shift.x(), MAX_TEX_COORD) );
while ( adjusted_t.x() < 0 ) {
adjusted_t.setx( adjusted_t.x() + MAX_TEX_COORD );
}
adjusted_t.sety( fmod(t.y() + mod_shift.y(), MAX_TEX_COORD) );
while ( adjusted_t.y() < 0 ) {
adjusted_t.sety( adjusted_t.y() + MAX_TEX_COORD );
}
// cout << "adjusted_t " << adjusted_t << endl;
}
if ( adjusted_t.x() < FG_EPSILON ) {
adjusted_t.setx( 0.0 );
}
if ( adjusted_t.y() < FG_EPSILON ) {
adjusted_t.sety( 0.0 );
}
adjusted_t.setz( 0.0 );
// cout << "adjusted_t = " << adjusted_t << endl;
tex.push_back( adjusted_t );
}
return tex;
}

45
simgear/misc/texcoord.hxx Normal file
View File

@@ -0,0 +1,45 @@
// texcoord.hxx -- routine(s) to handle texture coordinate generation
//
// Written by Curtis Olson, started March 1999.
//
// Copyright (C) 1999 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 _TEXCOORD_HXX
#define _TEXCOORD_HXX
#ifndef __cplusplus
# error This library requires C++
#endif
#include <simgear/bucket/newbucket.hxx>
#include <simgear/math/fg_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,
const int_list& fan, double scale = 1.0 );
#endif // _TEXCOORD_HXX

313
simgear/misc/zfstream.cxx Normal file
View File

@@ -0,0 +1,313 @@
// A C++ I/O streams interface to the zlib gz* functions
//
// Written by Bernie Bright, 1998
// Based on zlib/contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
//
// Copyright (C) 1998 Bernie Bright - bbright@c031.aone.net.au
//
// 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 <memory.h>
#include "zfstream.hxx"
//
// Construct a gzfilebuf object.
// Allocate memory for 'get' buffer and zero all buffer pointers.
//
gzfilebuf::gzfilebuf()
: streambuf(),
file(NULL),
#if defined( __MWERKS__ )
mode(ios_openmode(0)),
#else
mode(0),
#endif
own_file_descriptor(false),
ibuf_size(0),
ibuffer(0)
{
// try {
ibuf_size = page_size / sizeof(char);
ibuffer = new char [ibuf_size];
// } catch (...) {
// delete [] ibuffer;
// }
// Null get and set pointers.
this->setg(0,0,0);
this->setp(0,0);
}
gzfilebuf::~gzfilebuf()
{
sync();
if ( own_file_descriptor )
this->close();
delete [] ibuffer;
}
void
gzfilebuf::cvt_iomode( char* p, ios_openmode io_mode )
{
// memset( char_mode, '\0', 10 );
// char* p = char_mode;
if ( io_mode & ios_in )
{
mode = ios_in;
*p++ = 'r';
}
else if ( io_mode & ios_app )
{
mode = ios_app;
*p++ = 'a';
}
else
{
mode = ios_out;
*p++ = 'w';
}
if ( io_mode & ios_binary )
{
mode |= ios_binary;
*p++ = 'b';
}
// Hard code the compression level
if ( io_mode & (ios_out | ios_app) )
{
*p++ = '9';
}
*p = '\0';
}
gzfilebuf*
gzfilebuf::open( const char *name, ios_openmode io_mode )
{
if ( is_open() )
return NULL;
char char_mode[10];
cvt_iomode( char_mode, io_mode );
if ( (file = gzopen(name, char_mode)) == NULL )
return NULL;
own_file_descriptor = true;
return this;
}
gzfilebuf*
gzfilebuf::attach( int file_descriptor, ios_openmode io_mode )
{
if ( is_open() )
return NULL;
char char_mode[10];
cvt_iomode( char_mode, io_mode );
if ( (file = gzdopen(file_descriptor, char_mode)) == NULL )
return NULL;
own_file_descriptor = false;
return this;
}
gzfilebuf*
gzfilebuf::close()
{
if ( is_open() )
{
sync();
gzclose( file );
file = NULL;
}
return this;
}
// int
// gzfilebuf::setcompressionlevel( int comp_level )
// {
// return gzsetparams(file, comp_level, -2);
// }
// int
// gzfilebuf::setcompressionstrategy( int comp_strategy )
// {
// return gzsetparams(file, -2, comp_strategy);
// }
streampos
gzfilebuf::seekoff( streamoff, ios_seekdir, int )
{
return streampos(EOF);
}
gzfilebuf::int_type
gzfilebuf::overflow( int_type )
{
#if 0
if ( !is_open() || !(mode & ios::out) )
return EOF;
if ( !base() )
{
if ( allocate() == EOF )
return EOF;
setg(0,0,0);
}
else
{
if (in_avail())
{
return EOF;
}
if (out_waiting())
{
if (flushbuf() == EOF)
return EOF;
}
}
int bl = blen();
setp( base(), base() + bl);
if ( c != EOF )
{
*pptr() = c;
pbump(1);
}
#endif
return 0;
}
int
gzfilebuf::sync()
{
if ( !is_open() )
return EOF;
if ( pptr() != 0 && pptr() > pbase() )
return flushbuf();
return 0;
}
gzfilebuf::int_type
gzfilebuf::flushbuf()
{
char* q = pbase();
int n = pptr() - q;
if ( gzwrite( file, q, n) < n )
return traits_type::eof();
setp(0,0);
return 0;
}
gzfilebuf::int_type
gzfilebuf::underflow()
{
// cerr << "gzfilebuf::underflow(): gptr()=" << (void*)gptr() << endl;
// Error if the file not open for reading.
if ( !is_open() || !(mode & ios_in) )
return traits_type::eof();
// If the input buffer is empty then try to fill it.
if ( gptr() != 0 && gptr() < egptr() )
{
return int_type(*gptr());
}
else
{
return fillbuf() == EOF ? traits_type::eof() : int_type(*gptr());
}
}
//
// Load the input buffer from the underlying gz file.
// Returns number of characters read, or EOF.
//
int
gzfilebuf::fillbuf()
{
int t = gzread( file, ibuffer, ibuf_size );
if ( t <= 0)
{
// disable get area
setg(0,0,0);
return EOF;
}
// Set the input (get) pointers
setg( ibuffer, ibuffer, ibuffer+t );
// cerr << "gzfilebuf::fillbuf():"
// << " t=" << t
// << ", ibuffer=" << (void*)ibuffer
// << ", ibuffer+t=" << (void*)(ibuffer+t) << endl;
return t;
}
#if 0
gzifstream::gzifstream()
: istream(&buffer), buffer()
{
clear( ios_badbit );
}
gzifstream::gzifstream( const char *name, ios_openmode io_mode )
: istream(&buffer), buffer()
{
this->open( name, io_mode );
}
gzifstream::gzifstream( int fd, ios_openmode io_mode )
: istream(&buffer), buffer()
{
buffer.attach( fd, io_mode );
}
gzifstream::~gzifstream()
{
}
void
gzifstream::open( const char *name, ios_openmode io_mode )
{
if ( !buffer.open( name, io_mode ) )
clear( ios_failbit | ios_badbit );
else
clear();
}
void
gzifstream::close()
{
if ( !buffer.close() )
clear( ios_failbit | ios_badbit );
}
#endif

155
simgear/misc/zfstream.hxx Normal file
View File

@@ -0,0 +1,155 @@
// A C++ I/O streams interface to the zlib gz* functions
//
// Written by Bernie Bright, 1998
// Based on zlib/contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
//
// Copyright (C) 1998 Bernie Bright - bbright@c031.aone.net.au
//
// 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 _zfstream_hxx
#define _zfstream_hxx
#include <simgear/compiler.h>
#include <zlib.h>
#ifdef FG_HAVE_STD_INCLUDES
# include <streambuf>
# include <istream>
# define ios_openmode ios_base::openmode
# define ios_in ios_base::in
# define ios_out ios_base::out
# define ios_app ios_base::app
# define ios_binary ios_base::binary
# define ios_seekdir ios_base::seekdir
# define ios_badbit ios_base::badbit
# define ios_failbit ios_base::failbit
FG_USING_STD(streambuf);
FG_USING_STD(ios_base);
FG_USING_STD(streampos);
FG_USING_STD(streamoff);
#else
# ifdef FG_HAVE_STREAMBUF
# include <streambuf.h>
# include <istream.h>
# else
# include <iostream.h>
# endif
//# define ios_openmode ios::open_mode
# define ios_openmode int
# define ios_in ios::in
# define ios_out ios::out
# define ios_app ios::app
#if defined(__GNUC__) && __GNUC_MINOR__ < 8
# define ios_binary ios::bin
#elif defined( FG_HAVE_NATIVE_SGI_COMPILERS )
# define ios_binary 0
#else
# define ios_binary ios::binary
#endif
# define ios_seekdir ios::seek_dir
# define ios_badbit ios::badbit
# define ios_failbit ios::failbit
# include <simgear/fg_traits.hxx>
#endif // FG_HAVE_STD_INCLUDES
//-----------------------------------------------------------------------------
//
//
//
class gzfilebuf : public streambuf
{
public:
#ifndef FG_HAVE_STD_INCLUDES
typedef char_traits<char> traits_type;
typedef char_traits<char>::int_type int_type;
typedef char_traits<char>::pos_type pos_type;
typedef char_traits<char>::off_type off_type;
#endif
gzfilebuf();
virtual ~gzfilebuf();
gzfilebuf* open( const char* name, ios_openmode io_mode );
gzfilebuf* attach( int file_descriptor, ios_openmode io_mode );
gzfilebuf* close();
// int setcompressionlevel( int comp_level );
// int setcompressionstrategy( int comp_strategy );
bool is_open() const { return (file != NULL); }
virtual streampos seekoff( streamoff off, ios_seekdir way, int which );
virtual int sync();
protected:
virtual int_type underflow();
virtual int_type overflow( int_type c = traits_type::eof() );
private:
int_type flushbuf();
int fillbuf();
// Convert io_mode to "rwab" string.
void cvt_iomode( char* mode_str, ios_openmode io_mode );
private:
gzFile file;
ios_openmode mode;
bool own_file_descriptor;
// Get (input) buffer.
int ibuf_size;
char* ibuffer;
enum { page_size = 4096 };
private:
// Not defined
gzfilebuf( const gzfilebuf& );
void operator= ( const gzfilebuf& );
};
//-----------------------------------------------------------------------------
//
//
//
struct gzifstream_base
{
gzifstream_base() {}
gzfilebuf gzbuf;
};
#endif // _zfstream_hxx

82
simgear/screen/GLBitmaps.cxx Executable file
View File

@@ -0,0 +1,82 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_WINDOWS_H
# include <windows.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <GL/glut.h>
#include <simgear/xgl/xgl.h>
#include "GLBitmaps.h"
GlBitmap::GlBitmap( GLenum mode, GLint width, GLint height, GLubyte *bitmap )
: m_bytesPerPixel(mode==GL_RGB?3:4), m_width(width), m_height(height), m_bitmap(NULL)
{
m_bitmapSize = m_bytesPerPixel*m_width*m_height;
if ( !m_bitmapSize )
{
GLint vp[4];
glGetIntegerv( GL_VIEWPORT, vp );
m_width = vp[2];
m_height = vp[3];
m_bitmapSize = m_bytesPerPixel*m_width*m_height;
}
m_bitmap = (GLubyte *)malloc( m_bitmapSize );
if ( bitmap ) memcpy( m_bitmap, bitmap, m_bitmapSize );
else glReadPixels( 0,0, m_width,m_height, mode, GL_UNSIGNED_BYTE, m_bitmap );
}
GlBitmap::~GlBitmap( )
{
if ( m_bitmap ) free( m_bitmap );
}
GLubyte *GlBitmap::getBitmap()
{
return m_bitmap;
}
void GlBitmap::copyBitmap( GlBitmap *from, GLint at_x, GLint at_y )
{
GLint newWidth = at_x + from->m_width;
GLint newHeight = at_y + from->m_height;
if ( newWidth < m_width ) newWidth = m_width;
if ( newHeight < m_height ) newHeight = m_height;
m_bitmapSize = m_bytesPerPixel*newWidth*newHeight;
GLubyte *newBitmap = (GLubyte *)malloc( m_bitmapSize );
GLint x,y;
for ( y=0; y<m_height; y++ )
{
GLubyte *s = m_bitmap + m_bytesPerPixel * (y * m_width);
GLubyte *d = newBitmap + m_bytesPerPixel * (y * newWidth);
memcpy( d, s, m_bytesPerPixel * m_width );
}
m_width = newWidth;
m_height = newHeight;
free( m_bitmap );
m_bitmap = newBitmap;
for ( y=0; y<from->m_height; y++ )
{
GLubyte *s = from->m_bitmap + from->m_bytesPerPixel * (y * from->m_width);
GLubyte *d = m_bitmap + m_bytesPerPixel * ((at_y+y) * m_width + at_x);
for ( x=0; x<from->m_width; x++ )
{
d[0] = s[0];
d[1] = s[1];
d[2] = s[2];
if ( m_bytesPerPixel == 4 )
{
d[3] = (from->m_bytesPerPixel == 4) ? s[3] : 0;
}
s += from->m_bytesPerPixel;
d += m_bytesPerPixel;
}
}
}

14
simgear/screen/GLBitmaps.h Executable file
View File

@@ -0,0 +1,14 @@
class GlBitmap
{
public:
GlBitmap( GLenum mode=GL_RGB, GLint width=0, GLint height=0, GLubyte *bitmap=0 );
~GlBitmap();
GLubyte *getBitmap();
void copyBitmap( GlBitmap *from, GLint at_x, GLint at_y );
private:
GLint m_bytesPerPixel;
GLint m_width;
GLint m_height;
GLint m_bitmapSize;
GLubyte *m_bitmap;
};

View File

@@ -0,0 +1,12 @@
includedir = @includedir@/screen
lib_LIBRARIES = libsgscreen.a
include_HEADERS = screen-dump.hxx
libsgscreen_a_SOURCES = \
GLBitmaps.cxx GLBitmaps.h \
screen-dump.cxx \
win32-printer.h
INCLUDES += -I$(top_builddir)/src

View File

@@ -0,0 +1,83 @@
// screen-dump.cxx -- dump a copy of the opengl screen buffer to a file
//
// Contributed by Richard Kaszeta <bofh@me.umn.edu>, started October 1999.
//
// 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$
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_WINDOWS_H
# include <windows.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <GL/glut.h>
#include <simgear/xgl/xgl.h>
#include "screen-dump.hxx"
#define RGB 3 // 3 bytes of color info per pixel
#define RGBA 4 // 4 bytes of color+alpha info
void my_glWritePPMFile(const char *filename, GLubyte *buffer, int win_width, int win_height, int mode)
{
int i, j, k, q;
unsigned char *ibuffer;
FILE *fp;
int pixelSize = mode==GL_RGBA?4:3;
ibuffer = (unsigned char *) malloc(win_width*win_height*RGB);
fp = fopen(filename, "wb");
fprintf(fp, "P6\n# CREATOR: glReadPixel()\n%d %d\n%d\n",
win_width, win_height, UCHAR_MAX);
q = 0;
for (i = 0; i < win_height; i++)
for (j = 0; j < win_width; j++)
for (k = 0; k < RGB; k++)
ibuffer[q++] = (unsigned char)
*(buffer + (pixelSize*((win_height-1-i)*win_width+j)+k));
fwrite(ibuffer, sizeof(unsigned char), RGB*win_width*win_height, fp);
fclose(fp);
free(ibuffer);
printf("wrote file (%d x %d pixels, %d bytes)\n",
win_width, win_height, RGB*win_width*win_height);
}
// dump the screen buffer to a ppm file
void my_glDumpWindow(const char *filename, int win_width, int win_height) {
GLubyte *buffer;
buffer = (GLubyte *) malloc(win_width*win_height*RGBA);
// read window contents from color buffer with glReadPixels
glFinish();
glReadPixels(0, 0, win_width, win_height,
GL_RGBA, GL_UNSIGNED_BYTE, buffer);
my_glWritePPMFile( filename, buffer, win_width, win_height, GL_RGBA );
free(buffer);
}

View File

@@ -0,0 +1,26 @@
// screen-dump.hxx -- dump a copy of the opengl screen buffer to a file
//
// Contributed by Richard Kaszeta <bofh@me.umn.edu>, started October 1999.
//
// 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$
// dump the screen buffer to a ppm file
void my_glDumpWindow( const char *filename, int win_width, int win_height );
void my_glWritePPMFile( const char *filename, GLubyte *buffer, int win_width,
int win_height, int mode);

View File

@@ -0,0 +1,325 @@
class CGlPrinter
{
public:
typedef enum { RENDER_TO_PRINTER, RENDER_TO_BITMAP, READ_BITMAP, PRINT_BITMAP } PRINTMODE;
public:
inline CGlPrinter( PRINTMODE mode = READ_BITMAP );
inline ~CGlPrinter();
inline bool Begin( char *title, int w=0, int h=0 );
inline void End( GLubyte *bm=NULL );
inline double GetAspect();
inline int GetHorzRes();
inline int GetVertRes();
private:
PRINTMODE m_printMode;
PRINTDLG m_printDLG;
BITMAPINFO m_bitmapInfo;
void *m_bitmap;
HBITMAP bitmapHandle;
HDC m_bitmapDC;
HGLRC m_printerHGLRC;
HGLRC m_bitmapHGLRC;
int m_pageWidth; // Dimension of printer page (x)
int m_pageHeight; // Dimension of printer page (y)
};
inline double CGlPrinter::GetAspect()
{
return (double)m_pageWidth/(double)m_pageHeight;
}
inline int CGlPrinter::GetHorzRes()
{
return m_pageWidth;
}
inline int CGlPrinter::GetVertRes()
{
return m_pageHeight;
}
inline CGlPrinter::CGlPrinter( PRINTMODE mode ) :
m_printerHGLRC( 0 ), m_bitmapHGLRC( 0 ), m_printMode( mode ), m_bitmap( NULL )
{
}
inline CGlPrinter::~CGlPrinter()
{
}
inline bool CGlPrinter::Begin( char *title, int w, int h )
{
// Pixel format for Printer Device context
static PIXELFORMATDESCRIPTOR pPrintfd = {
sizeof(PIXELFORMATDESCRIPTOR), // Size of this structure
1, // Version of this structure
PFD_DRAW_TO_WINDOW | // Draw to Window (not to m_bitmap)
PFD_SUPPORT_OPENGL | // Support OpenGL calls
PFD_SUPPORT_GDI | // Allow GDI drawing in window too
PFD_DEPTH_DONTCARE, // Don't care about depth buffering
PFD_TYPE_RGBA, // RGBA Color mode
24, // Want 24bit color
0,0,0,0,0,0, // Not used to select mode
0,0, // Not used to select mode
0,0,0,0,0, // Not used to select mode
0, // Size of depth buffer
0, // Not used to select mode
0, // Not used to select mode
0, // Not used to select mode
0, // Not used to select mode
0,0,0 }; // Not used to select mode
DOCINFO docInfo; // Document Info
int nPixelFormat; // Pixel format requested
// Get printer information
memset(&m_printDLG,0,sizeof(PRINTDLG));
m_printDLG.lStructSize = sizeof(PRINTDLG);
m_printDLG.hwndOwner = GetForegroundWindow();
m_printDLG.hDevMode = NULL;
m_printDLG.hDevNames = NULL;
m_printDLG.Flags = PD_RETURNDC | PD_ALLPAGES;
// Display printer dialog
if(!PrintDlg(&m_printDLG))
{
printf( "PrintDlg() failed %lx\n", GetLastError() );
return false;
}
// Get the dimensions of the page
m_pageWidth = GetDeviceCaps(m_printDLG.hDC, HORZRES);
m_pageHeight = GetDeviceCaps(m_printDLG.hDC, VERTRES);
// Initialize DocInfo structure
docInfo.cbSize = sizeof(DOCINFO);
docInfo.lpszDocName = title;
docInfo.lpszOutput = NULL;
// Choose a pixel format that best matches that described in pfd
nPixelFormat = ChoosePixelFormat(m_printDLG.hDC, &pPrintfd);
// Watch for no pixel format available for this printer
if(nPixelFormat == 0)
{
// Delete the printer context
DeleteDC(m_printDLG.hDC);
printf( "ChoosePixelFormat() failed %lx\n", GetLastError() );
return false;
}
// Start the document and page
StartDoc(m_printDLG.hDC, &docInfo);
StartPage(m_printDLG.hDC);
// Set the pixel format for the device context, but watch for failure
if(!SetPixelFormat(m_printDLG.hDC, nPixelFormat, &pPrintfd))
{
// Delete the printer context
DeleteDC(m_printDLG.hDC);
printf( "SetPixelFormat() failed %lx\n", GetLastError() );
return false;
}
// Create the Rendering context and make it current
if ( m_printMode == RENDER_TO_PRINTER )
{
m_printerHGLRC = wglCreateContext(m_printDLG.hDC);
wglMakeCurrent(m_printDLG.hDC, m_printerHGLRC);
}
else
{
memset( &m_bitmapInfo, 0, sizeof(BITMAPINFO) );
m_bitmapInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
if ( m_printMode == READ_BITMAP )
{
GLint vp[4];
glGetIntegerv( GL_VIEWPORT, vp );
m_bitmapInfo.bmiHeader.biWidth = vp[2];
m_bitmapInfo.bmiHeader.biHeight = (vp[3] + 3) & ~3;
}
else
{
if ( m_printMode == RENDER_TO_BITMAP )
{
m_bitmapInfo.bmiHeader.biWidth = m_pageWidth;
m_bitmapInfo.bmiHeader.biHeight = m_pageHeight;
}
else
{
// PRINT_BITMAP
m_bitmapInfo.bmiHeader.biWidth = w;
m_bitmapInfo.bmiHeader.biHeight = h;
}
}
m_bitmapInfo.bmiHeader.biPlanes = 1;
m_bitmapInfo.bmiHeader.biBitCount = 24;
m_bitmapInfo.bmiHeader.biCompression = BI_RGB;
m_bitmapInfo.bmiHeader.biSizeImage = m_bitmapInfo.bmiHeader.biWidth*m_bitmapInfo.bmiHeader.biHeight*3;
m_bitmapInfo.bmiHeader.biXPelsPerMeter = 2952; // 75dpi
m_bitmapInfo.bmiHeader.biYPelsPerMeter = 2952; // 75dpi
m_bitmapInfo.bmiHeader.biClrUsed = 0;
m_bitmapInfo.bmiHeader.biClrImportant = 0;
bitmapHandle = CreateDIBSection( NULL, &m_bitmapInfo, DIB_RGB_COLORS, &m_bitmap, NULL, 0);
m_bitmapDC = CreateCompatibleDC( NULL );
if ( m_bitmapDC == NULL )
{
DeleteDC(m_printDLG.hDC);
printf( "CreateCompatibleDC() failed %lx\n", GetLastError() );
return false;
}
if ( SelectObject( m_bitmapDC, bitmapHandle ) == NULL )
{
DeleteDC(m_printDLG.hDC);
DeleteDC(m_bitmapDC);
printf( "SelectObject() failed %lx\n", GetLastError() );
return false;
}
PIXELFORMATDESCRIPTOR pfd;
memset( &pfd, 0, sizeof(PIXELFORMATDESCRIPTOR) );
pfd.nVersion = 1 ;
pfd.dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL;
pfd.iPixelType = PFD_TYPE_RGBA ;
pfd.cColorBits = 24;
pfd.iLayerType = PFD_MAIN_PLANE;
int pixelFormat = ::ChoosePixelFormat(m_bitmapDC, &pfd);
SetPixelFormat (m_bitmapDC, pixelFormat, &pfd);
if ( m_printMode == RENDER_TO_BITMAP )
{
m_bitmapHGLRC = wglCreateContext( m_bitmapDC );
wglMakeCurrent( m_bitmapDC, m_bitmapHGLRC );
}
}
if ( m_printMode == RENDER_TO_PRINTER || m_printMode == RENDER_TO_BITMAP )
{
// Set viewing volume info
//glViewport(0,0,m_pageWidth/2,m_pageHeight/2); // Put this in to restrict area of page.
GLfloat nRange = 100.0f;
// Reset projection matrix stack
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Establish clipping volume (left, right, bottom, top, near, far)
// This keeps the perspective square regardless of window or page size
if (m_pageHeight <= m_pageWidth)
{
glOrtho (-nRange, nRange, -nRange*m_pageHeight/m_pageWidth, nRange*m_pageHeight/m_pageWidth, -nRange, nRange);
}
else
{
glOrtho (-nRange*m_pageWidth/m_pageHeight, nRange*m_pageWidth/m_pageHeight, -nRange, nRange, -nRange, nRange);
}
// Reset Model view matrix stack
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(270.0f, 1.0, 0.0, 0.0);
}
return true;
}
inline void CGlPrinter::End( GLubyte *bm )
{
if ( m_printDLG.hDC )
{
glFinish();
if ( m_printMode == RENDER_TO_PRINTER )
{
if ( m_printerHGLRC )
{
wglDeleteContext( m_printerHGLRC );
}
}
else
{
if ( m_printMode == RENDER_TO_BITMAP )
{
BitBlt( m_printDLG.hDC, 0,0, m_pageWidth,m_pageHeight, m_bitmapDC, 0,0, SRCCOPY );
}
else
{
if ( m_printMode == READ_BITMAP )
{
glPixelStorei( GL_PACK_ALIGNMENT, 4 );
glPixelStorei( GL_PACK_ROW_LENGTH, 0 );
glPixelStorei( GL_PACK_SKIP_ROWS, 0 );
glPixelStorei( GL_PACK_SKIP_PIXELS, 0 );
//GLubyte *tempbitmap = (GLubyte *) malloc(m_bitmapInfo.bmiHeader.biWidth*m_bitmapInfo.bmiHeader.biHeight*4);
glReadPixels( 0,0, m_bitmapInfo.bmiHeader.biWidth,m_bitmapInfo.bmiHeader.biHeight,
GL_RGB, GL_UNSIGNED_BYTE, m_bitmap );
}
else
{
//PRINT_BITMAP
memcpy( m_bitmap, bm, m_bitmapInfo.bmiHeader.biSizeImage );
}
int i,j;
GLubyte *rgb, temp;
for ( i = 0; i < m_bitmapInfo.bmiHeader.biHeight; i++ )
{
for ( j = 0, rgb = ((GLubyte *)m_bitmap) + i * m_bitmapInfo.bmiHeader.biWidth * 3;
j < m_bitmapInfo.bmiHeader.biWidth;
j++, rgb +=3 )
{
temp = rgb[0];
rgb[0] = rgb[2];
rgb[2] = temp;
}
}
long width = m_pageWidth;
long height = width * m_bitmapInfo.bmiHeader.biHeight / m_bitmapInfo.bmiHeader.biWidth;
if ( height > m_pageHeight )
{
height = m_pageHeight;
width = height * m_bitmapInfo.bmiHeader.biWidth / m_bitmapInfo.bmiHeader.biHeight;
}
long xoffset = (m_pageWidth - width) / 2;
long yoffset = (m_pageHeight - height) / 2;
StretchBlt( m_printDLG.hDC, xoffset, yoffset, width, height, m_bitmapDC, 0, 0,
m_bitmapInfo.bmiHeader.biWidth, m_bitmapInfo.bmiHeader.biHeight, SRCCOPY );
}
if ( m_bitmapDC )
{
DeleteDC( m_bitmapDC );
}
if ( bitmapHandle )
{
DeleteObject( bitmapHandle );
}
if ( m_bitmapHGLRC )
{
wglDeleteContext( m_bitmapHGLRC );
}
}
/* EndPage... */
if ( EndPage( m_printDLG.hDC ) <=0 )
{
printf( "EndPage() failed\n" );
}
/* EndDoc... */
if ( EndDoc( m_printDLG.hDC ) <=0 )
{
printf( "EndDoc() failed\n" );
}
// Delete the printer context when done with it
DeleteDC(m_printDLG.hDC);
// Restore window rendering context
//wglMakeCurrent(hDC, hRC);
wglMakeCurrent( NULL, NULL );
}
}

View File

@@ -0,0 +1,17 @@
includedir = @includedir@/serial
noinst_PROGRAMS = testserial
lib_LIBRARIES = libsgserial.a
include_HEADERS = serial.hxx
libsgserial_a_SOURCES = serial.cxx
testserial_SOURCES = testserial.cxx
testserial_LDADD = \
$(top_builddir)/src/serial/libsgserial.a \
$(top_builddir)/src/debug/libsgdebug.a
INCLUDES += -I$(top_builddir)/src

446
simgear/serial/serial.cxx Normal file
View File

@@ -0,0 +1,446 @@
// serial.cxx -- Unix serial I/O support
//
// Written by Curtis Olson, started November 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$
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <simgear/compiler.h>
#ifdef FG_HAVE_STD_INCLUDE
# include <cerrno>
#else
# include <errno.h>
#endif
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
// maybe include something???
#else
# include <termios.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <unistd.h>
#endif
#include <simgear/debug/logstream.hxx>
#include "serial.hxx"
FGSerialPort::FGSerialPort()
: dev_open(false)
{
// empty
}
FGSerialPort::FGSerialPort(const string& device, int baud) {
open_port(device);
if ( dev_open ) {
set_baud(baud);
}
}
FGSerialPort::~FGSerialPort() {
// closing the port here screws us up because if we would even so
// much as make a copy of an FGSerialPort object and then delete it,
// the file descriptor gets closed. Doh!!!
}
bool FGSerialPort::open_port(const string& device) {
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
fd = CreateFile( device.c_str(),
GENERIC_READ | GENERIC_WRITE,
0, // dwShareMode
NULL, // lpSecurityAttributes
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL );
if ( fd == INVALID_HANDLE_VALUE )
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL );
FG_LOG( FG_IO, FG_ALERT, "Error opening serial device \""
<< device << "\" " << (const char*) lpMsgBuf );
LocalFree( lpMsgBuf );
return false;
}
dev_open = true;
return true;
#else
struct termios config;
fd = open(device.c_str(), O_RDWR | O_NONBLOCK);
cout << "Serial fd created = " << fd << endl;
if ( fd == -1 ) {
FG_LOG( FG_IO, FG_ALERT, "Cannot open " << device
<< " for serial I/O" );
return false;
} else {
dev_open = true;
}
// set required port parameters
if ( tcgetattr( fd, &config ) != 0 ) {
FG_LOG( FG_IO, FG_ALERT, "Unable to poll port settings" );
return false;
}
// cfmakeraw( &config );
// cout << "config.c_iflag = " << config.c_iflag << endl;
// software flow control on
config.c_iflag |= IXON;
// config.c_iflag |= IXOFF;
// config.c_cflag |= CLOCAL;
#if ! defined( sgi )
// disable hardware flow control
config.c_cflag &= ~(CRTSCTS);
#endif
// cout << "config.c_iflag = " << config.c_iflag << endl;
if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
FG_LOG( FG_IO, FG_ALERT, "Unable to update port settings" );
return false;
}
return true;
#endif
}
bool FGSerialPort::close_port() {
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
CloseHandle( fd );
#else
close(fd);
#endif
dev_open = false;
return true;
}
bool FGSerialPort::set_baud(int baud) {
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
return true;
#else
struct termios config;
speed_t speed = B9600;
if ( tcgetattr( fd, &config ) != 0 ) {
FG_LOG( FG_IO, FG_ALERT, "Unable to poll port settings" );
return false;
}
if ( baud == 300 ) {
speed = B300;
} else if ( baud == 1200 ) {
speed = B1200;
} else if ( baud == 2400 ) {
speed = B2400;
} else if ( baud == 4800 ) {
speed = B4800;
} else if ( baud == 9600 ) {
speed = B9600;
} else if ( baud == 19200 ) {
speed = B19200;
} else if ( baud == 38400 ) {
speed = B38400;
} else if ( baud == 57600 ) {
speed = B57600;
} else if ( baud == 115200 ) {
speed = B115200;
#if defined( linux ) || defined( __FreeBSD__ )
} else if ( baud == 230400 ) {
speed = B230400;
#endif
} else {
FG_LOG( FG_IO, FG_ALERT, "Unsupported baud rate " << baud );
return false;
}
if ( cfsetispeed( &config, speed ) != 0 ) {
FG_LOG( FG_IO, FG_ALERT, "Problem setting input baud rate" );
return false;
}
if ( cfsetospeed( &config, speed ) != 0 ) {
FG_LOG( FG_IO, FG_ALERT, "Problem setting output baud rate" );
return false;
}
if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
FG_LOG( FG_IO, FG_ALERT, "Unable to update port settings" );
return false;
}
return true;
#endif
}
string FGSerialPort::read_port() {
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
string result = "";
return result;
#else
const int max_count = 1024;
char buffer[max_count+1];
int count;
string result;
count = read(fd, buffer, max_count);
// cout << "read " << count << " bytes" << endl;
if ( count < 0 ) {
// error condition
if ( errno != EAGAIN ) {
FG_LOG( FG_IO, FG_ALERT,
"Serial I/O on read, error number = " << errno );
}
return "";
} else {
buffer[count] = '\0';
result = buffer;
return result;
}
#endif
}
int FGSerialPort::read_port(char *buf, int len) {
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
buf[0] = '\0';
return 0;
#else
string result;
int count = read(fd, buf, len);
// cout << "read " << count << " bytes" << endl;
if ( count < 0 ) {
// error condition
if ( errno != EAGAIN ) {
FG_LOG( FG_IO, FG_ALERT,
"Serial I/O on read, error number = " << errno );
}
buf[0] = '\0';
return 0;
} else {
buf[count] = '\0';
return count;
}
#endif
}
int FGSerialPort::write_port(const string& value) {
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
LPCVOID lpBuffer = value.c_str();
DWORD nNumberOfBytesToWrite = value.length();
DWORD lpNumberOfBytesWritten;
OVERLAPPED lpOverlapped;
if ( WriteFile( fd,
lpBuffer,
nNumberOfBytesToWrite,
&lpNumberOfBytesWritten,
&lpOverlapped ) == 0 )
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL );
FG_LOG( FG_IO, FG_ALERT, "Serial I/O write error: "
<< (const char*) lpMsgBuf );
LocalFree( lpMsgBuf );
return int(lpNumberOfBytesWritten);
}
return int(lpNumberOfBytesWritten);
#else
static bool error = false;
int count;
if ( error ) {
FG_LOG( FG_IO, FG_ALERT, "attempting serial write error recovery" );
// attempt some sort of error recovery
count = write(fd, "\n", 1);
if ( count == 1 ) {
// cout << "Serial error recover successful!\n";
error = false;
} else {
return 0;
}
}
count = write(fd, value.c_str(), value.length());
// cout << "write '" << value << "' " << count << " bytes" << endl;
if ( (int)count == (int)value.length() ) {
error = false;
} else {
if ( errno == EAGAIN ) {
// ok ... in our context we don't really care if we can't
// write a string, we'll just get it the next time around
error = false;
} else {
error = true;
FG_LOG( FG_IO, FG_ALERT,
"Serial I/O on write, error number = " << errno );
}
}
return count;
#endif
}
int FGSerialPort::write_port(const char* buf, int len) {
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
LPCVOID lpBuffer = buf;
DWORD nNumberOfBytesToWrite = len;
DWORD lpNumberOfBytesWritten;
OVERLAPPED lpOverlapped;
if ( WriteFile( fd,
lpBuffer,
nNumberOfBytesToWrite,
&lpNumberOfBytesWritten,
&lpOverlapped ) == 0 )
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL );
FG_LOG( FG_IO, FG_ALERT, "Serial I/O write error: "
<< (const char*) lpMsgBuf );
LocalFree( lpMsgBuf );
return int(lpNumberOfBytesWritten);
}
return int(lpNumberOfBytesWritten);
#else
static bool error = false;
int count;
if ( error ) {
// attempt some sort of error recovery
count = write(fd, "\n", 1);
if ( count == 1 ) {
// cout << "Serial error recover successful!\n";
error = false;
} else {
return 0;
}
}
count = write(fd, buf, len);
// cout << "write '" << buf << "' " << count << " bytes" << endl;
if ( (int)count == len ) {
error = false;
} else {
error = true;
if ( errno == EAGAIN ) {
// ok ... in our context we don't really care if we can't
// write a string, we'll just get it the next time around
} else {
FG_LOG( FG_IO, FG_ALERT,
"Serial I/O on write, error number = " << errno );
}
}
return count;
#endif
}

82
simgear/serial/serial.hxx Normal file
View File

@@ -0,0 +1,82 @@
// serial.hxx -- Unix serial I/O support
//
// Written by Curtis Olson, started November 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 _SERIAL_HXX
#define _SERIAL_HXX
#ifndef __cplusplus
# error This library requires C++
#endif
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
# include <windows.h>
#endif
#include <simgear/compiler.h>
#include STL_STRING
FG_USING_STD(string);
// if someone know how to do this all with C++ streams let me know
// #include <stdio.h>
class FGSerialPort
{
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
typedef HANDLE fd_type;
#else
typedef int fd_type;
#endif
private:
fd_type fd;
bool dev_open;
public:
FGSerialPort();
FGSerialPort(const string& device, int baud);
~FGSerialPort();
bool open_port(const string& device);
bool close_port();
bool set_baud(int baud);
string read_port();
int read_port(char *buf, int len);
int write_port(const string& value);
int write_port(const char *buf, int len);
inline bool is_enabled() { return dev_open; }
};
#endif // _SERIAL_HXX

View File

@@ -0,0 +1,30 @@
#include <string>
#include <simgear/debug/logstream.hxx>
#include "serial.hxx"
main () {
FGSerialPort port;
string value;
bool result;
fglog().setLogLevels( FG_ALL, FG_INFO );
cout << "start of main" << endl;
result = port.open_port("/dev/ttyS1");
cout << "opened port, result = " << result << endl;
result = port.set_baud(4800);
cout << "set baud, result = " << result << endl;
port.write_port("ATDT 626-9800\n");
while ( true ) {
value = port.read_port();
if ( value.length() ) {
cout << "-> " << value << endl;
}
}
}

Some files were not shown because too many files have changed in this diff Show More