/********************************************************************
Quadratischer Henon Attraktor
Plugin für Cinema Version 8.0
(c) Jürgen Meier (Juergen-Meier@Hamburg.de)
Version : 1.10
29.06.2003
*********************************************************************/

// Globale Variablen und Konstanten
   // Plugin ID Nummer
      const var cPluginID = 1006511;
   // Pluginname
      const var cPlugName = "Quadratischer Henon Attraktor";
   // Pluginhilfstext
      const var cPlugHelp = "Erzeugt den Quadratischer Henon Attraktor";
   // Objektname
      const var cObjName = "Quadratischer Henon Attraktor";
   // Index
      var i,j;
   // Koordinaten der Punkte
      var x,y,z;
   // Alter Wert von x
      var xa;
   // Differenzen
      var dx,dy,dz;
   // Breite des Menütextes
      var Breite=150;
   // Maximalwerte
      var cMaxFloat=1000000;
      var cMaxInt=100000000;
   // Objektvariable
      var qObj;
   // Dialogvariable
      var gDial;
   // Attraktorspezifische Variablen
      // Konstanten
         var a=1.5237;
         var d=0.04;
      // Hilfsvariablen
         var cosa,sina;
      // Maximalwert für x und y
         var max=500;
      // Radius
         var Radius=0.2;
      // Anzahl Iterationen
         var N=500;
      // Anzahl Zyklen
         var NZ=50;
      // Startwerte
         var x0=0.01;
         var y0=0.01;
      // Skalierungsfaktor
         var Faktor=100;


// ******************************************************************
// Funktion zum Objekt aktivieren (c) h.g.seib
// ******************************************************************
   fSetActiveObject(vDoc,vObj)
   {
   // Aktives Objekt ermitteln
      var vAObj = GetActiveObject(vDoc);
   // Active object Bit bzw. Flag setzen
      if (vAObj) vAObj->DelBit(BIT_AOBJ);
          vObj->SetBit(BIT_AOBJ);
   // Änderung im Dokument bekanngeben (neues Objekt selektiert)
      GeEventAdd(NEW_ACTIVE_OBJECT);
   }

// ******************************************************************
// Funktion zur Berechnung des Attraktors
   fAttraktor(vDoc)
   {
   // Nullobjekt erzeugen
      var attraktor = new(NullObject);
   // Name zuweisen
      attraktor->SetName(cObjName);
   // Nullobjekt in die Szene einfügen
      vDoc->InsertObject(attraktor,NULL,NULL);
   // Attraktor berechnen
      // Ersten Punkt berechnen
         // Startwerte übergeben
            xa=x0;
            y=y0;
         // Hilfsvariablen berechnen
            cosa=cos(a);
            sina=sin(a);
         // Punkt berechnen
            x=xa*cosa-(y-xa*xa)*sina;
            y=xa*sina+(y-xa*xa)*cosa;
         // x Wert aktualisieren
            xa=x;
      // Zyklen durchlaufen
         for (j=1;j<NZ+1;j++)
         {
            // Nullobjekt erzeugen
               var g = new(NullObject);
            // Name zuweisen
               g->SetName("Gruppe "+tostring(j));
            // Nullobjekt in die Szene einfügen
               vDoc->InsertObject(g,attraktor,NULL);
            // Punkte eines Zyklus berechnen
               for (i=0;i<N;i++)
                   {
                    // x und y überprüfen
                       if (xa<max) {
                    // Neue Koordinaten berechnen
                       x=xa*cosa-(y-xa*xa)*sina;
                       y=xa*sina+(y-xa*xa)*cosa;
                    // Neues Sphere Object erzeugen
                       var kugel = new(SphereObject);
                    // Container erzeugen
                       var sc = kugel->GetContainer();
                    // Radius der Kugel setzen
                       sc->SetData(PRIM_SPHERE_RAD,Radius);
                    // Container Variablen zurückgeben
                       kugel->SetContainer(sc);
                    // Name zuweisen
                       kugel->SetName("Kugel "+tostring(i+1));
                    // Kugel positionieren
                       kugel->SetPosition(vector(x*Faktor,y*Faktor,0));
                    // Objekt in der Dokumenthierarchie positionieren
                       vDoc->InsertObject(kugel,g,NULL);
                       GeEventAdd(DOCUMENT_CHANGED);
                    // x Wert aktualisieren
                       xa=x;
                       }
                   }
            // Neue Startwerte berechnen
               xa=x0+j*d;
               y=y0+j*d;
         }
   // Objekt aktivieren
      fSetActiveObject(vDoc,attraktor);
      GeEventAdd(DOCUMENT_CHANGED);
    return TRUE;
   }

// ******************************************************************
// Ableitung der Klasse MyDialog von GeDialog
// ******************************************************************
class MyDialog : GeDialog
{
   public:
      MyDialog();
      CreateLayout();
      Init();
      CoreMessage(vID,vMSG);
      Command(vID,vMSG);
}
// ******************************************************************
// Deklaration des Konstruktors
   MyDialog::MyDialog()
   {
   // Konstruktor der parent class aufrufen
      super(cPluginID);
   }

