home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d536 / chemesthetics.lha / Chemesthetics / Source / Source.LZH / chemest.c < prev    next >
C/C++ Source or Header  |  1991-06-12  |  27KB  |  1,126 lines

  1. /***************************************************************************
  2.   chemest.c : Hauptprogramm von Chemesthetics
  3. ***************************************************************************/
  4.  
  5. #include <stdio.h>
  6. #include <math.h>
  7. #include <libraries/mathffp.h>
  8. #include <intuition/intuitionbase.h>
  9. #include <graphics/gfxbase.h>
  10. #include <libraries/dosextens.h>
  11. #include <libraries/arpbase.h>
  12. #include <libraries/reqbase.h>
  13. #include <clib/req_protos.h>
  14. #include <req.h>  /* enthält #pragmas für req.library */
  15. #include <exec/memory.h>
  16. #include <time.h>
  17. #include <proto/mathffp.h>
  18. #include "messages.h"
  19. #include "chem_defs.h"
  20. #include "chemest.h"
  21. #define OK 0
  22. #define NOK 1
  23. #define RESX 640.0               /* Breite des Bildes */
  24. double      VERGRFAKTOR = 0.3;           /* Umrechnungsfaktor pm -> Pixels   */
  25.  
  26. int      HEIGHT = 256;            /* Default, wird bei NTSC-Screen geaendert */
  27. BOOL      reflexion = FALSE, reqlib_used=FALSE;
  28. int      koordmx, koordmy, n, ref;
  29. int      reflexionsfarbe, schattenfarbe, aktfarb, beanz;    /*Anzahl der Kalotten, die
  30.                            das betrachtete Atom
  31.                            berhren bzw. schneiden*/
  32.  
  33. double      mattheit, matthm1, abstand, aspect, vergr, zf;
  34. int      drehx = 0, drehy = 0, drehz = 0;
  35.  
  36. VEKTOR      l, b;                /*Lichtquelle, Beobachter*/
  37.  
  38. int      atomanz;               /*Anzahl der Atome    */
  39. int      geladene_Atome;           /* Anzahl der Atome im Datenfile */
  40.  
  41. T_A      a, alt;               /*Atome            */
  42.  
  43. T_MB      mb;                   /*moegliche Beruehrungen*/
  44.  
  45. long      conwin;
  46. char      dn[DSIZE+FCHARS+2];
  47. char      Dateiname[FCHARS+1], IFFDateiname[FCHARS+1];
  48. char      Pfadname[DSIZE+1],Titel[80];
  49. UBYTE     *atomliste[105];
  50. USHORT      code;
  51. USHORT      GadgetID;
  52.  
  53. struct Atom *GAtom[106];
  54. struct ChemPrefs ChemPrefs= { 1.5,TRUE,TRUE,FALSE };
  55. struct IntuitionBase *IntuitionBase;
  56. struct GfxBase *GfxBase;
  57. struct ArpBase *ArpBase;
  58. struct ReqLib *ReqBase;
  59. struct Screen *FirstScreen;
  60. struct Window *Window1, *Window2;
  61. struct IntuiMessage *message;
  62. struct Gadget *GadgetPtr;
  63. struct Remember *RememberPtr = NULL;
  64. struct Process *MyProcess;
  65. struct ReqFileRequester FileStr; /* kommt aus reqbase.h */
  66. FILE *datei;
  67. APTR OldErrorWin;          /* Windowstruktur vor dem Starten des Tasks */
  68.  
  69. extern char ProgId[], Version[];
  70.  
  71. /* Prototypes for functions defined in chemest.c */
  72.  
  73. #ifndef __NOPROTO
  74. #ifndef __PROTO
  75. #define __PROTO(a) a
  76. #endif
  77. #else
  78. #ifndef __PROTO
  79. #define __PROTO(a) ()
  80. #endif
  81. #endif
  82.  
  83. int dateieinlesen __PROTO((void));
  84. void dateispeichern __PROTO((void));
  85. void Bild_speichern __PROTO((void));
  86. void Load_Datafile __PROTO((void));
  87. void Farben __PROTO((void));
  88. void set_screenmode __PROTO((int height));
  89. void bringeaufeinheitsvektor __PROTO((register VEKTOR *v));
  90. double cowinkelzwischen __PROTO((VEKTOR *v_v1, VEKTOR *v_v2));
  91. void plot __PROTO((double x, double y, double hell1, double hell2));
  92. void spiegle __PROTO((VEKTOR *v_v2, VEKTOR *v1));
  93. void moeglicheberuehrungentesten __PROTO((void));
  94. BOOL beruehrung __PROTO((double x, double y, double z));
  95. int __regargs atomzeichnen __PROTO((ATOMTYP *v_m));
  96. void atomskizze __PROTO((ATOMTYP *v_m));
  97. void atomeordnen __PROTO((void));
  98. void atomezentrieren __PROTO((void));
  99. void atomedrehen __PROTO((char achse, double dx));
  100. int farbnr __PROTO((ATOMTYP *v_atom));
  101. void PrintName __PROTO((void));
  102. void Werte_loeschen __PROTO((void));
  103. void Menu_Auswertung __PROTO((USHORT Menu_Nr));
  104. void main __PROTO((void));
  105. int Nachricht __PROTO((struct Window *win));
  106. void Open_All __PROTO((void));
  107. void Close_All __PROTO((BOOL status));
  108.  
  109. /* ------------------------------- external references ------------------ */
  110.  
  111. extern void Prepare(),PrepareLogo(),FreeLogo(),PrepareEGadgets(),
  112.         FreeEGadgets(),floh(),StatRequest(),license(),SimpleRequest(),
  113.         SysInfo();
  114. extern long save();
  115. extern short TwoGadRequest();
  116. extern UBYTE *AllocRemeber();
  117. extern double bildverh();
  118. extern struct Message *GetMsg();
  119. extern struct Task *FindTask();
  120. extern struct Window *OpenWindow();
  121.  
  122. /* --------- Menuefunktionen ----------------------------------------*/
  123.  
  124. int      dateieinlesen()
  125.  /* versucht, die Molekuel-Datei dn einzulesen */
  126. {
  127.   char        dummy[20];
  128.   int        i;
  129.   FILE       *datei;
  130.  
  131.   strcpy(Titel,LOAD_MOL);
  132.   if(FileRequester(&FileStr))
  133.   {
  134.     datei = fopen(dn, "r");
  135.     if (datei)
  136.     {
  137.       SetPointer(Window1, wptr->Pointer, wptr->Height,
  138.          wptr->Width, wptr->XOffset, wptr->YOffset);
  139.       Werte_loeschen();                /* alte Werte loeschen */
  140.       fgets(dummy,4,datei);
  141.       atomanz=atoi(dummy);
  142.       if(atomanz==0)
  143.       {
  144.     SimpleRequest(WRONG_DATA);
  145.     return 0;
  146.       }
  147.       for (i = 1; i <= atomanz; i++)
  148.       {
  149.     fgets(a[i].name, 4, datei);
  150.     a[i].name[strlen(a[i].name)-1]='\0';  /* \n loeschen */
  151.     fgets(dummy,7,datei); a[i].x=atoi(dummy);
  152.     fgets(dummy,7,datei); a[i].y=atoi(dummy);
  153.     fgets(dummy,7,datei); a[i].z=atoi(dummy);
  154.     fgets(dummy,7,datei); a[i].r=atoi(dummy);
  155.     alt[i] = a[i];               /* Originale f. Editieren sichern */
  156.       }
  157.       fgets(dummy,19,datei); zf=atof(dummy);
  158.       fgets(dummy,19,datei); drehx=atoi(dummy);
  159.       fgets(dummy,19,datei); drehy=atoi(dummy);
  160.       fgets(dummy,19,datei); drehz=atoi(dummy);
  161.       fgets(dummy,19,datei); l.x=atof(dummy);
  162.       fgets(dummy,19,datei); l.y=atof(dummy);
  163.       fgets(dummy,19,datei); l.z=atof(dummy);
  164.       fgets(dummy,19,datei); ref=atoi(dummy);
  165.       fclose(datei);
  166.       ClearPointer(Window1);
  167.       if (zf == 0.0 || zf > 100)
  168.       {
  169.     SimpleRequest(WRONG_DATA);
  170.     return 0;
  171.       }
  172.       else
  173.     return 1;
  174.     }
  175.     else
  176.       return 0;
  177.   }
  178.   else
  179.     return 0;
  180.   reqlib_used=TRUE; /* wirklich benutzt! */
  181. }
  182.  
  183. void      dateispeichern()             /* speichert die Molekuel-Datei */
  184. {
  185.   int        i;
  186.  
  187.   strcpy(Titel,SAVE_MOL);
  188.   if(FileRequester(&FileStr))
  189.   {
  190.     datei = fopen(dn, "w");
  191.     if (datei)
  192.     {
  193.       SetPointer(Window1, wptr->Pointer, wptr->Height,
  194.          wptr->Width, wptr->XOffset, wptr->YOffset);
  195.       fprintf(datei, "%d\n", atomanz);
  196.       for (i = 1; i <= atomanz; i++)
  197.       {
  198.     fprintf(datei, "%s\n", alt[i].name);
  199.     fprintf(datei, "%d\n", alt[i].x);
  200.     fprintf(datei, "%d\n", alt[i].y);
  201.     fprintf(datei, "%d\n", alt[i].z);
  202.     fprintf(datei, "%d\n", alt[i].r);
  203.       }
  204.       fprintf(datei, "%lf\n", zf);
  205.       fprintf(datei, "%d\n", drehx);
  206.       fprintf(datei, "%d\n", drehy);
  207.       fprintf(datei, "%d\n", drehz);
  208.       fprintf(datei, "%lf\n", l.x);
  209.       fprintf(datei, "%lf\n", l.y);
  210.       fprintf(datei, "%lf\n", l.z);
  211.       fprintf(datei, "%d\n", ref);
  212.       fclose(datei);
  213.       ClearPointer(Window1);
  214.     }
  215.   }
  216.   reqlib_used=TRUE; /* wirklich benutzt! */
  217. }
  218.  
  219. void      Bild_speichern()
  220. {
  221.   int        i;
  222.  
  223.   i = strpos(Dateiname, ".cdm");
  224.   if (i > 0)
  225.   {
  226.     strncpy(IFFDateiname, Dateiname, i);
  227.     IFFDateiname[i] = '\0';
  228.     strcat(IFFDateiname, ".iff");
  229.   }
  230.   strcpy(Titel,SAVE_IFF);
  231.   strcpy(Dateiname,IFFDateiname);
  232.   if(FileRequester(&FileStr))
  233.   {
  234.     SetPointer(Window1, wptr->Pointer, wptr->Height,
  235.            wptr->Width, wptr->XOffset, wptr->YOffset);
  236.     if(!(save(dn,FirstScreen,Window1->Width,HEIGHT)))
  237.     {
  238.       ClearPointer(Window1);
  239.       SimpleRequest("%s", IFF_ERROR);
  240.     }
  241.     ClearPointer(Window1);
  242.   }
  243.   reqlib_used=TRUE;
  244. }
  245.  
  246. void      Load_Datafile()
  247. {
  248.   int        i;
  249.   char       dummy[20];
  250.  
  251. #ifdef GERMAN
  252.   datei = fopen("chems_g.dat", "r");
  253. #endif
  254. #ifdef ENGLISH
  255.   datei = fopen("chems_e.dat", "r");
  256. #endif
  257.   if (datei)
  258.   {
  259.     SetPointer(Window1, wptr->Pointer, wptr->Height,
  260.            wptr->Width, wptr->XOffset, wptr->YOffset);
  261.     WrConWin(conwin, READING_DATA);
  262.     fgets(dummy,19,datei); geladene_Atome=atoi(dummy);
  263.     for (i = 1; i <= geladene_Atome; i++)
  264.     {
  265.       GAtom[i] = (struct Atom *) AllocRemember(&RememberPtr,
  266.                     sizeof(struct Atom), MEMF_CLEAR);
  267.       if (GAtom[i] == NULL)
  268.       {
  269.     WrConWin(conwin, ERROR_NO_MEM);
  270.     DisplayAlert(RECOVERY_ALERT,
  271. #ifdef GERMAN
  272.              "\1\0\30 Kein Speicher fuer Daten-File\0c\1\0\50 Maustaste druecken.\0\0",
  273. #endif
  274. #ifdef ENGLISH
  275.              "\1\0\30 No memory for data file\0c\1\0\50 Click mouse button.\0\0",
  276. #endif
  277.              70);
  278.     Close_All(NOK);
  279.       }
  280.       fgets(GAtom[i]->Kurzz, 4, datei);
  281.       GAtom[i]->Kurzz[strlen(GAtom[i]->Kurzz) - 1] = '\0';
  282.       fgets(GAtom[i]->Name, 21, datei);
  283.       atomliste[i - 1] = (UBYTE *) GAtom[i]->Name;
  284.       GAtom[i]->Name[strlen(GAtom[i]->Name) - 1] = '\0';
  285.       fgets(dummy,19,datei); GAtom[i]->Farbe=atoi(dummy);
  286.     }
  287.     GAtom[105] = (struct Atom *) AllocRemember(&RememberPtr,
  288.                     sizeof(struct Atom), MEMF_CLEAR);
  289.     strcpy(GAtom[105]->Name, "??????????");
  290.     fclose(datei);
  291.     WrConWin(conwin, "ok\n");
  292.     ClearPointer(Window1);
  293.   }
  294.   else
  295.   {
  296.     WrConWin(conwin, ERROR_OPEN_DATA);
  297.     Delay(150L);
  298.     Close_All(NOK);
  299.   }
  300. }
  301.  
  302. void      Farben()
  303. {
  304.   int        rwert;
  305.  
  306.   rwert = palette_request(Window1, -1, -1, PALETTE_REQ, "DEFAULT", 4);
  307.   if (rwert == 5)                      /* Default Farben! */
  308.     LoadRGB4(&FirstScreen->ViewPort, &Def_Pal[0], 16);
  309. }
  310.  
  311. void set_screenmode(height) /* undokumentiert!!, ändert Screen in NTSC-
  312.                    oder PAL-Screen, je nach 'height' */
  313. int height;
  314. {
  315.   MyProcess->pr_WindowPtr=OldErrorWin;
  316.  
  317.   if (Window1)
  318.     ClearMenuStrip(Window1);
  319.   if (Window1)
  320.     CloseWindowSafely(Window1, NULL);
  321.   if (FirstScreen)
  322.     CloseScreen(FirstScreen);
  323.   HEIGHT=height;
  324.   if((HEIGHT > 200) && (GfxBase->DisplayFlags & (UWORD)NTSC))
  325.     HEIGHT=200;
  326.   FirstNewScreen.Height = HEIGHT;
  327.   if (!(FirstScreen = (struct Screen *)
  328.     OpenScreen(&FirstNewScreen)))
  329.   {
  330.     WrConWin(conwin, NO_SCREEN);
  331.     Delay(150L);
  332.     Close_All(NOK);
  333.   }
  334.   LoadRGB4(&FirstScreen->ViewPort, &Pal[0], 16);
  335.   HauptFenster.Height = HEIGHT;
  336.   HauptFenster.Screen = FirstScreen;
  337.   if (!(Window1 = (struct Window *)
  338.     OpenWindow(&HauptFenster)))
  339.   {
  340.     WrConWin(conwin, NO_MAIN_WIN);
  341.     Delay(150L);
  342.     Close_All(NOK);
  343.   }
  344.   SetMenuStrip(Window1, &Menu1);
  345.   MyProcess = (struct Process *)FindTask((char *)0);
  346.   OldErrorWin = MyProcess->pr_WindowPtr; /* alten Window-Pointer sichern */
  347.   MyProcess->pr_WindowPtr=(APTR) Window1; /* Requests auf neuen Screen */
  348.   koordmy = round(((double) HEIGHT - 26.0) / 2.0);
  349.   if(HEIGHT<256)
  350.     ChemPrefs.bv=2.0;
  351.   else
  352.     ChemPrefs.bv=1.5;
  353.   aspect = ((double) HEIGHT - 26.0) / RESX * ChemPrefs.bv;
  354.   ShowTitle(FirstScreen,ChemPrefs.Title);
  355. }
  356.  
  357. /* --------- interne Programmroutinen -------------------------------*/
  358.  
  359. void      bringeaufeinheitsvektor(v)
  360. register VEKTOR   *v;
  361.  
  362. /* Der Vektor wird durch seine Laenge dividiert
  363.      und erhaelt dadurch die Laenge 1         */
  364. {
  365.   register double    r;             /*Laenge*/
  366.  
  367.   r = sqrt(v->x * v->x + v->y * v->y + v->z * v->z);
  368.   if (r > 0.0)
  369.   {
  370.     v->x = v->x / r;
  371.     v->y = v->y / r;
  372.     v->z = v->z / r;
  373.   }
  374. }
  375.  
  376.  
  377. double      cowinkelzwischen(v_v1, v_v2)
  378. VEKTOR     *v_v1, *v_v2;
  379.  
  380. /* Cosinus des Winkels zwischen den Vektoren v1 und v2 */
  381. {
  382.   double    r_cowinkelzwischen;
  383.   VEKTOR    v1, v2;
  384.  
  385.   v1 = *v_v1;
  386.   v2 = *v_v2;
  387.   bringeaufeinheitsvektor(&v1);
  388.   bringeaufeinheitsvektor(&v2);
  389.   r_cowinkelzwischen = v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
  390.   return r_cowinkelzwischen;
  391. }
  392.  
  393.  
  394. void      plot(x, y, hell1, hell2)
  395. double      x, y, hell1, hell2;
  396.  
  397. /* Farbgebung nach Ordered-Dither-Verfahren
  398.      in 17 Helligkeisstufen
  399.   Uebergabe: 0 <= hell <= 16
  400.      hell1: Farbe der Kalotte
  401.      hell2: Spiegelung der Beleuchtung */
  402. {
  403.   typedef char T_FARBMATRIX[4][4];
  404.   static T_FARBMATRIX farbmatrix =
  405.   {
  406.     {0, 8, 2, 10},
  407.     {12, 4, 14, 6},
  408.     {3, 11, 1, 9},
  409.     {15, 7, 13, 5}};
  410.   int        kx, ky;
  411.  
  412.   kx = round(koordmx + x);
  413.   ky = round(koordmy - y);
  414.   if (hell2 > (double) farbmatrix[(kx & 3)][(ky & 3)])
  415.     Pixel(Window1, reflexionsfarbe, kx, ky)     /* Spiegelung */
  416.       ;
  417.   else if (hell1 > (double) farbmatrix[(kx & 3)][(ky & 3)])
  418.     Pixel(Window1, aktfarb, kx, ky)    /* Farbe der Kalotte */
  419.       ;
  420.   else
  421.     Pixel(Window1, schattenfarbe, kx, ky);      /* Schatten */
  422. }
  423.  
  424.  
  425. void      spiegle(v_v2, v1)
  426. VEKTOR     *v_v2, *v1;
  427.  
  428. /* v1 wird an der Ebene gespiegelt, die zu v2 normal steht */
  429. {
  430.   VEKTOR    v2;
  431.   double    coa;               /* 1/Cos des eingeschlossenen Winkels */
  432.  
  433.   v2 = *v_v2;
  434.   bringeaufeinheitsvektor(v1);
  435.   bringeaufeinheitsvektor(&v2);
  436.   coa = -1.0 / (v1->x * v2.x + v1->y * v2.y + v1->z * v2.z);
  437.   v1->x = v1->x * coa + 2.0 * v2.x;
  438.   v1->y = v1->y * coa + 2.0 * v2.y;
  439.   v1->z = v1->z * coa + 2.0 * v2.z;
  440. }
  441.  
  442.  
  443. void      moeglicheberuehrungentesten()
  444. /* laedt die Nummern aller Atome, die das betrachtete Atom
  445.      schneiden oder berhren, ins Array mb */
  446. {
  447.   int        i;
  448.   double    dist;               /* Abstand zwischen den Mittelpunkten des
  449.                     betrachteten und eines anderen Atomes      */
  450.  
  451.   beanz = 0;
  452.   if (n > 1)
  453.   {
  454.     for (i = 1; i <= n - 1; i++)
  455.     {
  456.       dist = (double) ((int) (a[n].x - a[i].x) * (int) (a[n].x - a[i].x))
  457.     + (double) ((int) (a[n].y - a[i].y) * (int) (a[n].y - a[i].y))
  458.     + (double) ((int) (a[n].z - a[i].z) * (int) (a[n].z - a[i].z));
  459.       if (dist < 1e-5)
  460.     dist = 1e-5;
  461.       if (sqrt(dist) < (double) ((double) a[i].r + a[n].r))
  462.       {
  463.     beanz++;
  464.     mb[beanz] = i;
  465.       }
  466.     }
  467.   }
  468. }
  469.  
  470.  
  471. BOOL     beruehrung(x, y, z)
  472. double      x, y, z;
  473.  
  474. /* testet, ob der Punkt (x,y,z), der auf der Oberflaeche
  475.      der betrachteten Kalotte liegt, eventuell innerhalb einer
  476.      anderen Kalotte liegt und deshalb unsichtbar bleiben muss:
  477.      => Beruehrung := true    */
  478. {
  479.   BOOL        r_beruehrung;
  480.   int        i;
  481.   double    dist;               /*Abstand der Mittelpunkte*/
  482.   BOOL        flag;               /*wird gesetzt, wenn die
  483.                            oben genannte Bedingung zutrifft */
  484.  
  485.   r_beruehrung = FALSE;
  486.   if (beanz > 0)
  487.   {
  488.     i = 1;
  489.     flag = FALSE;
  490.     do
  491.     {
  492.       dist = (x - a[mb[i]].x) * (x - a[mb[i]].x)
  493.     + (y - a[mb[i]].y) * (y - a[mb[i]].y)
  494.     + (z - a[mb[i]].z) * (z - a[mb[i]].z);
  495.       if (dist < 1e-5)
  496.     dist = 1e-5;
  497.       if (sqrt(dist) < (double) a[mb[i]].r)
  498.     flag = TRUE;
  499.       i++;
  500.     } while (!((i > beanz) || flag));
  501.     if (flag)
  502.       r_beruehrung = TRUE;
  503.   }
  504.   return r_beruehrung;
  505. }
  506.  
  507.  
  508. int    __regargs atomzeichnen(v_m)
  509. ATOMTYP  *v_m;
  510.  
  511. /* zeichnet eine Kalotte */
  512. {
  513.   ATOMTYP   m;
  514.   int        xbild, zbild, zmbild, rbild, rzbild, mxbild, mzbild, lirand,
  515.         rerand;               /* Anfang, Ende einer Pixelzeile */
  516.   double    farbe1, farbe2, perspfaktor, vp, avp, r2double, rz2double,
  517.         radbild, r2bild, cowinkel; /* Cosinus               */
  518.   VEKTOR    o, vo, vl, vb, vs;           /* vgl. Skizze!         */
  519.  
  520.   m = *v_m;
  521.   moeglicheberuehrungentesten();
  522.   perspfaktor = abstand / (abstand + m.y);
  523.   vp = vergr * perspfaktor;
  524.   avp = aspect / vp;
  525.   r2double = (double) ((int) (m.r) * (int) (m.r));
  526.   radbild = m.r * vp;
  527.   mxbild = round(m.x / avp);           /*Koordinaten des Mittelpunktes*/
  528.   mzbild = round(m.z * vp);            /*der Kalotte in Pixels        */
  529.   rbild = trunc(radbild);
  530.   r2bild = radbild * radbild;
  531.   for (zbild = rbild; zbild >= -rbild; zbild--)
  532.   {
  533.     vo.z = zbild / vp;
  534.     o.z = vo.z + m.z;
  535.     vl.z = l.z - o.z;
  536.     rz2double = r2double - vo.z * vo.z;
  537.     rzbild = trunc(sqrt(r2bild - (double) (zbild * zbild)) / aspect);
  538.     lirand = 20000;
  539.     rerand = 20000;
  540.     xbild = -rzbild;               /* Feststellen der Raender des
  541.                       sichtbaren Bereiches einer
  542.                       Pixelzeile der Kalotte */
  543.     do
  544.     {
  545.       vo.x = xbild * avp;
  546.       vo.y = -sqrt(rz2double - vo.x * vo.x);
  547.       if (beruehrung(m.x + vo.x, m.y + vo.y, o.z))
  548.     (xbild)++;
  549.       else
  550.     lirand = xbild;
  551.     } while (!((lirand == xbild) || (xbild > rzbild)));
  552.     if (lirand <= rzbild)
  553.     {
  554.       xbild = rzbild;
  555.       do
  556.       {
  557.     vo.x = xbild * avp;
  558.     vo.y = -sqrt(rz2double - vo.x * vo.x);
  559.     if (beruehrung(m.x + vo.x, m.y + vo.y, o.z))
  560.       (xbild)--;
  561.     else
  562.       rerand = xbild;
  563.       } while (!((rerand == xbild) || (xbild < -rzbild)));
  564.       zmbild = zbild + mzbild;           /* Berechnung der Farbe aller sichtbaren Punkte
  565.         der Pixelzeile                  */
  566.       for (xbild = lirand; xbild <= rerand; xbild++)
  567.       {
  568.     farbe2 = 0.0;
  569.     vo.x = xbild * avp;
  570.     vo.y = -sqrt(rz2double - vo.x * vo.x);
  571.     o.x = vo.x + m.x;
  572.     o.y = vo.y + m.y;
  573.     vl.x = l.x - o.x;
  574.     vl.y = l.y - o.y;
  575.     cowinkel = cowinkelzwischen(&vl, &vo);
  576.     farbe1 = 16.0 * cowinkel;      /* Reflexion */
  577.     if (reflexion)
  578.       if (cowinkel > 0.0)
  579.       {
  580.         vs = vl;
  581.         spiegle(&vo, &vs);         /*vS enthlt jetzt den gespiegelten Lichtvektor*/
  582.         vb.x = b.x - o.x;
  583.         vb.y = b.y - o.y;
  584.         vb.z = b.z - o.z;
  585.         cowinkel = cowinkelzwischen(&vb, &vs);
  586.         cowinkel = cowinkel / mattheit - matthm1;
  587.         farbe2 = 16.0 * cowinkel;
  588.       }
  589.     plot((double) xbild + mxbild, (double) zmbild, farbe1, farbe2);
  590.     if (message = (struct IntuiMessage *) GetMsg(Window1->UserPort))
  591.     {
  592.       int        nklasse;
  593.  
  594.       nklasse = message->Class;
  595.       code = message->Code;
  596.       GadgetPtr = (struct Gadget *) message->IAddress;
  597.       GadgetID = GadgetPtr->GadgetID;
  598.       ReplyMsg(message);
  599.       while (message = (struct IntuiMessage *) GetMsg(Window1->UserPort))
  600.         ReplyMsg(message);
  601.       return nklasse;
  602.     }
  603.       }
  604.     }
  605.   }
  606.   return 0;
  607. }
  608.  
  609.  
  610. void      atomskizze(v_m)
  611. ATOMTYP  *v_m;
  612.  
  613. /* zeichnet den Umriss einer Kalotte */
  614. {
  615.   ATOMTYP   m;
  616.   double    vp, radbild;           /*Radius der Kalotte am Bild in Pixels    */
  617.  
  618.   m = *v_m;
  619.   vp = vergr * abstand / (abstand + m.y);
  620.   radbild = vp * (double) m.r;
  621.   Ellipse(Window1, aktfarb, koordmx + round(vp * m.x / aspect), koordmy - round(vp * m.z),
  622.     (int) (round(radbild / aspect) - 2.0), (int) (round(radbild) - 2.0));
  623. }
  624.  
  625.  
  626. void      atomeordnen()
  627. /* ordnet die Atome von hinten nach vorne */
  628. {
  629.   int        i;
  630.   ATOMTYP   zwi;
  631.   BOOL        flag;
  632.  
  633.   do
  634.   {
  635.     flag = FALSE;
  636.     for (i = 1; i <= atomanz - 1; i++)
  637.     {
  638.       if ((a[i].y < a[i + 1].y))
  639.       {
  640.     zwi = a[i];
  641.     a[i] = a[i + 1];
  642.     a[i + 1] = zwi;
  643.     flag = TRUE;
  644.       }
  645.     }
  646.   } while (flag != FALSE);
  647. }
  648.  
  649.  
  650. void      atomezentrieren()
  651. /* zentriert die Atome im Koordinatensystem */
  652. {
  653.   int        i, dx, dy, dz, minx, maxx, miny, maxy, minz, maxz;
  654.  
  655.   maxx = -30000;
  656.   maxy = maxx;
  657.   maxz = maxx;
  658.   minx = 30000;
  659.   miny = minx;
  660.   minz = minx;
  661.   for (i = 1; i <= atomanz; i++)
  662.   {
  663.     if (a[i].x < minx)
  664.       minx = a[i].x;
  665.     if (a[i].x > maxx)
  666.       maxx = a[i].x;
  667.     if (a[i].y < miny)
  668.       miny = a[i].y;
  669.     if (a[i].y > maxy)
  670.       maxy = a[i].y;
  671.     if (a[i].z < minz)
  672.       minz = a[i].z;
  673.     if (a[i].z > maxz)
  674.       maxz = a[i].z;
  675.   }
  676.   dx = (int) round(((double) maxx + minx) / 2.0);
  677.   dy = (int) round(((double) maxy + miny) / 2.0);
  678.   dz = (int) round(((double) maxz + minz) / 2.0);
  679.   for (i = 1; i <= atomanz; i++)
  680.   {
  681.     a[i].x = a[i].x - dx;
  682.     a[i].y = a[i].y - dy;
  683.     a[i].z = a[i].z - dz;
  684.   }
  685. }
  686.  
  687.  
  688. void      atomedrehen(achse, dx)
  689. char      achse;
  690. double      dx;
  691.  
  692. /* dreht alle Atome um den Winkel dx
  693.      um die Koordinatenachse "Achse"    */
  694. {
  695.   int        xalt, yalt, zalt, i;
  696.   double    sx, cx;
  697.  
  698.   dx = dx / 180.0 * PI;            /*Umrechnung in rad*/
  699.   sx = sin(dx);
  700.   cx = cos(dx);
  701.   for (i = 1; i <= atomanz; i++)
  702.   {
  703.     xalt = a[i].x;
  704.     yalt = a[i].y;
  705.     zalt = a[i].z;
  706.     switch (achse)
  707.     {
  708.       case 'x':
  709.     a[i].y = round(yalt * cx + zalt * sx);
  710.     a[i].z = round(-yalt * sx + zalt * cx);
  711.     break;
  712.       case 'y':
  713.     a[i].x = round(xalt * cx - zalt * sx);
  714.     a[i].z = round(xalt * sx + zalt * cx);
  715.     break;
  716.       case 'z':
  717.     a[i].x = round(xalt * cx + yalt * sx);
  718.     a[i].y = round(-xalt * sx + yalt * cx);
  719.     break;
  720.     }
  721.  
  722.   }
  723. }
  724.  
  725. int      farbnr(v_atom)
  726. ATOMTYP  *v_atom;
  727.  
  728.  /* Zuteilung der Farbe einer Kalotte */
  729. {
  730.   register int i;
  731.   int        f;
  732.   ATOMTYP   atom;
  733.  
  734.   f = 0;
  735.   atom = *v_atom;
  736.   /* in diese Tabelle gewuenschte Farben je nach Graphikkarte
  737.      und persoenlichem Geschmack eintragen (nicht Schwarz!)
  738.      und Tabelle nach Bedarf erweitern */
  739.  
  740.   reflexionsfarbe = 2;
  741.   schattenfarbe = 1;
  742.   for (i = 1; i <= geladene_Atome; i++)
  743.   {
  744.     if (!strcmp(atom.name, GAtom[i]->Kurzz))
  745.     {
  746.       f = GAtom[i]->Farbe;
  747.       i = geladene_Atome;
  748.     }
  749.   }
  750.   if (f == 0)
  751.   {
  752.     SimpleRequest("%s %s", NO_ATOM, atom.name);
  753.     return (7);                        /* als default nehmen */
  754.   }
  755.   else
  756.     return (f);
  757. }
  758.  
  759. void      PrintName()
  760. {
  761.   int        i;
  762.   char        dummy[31];
  763.  
  764.   i = strpos(Dateiname, ".");
  765.   if (i > 0)
  766.   {
  767.     strncpy(dummy, Dateiname, i);
  768.     dummy[i] = '\0';
  769.   }
  770.   else
  771.     strcpy(dummy, Dateiname);
  772.   Shadow(Window1, dummy, 1, 13, 20, HEIGHT - 6);
  773. }
  774.  
  775. void      Werte_loeschen()
  776. {
  777.   register int i;
  778.  
  779.   for (i = 1; i <= MAXATOM; i++)
  780.   {
  781.     strcpy(alt[i].name, "");
  782.     alt[i].x = 0;
  783.     alt[i].y = 0;
  784.     alt[i].z = 0;
  785.     alt[i].r = 0;
  786.     strcpy(a[i].name, "");
  787.     a[i].x = 0;
  788.     a[i].y = 0;
  789.     a[i].z = 0;
  790.     a[i].r = 0;
  791.   }
  792.   zf = 0.0;
  793.   drehx = 0;
  794.   drehy = 0;
  795.   drehz = 0;
  796.   l.x = 0.0;
  797.   l.y = 0.0;
  798.   l.z = 0.0;
  799.   ref = 0;
  800. }
  801.  
  802. void Menu_Auswertung(Menu_Nr)
  803. USHORT      Menu_Nr;
  804. {
  805.   USHORT    Menu, MenuItem;
  806.   long stime,etime;
  807.  
  808.   Menu = MENUNUM(Menu_Nr);
  809.   MenuItem = ITEMNUM(Menu_Nr);
  810. /*  SubItem = SUBNUM(Menu_Nr); */  /* fuer spaeteren Gebrauch */
  811.  
  812.   switch (Menu)
  813.   {
  814.     case 0:                   /* Copyright, Credits */
  815.       switch (MenuItem)
  816.       {
  817.     case 3:
  818.       Credits();
  819.       break;
  820.       }
  821.       break;
  822.     case 1:                   /* Projekt */
  823.       switch (MenuItem)
  824.       {
  825.     case 0:
  826.       if (dateieinlesen())
  827.         Prepare();
  828.       break;
  829.     case 1:
  830.       dateispeichern();
  831.       break;
  832.     case 2:
  833.       Bild_speichern();
  834.       break;
  835.     case 3:
  836.       SysInfo();
  837.       break;
  838.     case 4:
  839.       if(TwoGadRequest(CONFIRM_QUIT))
  840.         Close_All(OK);
  841.       break;
  842.       }
  843.       break;
  844.     case 2:                   /* Edit */
  845.       switch (MenuItem)
  846.       {
  847.     case 0:
  848.       if (Eingabe())
  849.         Prepare();                 /* bei OK */
  850.       break;
  851.     case 1:
  852.       Farben();
  853.       break;
  854.       }
  855.       break;
  856.     case 3:                   /* Zeichnen */
  857.       switch (MenuItem)
  858.       {
  859.     case 0:
  860.       Cls(Window1, 0);
  861.       Logo();
  862.       for (n = 1; n <= atomanz; n++)
  863.       {
  864.         aktfarb = farbnr(&a[n]);
  865.         atomskizze(&a[n]);
  866.       }
  867.       PrintName();
  868.       break;
  869.     case 1:
  870.       Block(Window1, 0, 20, HEIGHT - 12, 280, 11);
  871.       Print(Window1, PRESS_MB, 1, 0, 20, HEIGHT - 6);
  872.       Logo();
  873.       stime=time(&stime);
  874.       for (n = 1; n <= atomanz; n++)
  875.       {
  876.         aktfarb = farbnr(&a[n]);
  877.         if (atomzeichnen(&a[n]))   /* solange FALSE, bis Maustaste gedr. */
  878.           break;
  879.       }
  880.       etime=time(&etime);
  881.       Block(Window1, 0, 20, HEIGHT - 12, 280, 11);
  882.       PrintName();
  883.       StatRequest(Window1,etime-stime,n-1);
  884.       break;
  885.       }
  886.       break;
  887.     case 4:                   /* Einstellungen */
  888.       switch (MenuItem)
  889.       {
  890.     case 0:
  891.       prefs(&ChemPrefs);
  892.       if(ChemPrefs.bv<1.0)
  893.         ChemPrefs.bv=1.0;
  894.       aspect = ((double) HEIGHT - 26.0) / RESX * ChemPrefs.bv;
  895.       break;
  896.       }
  897.       break;
  898.   }
  899. }
  900.  
  901. void      main()                       /* Hauptprogramm            */
  902. {
  903.   Open_All();
  904.   koordmx = round(RESX / 2.0);
  905.   koordmy = round(((double) HEIGHT - 26.0) / 2.0);
  906.   if(HEIGHT<256)
  907.     ChemPrefs.bv=2.0;
  908.   aspect = ((double) HEIGHT - 26.0) / RESX * ChemPrefs.bv;
  909.  
  910.   vergr = VERGRFAKTOR;
  911.   Werte_loeschen();                    /* sicherheitshalber loeschen, damit nicht irgend-
  912.                       welcher Muell vorhanden ist */
  913.   FOREVER
  914.   {
  915.     switch (Nachricht(Window1))
  916.     {
  917.       case MENUPICK:
  918.     Menu_Auswertung(code);
  919.     break;
  920.       case VANILLAKEY:      /* alle diese Features sind nicht dokumentiert,
  921.                  da sie nur für mich interessant sind! */
  922.     switch(code)
  923.     {
  924.       case 'l':
  925.       case 'L':
  926.         license();
  927.         break;
  928.       case 'N':
  929.         set_screenmode(200);
  930.         break;
  931.       case 'P':
  932.         set_screenmode(256);
  933.         break;
  934.      }
  935.      break;
  936.     }
  937.   }
  938. }
  939.  
  940. /*--------------------------- Unterroutinen ------------------------------*/
  941.  
  942. int Nachricht(win)
  943. struct Window *win;
  944. {
  945.   int        nklasse;
  946.  
  947.   FOREVER
  948.   {
  949.     if ((message = (struct IntuiMessage *) GetMsg(win->UserPort)) == NULL)
  950.     {
  951.       Wait(1L << win->UserPort->mp_SigBit);
  952.       continue;
  953.     }
  954.     nklasse = message->Class;
  955.     code = message->Code;
  956.     GadgetPtr = (struct Gadget *) message->IAddress;
  957.     GadgetID = GadgetPtr->GadgetID;
  958.     ReplyMsg(message);
  959.     while (message = (struct IntuiMessage *) GetMsg(win->UserPort))
  960.       ReplyMsg(message);
  961.     break;
  962.   }
  963.   return (nklasse);
  964. }
  965.  
  966. void Open_All()
  967. {
  968.   if (!(IntuitionBase = (struct IntuitionBase *)
  969.     OpenLibrary("intuition.library", 0L)))
  970.   {
  971.     printf(NO_INTUI);
  972.     Close_All(NOK);
  973.   }
  974.  
  975.   conwin = OpenRevWin("CON:120/88/400/80/Chemesthetics");
  976.   if (conwin == -1)
  977.   {
  978.     printf(NO_CONSOLE);
  979.     Close_All(NOK);
  980.   }
  981.  
  982.   if (!(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0L)))
  983.   {
  984.     WrConWin(conwin, NO_GFX);
  985.     Delay(150L);
  986.     Close_All(NOK);
  987.   }
  988.  
  989.   if (!(TestFile("libs:arp.library")))
  990.   {
  991.     WrConWin(conwin, NO_ARP);
  992.     Delay(150L);
  993.     Close_All(NOK);
  994.   }
  995.  
  996.   if (!(ArpBase = (struct ArpBase *) OpenLibrary(ArpName, ArpVersion)))
  997.   {
  998.     WrConWin(conwin, ERROR_NO_ARP);
  999.     Delay(150L);
  1000.     Close_All(NOK);
  1001.   }
  1002.  
  1003.   if (!(TestFile("libs:req.library")))
  1004.   {
  1005.     WrConWin(conwin, NO_REQ_LIB);
  1006.     Delay(150L);
  1007.     Close_All(NOK);
  1008.   }
  1009.   else
  1010.   {
  1011.     if (!(ReqBase = (struct ReqLib *) OpenLibrary("req.library",0L)))
  1012.     {
  1013.       WrConWin(conwin, ERROR_NO_REQ);
  1014.       Delay(150L);
  1015.       Close_All(NOK);
  1016.     }
  1017.     else
  1018.     {
  1019.       dn[0]=0;
  1020.       FileStr.Title= Titel;
  1021.       FileStr.PathName = dn;
  1022.       FileStr.Dir = Pfadname;
  1023.       FileStr.File = Dateiname;
  1024.       FileStr.Flags = FRQCACHINGM|FRQCACHEPURGEM;
  1025.       FileStr.dirnamescolor = 8;
  1026.       FileStr.devicenamescolor = 4;
  1027.       strcpy(Pfadname,"Examples");
  1028.       strcpy(Dateiname,"");
  1029.     }
  1030.   }
  1031.  
  1032. #ifdef GERMAN
  1033.   if (!(TestFile("chems_g.dat")))
  1034. #endif
  1035. #ifdef ENGLISH
  1036.   if (!(TestFile("chems_e.dat")))
  1037. #endif
  1038.   {
  1039.       WrConWin(conwin, NO_DATA);
  1040.       Delay(100L);
  1041.       Close_All(NOK);
  1042.   }
  1043.  
  1044.   PrepareSanduhr();
  1045.   Load_Datafile();
  1046.   sprintf(Ver, "%s V%s", ProgId, Version);
  1047.  
  1048.   if(GfxBase->DisplayFlags & (UWORD)NTSC)
  1049.     HEIGHT=200;
  1050.   FirstNewScreen.Height = HEIGHT;
  1051.   if (!(FirstScreen = (struct Screen *)
  1052.     OpenScreen(&FirstNewScreen)))
  1053.   {
  1054.     WrConWin(conwin, NO_SCREEN);
  1055.     Delay(150L);
  1056.     Close_All(NOK);
  1057.   }
  1058.  
  1059.   LoadRGB4(&FirstScreen->ViewPort, &Pal[0], 16);
  1060.  
  1061.   if (Metalworx(FirstScreen))
  1062.     WrConWin(conwin, NO_METAL_WIN);
  1063.  
  1064.   HauptFenster.Height = HEIGHT;
  1065.   HauptFenster.Screen = FirstScreen;
  1066.  
  1067.   if (!(Window1 = (struct Window *)
  1068.     OpenWindow(&HauptFenster)))
  1069.   {
  1070.     WrConWin(conwin, NO_MAIN_WIN);
  1071.     Delay(150L);
  1072.     Close_All(NOK);
  1073.   }
  1074.   SetMenuStrip(Window1, &Menu1);
  1075.   MyProcess = (struct Process *)FindTask((char *)0);
  1076.   OldErrorWin = MyProcess->pr_WindowPtr; /* alten Window-Pointer sichern */
  1077.   MyProcess->pr_WindowPtr=(APTR) Window1; /* Requests auf neuen Screen */
  1078.  
  1079.   license();
  1080.   ShowTitle(FirstScreen,ChemPrefs.Title);
  1081.   PrepareLogo();
  1082.   PrepareEGadgets();
  1083. }
  1084.  
  1085. /****************************************
  1086. * Funktion: Alles geoeffnete schliessen *
  1087. ****************************************/
  1088.  
  1089. void Close_All(status)
  1090. BOOL status;
  1091. {
  1092.   MyProcess->pr_WindowPtr=OldErrorWin;    /* alten Window-Pointer wieder
  1093.                        herstellen */
  1094.   if(reqlib_used)
  1095.     PurgeFiles(&FileStr);           /* Speicher f. FileListe freigeben */
  1096.   FreeEGadgets();
  1097.   FreeLogo();
  1098.   if (RememberPtr)
  1099.     FreeRemember(RememberPtr, TRUE);
  1100.   if (Window1)
  1101.     ClearMenuStrip(Window1);
  1102.   if (Window1)
  1103.     CloseWindowSafely(Window1, NULL);
  1104.   if (FirstScreen)
  1105.     CloseScreen(FirstScreen);
  1106.   FreeSanduhr();
  1107.   if (ReqBase)
  1108.     CloseLibrary(ReqBase);
  1109.   if (ArpBase)
  1110.     CloseLibrary(ArpBase);
  1111.   if (GfxBase)
  1112.     CloseLibrary(GfxBase);
  1113.   if (conwin != -1)
  1114.   {
  1115.     WrConWin(conwin, "Thanx! Have a nice day!");
  1116.     Delay(100L);
  1117.     close(conwin);
  1118.   }
  1119.   if (IntuitionBase)
  1120.     CloseLibrary(IntuitionBase);
  1121.   if (status == OK)
  1122.     exit(0);
  1123.   else
  1124.     exit(1);
  1125. }
  1126.