[comp.sources.amiga] v89i212: cm - celestial mechanics gravity simulator, Part01/02

page%swap@Sun.COM (Bob Page) (11/13/89)

Submitted-by: guineau@wjg.enet.dec.com (W. John Guineau)
Posting-number: Volume 89, Issue 212
Archive-name: applications/cm.1

CM is a celestial mechanics simulator with an Intuition interface.
You construct a layout of Bodies and specify various parameters
for the bodies and the simulation.  CM then animates the bodies
according to the laws of gravational attraction ( F = Gm1m2/r^2 ).
Setups may be saved to disk to later re-inact interesting scenarios.

# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
#	3body.DAT
#	cm.c
#	cm.doc
# This is archive 1 of a 2-part kit.
# This archive created: Sun Nov 12 20:10:27 1989
echo "extracting 3body.DAT"
sed 's/^X//' << \SHAR_EOF > 3body.DAT
X--- CM Setup Data ---
XG=6.670e+00
Xds=1.000e+00
Xdt=5.000e-01
Xt=0
XTrailLength=-1
XShowTime=1
X--- CM Body Data ---
X#=name ;pen;fixed;Radius;Mass;x,y;Vx,Vy;Dir
X0=SUN ;2;0;0;1.000e+03;3.030e+02,1.910e+02;0.000e+00,0.000e+00;0.000e+00
X1=PLANET1 ;4;0;0;1.000e+01;4.310e+02,1.900e+02;0.000e+00,4.000e+00;9.000e+01
X2=PLANET2 ;6;0;0;1.000e+01;7.900e+01,1.930e+02;0.000e+00,-5.000e+00;2.700e+02
SHAR_EOF
echo "extracting cm.c"
sed 's/^X//' << \SHAR_EOF > cm.c
X/*
X * Celestial Mechanics Simulation Tool
X *
X *	W. John Guineau
X *      3 Royal Crest Drive #9
X *      Marlboro, Mass. 01752
X *      (508) 485-6233
X *
X * Files:
X *	    cm.c
X *	    cm.h
X *          cm.doc
X *
X * To Compile with Lattice 5.02:
X *
X *	    lc -b0 -Lm cm
X *
X *
X *			      NOTICE
X *			      ------ 
X *
X *  I have placed this software in the Public Domain with the
X * condition that all the files remain together and that I remain
X * listed as the original author. This software may not be used for
X * commercial purposes or to make money in any way without expressed
X * written permission from the author (me). I'm including the source
X * code so if you make any significant modifications please concider
X * sending me a copy at the above address. I'd also be interested in
X * any interesting saved setup files you create.
X *
X *
X * This is my first Amiga program so I welcome any comments at all.
X * I wrote this program as both a way to learn the Amiga environment
X * and in response to a conversation I had with a friend on Celestial
X * Mechanics.
X *
X *
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <math.h>
X
X#include <exec/types.h>
X#include <exec/ports.h>
X#include <exec/devices.h>
X#include <libraries/dosextens.h>
X#include <intuition/intuition.h>
X#include <intuition/intuitionbase.h>
X#include <graphics/rastport.h>
X#include <graphics/gfxbase.h>
X#include <graphics/gfx.h>
X#include <graphics/display.h>
X#include <graphics/text.h>
X
X
X
X
X#include "cm.h"
X
X
X
X#define NOWAIT 0
X#define WAIT   1
X
X
Xextern struct IntuitionBase *IntuitionBase;
Xextern struct GfxBase *GfxBase;
Xstruct IntuiMessage *message;
X
Xstruct Screen *s;
Xstruct Window *w;
Xstruct Window *pw;
Xstruct RastPort *rp;
Xstruct RastPort *prp;
Xstruct ViewPort *vp;
X
X
X#define ReqNone  0
X#define ReqBody  1
X#define ReqSetup 2
X#define ReqFile  3
X#define ReqAbout 4
X
X
XUBYTE  CancelHit=0;	   /* If user selects CANCEL from Reqester */
XUBYTE  ReqActive=ReqNone;  /* Set when a Reqester is active */
X			   /*  to keep DoIntuiEvents() from returning */
X			   /*  until it gets a REQCLEAR msg */
X
X
Xstruct setup {
X   double   G;
X   double   ds;
X   double   dt;
X   UBYTE    t;
X   WORD     TrailLength;
X   UBYTE    ShowTime;
X} SI;
X
X#define MAXTRAILEN 300
X   
Xstruct Body {		    /* Info for a Celestial Body */
X   UBYTE    real;	    /* If it's real */
X   UBYTE    fixed;	    /* Body fixed in place */
X   UBYTE    pen;            /* Color Register */
X   char     name[10];	    /* user given name */
X   ULONG    Radius;	    /* radius */
X   double   Mass;	    /* mass */
X   double   x,y;	    /* current position */
X   double   Vx,Vy;	    /* velocity components */
X   double   Fx,Fy;	    /* resultant force components */
X   double   Dir;	    /* direction angle (radians) */
X   double   TrailX[MAXTRAILEN]; /* X of trail of pixels to clear */
X   double   TrailY[MAXTRAILEN]; /* X of trail of pixels to clear */
X   WORD     TrailIDX;
X};
X
X
X#define MAXBODYS 10
Xstruct Body Bodys[MAXBODYS];		 /* The array of bodys */
XBYTE   CurBody,TotalBodys=0;
X
XULONG	Et;				/* elapsed time */
X
X
X#define MODE_CREATE 1
X#define MODE_MODIFY 2
X#define MODE_START  3
X#define MODE_STOP   4
XUBYTE	mode = MODE_STOP;		/* Current simulation mode */
X
X
X
X
X/* pointer text for ShowMouse() */
Xchar	pbuf[80];
Xstruct IntuiText pos_txt = {
X   WHTPEN,BLKPEN,			/* FrontPen, BackPen */
X   JAM2,				/* DrawMode */
X   7,2,  				/* LeftEdge, TopEdge */
X   &TxtAt_Plain,			/* TextAttr */
X   pbuf,				/* IText */
X   NULL 				/* NextText */
X};
X
X
X
Xstruct	MsgPort *TimerPort;	    /* for Timer stuff */
Xstruct	timerequest *TR;
XUBYTE	TimerOpen=0;
X
X
X
X
X
X/* ============================================================
X *   Main
X *
X * ============================================================*/
X
Xmain(argc,argv)
Xint   argc;
Xchar  *argv[];
X{
X
XOpenStuff();
XInit();
X
XDoIntuiEvents(WAIT);
X
Xreturn(0);
X
X}
X
X
X
X
X
X
X
X
X
XOpenStuff()
X{
X
XTimerPort = (struct MsgPort *)CreatePort(0,0);
Xif(TimerPort == 0) {
X   printf("Cant get a Timer Port\n");
X   CleanUp();
X   exit(10);
X};
X
XTR = (struct timerequest *)CreateExtIO(TimerPort,
X				       sizeof(struct timerequest));
Xif(TR == 0) {
X   printf("Cant get a Timer Request\n");
X   CleanUp();
X   exit(11);
X};
X
X
Xif(OpenDevice(TIMERNAME,UNIT_VBLANK,TR,0) != 0) {
X   printf("Cant open Timer Device\n");
X   CleanUp();
X   exit(12);
X};
XTimerOpen = 1;
X
X
Xif(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0))) {
X   printf("no graphics library!!!\n");
X   CleanUp();
X   exit(13);
X};
X
Xif(!(IntuitionBase = (struct IntuitionBase *)
X			      OpenLibrary("intuition.library",0))) {
X   printf("no intuition here!!\n");
X   CleanUp();
X   exit(14);
X};
X
X
X
Xif (!(s = (struct Screen *)OpenScreen(&ns) )) {
X   printf("could not open the screen\n");
X   CleanUp();
X   exit(15);
X};
X
X
X/*
X * set up color map for new screen
X */
Xvp = (struct ViewPort *)&s->ViewPort;
XLoadRGB4(vp,colortable,COLORS);
X
Xnw.Screen = s;	     /* point to our screen */
Xnpw.Screen = s;	     /* pointer window struct also */
X
Xif (!(w = (struct Window *)OpenWindow(&nw) )) {
X   printf("could not open the window\n");
X   CleanUp();
X   exit(16);
X};
X
Xrp = w->RPort;
XSetAPen(rp,WHTPEN);
X
XSetMenuStrip(w,&Control);
X
Xreturn(0);
X
X}
X
X
X
XInit()
X{
X
XSI.G = 6.67;
XSI.ds = 1.0;
XSI.dt = 1.0;
XSI.t = 0;
XSI.TrailLength = 0;
X
Xcancel_text.IText = cantxt;
X
XOffMenu(w,MN_CStop);
XOffMenu(w,MN_EMod);
XOffMenu(w,MN_FSScr);
X
X
XClearScreen();
XClearBodys();
XSetupGADefaults();
XBodyGADefaults();
X
Xreturn(0);
X
X}
X
X
X
X
XClearScreen()
X{
X
XSetRast(rp,0);
X
XSetAPen(rp,WHTPEN);
X
Xreturn(0);
X
X}
X
X
XDoIntuiEvents(wait)
XUBYTE wait;
X{
XULONG  MessageClass;
XUSHORT code,qual;
Xstruct Gadget *GAD;
Xstruct MsgPort *mp;
X
Xmp = w->UserPort;
X
Xfor(;;) {
X
X   if(message = (struct IntuiMessage *)GetMsg(w->UserPort)) {
X
X      MessageClass = message->Class;
X      code = message->Code;
X      qual = message->Qualifier;
X      GAD = (struct Gadget *)message->IAddress;
X
X      ReplyMsg(message);
X
X      switch (MessageClass) {
X
X	 case GADGETUP	  : DoGadget(GAD);
X			    break;
X
X	 case MENUPICK    : if(code != MENUNULL) {
X                               DoMenu(code);
X                            };
X                            break;
X
X	 case CLOSEWINDOW : CleanUp();
X			    exit(0);
X			    break;
X
X	 case MOUSEBUTTONS: if(code == SELECTDOWN) {
X			       MakeBody(w->GZZMouseX,w->GZZMouseY);
X			    };
X			    break;
X
X	 case MOUSEMOVE   : if(mode == MODE_CREATE) {
X			       ShowMouse(w->GZZMouseX,w->GZZMouseY);
X			    };
X			    break;
X
X	 case REQCLEAR	  : 
X			    ReqActive = ReqNone;
X			    break;
X
X	 default	  : 
X			    break;
X
X      };
X
X   } else {
X
X      if(!wait&&!ReqActive) return(0);
X
X      WaitPort(mp);
X
X   };
X
X};
Xreturn(0);
X}
X
X
X
XDoGadget(GAD)
Xstruct	Gadget *GAD;
X{
XULONG	val;
Xstruct	StringInfo *info;
X
X
Xinfo = (struct StringInfo *)GAD->SpecialInfo;
Xval  = info->LongInt;
X
Xswitch(GAD->GadgetID) {
X
X   case NAMEGAD		: 
X                          ActivateGadget(&mass,w,&BodyInfo);
X                          break;
X   case RADIUSGAD       : 
X                          break;
X
X   case MASSGAD         : 
X                          ActivateGadget(&velocity,w,&BodyInfo);
X                          break;
X
X   case VELOCITYGAD     : 
X                          ActivateGadget(&direction,w,&BodyInfo);
X                          break;
X
X   case DIRECTIONGAD    : 
X                          break;
X
X   case OKGAD		: 
X			  CancelHit=0;
X                          if(pw)
X                             WindowToFront(pw);
X			  break;
X
X   case CANCELGAD	: 
X			  CancelHit=1;
X                          if(pw)
X                             WindowToFront(pw);
X			  break;
X
X   case RESETGAD        : 
X                          switch(ReqActive) {
X                             case ReqBody  : BodyGADefaults();
X                                             RefreshGadgets(&mass,
X                                                            w,&BodyInfo);
X                                             break;
X                             case ReqSetup : SetupGADefaults();
X                                             RefreshGadgets(&dt,
X                                                            w,&SetupInfo);
X                                             break;
X                            
X                          };
X                          break;
X
X   case GGAD            : 
X                          ActivateGadget(&dt,w,&SetupInfo);
X                          break;
X
X   case DTGAD           : 
X                          ActivateGadget(&t,w,&SetupInfo);
X                          break;
X
X   case TGAD            : 
X                          ActivateGadget(&ds,w,&SetupInfo);
X                          break;
X
X   case DSGAD           : 
X                          ActivateGadget(&tl,w,&SetupInfo);
X                          break;
X
X   case TLGAD           : 
X                          break;
X
X   case COLOR1GAD	: 
X                          Bodys[CurBody].pen = (UBYTE)GAD->UserData;
X                          break;
X   case COLOR2GAD	: 
X                          Bodys[CurBody].pen = (UBYTE)GAD->UserData;
X                          break;
X   case COLOR3GAD	: 
X                          Bodys[CurBody].pen = (UBYTE)GAD->UserData;
X                          break;
X   case COLOR4GAD	: 
X                          Bodys[CurBody].pen = (UBYTE)GAD->UserData;
X                          break;
X   case COLOR5GAD	: 
X                          Bodys[CurBody].pen = (UBYTE)GAD->UserData;
X                          break;
X   case COLOR6GAD	: 
X                          Bodys[CurBody].pen = (UBYTE)GAD->UserData;
X                          break;
X   case COLOR7GAD	: 
X                          Bodys[CurBody].pen = (UBYTE)GAD->UserData;
X                          break;
X   case FNOKGAD		: 
X                          CancelHit=0;
X                          break;
X   case FNCANGAD	: 
X                          CancelHit=1;
X                          break;
X   case STGAD		: if(st.Flags&SELECTED) {
X                             st.GadgetText = &yes_text;
X                             RefreshGadgets(&st,w,&SetupInfo);
X                             SI.ShowTime=1;
X                          } else {
X                             st.GadgetText = &no_text;
X                             RefreshGadgets(&st,w,&SetupInfo);
X                             SI.ShowTime=0;
X                          };
X                          break;
X   case FXGAD		: if(fixed.Flags&SELECTED) {
X                             fixed.GadgetText = &yes_text;
X                             RefreshGadgets(&fixed,w,&BodyInfo);
X                             Bodys[CurBody].fixed=1;
X                          } else {
X                             fixed.GadgetText = &no_text;
X                             RefreshGadgets(&fixed,w,&BodyInfo);
X                             Bodys[CurBody].fixed=0;
X                          };
X                          break;
X
X   default		: 
X			  break;
X
X};
X
Xreturn(0);
X}
X
X
X
XDoMenu(MN)
XUSHORT MN;
X{
X
Xswitch(MENUNUM(MN)) {
X
X   case M_Control : 
X                    switch(ITEMNUM(MN)) { 
X
X                       case I_Stop    : 
X                                        mode = MODE_STOP;
X                                        ClosePw();
X			                OffMenu(w,MN_CStop);
X			                OnMenu(w,MN_ECreate);
X			                OnMenu(w,MN_ESetup);
X			                OnMenu(w,MN_EMod);
X			                OnMenu(w,MN_EClearS);
X			                OnMenu(w,MN_EClearB);
X                                        OnMenu(w,MN_FSDat);
X                                        OnMenu(w,MN_FLDat);
X                                        OnMenu(w,MN_CStart);
X                                        break;
X                       case I_Start   : 
X                                        if(TotalBodys == 0) {
X			                   MSG("No Bodys Created!!","OK","OK");
X			                   break;
X			                };
X			                mode = MODE_START;
X			                ModifyIDCMP(w,IDCMPFL);
X                                        if(SI.ShowTime) OpenPw();
X			                OffMenu(w,MN_ECreate);
X			                OffMenu(w,MN_ESetup);
X			                OffMenu(w,MN_EMod);
X			                OffMenu(w,MN_CStart);
X			                OffMenu(w,MN_EClearS);
X			                OffMenu(w,MN_EClearB);
X                                        OffMenu(w,MN_FSDat);
X                                        OffMenu(w,MN_FLDat);
X                                        OnMenu(w,MN_CStop);
X   			                DoSimulation();
X                                        break;
X                    };
X                    break;
X
X   case M_Edit    :
X                    switch(ITEMNUM(MN)) {
X
X                       case I_ClearB  : if(MSG("Really Clear Bodys?",
X                                               "YES!","NO!!")) {
X                                           ClearBodys();
X                                           OnMenu(w,MN_FSDat);
X                                           OnMenu(w,MN_FLDat);
X                                        };
X
X                                        break;
X                       case I_ClearS  : 
X                                        ClearScreen();
X                                        break;
X                       case I_Modify  : 
X                                        mode = MODE_MODIFY;
X                                        ModifyBodys();
X                                        break;
X                       case I_Create  : 
X                                        mode = MODE_CREATE;
X			                ModifyIDCMP(w,IDCMPFL_MM);
X                                        OpenPw();
X			                OnMenu(w,MN_CStart);
X			                OnMenu(w,MN_EMod);
X			                OffMenu(w,MN_ECreate);
X                                        OffMenu(w,MN_FLDat);
X                                        cancel_text.IText = cantxt;
X                                        break;
X                       case I_Setup   : 
X                                        Request(&SetupInfo,w);
X                                        Sleep(0L,100000L);
X                                        ActivateGadget(&G,w,&SetupInfo);
X                                        ReqActive = ReqSetup;
X                                        DoIntuiEvents(NOWAIT);
X                                        cancel_text.IText = cantxt;
X                                        if(!CancelHit) GetSetupInfo();
X                                        break;
X                    };
X                    break;
X
X   case M_File    :
X                    switch(ITEMNUM(MN)) {
X
X                       case I_Exit    : 
X                                        CleanUp();
X                                        exit(0);
X                                        break;
X                       case I_SavScr  : 
X                                        break;
X                       case I_SavDat  : 
X                                        DoSaveData();
X                                        break;
X                       case I_LoadDat : 
X                                        DoLoadData();
X                                        break;
X                       case I_About   : 
X                                        Request(&RAbout,w);
X                                        ReqActive = ReqAbout;
X                                        DoIntuiEvents(NOWAIT);
X                                        break;
X                    };
X                    break;
X
X};
X
Xreturn(0);
X
X}
X
X
X
XShowMouse(x,y)
XSHORT x,y;
X{
X
Xif(x<0||y<0) return(0);
X
Xsprintf(pbuf,"  %.3e , %.3e",
X   (double)(x)*SI.ds,(double)(w->GZZHeight-y+1)*SI.ds);
XPrintIText(prp,&pos_txt,0,0);
X
Xreturn(0);
X}
X
XOpenPw()
X{
X
Xif(pw) return(0);
X
Xif (!(pw = (struct Window *)OpenWindow(&npw) )) {
X   printf("could not open the pointer window\n");
X   CleanUp();
X   exit(17);
X};
X
Xprp = pw->RPort;
XSetAPen(prp,BLKPEN);
XSetBPen(prp,WHTPEN);
X
Xreturn(0);
X
X}
X
XClosePw()
X{
Xif(pw) CloseWindow(pw);
Xpw = (struct Window *)NULL;
Xreturn(0);
X}
X
X
X
XGetBodyInfo()
X{
Xdouble V;
X
X
Xstrcpy(Bodys[CurBody].name,name_sbuf);
X
Xif(sscanf(mass_sbuf,"%le",&Bodys[CurBody].Mass) != 1) {
X   MSG("Bad Value for Mass!","OK","OK");
X   return(0);
X};
X
XBodys[CurBody].Dir  =
X   (double)direction_txstr.LongInt * PI/180.0;
X
Xif(sscanf(velocity_sbuf,"%le",&V) != 1) {
X   MSG("Bad Value for Velocity!","OK","OK");
X   return(0);
X};
X
XBodys[CurBody].Vx  =
X   V * cos(Bodys[CurBody].Dir);
XBodys[CurBody].Vy  =
X   V * sin(Bodys[CurBody].Dir);
X
Xif(Bodys[CurBody].pen == 0)
X   Bodys[CurBody].pen = WHTPEN;
X
XBodys[CurBody].Fx  =  0.0;
XBodys[CurBody].Fy  =  0.0;
X
X
Xreturn(0);
X}
X
X
X
X
X
XGetSetupInfo()
X{
XWORD	n;
X
Xif(sscanf(G_sbuf,"%le",&SI.G) != 1) {
X   MSG("Bad Value for G!","OK","OK");
X   return(0);
X};
X
Xif(sscanf(ds_sbuf,"%le",&SI.ds) != 1) {
X   MSG("Bad Value for ds!","OK","OK");
X   return(0);
X};
X
Xif(sscanf(dt_sbuf,"%le",&SI.dt) != 1) {
X   MSG("Bad Value for dt!","OK","OK");
X   return(0);
X};
X
XSI.t  = (UBYTE)t_txstr.LongInt;
X
Xn = (WORD)tl_txstr.LongInt;
Xif(n>MAXTRAILEN) {
X   MSG("TrailLength too large!","OK","OK");
X   return(0);
X};
X
XSI.TrailLength=n;
X
Xreturn(0);
X}
X
X
X
X
XMakeBody(x,y)
XSHORT x,y;
X{
X
X
Xif(mode != MODE_CREATE)
X   return(0);
Xif(x<0 || y<0)
X   return(0);
X
Xif(TotalBodys++ > MAXBODYS) {
X   TotalBodys--;
X   MSG("No More Body's Available!!","OK","OK");
X   return(0);
X};
X
XSetAPen(rp,REDPEN);
XWritePixel(rp,x,y);
XCurBody = FindFreeBody();
Xif(CurBody == -1) {
X   TotalBodys--;
X   MSG("No More Body's Available!!","OK","OK");
X   return(0);
X};
Xcancel_text.IText = cantxt;
X
XBodyGADefaults();
Xsprintf(xy_buf," %.3e , %.3e ",
X   (double)(x)*SI.ds,(double)(w->GZZHeight-y+1)*SI.ds);
XRequest(&BodyInfo,w);
XReqActive = ReqBody;
XSleep(0L,100000L);
XActivateGadget(&name,w,&BodyInfo);
XDoIntuiEvents(NOWAIT);
X
Xif(CancelHit) {
X   TotalBodys--;
X   SetAPen(rp,BLKPEN);
X   WritePixel(rp,x,y);
X   return(0);
X};
X
XGetBodyInfo();
X
Xif(Bodys[CurBody].Mass == 0.0) {
X   TotalBodys--;
X   SetAPen(rp,BLKPEN);
X   WritePixel(rp,x,y);
X   MSG("Mass can't be ZERO!!","OK","OK");
X   return(0);
X};
X
XBodys[CurBody].x = (double)(x)*SI.ds;
XBodys[CurBody].y = (double)(y)*SI.ds;
XBodys[CurBody].real = 1;
XSetAPen(rp,Bodys[CurBody].pen);
XWritePixel(rp,x,y);
X
Xreturn(0);
X
X}
X
XFindFreeBody()
X{
Xint	x;
X
Xfor(x=0 ; x<MAXBODYS ; x++)
X   if(!Bodys[x].real) return(x);
X
Xreturn(-1);
X
X}
X
X
XModifyBodys()
X{
Xint 	n;
XSHORT	x,y;
X
X
Xmode = MODE_MODIFY;
XModifyIDCMP(w,IDCMPFL);
XClosePw();
XOffMenu(w,MN_CStart);
XOffMenu(w,MN_EMod);
XOffMenu(w,MN_ECreate);
Xcancel_text.IText = deltxt;
X
X
Xfor(n=0 ; n<MAXBODYS ; n++) {
X
X   CurBody = n;
X   if(Bodys[n].real) {
X
X      Bodys[n].real=0;
X
X      LoadBodyReq(n);
X      x = (SHORT)(Bodys[n].x/SI.ds);
X      y = (SHORT)(Bodys[n].y/SI.ds);
X
X      color_text.FrontPen = Bodys[n].pen;
X      sprintf(xy_buf," %.3e , %.3e ",
X              (double)(x)*SI.ds,(double)(w->GZZHeight-y+1)*SI.ds);
X      Request(&BodyInfo,w);
X      Sleep(0L,100000L);
X      ReqActive = ReqBody;
X      ActivateGadget(&name,w,&BodyInfo);
X      DoIntuiEvents(NOWAIT);
X   
X      if(CancelHit) {		/* GAD really says "DELETE" */
X         TotalBodys--;
X         SetAPen(rp,BLKPEN);
X         WritePixel(rp,x,y);
X         continue;
X      };
X   
X      GetBodyInfo();
X   
X      if(Bodys[n].Mass == 0.0) {
X         TotalBodys--;
X         SetAPen(rp,BLKPEN);
X         WritePixel(rp,(SHORT)x,(SHORT)y);
X         MSG("Mass can't be ZERO!!","OK","OK");
X         continue;
X      };
X   
X      Bodys[n].real=1;
X      SetAPen(rp,Bodys[CurBody].pen);
X      WritePixel(rp,x,y);
X
X   };
X};
X
X
Xcolor_text.FrontPen = WHTPEN;
X
XOnMenu(w,MN_CStart);
XOnMenu(w,MN_ECreate);
Xif(TotalBodys)
X   OnMenu(w,MN_EMod);
Xelse
X   OffMenu(w,MN_EMod);
X
Xreturn(0);
X
X}
X
X
X
XLoadBodyReq(n)
Xint	n;
X{
Xdouble	v;
X
Xname_txstr.NumChars = sprintf(name_sbuf,"%s",Bodys[n].name);
Xmass_txstr.NumChars = sprintf(mass_sbuf,"%.3e",Bodys[n].Mass);
X
Xdirection_txstr.LongInt = (ULONG)(Bodys[n].Dir * 180.0/PI);
Xdirection_txstr.NumChars = sprintf(direction_sbuf,"%ld",
X                                   direction_txstr.LongInt);
X
Xv = Bodys[n].Vx*Bodys[n].Vx + Bodys[n].Vy*Bodys[n].Vy;
Xv = sqrt(v);
Xvelocity_txstr.NumChars = sprintf(velocity_sbuf,"%.3e",v);
X
Xif(Bodys[n].fixed) {
X   fixed.GadgetText = &yes_text;
X   fixed.Flags |= SELECTED;
X} else {
X   fixed.GadgetText = &no_text;
X   fixed.Flags &= ~SELECTED;
X}
X
Xreturn(0);
X}
X
X
X
X
XDoSimulation()
X{
XUBYTE b;
Xdouble	 F,Fx=0.0,Fy=0.0,V;
X
X
XEt = 0L;
X
Xwhile(mode == MODE_START) {
X
X if(SI.ShowTime) {
X   sprintf(pbuf," Time  %ld",Et);
X   PrintIText(prp,&pos_txt,0,0);
X };
X
X /*
X  * Calculate new directions & velocities
X  * resulting from all external forces (all other bodies)
X  */
X
X for(b=0 ; b<MAXBODYS ; b++ ) {
X
X   if(!Bodys[b].real) continue;
X   if(Bodys[b].fixed) continue;
X
X   GetForces(b,&Fx,&Fy);
X
X   if(Fx != 0.0 && Fy != 0.0) {
X
X      F = sqrt(Fx*Fx+Fy*Fy);           /* Total force on this body */
X				       /*  indirection of A */
X      V = F*SI.dt/Bodys[b].Mass;       /* FT = MV (impulse) */
X
X      Bodys[b].Vx += V*Fx/F; /* Fx/F = cos(A). adj vel as a result of impulse */
X      Bodys[b].Vy += V*Fy/F; /* Fy/F = sin(A).  in direction of resultant Force */
X
X      Bodys[b].Dir = atan2(Bodys[b].Vy,Bodys[b].Vx);  /* new direction */
X      if(Bodys[b].Dir < 0.0)
X	 Bodys[b].Dir += 2.0*PI;
X   };
X
X
X };
X
X /*
X  * Display new positions
X  */
X
X for(b=0 ; b<MAXBODYS ; b++) {
X
X   if(!Bodys[b].real) continue;
X
X   if(!SI.TrailLength) {
X      SetAPen(rp,BLKPEN);
X      WritePixel(rp,(SHORT)(Bodys[b].x/SI.ds),(SHORT)(Bodys[b].y/SI.ds));
X   } else {
X      if(SI.TrailLength>0) {
X         if(Bodys[b].TrailIDX >= SI.TrailLength)
X            Bodys[b].TrailIDX=0;
X         if(Bodys[b].TrailX[Bodys[b].TrailIDX]>=0) {
X            SetAPen(rp,BLKPEN);
X            WritePixel(rp,(SHORT)(Bodys[b].TrailX[Bodys[b].TrailIDX]/SI.ds),
X                          (SHORT)(Bodys[b].TrailY[Bodys[b].TrailIDX]/SI.ds));
X            
X         };
X         Bodys[b].TrailX[Bodys[b].TrailIDX] = Bodys[b].x;
X         Bodys[b].TrailY[Bodys[b].TrailIDX] = Bodys[b].y;
X         Bodys[b].TrailIDX++;
X      };
X   };
X
X   Bodys[b].x += (Bodys[b].Vx * SI.dt);
X   Bodys[b].y -= (Bodys[b].Vy * SI.dt);
X
X   SetAPen(rp,Bodys[b].pen);
X   WritePixel(rp,(SHORT)(Bodys[b].x/SI.ds),(SHORT)(Bodys[b].y/SI.ds));
X
X };
X
XDoIntuiEvents(NOWAIT);
X
Xif(SI.t)
X   Sleep(0L,(ULONG)SI.t*1000L);
X
XEt++;
X
X};
X
Xreturn(0);
X}
X
X
XGetForces(b,fx,fy)
XUBYTE b;
Xdouble *fx,*fy;
X{
Xint x;
Xdouble dY,dX,Fx,Fy,F,R;
X
XFx = Fy = 0.0;
Xfor(x=0 ; x<MAXBODYS ; x++) {
X
X   if(x==b) continue;
X   if(!Bodys[x].real) continue;
X
X   dX =  (Bodys[x].x - Bodys[b].x) * SI.ds; /* X2 - X1 */
X   dY =  (Bodys[b].y - Bodys[x].y) * SI.ds; /* Y2 - Y1 BUT */
X					     /* normalized to bottom */
X					     /* left of window */
X
X   R = dX*dX+dY*dY;	/* part of sqrt(x^2+y^2) */
X			/* for F calc below. F needs R^2 so we'll */
X			/* do sqrt() part after (sqrt(x)^2 = x) */
X
X   F =	SI.G * (Bodys[b].Mass * Bodys[x].Mass) / R;
X
X   R = sqrt(R);         /* distance between points */
X
X   Fx += F*(dX/R);    /* dX/R = cos(A) but faster */
X   Fy += F*(dY/R);    /* dY/R = sin(A) but faster */
X
X};
X
X*fx = Fx;
X*fy = Fy;
X
Xreturn(0);
X}
X
X
XSetupGADefaults()
X{
X
Xstrcpy(G_sbuf,"6.67e0");
XG_txstr.NumChars=6;
X
Xstrcpy(t_sbuf,"0");
Xt_txstr.NumChars=1;
Xt_txstr.LongInt = 0L;
X
Xstrcpy(ds_sbuf,"1.0e0");
Xds_txstr.NumChars=5;
X
Xstrcpy(dt_sbuf,"1.0e0");
Xdt_txstr.NumChars=5;
X
Xstrcpy(tl_sbuf,"0");
Xdt_txstr.NumChars=1;
X
Xst.GadgetText = &no_text;
Xst.Flags &= ~SELECTED;
X
Xreturn(0);
X
X}
X
X
XBodyGADefaults()
X{
X
Xstrcpy(name_sbuf,"SUN");
Xname_txstr.NumChars=3;
X
Xstrcpy(mass_sbuf,"1.0e0");
Xmass_txstr.NumChars=5;
X
Xstrcpy(velocity_sbuf,"0.0e0");
Xvelocity_txstr.NumChars=5;
X
Xstrcpy(direction_sbuf,"0");
Xdirection_txstr.NumChars=1;
Xdirection_txstr.LongInt = 0L;
X
Xfixed.GadgetText = &no_text;
Xfixed.Flags &= ~SELECTED;
X
Xreturn(0);
X
X}
X
X
X
XClearBodys()
X{
Xint	x,t;
X
Xfor(x=0 ; x<MAXBODYS ; x++) {
X   Bodys[x].real = 0;
X   Bodys[x].pen = 0;
X
X   for(t=0 ; t<MAXTRAILEN ; t++) {
X      Bodys[x].TrailX[t]=-1.0;
X      Bodys[x].TrailY[t]=-1.0;
X   };
X   Bodys[x].TrailIDX = 0;
X
X};
X
XClearScreen();
XTotalBodys = 0;
X
Xreturn(0);
X
X}
X
X
X
XDoSaveData()
X{
Xint	x;
XFILE	*fp;
X
X
XRequest(&FileName,w);
XSleep(0L,100000L);
XActivateGadget(&fn,w,&FileName);
XReqActive = ReqFile;
XDoIntuiEvents(NOWAIT);
X
Xif(CancelHit)
X   return(0);
X
X
Xfp = fopen(fn_sbuf,"w");
Xif(!fp) {
X   MSG("Can't open output file!","OK!","OH WELL!");
X   return(0);
X};
X
Xfprintf(fp,"--- CM Setup Data ---\n");
Xfprintf(fp,"G=%.3e\n",SI.G);
Xfprintf(fp,"ds=%.3e\n",SI.ds);
Xfprintf(fp,"dt=%.3e\n",SI.dt);
Xfprintf(fp,"t=%d\n",(int)SI.t);
Xfprintf(fp,"TrailLength=%d\n",(int)SI.TrailLength);
Xfprintf(fp,"ShowTime=%d\n",(int)SI.ShowTime);
X
X
Xfprintf(fp,"--- CM Body Data ---\n");
Xfprintf(fp,"#=name ;pen;fixed;Radius;Mass;x,y;Vx,Vy;Dir\n");
Xfor(x=0 ; x<MAXBODYS ; x++)
X   if(Bodys[x].real) {
X      fprintf(fp,"%d=%s ;%d;%d;%ld;%.3e;%.3e,%.3e;%.3e,%.3e;%.3e\n",
X		x,
X		Bodys[x].name,
X		(int)Bodys[x].pen,
X                (int)Bodys[x].fixed,
X		Bodys[x].Radius,
X		Bodys[x].Mass,
X		Bodys[x].x,w->GZZHeight-Bodys[x].y+1,
X		Bodys[x].Vx,Bodys[x].Vy,
X		Bodys[x].Dir*180.0/PI);
X		
X   };
X
Xfclose(fp);
X
Xreturn(0);
X
X}
X
X
X
XDoLoadData()
X{
Xint	n;
XFILE	*fp;
Xchar	buf[101],name[10];
XULONG	pen,fixed,Radius;
Xdouble	x,y,Mass,Vx,Vy,Dir;
X
X
XCancelHit=0;
XRequest(&FileName,w);
XSleep(0L,100000L);
XActivateGadget(&fn,w,&FileName);
XReqActive = ReqFile;
XDoIntuiEvents(NOWAIT);
X
Xif(CancelHit)
X   return(0);
X
X
Xfp = fopen(fn_sbuf,"r");
Xif(!fp) {
X   MSG("Can't open Data File!","OK!","OH WELL!");
X   return(0);
X};
X
Xfgets(buf,100,fp);	/* forget first line, it's just a header */
Xfgets(buf,100,fp);
Xif(sscanf(buf,"G=%le\n",&SI.G) != 1) {
X   MSG("Bad data file (G)!","OK!","OOPS!");
X   fclose(fp);
X   return(0);
X};
X
Xfgets(buf,100,fp);
Xif(sscanf(buf,"ds=%le\n",&SI.ds) != 1) {
X   MSG("Bad data file (ds)!","OK!","OOPS!");
X   fclose(fp);
X   return(0);
X};
X
Xfgets(buf,100,fp);
Xif(sscanf(buf,"dt=%le\n",&SI.dt) != 1) {
X   MSG("Bad data file (dt)!","OK!","OOPS!");
X   fclose(fp);
X   return(0);
X};
X
Xfgets(buf,100,fp);
Xif(sscanf(buf,"t=%d\n",&n) != 1) {
X   MSG("Bad data file (t)!","OK!","OOPS!");
X   fclose(fp);
X   return(0);
X};
XSI.t = (UBYTE)n;
X
Xfgets(buf,100,fp);
Xif(sscanf(buf,"TrailLength=%d\n",&n) != 1) {
X   MSG("Bad data file (TrailLength)!","OK!","OOPS!");
X   fclose(fp);
X   return(0);
X};
X
Xif(n>MAXTRAILEN) {
X   MSG("TrailLength too big","OK!","OOPS!");
X   fclose(fp);
X   return(0);
X};
XSI.TrailLength = (WORD)n;
X
Xfgets(buf,100,fp);
Xif(sscanf(buf,"ShowTime=%d\n",&n) != 1) {
X   MSG("Bad data file (ShowTime)!","OK!","OOPS!");
X   fclose(fp);
X   return(0);
X};
XSI.ShowTime = (WORD)n;
Xif(n) {
X   st.GadgetText = &yes_text;
X   st.Flags |= SELECTED;
X} else {
X   st.GadgetText = &no_text;
X   st.Flags &= ~SELECTED;
X};   
X
X
XG_txstr.NumChars  = sprintf(G_sbuf,"%.3e",SI.G);
Xdt_txstr.NumChars = sprintf(dt_sbuf,"%.3e",SI.dt);
Xt_txstr.NumChars  = sprintf(t_sbuf,"%d",SI.t);
Xt_txstr.LongInt   = (ULONG)SI.t;
Xds_txstr.NumChars = sprintf(ds_sbuf,"%.3e",SI.ds);
Xtl_txstr.LongInt  = (LONG)SI.TrailLength; 
Xtl_txstr.NumChars = sprintf(tl_sbuf,"%d",SI.TrailLength);
X
XClearBodys();
X
Xfgets(buf,100,fp);
Xfgets(buf,100,fp);
X
Xwhile(fgets(buf,100,fp) != (char *)NULL) {
X   if(sscanf(buf,"%d=%s;%d;%d;%ld;%le;%le,%le;%le,%le;%le",
X             &n,name,&pen,&fixed,&Radius,&Mass,&x,&y,&Vx,&Vy,&Dir) != 11) {
X      MSG("Bad Body in data file","OK!","OOPS!");
X      fclose(fp);
X      return(0);
X   };
X   if(n>MAXBODYS) {
X      MSG("Bad Body # in data file","OK!","OOPS!");
X      fclose(fp);
X      return(0);
X   };
X
X   if(!Bodys[n].real) TotalBodys++; /* don't count same definition twice */
X   Bodys[n].real   = 1;
X   Bodys[n].pen    = pen;
X   Bodys[n].fixed  = fixed;
X   Bodys[n].Radius = Radius; 
X   Bodys[n].Mass   = Mass;
X   Bodys[n].x      = x;
X   Bodys[n].y      = w->GZZHeight-y+1;
X   Bodys[n].Vx     = Vx;
X   Bodys[n].Vy     = Vy;
X   Bodys[n].Dir    = Dir*PI/180.0;
X   strcpy(Bodys[n].name,name);
X
X   SetAPen(rp,pen);
X   WritePixel(rp,(SHORT)(Bodys[n].x/SI.ds),(SHORT)(Bodys[n].y/SI.ds));
X		
X};
X
Xfclose(fp);
X
XOnMenu(w,MN_ECreate);
XOnMenu(w,MN_EMod);
X
X
Xreturn(0);
X
X}
X
X
XMSG(msg,p,n)
Xchar	*msg,*p,*n;
X{
X
Xstruct IntuiText msg_txt = {
X   BLKPEN,REDPEN,			/* FrontPen, BackPen */
X   JAM1,				/* DrawMode */
X   10,20,				  /* LeftEdge, TopEdge */
X   &TxtAt_Plain,			/* TextAttr */
X   0,					/* IText */
X   NULL 				/* NextText */
X};
X
Xstruct IntuiText pos_txt = {
X   BLKPEN,REDPEN,			/* FrontPen, BackPen */
X   JAM1,				/* DrawMode */
X   3,3, 				/* LeftEdge, TopEdge */
X   &TxtAt_Plain,			/* TextAttr */
X   0,					/* IText */
X   NULL 				/* NextText */
X};
X
Xstruct IntuiText neg_txt = {
X   BLKPEN,REDPEN,			/* FrontPen, BackPen */
X   JAM1,				/* DrawMode */
X   3,3, 				/* LeftEdge, TopEdge */
X   &TxtAt_Plain,			/* TextAttr */
X   0,					/* IText */
X   NULL 				/* NextText */
X};
X
Xmsg_txt.IText = msg;
Xpos_txt.IText = p;
Xneg_txt.IText = n;
X
X
Xreturn(AutoRequest(w,&msg_txt,&pos_txt,&neg_txt,
X		   NULL,NULL,40+IntuiTextLength(&msg_txt),80));
X
X}
X
X
X
X
X
X
XSleep(secs,usecs)
XULONG	secs,usecs;
X{
X
XTR->tr_node.io_Command = TR_ADDREQUEST;
XTR->tr_time.tv_secs = secs;
XTR->tr_time.tv_micro = usecs;
XDoIO(TR);
X
Xreturn(0);
X
X}
X
X
X
X
X
XCleanUp()
X{
X
Xif(TimerPort) DeletePort(TimerPort);
Xif(TimerOpen) CloseDevice(TR);
Xif(TR) DeleteExtIO(TR,sizeof(struct timerequest));
Xif(w) {
X   ClearMenuStrip(w);
X   CloseWindow(w);
X};
Xif(pw) CloseWindow(pw);
Xif(s) {
X   CloseScreen(s);
X/*   FreeColorMap(cm); */
X};
Xif(GfxBase) CloseLibrary(GfxBase);
X(void)OpenWorkBench();
Xif(IntuitionBase) CloseLibrary(IntuitionBase);
Xreturn(0);
X}
X
X
X
X
X
X
X
X
X
X
SHAR_EOF
echo "extracting cm.doc"
sed 's/^X//' << \SHAR_EOF > cm.doc
X
X
X				CM
X
X		    Celestial Mechanics Simulator
X			    Version 1.0
X
X
X			   W. John Guineau
X		       3 Royal Crest Drive #9
X			Marlboro, Mass 01752
X			   (508) 485-6233
X
X
X
X			      NOTICE
X			      ------
X
X  I have placed this software in the Public Domain with the
Xcondition that all the files remain together and that I remain
Xlisted as the original author. This software may not be used for
Xcommercial purposes or to make money in any way without expressed
Xwritten permission from the author (me). I'm including the source
Xcode so if you make any significant modifications please concider
Xsending me a copy at the above address. I'd also be interested in
Xany interesting saved setup files you create.
X
X
XThis is my first Amiga program so I welcome any comments at all.
XI wrote this program as both a way to learn the Amiga environment
Xand in response to a conversation I had with a friend on Celestial
XMechanics.
X
X
X
X
X
X
X			    What is it?
X			    -----------
X
XCM is a Celestial Mechanics simulation tool. It allows you to
Xconstruct a layout of Masses (called Bodys) and specify various
Xparameters concerning both the bodys and the simulation. All input
Xis accomplished through a fully intuitionized interface. CM then
Xproceeds to animate the bodys according to the laws of gravational
Xattraction ( F = Gm1m2/r^2 ).  Setups may be saved to disk to allow
Xyou later re-inact interesting scenarios.
X
X
X
X
X			  Getting Started
X			  ---------------
X
XCM can be run from either the CLI or from workbench by double
Xclicking it's icon. In order for you to get a quick start, I've
Xincluded some interesting setup files (described below). Just run
XCM and select LoadData from the FILE menu. Enter the name of the
Xsaved simulation you want and hit return (or click OK in the file
Xrequestor).
X
XNext select START from the CONTROL menu. That's it!
X
XHere are the included setups:
X
X3BODY.DAT - This is a setup of 3 bodys (no kidding!). One is a
Xvery (relativly) massive body which is not moving. The other two
Xare much smaller and have initial velocities - one in a close
Xorbit, the other in a larger orbit. What makes this interesting is
Xthat on several occasions the two get close enough to affect
Xeachothers orbit. Then after about t=1400, they swap orbits.
X
XFIXED1.DAT - This is an example of a feature in creating bodys
Xwhere they can be "fixed" in place (i.e. not allowed to move).
XWhile this is not possible in reality, it makes for some interesting
Xeffects (and gives a good control on single body experiments).
X
XFIXED2.DAT - Another fixed body example. Watch this one around
Xt=1700!
X
X
XSVEM.DAT - This stands for SUN, VENUS, EARTH, MARS. It's a scale
Xexperiment of (guess what) the inner planets. While the masses,
Xvelocities and distances are correct, I don't quite have the
Xinitial directions just right (although it does indeed take the
XEarth 365 days to complete an orbit, as well as the other planets
Xare quite close to thier orbital period). This is a good example for
Xscaling time and distance.
X
XSMVEM.DAT - Another like above. SUN, MERCURY, VENUS, EARTH, MARS.
X
X
X
X
X			 How to use CM
X			 -------------
X
XCM is really pretty easy to use. You first need to decide on what
Xyou want to simulate. Then decide on an appropriate scale for
Xboth distance and time.
X
XThe visible universe is made up of 635 units in the x direction
Xand 377 units in the y direction. I say units instead of pixels
Xbecause CM lets you assign any arbitrary scale to the distance
Xbetween each pixel. Calculations are based on the scaled distance and on
Xscaled time. CM lets you specify an arbitrary amount of time for each
Xiteration of the simulation.
X
XThe non-visible universe extends virtually infinetly in all
Xdirections (2D space).
X
XTo see how scaling is useful concider the 3BODY.DAT example
X(described above). It has a distance scale of 1:1 and a time scale
Xof 0.5. Which brings up another useful variable to set - G. G is the
Xgravational constant and is, in reality, equal to 6.67E-11. CM
Xlets you specify what G is for the calculations. 3BODY.DAT uses
Xjust 6.67 for G, pretty amazing, huh? :-0.
X
XNow contrast 3BODY's settings with those of SVEM.DAT. This is a
Xreal scale model. The distance scale is 1E6, which just happens
Xto work nicely for distances in KiloMeters from the SUN to the inner
Xplanets. The time scale is 8.64E4. What is that?? It's the number of
Xseconds in one day. G is set to 6.67E-8, which is appropriate
Xfor the KiloMeter scaling of distance. Since the units for G are
Xbased on 1 second, time scaling must also be based on 1 second -
Xhence, 1 day in seconds. This means that for each iteration of the
Xsimulation, one day goes by and by placing the Earth body 150
Xunits (pixels) away from the SUN's location, it's really 150E6
Xkilometers away (it's correct mean distance). Ij addition to
Xdistance and time, you should use units for Mass and Velocity
Xthat are consistant with everything. Get the idea?
X
X
XThe best things to do are get a good book with real numbers and
Xexperiment. Eventually you'll get the feel for the scaling and
Xhow it affects the simulation.
X
X
X
X
X			     The Menus
X			     ---------
X
XWith that simple look at things, heres what the menu's do.
X
XThere are 3 main menus in the title bar: FILE, EDIT and CONTROL.
X
X
XThe FILE menu has the following items.
X
XABOUT	- Read this one and send mail to the address listed or just
X	  call to say hi! I'd love to hear from anyone using this
X	  program with questions, comments or whatever.
X
XLoadData
X	- This allows you to load in a previously saved setup file.
X	  The files are pretty simple. You can type or edit them but
X	  beware that CM expects the EXACT format they get saved in. Type
X	  one out and see!
X
X	  Selecting this item pops up a simple file requestor asking
X	  for the name.
X
X
XSaveData
X	- This allows you to save a setup. It's a good idea to
X	  save an experiment BEFORE you run it. That way you can
X	  reload it to modify the initial parameters.
X
X	  Selecting this item pops up a simple file requestor asking
X	  for the name.
X
XSaveScreen
X	- This item will dump the current screen to an IFF ILBM
X	  file (for use with DPaint or whatever). CM uses a hires
X	  interlaced, 8 color custom screen.
X
X	  This menu item is currently not implemented. If anyone is
X	  interested I will put it in. Actually I'll do it sometime
X	  anyway just to learn how!
X
XEXIT	- Exits CM. The window close gadget does the same thing.
X
X
X
XThe EDIT menu has the following items.
X
XSetup	- This pops up a requestor to allow you to set all the
X	  simulation parameters. The parameters are described
X	  below.
X
XCreate	- This puts CM into the Create Body mode. Once selected
X	  a small window will open at the top of the screen showing
X	  the current mouse coordinates (properly scaled). When the
X	  mouse is where you want a body, click the left button.
X	  A body requestor will pop up to let you fill in the
X	  information for that body. The body requestor is described
X	  below. You can create up to 10 bodys.
X
XModify	- Once you've created bodys (or loaded them in from a file)
X	  you can step through them to view/modify their parameters.
X	  You can also delete a body this way.
X
XClearScreen
X	- Just clears the screen. Useful when trails have
X	  cluttered the display.
X
XClearBodys
X	- Clears all body information. A requestor will ask you if
X	  you really want to do this.
X
X
XThe CONTROL menu has the following items.
X
XStart	- Starts a simulation. You must have bodys created to use
X	  this item.
X
XStop	- Stops a simulation in progress. Setup info can then be
X	  changed, bodys can be modified or saved and the simulation
X	  restarted.
X
X
XThe setup requestor allows you to change the following.
X
XG	- The gravational constant. Entered as a floating point
X	  number such as 6.67e-11.
X
XSim Time
X	- This is the time scaling for each iteration of the
X	  simulation. Specified as a floating point number.
X
XReal Time
X	- Normally the simulator runs at full speed. Putting a value
X	  other than zero here inserts a real delay, in miliseconds,
X	  between each iteration. Maybe useful for 68020/68030 users.
X	  Specified as an integer.
X
XUnits/Pixel
X	- This is the distance scale. It specifies the distance
X	  between pixels. Specified as a floating point number.
X
XTrailLength
X	- This decides how a bodys trail is dealt with.
X	  A value of ZERO means leave no trail.
X	  A value of -1 means leave an infinite trail.
X	  A value between 1 and 300 specifies the number of
X	    past locations to save. This creates worm like
X	    trails behind a body.
X
XShowTime
X	- If YES, the integer number of iterations will be displayed
X	  during the simulation. This number can then be multiplied
X	  by the time scale for real time. In some cases, such as
X	  with the SVEM and SMVEM examples, it can be read directly
X	  as days.
X
X
XThe Body requestor allows you to specify the following
Xcharacteristics of a body.
X
XNAME	- This is a name you give it (such as SUN, EARTH etc.)
X
X
XMASS	- This is it's mass. Entered as a floating point number.
X	  The units you use should be consistant with the rest
X	  of the setup information (i.e. G, scaling, velocity etc)
X
XVELOCITY
X	- The scalar velocity of the body. Floating point. Should
X	  be dimensionally consistant with the rest of the setup
X	  info.
X
XDIRECTION
X	- The angle of the velocity in degrees. 0 degrees is due
X	  east with 90 strait up, 180 due west and 270 due south.
X	  Integer number.
X
XCOLOR	- Clicking on a color will set the bodys color.
X
X
XFIXED	- YES means the body can't move. While this is not "real",
X	  it can be useful for experimentation.
X
X
XThe bodys current location is displayed below the FIXED gadget.
X
X
XIn both the SETUP and the BODY requestors, clicking on OK accepts
Xthe values, RESET sets them to their defaults and CANCEL quits the
Xoperation without any changes. In addition the BODY requestor will
Xdisplay DELETE in place of CANCEL during a MODIFY operation.
XSelcecting this will delete the body from the simulation.
X
X
X
X
X
X
X
X
X
X
SHAR_EOF
echo "End of archive 1 (of 2)"
# if you want to concatenate archives, remove anything after this line
exit