// ******************************************************************
// Deklaration der Methode CreateLayout
   MyDialog::CreateLayout()
   {     
   // Plugintitel setzen
      SetTitle(cPlugName);
   // Gruppe für die Konstanten
      AddGroupBeginV(1000,BFH_CENTER,2,"",0);
      {
         AddStaticText(0,BFH_LEFT,Breite,0," Konstante a",0);
         AddEditNumber(2000,BFH_LEFT,100,0);
      }
      // Vertikal orientierte Gruppe schliessen
         AddGroupEnd();
   // Waagerechte Trennlinie
      AddSeparatorH(0);
   // Gruppe für die Zyklen
      AddGroupBeginV(1003,BFH_CENTER,2,"",0);
      {
         AddStaticText(0,BFH_LEFT,Breite,0," Delta",0);
         AddEditNumber(2001,BFH_LEFT,100,0);
         AddStaticText(0,BFH_LEFT,Breite,0," Anzahl Zyklen",0);
         AddEditNumber(2002,BFH_LEFT,100,0);
      }
      // Vertikal orientierte Gruppe schliessen
         AddGroupEnd();
   // Waagerechte Trennlinie
      AddSeparatorH(0);
   // Gruppe für die Startwerte
      AddGroupBeginV(1001,BFH_CENTER,2,"",0);
      {
         AddStaticText(0,BFH_LEFT,Breite,0," Start x",0);
         AddEditNumber(2500,BFH_LEFT,100,0);
         AddStaticText(0,BFH_LEFT,Breite,0," Start y",0);
         AddEditNumber(2501,BFH_LEFT,100,0);
      }
      // Vertikal orientierte Gruppe schliessen
         AddGroupEnd();
   // Waagerechte Trennlinie
      AddSeparatorH(0);
   // Gruppe für die Parameter der Iteration
      AddGroupBeginV(1002,BFH_CENTER,2,"",0);
      {
         AddStaticText(0,BFH_LEFT,Breite,0," Radius Kugel",0);
         AddEditNumber(2502,BFH_LEFT,100,0);
         AddStaticText(0,BFH_LEFT,Breite,0," Anzahl N",0);
         AddEditNumber(2503,BFH_LEFT,100,0);
         AddStaticText(0,BFH_LEFT,Breite,0," Faktor",0);
         AddEditNumber(2504,BFH_LEFT,100,0);
      }
      // Vertikal orientierte Gruppe schliessen
         AddGroupEnd();
   // Waagerechte Trennlinie
      AddSeparatorH(0);
   // Button für den Start der Berechnung
      AddButton (3000,BFH_CENTER,200,0,"Start");
      return TRUE;
   }

// ******************************************************************
// Deklaration der Methode Init
   MyDialog::Init()
   {
   // Startwerte setzen
      SetFloat(2000,a,-cMaxFloat,cMaxFloat,0);
      SetFloat(2001,d,-cMaxFloat,cMaxFloat,0);
      SetInt(2002,NZ,0,cMaxInt,0);
      SetFloat(2500,x0,-cMaxFloat,cMaxFloat,0);
      SetFloat(2501,y0,-cMaxFloat,cMaxFloat,0);
      SetFloat(2502,Radius,-cMaxFloat,cMaxFloat,0);
      SetInt(2503,N,0,cMaxInt,0);
      SetFloat(2504,Faktor,0,cMaxFloat,0);
      return TRUE;
   }

// ******************************************************************
// Deklaration der Methode CoreMessage
   MyDialog::CoreMessage(vID,vMSG)
   {
      switch (vID)
         {
            case NEW_DOCUMENT:
            case DOCUMENT_CHANGED:
            case NEW_ACTIVE_OBJECT:
            case ACTIVE_OBJECT_CHANGED:
            return TRUE;
            break;
         }
      return FALSE;
   }

// ******************************************************************
// Deklaration der Methode Command
   MyDialog::Command(vID,vMSG)
   {
      var vDoc;
   //
      StopAllThreads();
      switch (vID)
      {
        case 3000 : // Start Button gedrückt
                      {
                         vDoc = GetActiveDocument();
                         if (!vDoc) return FALSE;
                         fAttraktor(vDoc);
                      }
        case 2000 : a=GetFloat(2000);
        case 2001 : d=GetFloat(2001);
        case 2002 : NZ=GetInt(2002);
        case 2500 : x0=GetFloat(2500);
        case 2501 : y0=GetFloat(2501);
        case 2502 : Radius=GetFloat(2502);
        case 2503 : N=GetInt(2503);
        case 2504 : Faktor=GetFloat(2504);
      }
      return TRUE;
   }


// ******************************************************************
// Ableitung der Klasse MyMenuPlugin von MenuPlugin
// ******************************************************************
   class MyMenuPlugin : MenuPlugin
   {  public:
          MyMenuPlugin();
          GetID();
          GetName();
          GetHelp();
          Execute(doc);
          RestoreLayout(secret);
   }
// ******************************************************************
// Deklaration des Konstruktors
   MyMenuPlugin::MyMenuPlugin()
   { 
      super();
   }

// ******************************************************************
// Deklaration der Methode GetID
   MyMenuPlugin::GetID()
   {
      return cPluginID;
   }

// ******************************************************************
// Deklaration der Methode GetName
   MyMenuPlugin::GetName()
   {
       return cPlugName;
   }

// ******************************************************************
// Deklaration der Methode GetHelp
   MyMenuPlugin::GetHelp()
   {
       return cPlugHelp;
   }

// ******************************************************************
// Deklaration der Methode Execute
   MyMenuPlugin::Execute(doc)
   {
      if (!gDial)
         gDial=new(MyDialog);
     gDial->Open(TRUE,-1,-1);
   }
// ******************************************************************
// Deklaration der Methode RestoreLayout
   MyMenuPlugin::RestoreLayout(secret)
   {
      if (!gDial)
         gDial=new(MyDialog);
      gDial->RestoreLayout(secret);
   }

// ******************************************************************
main()
{
    Register(MyMenuPlugin);
}

