home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / science / chemesthetics / source / source.lzh / chemest.c < prev    next >
C/C++ Source or Header  |  1990-12-06  |  23KB  |  1,015 lines

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