// INTERGALACTIC GRAVITATIONAL MOTION SIMULATOR // // v3.2 Last Updated 16 April 2000 // Programmed by D. Perley // http://www.people.cornell.edu/pages/dap29/programs.html // // You are free to perform any modifications to this code that you desire, // provided you retain my name above and credit me where appropriate. // The code may be redistributed free of restriction. // // All components of the software - interface, 3D projection, and n-body // simulator are included below. Only the graphics file EGAVGA.BGI and // the Borland C/C++ 3.1 header/library files are necessary outside this // file to recompile the program. #include #include #include #include #include #include #include #include #include #define Gphys 6.673e-11 //universal gravitational constant #define maxp 502 //maximum particles supportable (lim 968) #define sccx 320 //x-coordinate of center of screen #define sccy 240 //y-coordinate of center of screen #define zinc 1.5 //zoom step factor #define sinc 1.5 //shift increment #define rinc 5 //rotation increment angle #define dtor 0.0174532925 //conversion: degrees to radians void simmodule(void); //main module for simulator void corecalc(void); //calculates acceleration and moves particles void input(void); //finds user input and routes appropriately void graphiccalc(int p1); //calculates graphical gx and gy for p1 void drawparticle(int p1, int style, int cset); //draws/erases specified p void drawallparticles(int cset1, int cset2);//draws/erases/redraws all p void pause(void); //holds simulation during user pause void imagezoom(int zdir); //magnifies or minifies view space void imageshift(int sdir); //shifts image horizontally void changedelay(int ddir); //increases or decreases delay void displayinfo(void); //displays simulation statistics void clearinfo(void); //clears displayinfo() display void printmode(void); //special color/style for using PrintScrn void imagerotate(int rdir); //rotates image void initialize(void); //sets default conditions and init. grapics void initgalaxies(void); //creates galaxy disks void transform(float rxy, float rxz, float ryz); //transforms over 3 rotations void retroproject(void); //find initial galaxy positions in rev. time void snapshot(void); //records visual graphic data to disk void storepos(void); //store particle positions in dynamic array void storeinitial(void); //store essential initial conditions to disk void storesimulation(void); //store simulation to disk void loadsimulation(void); //load initstats and simulation details to disk void findpos(void); //find current particle positions from databank void initmemory(void); //initializes dynamic memory void terminate(void); //terminates active simulation int evendiv(float num, float den); //determines whether numbers divide evenly void IFmodule(void); //main module for interface void IFprintheader(void); //print interface header void IFgetsellabel(char * selptr, int l); //retrieve selection label int IFinput(void); //find user input in interface void IFchangesel(int dir, int l);//change selection in interface void liminput(char * inputstring, int lim, int digok, int alpok, int buf); void IFproperties(void); //module for interface properties page void IFgalaxies(void); //module for interface galaxies page int checkretro(void); //check retroprojecton parameters for errors int checkdisk(void); //check galaxy particle parameters for errors int checkprop(void); //check property parameters for errors void errmsg(char * errormessage);//get retroprojection error message void printfunct(int f1, int f2, int f3, int f4, int f5); //print funct. footer double fix(double rnum, int ndig);//round after ndig decimal place void IFparticles(void); //module for interface particles mage void printerrmsg(void); //prints error message in interface void savesettings(void); //saves interface settings to disk void loadsettings(int loadall); //loades interface settings from disk void tracking(void); //fixes camera on object int dopplercolor(int p1); //assigns p color based on z-axis velocity int fadecolor(int p1); //assigns p color based on z-axis distance void adjcolors(int cdir); //adjusts settings for color functions void kcalc(void); //calculates acceleration equation constants void printtime(void); //prints simulation name and current time float t; //time float timestep = 1; //time increment float maxt; //auto-termination time int dataentry = 0; //storage index int nump; //number of particles char com; //user input variable float centx = 0; //x-coordinate of effective center of screen float centy = 0; //y-coordinate of effective center of screen float centz = 0; //z-coordinate of effective center of screen float offx = 0; //x-axis distance from center and tracked particle float offy = 0; //y-axis distance from center and tracked particle float rota = 0; //x-y rotation float rotb = 0; //x-z rotation float rotc = 0; //y-z rotation float zoom = 1; //zoom factor int ptrack = 0; //tracked particle ID int exitflag = 0; //flags exit command int pauseflag = 0; //flags pause int displayflag = 0; //flags display info int store = 0; //data storage 0=none 1=RAM 2=disk int source = 0; //source of particle data 0=simulation 1=file int redraw = 2; //pixel redraw metod 0=flash 1=sequence int monitor = 1; //flags view simulation int style = 0; //particle set appearance int track = 0; //tracking mode 0=none 1=g1 2=g2 3=center-of-mass int doppler = 0; //flags doppler mimicry int fade = 0; //depth coloration long delay = 0; //steps in timing loop delay int tracers = 1; //flags tracers int recfreq = 30; //store data every recfreq stu int drawfreq = 2; //redraw particles every drawfreq stu int autosnap = 0; //automatically snapshot every autosnap stu int color; //color of drawn particle int fileindex = 0; //snapshot file index int skip; //flags skip user input float transx0, transy0, transz0; float transx1, transy1, transz1; //3-D transformation step variables float transx2, transy2, transz2; float igdis; //perigalacticon distance float igvel; //perigalacticon velocity float igecc; //eccentricity float iginc; //kinematic inclination float igarg; //kinematic rotation float igt0; //initial time (0 = perigalacticon) double smu = 1e+39; //value of simulation mass unit double sdu = 1e+19; //value of simulation distance unit double stu = 1e+13; //value of simulation time unit double G = 6.673e-3; //value of simulation gravitational constant int sduor = 0; int stuor = 1; //precedence in which units are rescaled int smuor = 2; int gor = 3; int check = 0; //flags acceptible parameters int nextpage = 0; //flags change pages int err = 0; //interface error code int errl = 0; //interface error location int rerr = 0; //retrotrajectory error code float galr, perir; //initial radii of encounter int runsim = 0; //flags initiate simulation int loadselflag = 0; //flags reprint all selections int pnucleus1, pnucleus2; //particle IDs of galactic nucleus particles float contrast = 5; //color contrast value float restvel = 0; //color base value int autoterminate; //flags automatically terminate simulation int pageturn; //flags cycle through interface float x[maxp + 1]; //x-coordinate float y[maxp + 1]; //y-coordinate float z[maxp + 1]; //z-coordinate float vx[maxp + 1]; //x-axis velocity float vy[maxp + 1]; //y-axis velocity float vz[maxp + 1]; //z-axis velocity float ax[maxp + 1]; //x-axis acceleration float ay[maxp + 1]; //y-axis acceleration float az[maxp + 1]; //z-axis acceleration float m[maxp + 1]; //mass int c[maxp + 1]; //pixel base color int c1[maxp + 1]; //pixel temporary color int c2[maxp + 1]; //tracer color int rx[maxp + 1]; //graphical x-coordinate int ry[maxp + 1]; //graphical y-coordinate float gx[3]; //galaxy initial x-coordinate float gy[3]; //galaxy initial y-coordinate float gz[3]; //galaxy initial z-coordinate float gvx[3]; //galaxy initial x velocity float gvy[3]; //galaxy initial y velocity float gvz[3]; //galaxy initial z velocity float gm[3]; //galaxy mass int gc[3] = {0, 10, 13}; //galaxy disk color int gring[3]; //number of rings in disk int grmin[3]; //radius of innermost ring int grmax[3]; //radius of outermost ring int gtilt[3]; //rotation of galaxy about y axis int gskew[3]; //rotation of galaxy about x axis int gp[3]; //particles per ring int gpo[3]; //relative mass density at center int gpmax[3]; //relative mass density at edge int grmmax[3]; //radius of massive disk float ki[3]; float kj[3]; //constants to abbreviate acceleratory equation float kk[3]; int numentry = 65; //total number of times stored in simulation file float far * sx[maxp + 1]; //points to memory storage for x coordinates float far * sy[maxp + 1]; //points to memory storage for y coordinates float far * sz[maxp + 1]; //points to memory storage for z coordinates FILE * fptr; //miscellaneous file pointer char simname[7] = "UNTITL"; //simulation name char capsname[7]; //simulation name (caps) char filepath[30] = ""; //file directory path char filename[13]; //file name char filelocation[45]; //file name and location /****************************************************************************/ int main(void) { //Main module for IGMS, calls major subroutine modules do { IFmodule(); initmemory(); initialize(); simmodule(); terminate(); } while (1); } /****************************************************************************/ void simmodule(void) { //Module for gravitational simulator, cycles time and calls sim. functions long n; //miscellaneous counting variable int p1; //particle ID if (track) tracking(); drawallparticles(0, 1); displayflag = 1; displayinfo(); pause(); clearinfo(); while (!exitflag) { if (store == 2) storepos(); //record if (!source) corecalc(); //calculate new particle if (source) findpos(); //positions if (autosnap > 0) { if (evendiv(t, autosnap)) snapshot(); } //autosnap if (!source) t += timestep; else t += recfreq * timestep; //timestep for (n = 1; n < (delay * (recfreq * source + 1)); n ++); //delay //delay if (track) tracking(); //track if ((evendiv(t / timestep, drawfreq)) || (source)) { if (redraw == 0) {drawallparticles(2 + !tracers, 0); drawallparticles(0, 1);} if (redraw == 1) drawallparticles(2 + !tracers, 1); //redraw if (redraw == 2) {drawallparticles(2 + !tracers, 1); drawallparticles(0, 1);} printtime(); } if (kbhit()) input(); //check for user input if ((store || source) && (t >= maxt)) {exitflag = 1; autoterminate = 1;} } return; } /****************************************************************************/ void corecalc(void) { //Calculates acceleration, accelerates, and moves all particles int p1, p2; //particle IDs int galaxy; //galaxy ID float dx, dy, dz; //distance between particles along axes float D; //resultant distance between particles float A; //resultant acceleration for (p1 = 1; p1 <= nump; p1 ++) { ax[p1] = ay[p1] = az[p1] = 0; for (p2 = 1; p2 <= nump; p2 ++) //determine acceleration { if ((p1 != p2) && (m[p2] != 0)) { dx = x[p2] - x[p1]; dy = y[p2] - y[p1]; dz = z[p2] - z[p1]; D = sqrt(pow(dx, 2) + pow(dy, 2) + pow(dz, 2)); galaxy = 0; if (p2 == pnucleus1) galaxy = 1; if (p2 == pnucleus2) galaxy = 2; if (D < grmmax[galaxy]) A = G * gm[galaxy] * (ki[galaxy] * D + kj[galaxy]) / kk[galaxy]; else A = G * m[p2] / pow(D, 2); ax[p1] += dx * A / D; ay[p1] += dy * A / D; az[p1] += dz * A / D; } } } for (p1 = 1; p1 <= nump; p1++) { vx[p1] += ax[p1] * timestep; //accelerate vy[p1] += ay[p1] * timestep; vz[p1] += az[p1] * timestep; x[p1] += vx[p1] * timestep; //move y[p1] += vy[p1] * timestep; z[p1] += vz[p1] * timestep; } galr = D; return; } /****************************************************************************/ void input(void) { //Finds user input and routes to appropriate function com = getch(); if (com == 27) {exitflag = 1; autoterminate = 0;} else exitflag = 0; if (com == '-') changedelay(0); if (com == '=') changedelay(1); if (com == 'i') imagezoom(0); if (com == 'o') imagezoom(1); if (com == 72) imageshift(1); if (com == 75) imageshift(2); if (com == 77) imageshift(3); if (com == 80) imageshift(4); if (com == 'r') imageshift(0); if (com == ',') imagerotate(0); if (com == '.') imagerotate(1); if (com == 'l') imagerotate(2); if (com == ';') imagerotate(3); if (com == 'p') imagerotate(4); if (com == '[') imagerotate(5); if (com == 'c') {clearviewport(); displayflag = 0; drawallparticles(0, 1);} if ((com == ' ') && (!pauseflag)) pause(); if (com == '/') {if (displayflag) clearinfo(); displayflag = !displayflag; pause();} if (com == 't') tracers = !tracers; if (com == 'a') printmode(); if (com == 's') snapshot(); if (com == 'm') adjcolors(0); if (com == 'n') adjcolors(1); if (com == 'j') adjcolors(2); if (com == 'k') adjcolors(3); return; } /****************************************************************************/ void drawallparticles(int cset1, int cset2) { //Draws all particles according to color/reprocess instructions int p1; //particle ID int pstyle; //appearance of particles 0=point 1=cross 2,3=circle for (p1 = 1; p1 <= nump; p1 ++) { if (style == 0) pstyle = 0; if (style == 1) pstyle = 1; if (style == 2) pstyle = 2; if (style == 3) {if ((p1 == pnucleus1) || (p1 == pnucleus2)) pstyle = 1; else pstyle = 0;} if (style == 4) {if ((p1 == pnucleus1) || (p1 == pnucleus2)) pstyle = 3; else pstyle = 1;} if (cset1) drawparticle(p1, pstyle, cset1); if (cset2) graphiccalc(p1); if (cset2) drawparticle(p1, pstyle, cset2); } return; } /****************************************************************************/ void graphiccalc(int p1) { //Recalculates graphical coordinates and colors of particle transx0 = x[p1] - centx; transy0 = y[p1] - centy; transz0 = z[p1] - centz; transform(rota, rotb, rotc); rx[p1] = (int)(zoom * (transx2) + sccx + offx); ry[p1] = (int)(zoom * (transy2) + sccy + offy); if (!doppler || !fade) c1[p1] = c[p1]; if (doppler) c1[p1] = dopplercolor(p1); if (fade) c1[p1] = fadecolor(p1); return; } /****************************************************************************/ void drawparticle(int p1, int pstyle, int cset) { //Draws specified particle with specified style and color option if (cset == 1) color = c1[p1]; //draw particle if (cset == 2) color = c2[p1]; //erase particle with tracer if (cset == 3) color = 0; //erase if (cset == 4) color = 15; //black (15) particle for printmode if (pstyle == 0) putpixel(rx[p1], ry[p1], color); //0 = point if (pstyle == 1) { putpixel (rx[p1], ry[p1], color); //1 = cross putpixel (rx[p1] + 1, ry[p1], color); putpixel (rx[p1] - 1, ry[p1], color); putpixel (rx[p1], ry[p1] + 1, color); putpixel (rx[p1], ry[p1] - 1, color); } if ((pstyle == 2) || (pstyle == 3)) //2 = circle { //3 = filled circle setcolor(color); setfillstyle(1, color); circle(rx[p1], ry[p1], 2); if (pstyle == 3) floodfill(rx[p1], ry[p1], color); } return; } /****************************************************************************/ void pause(void) { //Pauses simulation and holds input function until unpaused pauseflag = 1; do { if (displayflag) displayinfo(); input(); } while ((com != ' ') && (exitflag == 0)); if ((displayflag == 1) && (exitflag == 0)) clearinfo(); if (tracers == 2) tracers = 1; pauseflag = 0; displayflag = 0; return; } /****************************************************************************/ void imagezoom(int zdir) { //Changes zoom factor if ((!zdir) && (zoom < 1000)) {zoom *= zinc; offx *= zinc; offy *= zinc;} if ((zdir) && (zoom > 0.01)) {zoom /= zinc; offx /= zinc; offy /= zinc;} clearviewport(); printtime(); drawallparticles(0, 1); return; } /****************************************************************************/ void imageshift(int sdir) { //Moves camera if (sdir == 0) {offy = 0; offx = 0;} if (sdir == 1) offy -= sinc; // zoom if (sdir == 2) offx -= sinc; // zoom if (sdir == 3) offx += sinc; // zoom if (sdir == 4) offy += sinc; // zoom if (tracers == 1) {tracers = 2; clearviewport(); printtime();} drawallparticles(3, 1); drawallparticles(0, 1); if ((!pauseflag) && (tracers == 2)) tracers = 1; return; } /****************************************************************************/ void changedelay(int ddir) { //Adjusts delay value if (ddir) { if ((delay > 0) && (delay < 400000)) delay *= 2; if (delay == 0) delay = 100; } else { if (delay == 100) delay = 0; if (delay > 100) delay /= 2; } return; } /****************************************************************************/ void displayinfo(void) { //Prints simulator information on screen int n; //miscellaneous counting variable for (n = 0; n < 7; n ++) capsname[n] = toupper(simname[n]); gotoxy(1, 1); printf(" simname: %s", capsname); if (timestep >= 1) { gotoxy(1, 2); printf(" time: %.0f ", t); gotoxy(1, 4); printf("timestep: %.0f ", timestep); } else { gotoxy(1, 2); printf(" time: %.3f ", t); gotoxy(1, 4); printf("timestep: %.3f ", timestep); } gotoxy(1, 3); printf(" %.1f Myr ", t * stu / 3.1557e+13); gotoxy(1, 5); printf(" delay: %ld ", delay); gotoxy(1, 6); printf(" zoom: %.0f\% ", zoom * 100); gotoxy(1, 7); printf("x offset: %.2f ", offx); gotoxy(1, 8); printf("y offset: %.2f ", offy); gotoxy(1, 9); printf("a rotate: %.0f ", rota); gotoxy(1, 10); printf("b rotate: %.0f ", rotb); gotoxy(1, 11); printf("c rotate: %.0f ", rotc); gotoxy(1, 12); printf("contrast: %.2f ", contrast); gotoxy(1, 13); printf(" restvel: %.1f ", restvel); return; } /****************************************************************************/ void clearinfo(void) { //Clears previously printed displayinfo information int n; //miscellaneous counting variable gotoxy(1,1); for (n = 1; n <= 13; n++) printf(" \n"); printtime(); return; } /****************************************************************************/ void printmode(void) { //Reprints all particles as black on white background for easy printing drawallparticles(3, 0); setbkcolor(15); drawallparticles(0, 1); setpalette(15, 0); setpalette(8, 7); setcolor(15); drawallparticles(4, 0); getch(); setbkcolor(0); setpalette(8, 56); setpalette(15, 63); drawallparticles(3, 0); drawallparticles(0, 1); return; } /****************************************************************************/ void imagerotate(int rdir) { //changes 3-D viewing angle if (tracers == 1) { tracers = 2; clearviewport(); printtime(); } if (rdir == 0) rota += rinc; if (rdir == 1) rota -= rinc; if (rdir == 2) rotb += rinc; if (rdir == 3) rotb -= rinc; if (rdir == 4) rotc += rinc; if (rdir == 5) rotc -= rinc; if (rota < -179) rota = 180; if (rotb < -179) rotb = 180; if (rotc < -179) rotc = 180; if (rota > 184) rota = -175; if (rotb > 184) rotb = -175; if (rotc > 184) rotc = -175; drawallparticles(3, 0); drawallparticles(0, 1); return; } /****************************************************************************/ void initialize(void) { //Module for preparing system and variables for simulation int gdriver; int gmode; int errorcode; dataentry = 0; if (!source) { if (!pageturn) { if ((checkretro()) && (!rerr)) retroproject(); else t = 0; initgalaxies(); } if (store == 0) maxt = 50000; if (store > 0) maxt = numentry * recfreq * timestep + igt0; } else { loadsimulation(); dataentry = 0; findpos(); t = igt0; maxt = (numentry - 1) * recfreq * timestep + igt0; } x[0] = y[0] = z[0] = 0; centx = centy = centz = 0; if ((track == 1) || (track == 2)) ptrack = track; else ptrack = 0; if ((track == 3) || (source == 1)) {m[1] = gm[1]; m[2] = gm[2];} if (gm[1] > 0) pnucleus1 = 1; else pnucleus1 = 0; if (gm[2] > 0) pnucleus2 = 2; else pnucleus2 = 0; gdriver = DETECT; initgraph(&gdriver, &gmode, "EGAVGA.BGI"); return; } /****************************************************************************/ void initgalaxies(void) { //Creates galaxy disks based on disk parameters int galaxy; //galaxy ID float ringspace; //space between rings int ring; //ring ID float ringr; //radius of ring int np; //new particle ID int npmax; //ID of last particle of ring float ia; //orientation of ring particle to nucleus int ringp; //particles per ring float egm; //effective galactic mass np = 1; if (gm[1] > 0) { x[1] = gx[1]; y[1] = gy[1]; z[1] = gz[1]; m[1] = gm[1]; vx[1] = gvx[1]; vy[1] = gvy[1]; vz[1] = gvz[1]; c[1] = 15; c2[1] = 8; np ++; } if (gm[2] > 0) { x[2] = gx[2]; y[2] = gy[2]; z[2] = gz[2]; m[2] = gm[2]; vx[2] = gvx[2]; vy[2] = gvy[2]; vz[2] = gvz[2]; c[2] = 15; c2[2] = 8; np ++; } kcalc(); for (galaxy = 1; galaxy <= 2; galaxy ++) { if ((gring[galaxy] > 0) && (gm[galaxy] > 0)) { if (gring[galaxy] > 1) ringspace = ((float)(grmax[galaxy] - grmin[galaxy]) / (float)(gring[galaxy] - 1)); else ringspace = 0; ringr = grmin[galaxy]; ringp = gp[galaxy]; for (ring = 1; ring <= gring[galaxy]; ring ++) { ia = 0; npmax = np + ringp - 1; if (ringr < grmmax[galaxy]) egm = m[galaxy] * pow(ringr, 2) * (ki[galaxy] * ringr + kj[galaxy]) / kk[galaxy]; else egm = m[galaxy]; for (; np <= npmax; np ++) { m[np] = 0; c[np] = gc[galaxy]; c2[np] = 0; ia += 2 * 3.14159 / ringp; transx0 = cos(ia) * ringr; transy0 = sin(ia) * ringr; transz0 = 0; transform(0, gtilt[galaxy], gskew[galaxy]); x[np] = transx2 + gx[galaxy]; y[np] = transy2 + gy[galaxy]; z[np] = transz2 + gz[galaxy]; transx0 = - sqrt(G * egm / ringr) * sin(ia); transy0 = sqrt(G * egm / ringr) * cos(ia); transz0 = 0; transform(0, gtilt[galaxy], gskew[galaxy]); vx[np] = transx2 + gvx[galaxy]; vy[np] = transy2 + gvy[galaxy]; vz[np] = transz2 + gvz[galaxy]; } ringr += ringspace; } } } nump = np - 1; return; } /****************************************************************************/ void transform(float rxy, float rxz, float ryz) { //Applies 3-D axis rotation to recalcuate x, y, z coordinates or vectors rxy = rxy * dtor; rxz = rxz * dtor; ryz = ryz * dtor; transx1 = transx0 * cos(rxy) + transy0 * sin(rxy); transy1 = transy0 * cos(rxy) - transx0 * sin(rxy); transx2 = transx1 * cos(rxz) + transz0 * sin(rxz); transz1 = transz0 * cos(rxz) - transx1 * sin(rxz); transy2 = transy1 * cos(ryz) + transz1 * sin(ryz); transz2 = transz1 * cos(ryz) - transy1 * sin(ryz); return; } /****************************************************************************/ void retroproject(void) { //Simulates galactic nuclei in reverse time to find initial properties float egm1; //effective galaxy 1 mass float egm2; //effective galaxy 2 mass float igvel1; //resultant velocity of galaxy 1 float igvel2; //resultant velocity of galaxy 2 transx0 = igdis; transy0 = 0; transz0 = 0; transform(igarg - 90, iginc, 0); x[1] = -transx2 / 2; y[1] = -transy2 / 2; z[1] = -transz2 / 2; x[2] = transx2 / 2; y[2] = transy2 / 2; z[2] = transz2 / 2; kcalc(); if (igdis < grmmax[1]) egm1 = gm[1] * pow(igdis, 2) * (ki[1] * igdis + kj[1]) / kk[1]; else egm1 = gm[1]; if (igdis < grmmax[2]) egm2 = gm[2] * pow(igdis, 2) * (ki[2] * igdis + kj[2]) / kk[2]; else egm2 = gm[2]; igvel1 = sqrt(G * egm2 * (1 + igecc) / ( (egm1 / egm2 + 1) * igdis)); igvel2 = sqrt(G * egm1 * (1 + igecc) / ( (egm2 / egm1 + 1) * igdis)); transx0 = 0; transy0 = igvel1; transz0 = 0; transform(igarg - 90, iginc, 0); vx[1] = -transx2; vy[1] = -transy2; vz[1] = -transz2; transx0 = 0; transy0 = igvel2; transz0 = 0; transform(igarg - 90, iginc, 0); vx[2] = transx2; vy[2] = transy2; vz[2] = transz2; m[1] = gm[1]; m[2] = gm[2]; timestep = -timestep; nump = 2; t = 0; galr = perir = igdis; while (t > igt0) { corecalc(); t += timestep; } timestep = -timestep; gx[1] = x[1]; gy[1] = y[1]; gz[1] = z[1]; gx[2] = x[2]; gy[2] = y[2]; gz[2] = z[2]; gvx[1] = vx[1]; gvy[1] = vy[1]; gvz[1] = vz[1]; gvx[2] = vx[2]; gvy[2] = vy[2]; gvz[2] = vz[2]; return; } /****************************************************************************/ void snapshot(void) { //Records graphical image of data to disk for later viewing with snapreader int n; //miscellaneous counting variable int p1; //particle ID strcpy(filelocation, filepath); //hold directory path clearviewport(); strcpy(filename, simname); if (fileindex < 10) { strcat(filename, "0"); strcat(filename, ecvt(fileindex, 0, 0, 0)); } else strcat(filename, ecvt(fileindex, 2, 0, 0)); strcat(filename, ".SNP"); gotoxy(40, 1); printf("Snapshot image created as %s", filename); strcat(filelocation, filename); fptr = fopen(filelocation, "w"); if (!fptr) {printf("\a"); exit(1);} fprintf(fptr, "%d %f ", nump, t); for (p1 = 0; p1 <= nump; p1 ++) { fprintf(fptr, "%d %d %d ", rx[p1], ry[p1], c[p1]); } fclose(fptr); fileindex += 1; drawallparticles(0, 1); return; } /*******************************************************************/ void storepos(void) { //Stores current particle positions in memory int p1; //particle ID if ((evendiv(t / timestep, recfreq)) && (dataentry < numentry)) { for (p1 = 1; p1 <= nump; p1 ++) { sx[p1][dataentry] = x[p1]; sy[p1][dataentry] = y[p1]; sz[p1][dataentry] = z[p1]; } gotoxy(1, 1); printf("%d", dataentry); dataentry ++; } return; } /****************************************************************************/ void storeinitial(void) { //stores essential initial properties and interface settings to disk int p1; //particle ID strcpy(filelocation, filepath); strcpy(filename, simname); strcat(filename, ".INT"); strcat(filelocation, filename); fptr = fopen(filelocation, "w"); if (!fptr) {printf("\a"); exit(1);} fprintf(fptr, "%d %d %f %d %f ", nump, recfreq, timestep, numentry, igt0); for (p1 = 1; p1 <= nump; p1 ++) { fprintf(fptr, "%d ", c[p1]); } fclose(fptr); strcpy(filelocation, filepath); strcpy(filename, simname); strcat(filename, "I.SET"); strcat(filelocation, filename); savesettings(); return; } /****************************************************************************/ void storesimulation(void) { //Stores all historic particle positions to disk int p1; //particle ID strcpy(filelocation, filepath); strcpy(filename, simname); strcat(filename, ".SIM"); strcat(filelocation, filename); fptr = fopen(filelocation, "w"); if (!fptr) {printf("\a"); exit(1);} for (dataentry = 0; dataentry < numentry; dataentry ++) { for (p1 = 1; p1 <= nump; p1 ++) { fprintf(fptr, "%f %f %f ", sx[p1][dataentry], sy[p1][dataentry], sz[p1][dataentry]); } } fclose(fptr); return; } /****************************************************************************/ void loadsimulation(void) { //Loads historic particle positions from disk into memory int p1; //particle ID strcpy(filelocation, filepath); strcpy(filename, simname); strcat(filename, ".INT"); strcat(filelocation, filename); fptr = fopen(filelocation, "r"); if (!fptr) {printf("\a"); exit(1);} fscanf(fptr, "%d %d %f %d ", &nump, &recfreq, ×tep, &numentry); if (numentry == 0) numentry = 60; //accomodate old files else fscanf(fptr, "%f ", &igt0); for (p1 = 1; p1 <= nump; p1 ++) { fscanf(fptr, "%d ", &c[p1]); } fclose(fptr); strcpy(filelocation, filepath); strcpy(filename, simname); strcat(filename, ".SIM"); strcat(filelocation, filename); fptr = fopen(filelocation, "r"); if (!fptr) {printf("\a"); exit(1);} //should never happen for (dataentry = 0; dataentry < numentry; dataentry ++) { for (p1 = 1; p1 <= nump; p1 ++) { fscanf(fptr, "%f %f %f ", &sx[p1][dataentry], &sy[p1][dataentry], &sz[p1][dataentry]); } } fclose(fptr); return; } /****************************************************************************/ void findpos(void) { //Loads current position and calculates velocity from historic data int p1; //particle ID for (p1 = 1; p1 <= nump; p1 ++) { x[p1] = sx[p1][dataentry]; y[p1] = sy[p1][dataentry]; z[p1] = sz[p1][dataentry]; if (dataentry + 1 < numentry) { vx[p1] = (sx[p1][dataentry + 1] - x[p1]) / recfreq / timestep; vy[p1] = (sy[p1][dataentry + 1] - y[p1]) / recfreq / timestep; vz[p1] = (sz[p1][dataentry + 1] - z[p1]) / recfreq / timestep; } } dataentry ++; return; } /****************************************************************************/ void initmemory(void) { //Initializes dynamic memory to store historic coordinate data int index; //pointer array reference for (index = 0; index <= maxp; index ++) { sx[index] = (float far *) farmalloc(numentry * sizeof(float)); if (!sx[index]) {printf("Out of Memory"); getch(); exit(1);} } for (index = 0; index <= maxp; index ++) { sy[index] = (float far *) farmalloc(numentry * sizeof(float)); if (!sy[index]) {printf("Out of Memory"); getch(); exit(1);} } for (index = 0; index <= maxp; index ++) { sz[index] = (float far *) farmalloc(numentry * sizeof(float)); if (!sz[index]) {printf("Out of Memory"); getch(); exit(1);} } return; } /****************************************************************************/ void terminate(void) { //Frees memory and calls termination functions int index; //pointer array reference int n; //miscellaneous counting variable for (n = 0; n < 7; n ++) capsname[n] = toupper(simname[n]); if ((!autoterminate) && (!store)) {gotoxy(38, 1); printf("simulation terminated by user at %.0f", t);} if ((!autoterminate) && (store)) {gotoxy(41, 1); printf("simulation aborted by user at %.0f", t);} if ((autoterminate) && (store)) {gotoxy(34, 1); printf("simulation saved as %s.SIM at %.0f", capsname, t);} if ((autoterminate) && (!store)) {gotoxy(31, 1); printf("simulation terminated at end of data at %.0f", t);} if ((dataentry == numentry) && (store == 2)) { storeinitial(); storesimulation(); } getch(); closegraph(); for (index = 0; index < maxp; index ++) farfree(sx[index]); for (index = 0; index < maxp; index ++) farfree(sy[index]); for (index = 0; index < maxp; index ++) farfree(sz[index]); t = 0; return; } /****************************************************************************/ int evendiv(float num, float den) { //Determines whether one number is a multiple of another return ( (num / den) == floor(num / den)); } /****************************************************************************/ void IFmodule(void) { //Module for interface operations _setcursortype(_NOCURSOR); if (runsim) restorecrtmode(); textmode(3); nextpage = 1; pageturn = 0; do { if (nextpage) IFproperties(); if (nextpage) IFgalaxies(); if (nextpage) IFparticles(); } while ((!exitflag) && (!runsim)); if (exitflag) exit(0); return; } /****************************************************************************/ void IFgalaxies(void) { //Module for galaxy parameter page of interface int l; //current cursor location and option ID float holdfloat; //holds generic floating-point data char holdstring[13] = "\0"; //holds generic string data struct galaxies { char label[16]; char help[60]; int * ivar; float * fvar; int ypos, xlpos, xspos; } ; struct galaxies galx[41]; nextpage = 0; pageturn = 1; strcpy(galx[1].label, " x:"); strcpy(galx[1].help, "Initial x-coordinate of galaxy center"); galx[1].fvar = &gx[1]; galx[1].ivar = 0; galx[1].ypos = 5; galx[1].xlpos = 2; galx[1].xspos = 12; strcpy(galx[2].label, " y:"); strcpy(galx[2].help, "Initial y-coordinate of galaxy center"); galx[2].fvar = &gy[1]; galx[2].ivar = 0; galx[2].ypos = 6; galx[2].xlpos = 2; galx[2].xspos = 12; strcpy(galx[3].label, " z:"); strcpy(galx[3].help, "Initial z-coordinate of galaxy center"); galx[3].fvar = &gz[1]; galx[3].ivar = 0; galx[3].ypos = 7; galx[3].xlpos = 2; galx[3].xspos = 12; strcpy(galx[4].label, " vx:"); strcpy(galx[4].help, "Initial x-axis velocity of galaxy"); galx[4].fvar = &gvx[1]; galx[4].ivar = 0; galx[4].ypos = 8; galx[4].xlpos = 2; galx[4].xspos = 12; strcpy(galx[5].label, " vy:"); strcpy(galx[5].help, "Initial y-axis velocity of galaxy"); galx[5].fvar = &gvy[1]; galx[5].ivar = 0; galx[5].ypos = 9; galx[5].xlpos = 2; galx[5].xspos = 12; strcpy(galx[6].label, " vz:"); strcpy(galx[6].help, "Initial z-axis velocity of galaxy"); galx[6].fvar = &gvz[1]; galx[6].ivar = 0; galx[6].ypos = 10; galx[6].xlpos = 2; galx[6].xspos = 12; strcpy(galx[7].label, " Mass:"); strcpy(galx[7].help, "Total mass of galaxy"); galx[7].fvar = &gm[1]; galx[7].ivar = 0; galx[7].ypos = 11; galx[7].xlpos = 2; galx[7].xspos = 12; strcpy(galx[8].label, " Rmin:"); strcpy(galx[8].help, "Radius of innermost ring"); galx[8].fvar = 0; galx[8].ivar = &grmin[1]; galx[8].ypos = 13; galx[8].xlpos = 2; galx[8].xspos = 12; strcpy(galx[9].label, " Rmax:"); strcpy(galx[9].help, "Radius of outermost ring"); galx[9].fvar = 0; galx[9].ivar = &grmax[1]; galx[9].ypos = 14; galx[9].xlpos = 2; galx[9].xspos = 12; strcpy(galx[10].label, " Rings:"); strcpy(galx[10].help, "Total number of rings"); galx[10].fvar = 0; galx[10].ivar = &gring[1]; galx[10].ypos = 15; galx[10].xlpos = 2; galx[10].xspos = 12; strcpy(galx[11].label, "Particles:"); strcpy(galx[11].help, "Particles per ring"); galx[11].fvar = 0; galx[11].ivar = &gp[1]; galx[11].ypos = 16; galx[11].xlpos = 2; galx[11].xspos = 12; strcpy(galx[12].label, " Tilt:"); strcpy(galx[12].help, "x-z inclination of galaxy"); galx[12].fvar = 0; galx[12].ivar = >ilt[1]; galx[12].ypos = 17; galx[12].xlpos = 2; galx[12].xspos = 12; strcpy(galx[13].label, " Skew:"); strcpy(galx[13].help, "y-z inclination of galaxy"); galx[13].fvar = 0; galx[13].ivar = &gskew[1]; galx[13].ypos = 18; galx[13].xlpos = 2; galx[13].xspos = 12; strcpy(galx[14].label, " Color:"); strcpy(galx[14].help, "Color of disk particles"); galx[14].fvar = 0; galx[14].ivar = &gc[1]; galx[14].ypos = 19; galx[14].xlpos = 2; galx[14].xspos = 12; strcpy(galx[15].label, " x:"); strcpy(galx[15].help, galx[1].help); galx[15].fvar = &gx[2]; galx[15].ivar = 0; galx[15].ypos = 5; galx[15].xlpos = 26; galx[15].xspos = 36; strcpy(galx[16].label, " y:"); strcpy(galx[16].help, galx[2].help); galx[16].fvar = &gy[2]; galx[16].ivar = 0; galx[16].ypos = 6; galx[16].xlpos = 26; galx[16].xspos = 36; strcpy(galx[17].label, " z:"); strcpy(galx[17].help, galx[3].help); galx[17].fvar = &gz[2]; galx[17].ivar = 0; galx[17].ypos = 7; galx[17].xlpos = 26; galx[17].xspos = 36; strcpy(galx[18].label, " vx:"); strcpy(galx[18].help, galx[4].help); galx[18].fvar = &gvx[2]; galx[18].ivar = 0; galx[18].ypos = 8; galx[18].xlpos = 26; galx[18].xspos = 36; strcpy(galx[19].label, " vy:"); strcpy(galx[19].help, galx[5].help); galx[19].fvar = &gvy[2]; galx[19].ivar = 0; galx[19].ypos = 9; galx[19].xlpos = 26; galx[19].xspos = 36; strcpy(galx[20].label, " vz:"); strcpy(galx[20].help, galx[6].help); galx[20].fvar = &gvz[2]; galx[20].ivar = 0; galx[20].ypos = 10; galx[20].xlpos = 26; galx[20].xspos = 36; strcpy(galx[21].label, " Mass:"); strcpy(galx[21].help, galx[7].help); galx[21].fvar = &gm[2]; galx[21].ivar = 0; galx[21].ypos = 11; galx[21].xlpos = 26; galx[21].xspos = 36; strcpy(galx[22].label, " Rmin:"); strcpy(galx[22].help, galx[8].help); galx[22].fvar = 0; galx[22].ivar = &grmin[2]; galx[22].ypos = 13; galx[22].xlpos = 26; galx[22].xspos = 36; strcpy(galx[23].label, " Rmax:"); strcpy(galx[23].help, galx[9].help); galx[23].fvar = 0; galx[23].ivar = &grmax[2]; galx[23].ypos = 14; galx[23].xlpos = 26; galx[23].xspos = 36; strcpy(galx[24].label, " Rings:"); strcpy(galx[24].help, galx[10].help); galx[24].fvar = 0; galx[24].ivar = &gring[2]; galx[24].ypos = 15; galx[24].xlpos = 26; galx[24].xspos = 36; strcpy(galx[25].label, "Particles:"); strcpy(galx[25].help, galx[11].help); galx[25].fvar = 0; galx[25].ivar = &gp[2]; galx[25].ypos = 16; galx[25].xlpos = 26; galx[25].xspos = 36; strcpy(galx[26].label, " Tilt:"); strcpy(galx[26].help, galx[12].help); galx[26].fvar = 0; galx[26].ivar = >ilt[2]; galx[26].ypos = 17; galx[26].xlpos = 26; galx[26].xspos = 36; strcpy(galx[27].label, " Skew:"); strcpy(galx[27].help, galx[13].help); galx[27].fvar = 0; galx[27].ivar = &gskew[2]; galx[27].ypos = 18; galx[27].xlpos = 26; galx[27].xspos = 36; strcpy(galx[28].label, " Color:"); strcpy(galx[28].help, galx[14].help); galx[28].fvar = 0; galx[28].ivar = &gc[2]; galx[28].ypos = 19; galx[28].xlpos = 26; galx[28].xspos = 36; strcpy(galx[29].label, " Distance:"); strcpy(galx[29].help, "Distance between galactic centers at perigalacticon"); galx[29].fvar = &igdis; galx[29].ivar = 0; galx[29].ypos = 5; galx[29].xlpos = 53; galx[29].xspos = 68; strcpy(galx[30].label, " Eccentricity:"); strcpy(galx[30].help, "Relative velocity of galactic centers at perigalacticon"); galx[30].fvar = &igecc; galx[30].ivar = 0; galx[30].ypos = 6; galx[30].xlpos = 53; galx[30].xspos = 68; strcpy(galx[31].label, " Inclination:"); strcpy(galx[31].help, "Inclination of galaxy 2 orbital plane to galaxy 1 disk"); galx[31].fvar = &iginc; galx[31].ivar = 0; galx[31].ypos = 7; galx[31].xlpos = 53; galx[31].xspos = 68; strcpy(galx[32].label, " Argument:"); strcpy(galx[32].help, "Rotation of galaxy 2 perigalacticon point in orbital plane"); galx[32].fvar = &igarg; galx[32].ivar = 0; galx[32].ypos = 8; galx[32].xlpos = 53; galx[32].xspos = 68; strcpy(galx[33].label, " Initial Time:"); strcpy(galx[33].help, "Time of start of simulation relative to perigalacticon"); galx[33].fvar = &igt0; galx[33].ivar = 0; galx[33].ypos = 9; galx[33].xlpos = 53; galx[33].xspos = 68; strcpy(galx[34].label, " Cent. Density:"); strcpy(galx[34].help, "Relative area mass density at center of galactic disk"); galx[34].fvar = 0; galx[34].ivar = &gpo[1]; galx[34].ypos = 12; galx[34].xlpos = 53; galx[34].xspos = 68; strcpy(galx[35].label, " Edge Density:"); strcpy(galx[35].help, "Relative area mass density at edge of massive disk"); galx[35].fvar = 0; galx[35].ivar = &gpmax[1]; galx[35].ypos = 13; galx[35].xlpos = 53; galx[35].xspos = 68; strcpy(galx[36].label, "Massive Radius:"); strcpy(galx[36].help, "Radius of massive disk"); galx[36].fvar = 0; galx[36].ivar = &grmmax[1]; galx[36].ypos = 14; galx[36].xlpos = 53; galx[36].xspos = 68; strcpy(galx[37].label, " Cent. Density:"); strcpy(galx[37].help, galx[34].help); galx[37].fvar = 0; galx[37].ivar = &gpo[2]; galx[37].ypos = 17; galx[37].xlpos = 53; galx[37].xspos = 68; strcpy(galx[38].label, " Edge Density:"); strcpy(galx[38].help, galx[35].help); galx[38].fvar = 0; galx[38].ivar = &gpmax[2]; galx[38].ypos = 18; galx[38].xlpos = 53; galx[38].xspos = 68; strcpy(galx[39].label, "Massive Radius:"); strcpy(galx[39].help, galx[36].help); galx[39].fvar = 0; galx[39].ivar = &grmmax[2]; galx[39].ypos = 19; galx[39].xlpos = 53; galx[39].xspos = 68; textcolor(7); textbackground(0); clrscr(); IFprintheader(); gotoxy(72, 1); cprintf("Galaxies"); gotoxy(2, 4); cprintf("GALAXY 1"); gotoxy(26, 4); cprintf("GALAXY 2"); gotoxy(54, 4); cprintf("RETROTRAJECTORY"); gotoxy(54, 11); cprintf("GALAXY 1 MODEL"); gotoxy(54, 16); cprintf("GALAXY 2 MODEL"); textcolor(7); for (l = 1; l <= 39; l ++) { gotoxy(galx[l].xlpos, galx[l].ypos); cprintf("%s", galx[l].label); gotoxy(galx[l].xspos, galx[l].ypos); if (galx[l].fvar != 0) { * galx[l].fvar = fix(* galx[l].fvar, 5); gcvt(* galx[l].fvar, 7, holdstring); cprintf(" %s ", holdstring); } if (galx[l].ivar != 0) cprintf(" %d ", * galx[l].ivar); } l = 1; do { textcolor(7); gotoxy(10, 22); cprintf(" "); gotoxy(10, 22); cprintf("%s", galx[l].help); printfunct(0, 4, 1, checkretro(), 0); textcolor(15); gotoxy(galx[l].xlpos, galx[l].ypos); cprintf("%s", galx[l].label); textbackground(3); gotoxy(galx[l].xspos + 1, galx[l].ypos); if (galx[l].fvar != 0) gcvt(* galx[l].fvar, 7, holdstring); if (galx[l].ivar != 0) itoa(* galx[l].ivar, holdstring, 10); liminput(holdstring, 10, 1, 0, 1); holdfloat = strtod(holdstring, 0); if (((l >= 7) && (l <= 11)) || ((l >= 21) && (l <= 25)) || (l == 14) || (l == 28) || (l == 29) || (l == 30) || (l > 33)) holdfloat = fabs(holdfloat); if ((l == 33) && (holdfloat != 0)) holdfloat = -fabs(holdfloat); if (((l == 10) || (l == 24)) && (holdfloat > 30)) holdfloat = 30; if (((l == 11) || (l == 25)) && (holdfloat > 300)) holdfloat = 300; if ((l == 12) || (l == 13) || (l == 26) || (l == 27) || (l == 31) || (l == 32)) { if (holdfloat < -180) holdfloat += 360 * (int)(abs(holdfloat) / 360) + 360; holdfloat += 179; holdfloat = (int)(holdfloat) % 360; holdfloat -= 179; } if ((l == 14) || (l == 28)) holdfloat = (int)(holdfloat) % 16; if ((l == 33) && (holdfloat < -1e+6)) holdfloat = 0; if (((l == 8) || (l == 9) || (l == 22) || (l == 23) || (l == 36) || (l == 39)) && (holdfloat > 1000)) holdfloat = 1000; if (galx[l].fvar != 0) * galx[l].fvar = holdfloat; if (galx[l].ivar != 0) { if (fabs(holdfloat) < 32767) * galx[l].ivar = (int)(holdfloat); else * galx[l].ivar = 0; } textcolor(7); textbackground(0); gotoxy(galx[l].xspos, galx[l].ypos); cprintf(" "); gotoxy(galx[l].xlpos, galx[l].ypos); cprintf("%s", galx[l].label); gotoxy(galx[l].xspos, galx[l].ypos); if (galx[l].fvar != 0) {gcvt(* galx[l].fvar, 7, holdstring); cprintf(" %s ", holdstring);} if (galx[l].ivar != 0) cprintf(" %d ", * galx[l].ivar); if (com == 72) l --; if (com == 80) l ++; if (l == 0) l = 39; if (l == 40) l = 1; if (com == 60) nextpage = -1; if (com == 61) exitflag = 1; if (com == 62) { if ((checkretro()) && (!rerr)) { err = 0; retroproject(); if (!err) { for (l = 1; l <= 20; l ++) { if (l == 7) l = 15; * galx[l].fvar = fix(* galx[l].fvar, 5); gotoxy(galx[l].xspos, galx[l].ypos); gcvt(* galx[l].fvar, 7, holdstring); cprintf(" %s ", holdstring); holdfloat = strtod(holdstring, 0); * galx[l].fvar = holdfloat; } } l = 1; } err = rerr; printerrmsg(); if (err) l = errl; } if (nextpage) { err = checkdisk(); printerrmsg(); if (err) { l = errl; nextpage = 0; } } } while (!exitflag && !nextpage); com = 0; } /****************************************************************************/ void IFproperties(void) { //Module for metaproperty parameter if simulator interface int n; //miscellaneous counting variable int l; //cursor position and option ID int dir; //selection change instructional code char sellabel[18]; //selection label struct properties { char label[18]; char help[60]; int ypos, xlpos, xspos; } ; struct properties prop[21]; nextpage = 0; com = 0; check = 0; runsim = 0; strcpy(prop[1].label, " Simulation Name:"); strcpy(prop[1].help, "Simulation title, max 6 characters"); prop[1].ypos = 5; prop[1].xlpos = 5; prop[1].xspos = 22; strcpy(prop[2].label, " Input:"); strcpy(prop[2].help, "Source of coordinate data"); prop[2].ypos = 6; prop[2].xlpos = 5; prop[2].xspos = 22; strcpy(prop[3].label, " Output:"); strcpy(prop[3].help, "Storage of coordinate data"); prop[3].ypos = 7; prop[3].xlpos = 5; prop[3].xspos = 22; strcpy(prop[4].label, "Record Frequency:"); strcpy(prop[4].help, "Coordinate data is recorded in memory every x timesteps"); prop[4].ypos = 8; prop[4].xlpos = 5; prop[4].xspos = 22; strcpy(prop[5].label, " Load Settings:"); strcpy(prop[5].help, "Load previously recorded settings into interface"); prop[5].ypos = 10; prop[5].xlpos = 5; prop[5].xspos = 22; strcpy(prop[6].label, " Save Settings:"); strcpy(prop[6].help, "Save current settings to disk"); prop[6].ypos = 11; prop[6].xlpos = 5; prop[6].xspos = 22; strcpy(prop[7].label, " Coarse Timestep:"); strcpy(prop[7].help, "Basic timestep unit (stu)"); prop[7].ypos = 15; prop[7].xlpos = 5; prop[7].xspos = 22; strcpy(prop[8].label, " Fine Timestep:"); strcpy(prop[8].help, "Minimum timestep unit (stu)"); prop[8].ypos = 16; prop[8].xlpos = 5; prop[8].xspos = 22; strcpy(prop[9].label, " Delay:"); strcpy(prop[9].help, "Duration of decelerating timing loop"); prop[9].ypos = 17; prop[9].xlpos = 5; prop[9].xspos = 22; strcpy(prop[10].label, " Monitoring:"); strcpy(prop[10].help, "Display simulation on screen"); prop[10].ypos = 5; prop[10].xlpos = 39; prop[10].xspos = 56; strcpy(prop[11].label, " Redraw Method:"); strcpy(prop[11].help, "Particle redraw: erase before or during particle draw"); prop[11].ypos = 6; prop[11].xlpos = 39; prop[11].xspos = 56; strcpy(prop[12].label, " Draw Frequency:"); strcpy(prop[12].help, "Screen is updated every x timesteps"); prop[12].ypos = 7; prop[12].xlpos = 39; prop[12].xspos = 56; strcpy(prop[13].label, " Particle Style:"); strcpy(prop[13].help, "Size and shape of particle images"); prop[13].ypos = 8; prop[13].xlpos = 39; prop[13].xspos = 56; strcpy(prop[14].label, " Tracking:"); strcpy(prop[14].help, "Fix camera on specified object"); prop[14].ypos = 9; prop[14].xlpos = 39; prop[14].xspos = 56; strcpy(prop[15].label, " Doppler Mimicry:"); strcpy(prop[15].help, "Color particles by line-of-sight velocity"); prop[15].ypos = 10; prop[15].xlpos = 39; prop[15].xspos = 56; strcpy(prop[16].label, " Z-Axis Fade:"); strcpy(prop[16].help, "Color particles by line-of-sight distance"); prop[16].ypos = 11; prop[16].xlpos = 39; prop[16].xspos = 56; strcpy(prop[17].label, " SDU ="); strcpy(prop[17].help, "Simulation distance unit (meters)"); prop[17].ypos = 15; prop[17].xlpos = 39; prop[17].xspos = 56; strcpy(prop[18].label, " SMU ="); strcpy(prop[18].help, "Simulation mass unit (kilograms)"); prop[18].ypos = 16; prop[18].xlpos = 39; prop[18].xspos = 56; strcpy(prop[19].label, " STU ="); strcpy(prop[19].help, "Simulation time unit (seconds)"); prop[19].ypos = 17; prop[19].xlpos = 39; prop[19].xspos = 56; strcpy(prop[20].label, " G ="); strcpy(prop[20].help, "Simulation gravitational constant (smu^3 * stu^2 / sdu)"); prop[20].ypos = 18; prop[20].xlpos = 39; prop[20].xspos = 56; clrscr(); textcolor(7); IFprintheader(); gotoxy(70, 1); cprintf("Properties"); gotoxy(2, 4); cprintf("FILE"); gotoxy(2, 14); cprintf("TIME"); gotoxy(36, 4); cprintf("GRAPHICS"); gotoxy(36, 14); cprintf("SCALING"); textcolor(7); for (l = 1; l <= 20; l ++) { gotoxy(prop[l].xlpos, prop[l].ypos); cprintf("%s", prop[l].label); IFgetsellabel(sellabel, l); gotoxy(prop[l].xspos, prop[l].ypos); cprintf(" %s ", sellabel); } l = 1; do { textcolor(7); gotoxy(10, 22); cprintf(" "); gotoxy(10, 22); cprintf("%s", prop[l].help); printfunct((check + 1), !source * 3, 1, 0, 0); textcolor(15); gotoxy(prop[l].xlpos, prop[l].ypos); cprintf("%s", prop[l].label); if ((l != 1) && (l < 17)) textbackground(3); IFgetsellabel(sellabel, l); if (strlen(sellabel) > 0) {gotoxy(prop[l].xspos, prop[l].ypos); cprintf(" %s ", sellabel);} textcolor(7); textbackground(0); dir = IFinput(); if (dir < 3) { gotoxy(prop[l].xlpos, prop[l].ypos); cprintf("%s", prop[l].label); IFgetsellabel(sellabel, l); gotoxy(prop[l].xspos, prop[l].ypos); cprintf(" %s ", sellabel); } if (dir == 1) l++; if (dir == 2) l--; if (l > 20) l = 1; if (l < 1) l = 20; if (check == -1) { err = 0; err = checkprop(); printerrmsg(); if ((source == 1) && (!err)) { strcpy(filelocation, filepath); strcpy(filename, simname); strcat(filename, "I.SET"); strcat(filelocation, filename); loadsettings(0); } if (!err) check = 1; if (err) {if (errl) l = errl; check = 0; } } gotoxy(prop[l].xspos + 1, prop[l].ypos); textcolor(15); textbackground(3); if (dir > 2) IFchangesel(dir, l); textcolor(7); textbackground(0); if (!runsim) {gotoxy(prop[l].xspos, prop[l].ypos); cprintf(" ");} if (l >= 17) //print other selections { for (n = 17; n <= 20; n ++) { gotoxy(prop[n].xspos, prop[n].ypos); cprintf(" "); IFgetsellabel(sellabel, n); gotoxy(prop[n].xspos, prop[n].ypos); cprintf(" %s ", sellabel); } } if ((l == 7) || (l == 8)) { if (l == 7) n = 8; else n = 7; gotoxy(prop[n].xspos, prop[n].ypos); cprintf(" "); IFgetsellabel(sellabel, n); gotoxy(prop[n].xspos, prop[n].ypos); cprintf(" %s ", sellabel); } if (loadselflag) { for (n = 1; n <= 20; n ++) { gotoxy(prop[n].xspos, prop[n].ypos); cprintf(" "); IFgetsellabel(sellabel, n); gotoxy(prop[n].xspos, prop[n].ypos); cprintf(" %s ", sellabel); } loadselflag = 0; } } while (!exitflag && !nextpage && !runsim); return; } /****************************************************************************/ void IFparticles(void) { //Particle-viewing page of interface, displays properties for all particles int page = 0; //particle page ID int p1; //particle ID int endp; //last particle on page ID int ypos; //cursor y position int n; //miscellaneous counting variable nextpage = 0; initgalaxies(); textcolor(7); textbackground(0); clrscr(); IFprintheader(); gotoxy(71, 1); cprintf("Particles"); gotoxy(1, 3); cprintf("#p"); gotoxy(8, 3); cprintf("x"); gotoxy(18, 3); cprintf("y"); gotoxy(28, 3); cprintf("z"); gotoxy(41, 3); cprintf("vx"); gotoxy(51, 3); cprintf("vy"); gotoxy(61, 3); cprintf("vz"); gotoxy(72, 3); cprintf("m"); gotoxy(77, 3); cprintf("c"); printfunct(0, 5, 1, 0, 0); do { if (nump > (page + 1) * 16) endp = ((page + 1) * 16); else endp = nump; for (ypos = 4; ypos < 4 + 16; ypos ++) { gotoxy(1, ypos); for (n = 1; n < 81; n ++) putch(' '); } ypos = 4; for (p1 = page * 16 + 1; p1 <= endp; p1 ++) { gotoxy(1, ypos); cprintf("%d", p1); gotoxy(8 - (x[p1] < 0), ypos); cprintf("%.3f", x[p1]); gotoxy(18 - (y[p1] < 0), ypos); cprintf("%.3f", y[p1]); gotoxy(28 - (z[p1] < 0), ypos); cprintf("%.3f", z[p1]); gotoxy(41 - (vx[p1] < 0), ypos); cprintf("%.4f", vx[p1]); gotoxy(51 - (vy[p1] < 0), ypos); cprintf("%.4f", vy[p1]); gotoxy(61 - (vz[p1] < 0), ypos); cprintf("%.4f", vz[p1]); gotoxy(72, ypos); cprintf("%.0f", m[p1]); //.4f for non-pt. mass gotoxy(77, ypos); cprintf("%d", c[p1]); ypos += 1; } com = getch(); if (com == 61) exitflag = 1; if ((com == 80) && (endp < nump)) page ++; if ((com == 72) && (page > 0)) page --; if (com == 60) nextpage = 1; } while (!nextpage && !exitflag); return; } /****************************************************************************/ void IFprintheader(void) { //Prints header on top of interface screen int n; //miscellaneous counting variable gotoxy(1, 1); cprintf("INTERGALACTIC GRAVITATIONAL MOTION SIMULATOR 3.2"); gotoxy(1, 2); for (n = 1; n < 81; n ++) putch('-'); gotoxy(1, 21); for (n = 1; n < 81; n ++) putch('-'); gotoxy(1, 22); cprintf(" Help:"); gotoxy(1, 23); cprintf(" Error:"); return; } /****************************************************************************/ void IFgetsellabel(char * selptr, int l) { //Copies properties selection label into memory strcpy(selptr, ""); if (l == 1) strcpy(selptr, simname); if ((l == 2) && (source == 0)) strcpy(selptr, "simulation"); if ((l == 2) && (source == 1)) strcpy(selptr, "file"); if ((l == 3) && (store == 0)) strcpy(selptr, "none"); if ((l == 3) && (store == 1)) strcpy(selptr, "RAM"); if ((l == 3) && (store == 2)) strcpy(selptr, "disk"); if (l == 4) itoa(recfreq, selptr, 10); if (l == 7) gcvt(timestep, 5, selptr); if (l == 8) gcvt(timestep, 5, selptr); if (l == 9) ltoa(delay, selptr, 10); if ((l == 10) && (monitor == 0)) strcpy(selptr, "disabled"); if ((l == 10) && (monitor == 1)) strcpy(selptr, "enabled"); if ((l == 11) && (redraw == 0)) strcpy(selptr, "flash"); if ((l == 11) && (redraw == 1)) strcpy(selptr, "sequence"); if ((l == 11) && (redraw == 2)) strcpy(selptr, "sequence++"); if (l == 12) itoa(drawfreq, selptr, 10); if ((l == 13) && (style == 0)) strcpy(selptr, "point"); if ((l == 13) && (style == 1)) strcpy(selptr, "cross"); if ((l == 13) && (style == 2)) strcpy(selptr, "circle"); if ((l == 13) && (style == 3)) strcpy(selptr, "varsmall"); if ((l == 13) && (style == 4)) strcpy(selptr, "varlarge"); if ((l == 14) && (track == 0)) strcpy(selptr, "none"); if ((l == 14) && (track == 1)) strcpy(selptr, "galaxy 1"); if ((l == 14) && (track == 2)) strcpy(selptr, "galaxy 2"); if ((l == 14) && (track == 3)) strcpy(selptr, "center of mass"); if ((l == 15) && (doppler == 0)) strcpy(selptr, "disabled"); if ((l == 15) && (doppler == 1)) strcpy(selptr, "enabled"); if ((l == 16) && (fade == 0)) strcpy(selptr, "disabled"); if ((l == 16) && (fade == 1)) strcpy(selptr, "chromatic"); if (l == 17) gcvt(sdu, 4, selptr); if (l == 18) gcvt(smu, 4, selptr); if (l == 19) gcvt(stu, 4, selptr); if (l == 20) gcvt(G, 4, selptr); return; } /****************************************************************************/ int IFinput(void) { //Gets user input and flags appropriately in interface int dir = 0; //selection change instructional code do { if (!skip) com = getch(); skip = 0; if (com == 80) dir = 1; if (com == 72) dir = 2; if (com == 75) dir = 3; if (com == 77) dir = 4; if (com == 32) dir = 4; if ((com == 59) && (check != 1)) check = -1; if ((com == 59) && (check == 1)) runsim = 1; else runsim = 0; if ((com == 60) && (!source)) nextpage = -1; else nextpage = 0; if (com == 61) exitflag = 1; else exitflag = 0; //if (com == 63) IFviewcat(); //viewcat = 1; else viewcat = 0; } while (!dir && !exitflag && !check && !nextpage); return(dir); } /****************************************************************************/ void IFchangesel(int dir, int l) { char holdstring[13] = "\0"; //miscellaneous input/output string check = 0; if ((l == 1) && ((dir == 4) || (dir == 5))) liminput(simname, 6, 0, 1, 1); if (l == 2) source = abs(!source); if (l == 3) { if (dir == 3) store --; if (dir == 4) store ++; if (store == 3) store = 0; if (store == -1) store = 2; } if (l == 4) { if (dir == 3) recfreq -= (4 * (recfreq > 25) + 1) * (recfreq > 1); if (dir == 4) recfreq += (4 * (recfreq >= 25) + 1) * (recfreq < 100); } if (((l == 5) || (l == 6)) && (dir == 4)) { cprintf(" .SET"); gotoxy(wherex() - 10, wherey()); liminput(holdstring, 6, 0, 1, 0); textcolor(7); textbackground(0); if ((strlen(holdstring) > 0) && (com == 13)) { strcpy(filelocation, filepath); strcpy(filename, holdstring); strcat(filename, ".SET"); strcat(filelocation, filename); if (l == 5) loadsettings(1); if (l == 6) savesettings(); printerrmsg(); } } if ((l == 7) || (l == 8)) { if ((dir == 3) && (timestep <= 1) && (timestep > 0.0625)) timestep /= 2; if ((dir == 3) && (timestep > 1)) timestep -= 1; if ((dir == 3) && (timestep > 10)) timestep -= 4; if ((dir == 4) && (timestep >= 10) && (timestep < 200)) timestep += 4; if ((dir == 4) && (timestep >= 1) && (timestep < 200)) timestep += 1; if ((dir == 4) && (timestep < 1)) timestep *= 2; } if (l == 9) changedelay(dir - 3); if (l == 10) monitor = abs(!monitor); if (l == 11) { if (dir == 3) redraw --; if (dir == 4) redraw ++; if (redraw == 3) redraw = 0; if (redraw == -1) redraw = 2; } if (l == 12) { if (dir == 3) drawfreq -= (4 * (drawfreq > 25) + 1) * (drawfreq > 1); if (dir == 4) drawfreq += (4 * (drawfreq >= 25) + 1) * (drawfreq < 100); } if (l == 13) { if (dir == 3) style --; if (dir == 4) style ++; if (style == 5) style = 0; if (style == -1) style = 4; } if (l == 14) { if (dir == 3) track --; if (dir == 4) track ++; if (track == 4) track = 0; if (track == -1) track = 3; } if (l == 15) doppler = abs(!doppler); if (l == 16) fade = abs(!fade); if (l >= 17) { IFgetsellabel(holdstring, l); liminput(holdstring, 10, 1, 0, 1); sduor ++; smuor ++; stuor ++; gor ++; if (l == 17) {sdu = strtod(holdstring, 0); sduor = 0;} if (l == 18) {smu = strtod(holdstring, 0); smuor = 0;} if (l == 19) {stu = strtod(holdstring, 0); stuor = 0;} if (l == 20) {G = strtod(holdstring, 0); gor = 0;} if (sdu == 0) sdu = 1e+19; if (smu == 0) smu = 1e+39; if (stu == 0) stu = 1e+13; if (G == 0) G = 6.673e-3; if ((gor > sduor) && (gor > smuor) && (gor > stuor)) G = Gphys / pow(sdu, 3) * smu * pow(stu, 2); if ((stuor > sduor) && (stuor > smuor) && (stuor > gor)) stu = pow((G / Gphys * pow(sdu, 3) / smu), (0.5)); if ((smuor > sduor) && (smuor > stuor) && (smuor > gor)) smu = G / Gphys * pow(sdu, 3) / pow(stu, 2); if ((sduor > smuor) && (sduor > stuor) && (sduor > gor)) sdu = pow((smu * pow(stu, 2) * Gphys / G), (0.33333333)); } return; } /****************************************************************************/ void liminput(char * inputstring, int lim, int digok, int alpok, int buf) { //Special input function to recieve limited string input from keyboard int pos; //cursor position in string int inx; //initial cursor x position on screen int iny; //initial cursor y position on screen inx = wherex(); iny = wherey(); gotoxy(inx - 1, iny); for (pos = 0; pos <= lim; pos ++) putch(' '); if (buf) putch(' '); pos = strlen(inputstring); do { gotoxy(inx, iny); cprintf("%s", inputstring); if (pos < lim) {gotoxy(pos + inx, iny); putch('_');} do { com = getch(); } while ( !( ( islower(com) || isdigit(com) || (com == '_') ) && alpok ) && !( ( isdigit(com) || (com == 'e') || (com == '.') || (com == '+') || (com == '-') ) && digok ) && !( ( (com == 27) || (com == 13) || ((com >= 59) && (com <= 68)) || (com == 80) || (com == 72) || (com == 8) ) ) ); if (!( ( (com == 27) || (com == 13) || ((com >= 59) && (com <= 68)) || (com == 80) || (com == 72) || (com == 8) ) )) { if (islower(com) && (alpok == 1)) com -= 32; if (pos == lim) pos --; inputstring[pos] = com; inputstring[pos + 1] = '\0'; pos ++; if (isupper(com) && (alpok == 1)) com += 32; } if ((com == 8) && (pos > 0)) { inputstring[pos] = '\0'; gotoxy(pos + inx, iny); if (pos < lim) putch(' '); pos --; inputstring[pos] = '\0'; } if ((com == 27) || ((com >= 59) && (com <= 68)) || (com == 80) || (com == 72)) skip = 1; } while (!( (com == 27) || (com == 13) || ((com >= 59) && (com <= 68)) || (com == 80) || (com == 72))); return; } /****************************************************************************/ int checkretro(void) { //Checks validity of retroprojection parameters rerr = 0; if (((gpo[1] != 0) || (gpmax[1] != 0)) && (grmmax[1] == 0)) rerr = 19; if (((gpo[2] != 0) || (gpmax[2] != 0)) && (grmmax[2] == 0)) rerr = 20; if ((gpo[1] == 0) && (gpmax[1] == 0) && (grmmax[1] != 0)) rerr = 21; if ((gpo[2] == 0) && (gpmax[2] == 0) && (grmmax[2] != 0)) rerr = 22; if ((gm[1] == 0) && ((gpo[1] > 0) || (gpmax[1] > 0) || (grmmax[1] > 0))) rerr = 23; if ((gm[2] == 0) && ((gpo[2] > 0) || (gpmax[2] > 0) || (grmmax[2] > 0))) rerr = 24; if ((igdis <= 1) || (igecc < 0) || (gm[1] <= 0) || (gm[2] <= 0)) return 0; return 1; } /****************************************************************************/ int checkdisk(void) { //Checks validity of particle disk parameters err = 0; //major errors if ((gm[1] == 0) && (gp[1] > 0)) err = 8; if ((gm[2] == 0) && (gp[2] > 0)) err = 9; if ((gring[1] > 0) && (grmin[1] == 0)) err = 10; if ((gring[2] > 0) && (grmin[2] == 0)) err = 11; if ((grmax[1] < grmin[1]) || ((gring[1] > 1) && (grmin[1] == grmax[1]))) err = 12; if ((grmax[2] < grmin[2]) || ((gring[2] > 1) && (grmin[2] == grmax[2]))) err = 13; if ((gp[1] > 0) && (gring[1] == 0)) err = 14; if ((gp[2] > 0) && (gring[2] == 0)) err = 15; if (abs(gm[1] > 0) + abs(gm[2] > 0) + gring[1] * gp[1] + gring[2] * gp[2] > maxp) { if ((gring[1] * gp[1]) > (gring[2] * gp[2])) err = 16; else err = 17; } if ((gm[1] > 0) && (gm[2] > 0) && (gx[1] == gx[2]) && (gy[1] == gy[2]) && (gz[1] == gz[2])) err = 18; if (((gpo[1] != 0) || (gpmax[1] != 0)) && (grmmax[1] == 0)) err = 19; if (((gpo[2] != 0) || (gpmax[2] != 0)) && (grmmax[2] == 0)) err = 20; if ((gpo[1] == 0) && (gpmax[1] == 0) && (grmmax[1] != 0)) err = 21; if ((gpo[2] == 0) && (gpmax[2] == 0) && (grmmax[2] != 0)) err = 22; if ((gm[1] == 0) && ((gpo[1] > 0) || (gpmax[1] > 0) || (grmmax[1] > 0))) err = 23; if ((gm[2] == 0) && ((gpo[2] > 0) || (gpmax[2] > 0) || (grmmax[2] > 0))) err = 24; //minor errors (autofix) if (!err) { if (gp[1] == 0) {grmin[1] = grmax[1] = gring[1] = gtilt[1] = gskew[1] = 0;} if (gp[2] == 0) {grmin[2] = grmax[2] = gring[2] = gtilt[2] = gskew[2] = 0;} } return err; } /****************************************************************************/ int checkprop(void) { //Checks validity of metaproperty parameters err = 0; if (((source == 1) || (store == 2)) && (!strlen(simname))) err = 1; if (source && store) err = 2; if ( ((track == 1) && (gm[1] == 0)) || ((track == 2) && (gm[2] == 0)) || ((track == 3) && ((gm[1] == 0) || (gm[2] == 0)))) err = 3; if ((source) && (!err)) { strcpy(filelocation, filepath); strcpy(filename, simname); strcat(filename, ".INT"); strcat(filelocation, filename); fptr = fopen(filelocation, "r"); if (!fptr) err = 4; else fclose(fptr); } if ((nump == 0) && (source == 0)) err = 5; if (doppler && fade) err = 6; return err; } /****************************************************************************/ void errmsg(char * errorlabel) { //Copies appropriate error message into memory if (err == 0) strcpy(errorlabel, ""); if (err == 1) {strcpy(errorlabel, "no file name"), errl = 1;} if (err == 2) {strcpy(errorlabel, "input and output cannot both be disk"), errl = 3;} if (err == 3) {strcpy(errorlabel, "cannot track nonexistent galaxy"), errl = 14;} if (err == 4) {strcpy(errorlabel, "file not found"), errl = 1;} if (err == 5) {strcpy(errorlabel, "simulation not ready: change particles"), errl = 0;} if (err == 6) {strcpy(errorlabel, "multiple color effects enabled"), errl = 16;} if (err == 7) {strcpy(errorlabel, "settings file not found"), errl = 4;} if (err == 8) {strcpy(errorlabel, "galaxy with disk is massless"), errl = 7;} if (err == 9) {strcpy(errorlabel, "galaxy with disk is massless"), errl = 21;} if (err == 10) {strcpy(errorlabel, "inner ring radius is zero"), errl = 8;} if (err == 11) {strcpy(errorlabel, "inner ring radius is zero"), errl = 22;} if (err == 12) {strcpy(errorlabel, "outer ring within inner ring"), errl = 9;} if (err == 13) {strcpy(errorlabel, "outer ring within inner ring"), errl = 23;} if (err == 14) {strcpy(errorlabel, "no rings"), errl = 10;} if (err == 15) {strcpy(errorlabel, "no rings"), errl = 24;} if (err == 16) {strcpy(errorlabel, "number of particles exceeds limit"), errl = 11;} if (err == 17) {strcpy(errorlabel, "number of particles exceeds limit"), errl = 25;} if (err == 18) {strcpy(errorlabel, "galaxies have same location"), errl = 1;} if (err == 19) {strcpy(errorlabel, "density not applicable under point-mass"); errl = 34;} if (err == 20) {strcpy(errorlabel, "density not applicable under point-mass"); errl = 37;} if (err == 21) {strcpy(errorlabel, "massive disk has zero density"); errl = 34;} if (err == 22) {strcpy(errorlabel, "massive disk has zero density"); errl = 37;} if (err == 23) {strcpy(errorlabel, "model not applicable to massless galaxy"); errl = 7;} if (err == 24) {strcpy(errorlabel, "model not applicable to massless galaxy"); errl = 21;} if (err == 32) {strcpy(errorlabel, "orbit decay: increase velocity"); errl = 30;} return; } /****************************************************************************/ void printfunct(int f1, int f2, int f3, int f4, int f5) { //Prints available interface functions at bottom of screen textbackground(0); gotoxy(2, 24); if (f1 == 0){ textcolor(8); cprintf("F1 - Check"); } if (f1 == 1){ textcolor(7); cprintf("F1 - Check"); } if (f1 == 2){ textcolor(7); cprintf("F1 - Run "); } gotoxy(14, 24); if (f2 == 0){ textcolor(8); cprintf("F2 - Galaxies"); } if (f2 == 1){ textcolor(8); cprintf("F2 - Particles"); } if (f2 == 2){ textcolor(8); cprintf("F2 - Properties"); } if (f2 == 3){ textcolor(7); cprintf("F2 - Galaxies"); } if (f2 == 4){ textcolor(7); cprintf("F2 - Particles"); } if (f2 == 5){ textcolor(7); cprintf("F2 - Properties"); } gotoxy(31, 24); if (f3) textcolor(7); else textcolor(8); cprintf("F3 - Exit"); gotoxy(43, 24); if (f4) textcolor(7); else textcolor(8); cprintf("F4 - Retroproject"); gotoxy(63, 24); if (f5) textcolor(7); else textcolor(8); cprintf("F5 - Catalog"); textcolor(7); return; } /*********************************************************************/ double fix(double rnum, int ndig) { //Rounds to decimal place specified float rem; //decimal portion of rnum rnum *= pow(10, ndig); rem = fmod(rnum, 1); if (((rem > 0) && (rem < 0.5)) || (rem <= -0.5)) rnum = floor(rnum); else rnum = ceil(rnum); rnum /= pow(10, ndig); if (rnum == 0) rnum = fabs(rnum); return rnum; } /*********************************************************************/ void printerrmsg(void) { //Prints error message at bottom of interface screen char holderrmsg[48]; //string to hold error message gotoxy(10, 23); cprintf(" "); errmsg(holderrmsg); if (err) {gotoxy(10, 23); printf("%d: %s", err, holderrmsg);} return; } /********************************************************************/ void savesettings(void) { //Saves current interface parameters to disk fptr = fopen(filelocation, "w"); if (!fptr) err = 7; else { //sdu = round(stu, 5); smu = round(smu, 5); sdu = round(smu, 5); G = round(G, 5); err = 0; if (strlen(simname) == 0) strcpy(simname, "-");//null char fprintf(fptr, "%s\n", simname); fprintf(fptr, "%d %d %d %f %f %ld %d %d %d %d %d %d %d %e %e %e %e\n", source, store, recfreq, timestep, timestep, delay, monitor, redraw, drawfreq, style, track, doppler, fade, 0, 0, 0, 0); fprintf(fptr, "%f %f %f %f %f %f %f %d %d %d %d %d %d %d\n", gx[1], gy[1], gz[1], gvx[1], gvy[1], gvz[1], gm[1], grmin[1], grmax[1], gring[1], gp[1], gtilt[1], gskew[1], gc[1]); fprintf(fptr, "%f %f %f %f %f %f %f %d %d %d %d %d %d %d\n", gx[2], gy[2], gz[2], gvx[2], gvy[2], gvz[2], gm[2], grmin[2], grmax[2], gring[2], gp[2], gtilt[2], gskew[2], gc[2]); fprintf(fptr, "%f %f %f %f %f %d %d %d %d %d %d %d %d %d\n", igdis, igecc, iginc, igarg, igt0, gpo[1], gpmax[1], grmmax[1], gpo[2], gpmax[2], grmmax[2], 0, 0, 0); fclose(fptr); if (simname[0] == '-') strcpy(simname, ""); } return; } /****************************************************************************/ void loadsettings(int loadall) { //Loads previously saved interface parameters from disk int dummy; long dumml; //dummy variables to hold nonloaded settings fptr = fopen(filelocation, "r"); if (!fptr) err = 7; else { err = 0; fscanf(fptr, "%s\n", &simname); if (loadall) fscanf(fptr, "%d %d %d %f %f %ld %d %d %d %d %d %d %d ", &source, &store, &recfreq, ×tep, ×tep, &delay, &monitor, &redraw, &drawfreq, &style, &track, &doppler, &fade); else fscanf(fptr, "%d %d %d %f %f %ld %d %d %d %d %d %d %d ", &dummy, &dummy, &recfreq, ×tep, ×tep, &dumml, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy); fscanf(fptr, "%e %e %e %e ", &sdu, &smu, &stu, &G); fscanf(fptr, "%f %f %f %f %f %f %f %d %d %d %d %d %d %d ", &gx[1], &gy[1], &gz[1], &gvx[1], &gvy[1], &gvz[1], &gm[1], &grmin[1], &grmax[1], &gring[1], &gp[1], >ilt[1], &gskew[1], &gc[1]); fscanf(fptr, "%f %f %f %f %f %f %f %d %d %d %d %d %d %d ", &gx[2], &gy[2], &gz[2], &gvx[2], &gvy[2], &gvz[2], &gm[2], &grmin[2], &grmax[2], &gring[2], &gp[2], >ilt[2], &gskew[2], &gc[2]); fscanf(fptr, "%f %f %f %f %f %d %d %d %d %d %d", &igdis, &igecc, &iginc, &igarg, &igt0, &gpo[1], &gpmax[1], &grmmax[1], &gpo[2], &gpmax[2], &grmmax[2]); fclose(fptr); if (simname[0] == '-') strcpy(simname, ""); loadselflag = 1; } return; } /****************************************************************************/ void tracking(void) { //Fixes camera on specified object if ((track == 1) || (track == 2)) { ptrack = track; centx = x[ptrack]; centy = y[ptrack]; centz = z[ptrack]; } if (track == 3) { centx = (x[1] * m[1] + x[2] * m[2]) / (m[1] + m[2]); centy = (y[1] * m[1] + y[2] * m[2]) / (m[1] + m[2]); centz = (z[1] * m[1] + z[2] * m[2]) / (m[1] + m[2]); } return; } /****************************************************************************/ int dopplercolor(int p1) { //Assigns new color to particle depending on line-of-sight velocity float vs; //line-of-sight velocity transx0 = vx[p1]; transy0 = vy[p1]; transz0 = vz[p1]; transform(rota, rotb, rotc); vs = transz2 - restvel / 100; color = 4; // red if (vs > -0.04 * contrast) color = 12; // light red if (vs > -0.03 * contrast) color = 14; // yellow if (vs > -0.02 * contrast) color = 10; // light green if (vs > -0.01 * contrast) color = 2; // green if (vs > 0.00) color = 3; // cyan if (vs > 0.01 * contrast) color = 9; // light blue if (vs > 0.02 * contrast) color = 1; // blue if (vs > 0.03 * contrast) color = 5; // purple if (vs > 0.04 * contrast) color = 13; // light purple if (c[p1] == 15) color = 15; if (c[p1] == 0) color = 0; return color; } /****************************************************************************/ int fadecolor(int p1) { //Assigns new color to particle depending on line-of-sight depth float dz; //line of sight distance transx0 = x[p1]; transy0 = y[p1]; transz0 = z[p1]; transform(rota, rotb, rotc); dz = transz2 - restvel * 10; color = 4; // red if (dz > -40 * contrast) color = 12; // light red if (dz > -30 * contrast) color = 14; // yellow if (dz > -20 * contrast) color = 10; // light green if (dz > -10 * contrast) color = 2; // green if (dz > 0) color = 3; // cyan if (dz > 10 * contrast) color = 9; // light blue if (dz > 20 * contrast) color = 1; // blue if (dz > 30 * contrast) color = 5; // purple if (dz > 40 * contrast) color = 13; // light purple if (c[p1] == 15) color = 15; if (c[p1] == 0) color = 0; return color; } /****************************************************************************/ void adjcolors(int cdir) { //Adjusts contrast or rest position for color functions if ((cdir == 0) && (contrast >= 6)) contrast -= 0.5; if ((cdir == 0) && (contrast > 2)) contrast -= 0.5; if ((cdir == 1) && (contrast < 50)) contrast += 1.0; if ((cdir == 1) && (contrast < 6)) contrast -= 0.5; if ((cdir == 2) && (restvel > -20)) restvel -= 1; if ((cdir == 3) && (restvel < 20)) restvel += 1; drawallparticles(0, 1); return; } /****************************************************************************/ void kcalc(void) { //Calculates k constants to be used in acceleratory field equation int galaxy; //galaxy ID gotoxy(1, 1); for (galaxy = 1; galaxy <= 2; galaxy ++) { if ((grmmax[galaxy] >= 0) && ((gpmax[galaxy] > 0) || (gpo[galaxy] > 0))) { ki[galaxy] = ((float)gpmax[galaxy] - (float)gpo[galaxy]) / (3 * (float)grmmax[galaxy]); kj[galaxy] = (float)gpo[galaxy] / 2; kk[galaxy] = pow((float)grmmax[galaxy], 2) * ((float)gpmax[galaxy] / 3 + (float)gpo[galaxy] / 6); } else {ki[galaxy] = kj[galaxy] = kk[galaxy] = 0;} } return; } /****************************************************************************/ void printtime(void) { int n; //miscellaneous counting variable for (n = 0; n < 7; n ++) capsname[n] = toupper(simname[n]); gotoxy(11, 1); printf("%s", capsname); gotoxy(11, 2); printf("%.0f ", t); return; } /****************************************************************************/