home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Science / Science.zip / SPACE.ZIP / SPACE.C < prev    next >
Text File  |  1991-02-24  |  16KB  |  540 lines

  1. //------------------------------------------
  2. // Space.C
  3. //------------------------------------------
  4.  
  5. #define INCL_WIN
  6. #define INCL_GPI
  7. #define INCL_DOSPROCESS
  8. #define INCL_DOS
  9. #define INCL_GPIERRORS
  10. #define INCL_SHLERRORS
  11. #define INCL_WINERRORS
  12. #include <os2.h>
  13. #include <stdlib.h>
  14. #include <process.h>
  15. #include <stddef.h>
  16. #include <math.h>
  17. #include <stdio.h>
  18. #include <malloc.h>
  19. #include <ctype.h>
  20. #include "space.h"
  21.  
  22. #define M_PI     3.14159265358979323846
  23.  
  24.  
  25. //**** Global variables ****
  26. typedef struct
  27.      {
  28.      double  x_pos;
  29.      double  y_pos;
  30.      double  x_vel;
  31.      double  y_vel;
  32.      double  x_temp;
  33.      double  y_temp;
  34.      double  mass;
  35.      } star_type;
  36.  
  37. star_type *star;
  38. int  number_stars    = 0;
  39. long   x_shift       = 0;
  40. long   y_shift       = 0;
  41. double Time          = 1.0;
  42. double G_constant    = 1.0;
  43. double magnification = 1.0;
  44.  
  45. typedef struct
  46.      {
  47.      HPS     hps;
  48.      SHORT   width;
  49.      SHORT   height;
  50.      ULONG   thread_unterminated;
  51.      BOOL    run;
  52.      BOOL    repaint;
  53.      BOOL    load;
  54.      BOOL    center;
  55.      BOOL    magnification;
  56.      BOOL    terminate;
  57.      BOOL    trace;
  58.      } win_data;
  59.  
  60. HAB          hab;
  61. win_data     Win;
  62.  
  63.  
  64. //**** Prototypes ****
  65. void   load_star( void );
  66. double get_constant( FILE *star_file );
  67. void   thread( void *dummy );
  68. void   set_magnification( void );
  69. void   show_stars( long color );
  70. void   center_stars( void );
  71. void   move_star( int body );
  72. void   line( win_data *Win, SHORT x1, SHORT y1, SHORT x2, SHORT y2, LONG color );
  73. void   line_to( win_data *Win, SHORT xx, SHORT yy, LONG color );
  74. void   pset( win_data *Win, SHORT xx, SHORT yy, LONG color );
  75. void   move( win_data *Win, SHORT xx, SHORT yy );
  76.  
  77. //**** Window prototypes ****
  78. MRESULT EXPENTRY ClientWndProc( HWND, USHORT, MPARAM, MPARAM );
  79. MRESULT EXPENTRY AboutDlgProc ( HWND, USHORT, MPARAM, MPARAM );
  80.  
  81.  
  82. //---------------------------------------------------------------------------
  83. // Main process
  84. //---------------------------------------------------------------------------
  85. int main( void )
  86. {
  87.      static CHAR  szClientClass [] = "Space";
  88.      static ULONG flFrameFlags = FCF_TITLEBAR      | FCF_SYSMENU  |
  89.                                  FCF_SIZEBORDER    | FCF_MINMAX   |
  90.                                  FCF_SHELLPOSITION | FCF_TASKLIST |
  91.                                  FCF_MENU          | FCF_ICON;
  92.      HMQ          hmq;
  93.      HWND         hwndFrame, hwndClient;
  94.      QMSG         qmsg;
  95.  
  96.      load_star();
  97.  
  98.      hab = WinInitialize( 0 );
  99.      hmq = WinCreateMsgQueue( hab, 0 );
  100.  
  101.      WinRegisterClass( hab, szClientClass, ClientWndProc, CS_SIZEREDRAW, 0 );
  102.  
  103.      hwndFrame = WinCreateStdWindow( HWND_DESKTOP, WS_VISIBLE,
  104.                                      &flFrameFlags, szClientClass, NULL,
  105.                                      0L, 0, ID_RESOURCE, &hwndClient );
  106.  
  107.      while(WinGetMsg( hab, &qmsg, NULL, 0, 0 ) )
  108.           WinDispatchMsg( hab, &qmsg );
  109.  
  110.      free( star );
  111.      WinDestroyWindow( hwndFrame );
  112.      WinDestroyMsgQueue( hmq );
  113.      WinTerminate( hab );
  114.      return 0;
  115. }
  116.  
  117.  
  118. //---------------------------------------------------------------------------
  119. // Load star information
  120. //---------------------------------------------------------------------------
  121. void load_star()
  122. {
  123.      FILE   *star_file;
  124.      int    count;
  125.      double velocity, angle;
  126.  
  127.      if ( (star_file = fopen( "STARFILE.TXT", "r" )) == NULL )
  128.           {
  129.           exit( 0 );
  130.           }
  131.  
  132.      number_stars = (int)get_constant( star_file );
  133.      G_constant   = get_constant( star_file );
  134.      Time         = get_constant( star_file );
  135.      star = malloc( number_stars * sizeof( star_type ) );
  136.  
  137.      for (count=0; count<number_stars; ++count)
  138.           {
  139.           star[count].x_pos    = get_constant( star_file );
  140.           star[count].y_pos    = get_constant( star_file );
  141.           star[count].mass     = get_constant( star_file );
  142.           angle                = get_constant( star_file );
  143.           velocity             = get_constant( star_file );
  144.           star[count].x_vel = velocity * cos( angle );
  145.           star[count].y_vel = velocity * sin( angle );
  146.           }
  147.  
  148.      fclose( star_file );
  149.      return;
  150. }
  151.  
  152.  
  153. //---------------------------------------------------------------------------
  154. // get constant from file
  155. //---------------------------------------------------------------------------
  156. double get_constant( FILE *star_file )
  157. {
  158.      static char buffer[200] = {0};
  159.      static pos = 0;
  160.      char   chr;
  161.      double answer;
  162.  
  163.      do   {
  164.           chr = buffer[ pos++ ];
  165.           while (chr == 0  ||  chr == ';')
  166.                {
  167.                fgets( buffer, 200, star_file );
  168.                if (buffer == NULL)
  169.                     exit(0);
  170.                pos = 0;
  171.                chr = buffer[ pos++ ];
  172.                }
  173.           }
  174.      while( !isdigit(chr)  &&  chr != '+'  &&  chr != '-'  &&  chr != '.' );
  175.      --pos;
  176.      sscanf( &buffer[pos], "%lf", &answer );
  177.  
  178.      while( isdigit(chr)  ||  chr == '+'  ||  chr == '-'  ||  chr == '.'  ||  chr == 'e'  ||  chr == 'E' )
  179.           chr = buffer[ pos++ ];
  180.      --pos;
  181.  
  182.      return answer;
  183. }
  184.  
  185.  
  186. //---------------------------------------------------------------------------
  187. // Window message reciever
  188. //---------------------------------------------------------------------------
  189. MRESULT EXPENTRY ClientWndProc( HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2 )
  190. {
  191.      HDC            hdc;
  192.      SIZEL          sizl;
  193.  
  194.      switch( msg )
  195.           {
  196.           case WM_COMMAND:
  197.                switch( COMMANDMSG(&msg)->cmd )
  198.                     {
  199.                     case IDM_RELOAD:
  200.                          Win.load = TRUE;
  201.                          return 0;
  202.  
  203.                     case IDM_RECENTER:
  204.                          Win.center = TRUE;
  205.                          return 0;
  206.  
  207.                     case IDM_ZOOM_IN:
  208.                          magnification *= 2.0;
  209.                          Win.center = TRUE;
  210.                          return 0;
  211.  
  212.                     case IDM_ZOOM_OUT:
  213.                          magnification /= 2.0;
  214.                          Win.center = TRUE;
  215.                          return 0;
  216.  
  217.                     case IDM_TRACE:
  218.                          Win.trace = (Win.trace)? FALSE: TRUE;
  219.                          return 0;
  220.  
  221.                     case IDM_ABOUT:
  222.                          WinDlgBox( HWND_DESKTOP, hwnd, AboutDlgProc,
  223.                                     0, IDD_ABOUT, NULL );
  224.                          return 0;
  225.                     }
  226.                break;
  227.  
  228.           case WM_CREATE:
  229.                hdc = WinOpenWindowDC( hwnd );
  230.                sizl.cx = 0;
  231.                sizl.cy = 0;
  232.                Win.hps = GpiCreatePS( hab, hdc, &sizl,
  233.                                       PU_PELS    | GPIF_DEFAULT |
  234.                                       GPIT_MICRO | GPIA_ASSOC );
  235.                Win.terminate     = FALSE;
  236.                Win.run           = FALSE;
  237.                Win.load          = FALSE;
  238.                Win.magnification = TRUE;
  239.                Win.center        = TRUE;
  240.                Win.trace         = FALSE;
  241.                _beginthread( thread, NULL, 5000, NULL );
  242.                return 0;
  243.  
  244.           case WM_SIZE:
  245.                Win.width  = SHORT1FROMMP( mp2 );
  246.                Win.height = SHORT2FROMMP( mp2 );
  247.                Win.center = TRUE;
  248.                return 0;
  249.  
  250.           case WM_PAINT:
  251.                WinInvalidateRect( hwnd, NULL, FALSE );
  252.                WinBeginPaint( hwnd, Win.hps, NULL );
  253.                WinEndPaint( Win.hps );
  254.  
  255.                Win.repaint = TRUE;
  256.                Win.run     = TRUE;
  257.                return 0;
  258.  
  259.           case WM_DESTROY:
  260.                Win.terminate = TRUE;
  261.                DosSemWait( &Win.thread_unterminated, SEM_INDEFINITE_WAIT );
  262.                GpiDestroyPS( Win.hps );
  263.                return 0;
  264.           }
  265.      return WinDefWindowProc( hwnd, msg, mp1, mp2 );
  266. }
  267.  
  268.  
  269. //---------------------------------------------------------------------------
  270. // About dialogue box.
  271. //---------------------------------------------------------------------------
  272. MRESULT EXPENTRY AboutDlgProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  273. {
  274.      switch (msg)
  275.           {
  276.           case WM_COMMAND:
  277.                switch ( COMMANDMSG(&msg)->cmd )
  278.                     {
  279.                     case DID_OK:
  280.                     case DID_CANCEL:
  281.                          WinDismissDlg( hwnd, TRUE );
  282.                          return 0;
  283.                     }
  284.                break;
  285.           }
  286.      return WinDefDlgProc (hwnd, msg, mp1, mp2);
  287. }
  288.  
  289.  
  290. //---------------------------------------------------------------------------
  291. // Second thread
  292. //---------------------------------------------------------------------------
  293. void thread( void *dummy )
  294. {
  295.      HAB    hab;
  296.      RECTL  crl;
  297.      int    ii;
  298.  
  299.      DosSemSet( &Win.thread_unterminated );
  300.      DosSetPrty( PRTYS_PROCESS, PRTYC_IDLETIME, 0, 0 );
  301.      hab = WinInitialize( 0 );
  302.  
  303.      while( !Win.terminate )
  304.           {
  305.           DosSleep( 0L );
  306.           if ( Win.load )
  307.                {
  308.                Win.load = FALSE;
  309.                load_star();
  310.                Win.center = TRUE;
  311.                }
  312.       if ( Win.run )
  313.                {
  314.                if ( Win.magnification )
  315.                     set_magnification();
  316.                if ( Win.center )
  317.                     {
  318.                     Win.center = FALSE;
  319.                     center_stars();
  320.                     }
  321.                if ( Win.repaint )
  322.                     {
  323.                     Win.repaint = FALSE;
  324.                     crl.xLeft   = 0;
  325.                     crl.yBottom = 0;
  326.                     crl.xRight  = Win.width;
  327.                     crl.yTop    = Win.height;
  328.                     WinFillRect( Win.hps, &crl, CLR_BLACK );
  329.                     }
  330.  
  331.                for (ii=0; ii<number_stars; ++ii)
  332.                     move_star( ii );
  333.                // Erase stars.
  334.                if ( Win.trace )
  335.                     show_stars( CLR_BLUE );
  336.                else
  337.                     show_stars( CLR_BLACK );
  338.                // Draw stars.
  339.                for (ii=0; ii<number_stars; ++ii)
  340.                     {
  341.                     star[ii].x_pos = star[ii].x_temp;
  342.                     star[ii].y_pos = star[ii].y_temp;
  343.                     }
  344.                show_stars( CLR_WHITE );
  345.                }
  346.           }
  347.  
  348.      // Close hab and terminate thread.
  349.      WinTerminate( hab );
  350.      DosSemClear( &Win.thread_unterminated );
  351.      _endthread();
  352. }
  353.  
  354.  
  355. //---------------------------------------------------------------------------
  356. // Set magnification
  357. //---------------------------------------------------------------------------
  358. void set_magnification()
  359. {
  360.      double x_min, x_max, y_min, y_max, x_diff, y_diff, x_mag, y_mag;
  361.      int    ii;
  362.  
  363.      Win.magnification = FALSE;
  364.      x_min = 1e30; x_max = -1e30;
  365.      y_min = 1e30; y_max = -1e30;
  366.      for (ii=0; ii<number_stars; ++ii)
  367.           {
  368.           if (x_min > star[ii].x_pos)
  369.                x_min = star[ii].x_pos;
  370.           if (x_max < star[ii].x_pos)
  371.                x_max = star[ii].x_pos;
  372.           if (y_min > star[ii].y_pos)
  373.                y_min = star[ii].y_pos;
  374.           if (y_max < star[ii].y_pos)
  375.                y_max = star[ii].y_pos;
  376.           }
  377.      x_diff = x_max - x_min;
  378.      y_diff = y_max - y_min;
  379.      x_mag = 1e30;
  380.      y_mag = 1e30;
  381.      if (x_diff != 0)
  382.           x_mag = Win.width / x_diff;
  383.      if (y_diff != 0)
  384.           y_mag = Win.height / y_diff;
  385.      magnification = (x_mag > y_mag)? y_mag: x_mag;
  386.      return;
  387. }
  388.  
  389.  
  390. //---------------------------------------------------------------------------
  391. // Show stars on screen
  392. //---------------------------------------------------------------------------
  393. void show_stars( long color )
  394. {
  395.      int ii;
  396.      long xx, yy;
  397.  
  398.      for (ii=0; ii<number_stars; ++ii)
  399.           {
  400.           xx = (long)(star[ii].x_pos * magnification) + x_shift;
  401.           if (labs( xx ) > 32000)
  402.                return;
  403.           yy = (long)(star[ii].y_pos * magnification) + y_shift;
  404.           if (labs( yy ) > 32000)
  405.                return;
  406.           pset( &Win, (int)xx, (int)yy, color );
  407.           }
  408.      return;
  409. }
  410.  
  411.  
  412. //---------------------------------------------------------------------------
  413. // Center stars
  414. //---------------------------------------------------------------------------
  415. void center_stars()
  416. {
  417.      int    ii;
  418.      double x_center, y_center;
  419.  
  420.      // Find center position of stars.
  421.      x_center = 0;
  422.      y_center = 0;
  423.      for (ii=0; ii<number_stars; ++ii)
  424.           {
  425.           x_center += star[ii].x_pos * magnification;
  426.           y_center += star[ii].y_pos * magnification;
  427.           }
  428.      x_center /= number_stars;
  429.      y_center /= number_stars;
  430.  
  431.      // Shift stars position to center of window.
  432.      x_shift = (long)(Win.width  / 2 - x_center);
  433.      y_shift = (long)(Win.height / 2 - y_center);
  434.  
  435.      Win.repaint = TRUE;
  436.      return;
  437. }
  438.  
  439.  
  440. //---------------------------------------------------------------------------
  441. // calculate next position of star
  442. //---------------------------------------------------------------------------
  443. void move_star( int body )
  444. {
  445.      double distance, x_dist, y_dist;
  446.      double force, x_force, y_force;
  447.      double star_x_dist, star_y_dist;
  448.      double angle;
  449.      int ii;
  450.  
  451.      // Calculate star's x, y force toward other stars.
  452.      x_force = 0;
  453.      y_force = 0;
  454.      for (ii=0; ii<number_stars; ++ii)
  455.           {
  456.           if (ii == body)
  457.                continue;
  458.           x_dist   = star[ii].x_pos - star[body].x_pos;
  459.           y_dist   = star[ii].y_pos - star[body].y_pos;
  460.           distance = x_dist * x_dist + y_dist * y_dist;
  461.           force    = G_constant * star[body].mass * star[ii].mass / distance;
  462.           angle    = atan2( y_dist, x_dist );
  463.           x_force += force * cos( angle );
  464.           y_force += force * sin( angle );
  465.           DosSleep( 0L );
  466.           }
  467.  
  468.      // Add to star's x, y velocity the addition velocity from current force.
  469.      star[body].x_vel += Time * x_force / star[body].mass;
  470.      star[body].y_vel += Time * y_force / star[body].mass;
  471.  
  472.      // Calculate star's displacement durring Time.
  473.      star_x_dist = Time * star[body].x_vel;
  474.      star_y_dist = Time * star[body].y_vel;
  475.  
  476.      // Add star's displacement to star's current position.
  477.      star[body].x_temp = star[body].x_pos + star_x_dist;
  478.      star[body].y_temp = star[body].y_pos + star_y_dist;
  479.  
  480.      return;
  481. }
  482.  
  483.  
  484. //---------------------------------------------------------------------------
  485. // Line routine
  486. //---------------------------------------------------------------------------
  487. void line( win_data *Win, SHORT x1, SHORT y1, SHORT x2, SHORT y2, LONG color )
  488. {
  489.      POINTL  ptl;
  490.  
  491.      GpiSetColor( Win->hps, color );
  492.      ptl.x = x1;
  493.      ptl.y = y1;
  494.      GpiMove( Win->hps, &ptl );
  495.      ptl.x = x2;
  496.      ptl.y = y2;
  497.      GpiLine( Win->hps, &ptl );
  498. }
  499.  
  500.  
  501. //---------------------------------------------------------------------------
  502. // Line routine
  503. //---------------------------------------------------------------------------
  504. void line_to( win_data *Win, SHORT xx, SHORT yy, LONG color )
  505. {
  506.      POINTL  ptl;
  507.  
  508.      GpiSetColor( Win->hps, (long)color );
  509.      ptl.x = xx;
  510.      ptl.y = yy;
  511.      GpiLine( Win->hps, &ptl );
  512. }
  513.  
  514.  
  515. //---------------------------------------------------------------------------
  516. // Pset routine
  517. //---------------------------------------------------------------------------
  518. void pset( win_data *Win, SHORT xx, SHORT yy, LONG color )
  519. {
  520.      POINTL  ptl;
  521.  
  522.      GpiSetColor( Win->hps, color );
  523.      ptl.x = xx;
  524.      ptl.y = yy;
  525.      GpiSetPel( Win->hps, &ptl );
  526.      GpiMove( Win->hps, &ptl );
  527. }
  528.  
  529.  
  530. //---------------------------------------------------------------------------
  531. // Move Gpi pel routine
  532. //---------------------------------------------------------------------------
  533. void move( win_data *Win, SHORT xx, SHORT yy )
  534. {
  535.      POINTL  ptl;
  536.  
  537.      ptl.x = xx;
  538.      ptl.y = yy;
  539.      GpiMove( Win->hps, &ptl );
  540. }