/********************************************************************/ /**** ****/ /**** ****/ /**** Program : C-Plot.c ****/ /**** ****/ /**** Version : 03.71 ****/ /**** ****/ /**** Erstversion : 14.08.1988 ****/ /**** ****/ /**** Letzte Änderung : 09.08.1990 ****/ /**** ****/ /**** Compiliert mit : siehe MAKEFILE ****/ /**** ****/ /**** Gelinkt mit : siehe MAKEFILE ****/ /**** ****/ /********************************************************************/ /**** ****/ /**** ****/ /**** Copyright by Rüdiger Dreier ****/ /**** ****/ /**** ****/ /********************************************************************/ /* Einbinden der Include-Files */ #ifdef DEBUG #include #include #include "Plotter.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Variablendeklaration */ BOOL KoordinatenKreuz_gezeichnet; /* Gibt an, ob Koordinatenkreuz neu gezeichnet werden muß */ int GE=1; /* Für die Genauigkeit der Zeichnung */ int Groesse; APTR Konstantenstart; /* Zeiger auf die Konstanten */ struct Block *StartBlock; /* Zeiger auf ersten Block */ struct LayersBase *LayersBase; struct ViewPort *viep; /* Zeiger auf ViewPort */ struct IntuitionBase *IntuitionBase; /* Zeiger auf IntuitionBase */ struct ToolBase *ToolBase; struct Library *MathIeeeDoubTransBase; struct Window *Window; /* Zeiger auf Fenster */ struct RastPort *RastPort; /* Zeiger auf RastPort */ struct Screen *Screen; /* Zeiger auf Screen */ struct GfxBase *GfxBase; /* Zeiger auf Grafik-Library */ struct View *View; struct BitMap bitmap; struct Layer *layer; struct Layer_Info *layerinfo; struct info msgInfo; /* Strings */ UBYTE undo1[20]; /* Für Gadget, Intervall und Konstanten */ UBYTE undoFormel[MAXCHARS]; /* Für Gadget, Formeleingabe */ UBYTE xmpstring[20], xmnstring[20]; /* Strings für Intervall */ UBYTE ympstring[20], ymnstring[20]; /* Strings für Intervall */ UBYTE KonAString[20],KonBString[20]; /* Strings für Konstanten */ UBYTE KonCString[20],KonDString[20]; /* Strings für Konstanten */ UBYTE Formeln[11][MAXCHARS]; /* Strings für Formeln */ UBYTE Abgeleitet[2][MAXCHARS]; /* Strings für 1. und 2. Ableitung */ char SubMenuTitle[10][16]; /* Die Strings für die 10 SubItems */ SHORT XOffset,YOffset; /* Variablen, in denen wichtige Werte gespeichert werden */ LONG xx=609,yy=PLOT_Y; /* Punkte in x/y-Richtung */ double xmp,xmn,ymp,ymn; /* Intervallgrenzen */ double x0,y0; /* Position der Achsen */ double xm,ym; /* Maßstab für x/y-Achse */ /* Daten für Screen und Window */ struct NewScreen Schirm= { 0,0,640,YSCREEN,2,2,1,HIRES,CUSTOMSCREEN,NULL,"Plotter",NULL,NULL }; struct NewWindow Fenster= { 0,10,640,YSCREEN-10,FARBE0,FARBE1,MENUPICK|MOUSEBUTTONS|RAWKEY, BORDERLESS|ACTIVATE|REPORTMOUSE|SUPER_BITMAP, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, CUSTOMSCREEN }; /* Hauptprogramm */ VOID _main() { /* Einige Formeln vorschlagen */ strcpy(Formeln[0],"sin(x)"); strcpy(Formeln[1],"cos(x)"); strcpy(Formeln[2],"tan(x)"); strcpy(Formeln[3],"x^2"); strcpy(Formeln[4],"x^3"); strcpy(Formeln[5],"5*x"); strcpy(Formeln[6],"x"); strcpy(Formeln[7],"sqr(x)"); strcpy(Formeln[8],"ln(x)"); strcpy(Formeln[9],"log(x)"); /* Intervall vorschlagen */ strcpy(xmpstring,"pi"); strcpy(xmnstring,"-pi"); ympstring[0]='1'; /* global, NULL ist schon gesetzt */ ymnstring[0]='-'; ymnstring[1]='1'; /* Konstanten vorschlagen */ strcpy(KonAString,"-pi"); strcpy(KonBString,"-pi"); strcpy(KonCString,"-pi"); strcpy(KonDString,"-pi"); if(oeffne()) /* Öffnen der Libraries, Screen, Fenster */ { LoadRGB4(viep,Farb2,4L); /* Farben setzen */ UpdateMenuText(); /* SubMenuText erneuern */ UmwandlungInIntervall(); /* Intervallstrings in double umwandeln */ UmwandlungInKonstanten(); /* Konstantenstrings in double umwandeln */ MenuWahl(); /* Verwertet die Intuition-Messages */ } ende(); /* Gibt den belegten Speicher wieder frei */ } /* Routine, die Punkt setzt. Parameter DOUBLE */ VOID Pset(DOUBLE x1,DOUBLE y1) { Move(RastPort,Fix(Add(x1,RUNDEN))+Abstand,Fix(Add(y1,RUNDEN))+Abstand); Draw(RastPort,Fix(Add(x1,RUNDEN))+Abstand,Fix(Add(y1,RUNDEN))+Abstand); } /* Routine, die Linie zieht. Parameter DOUBLE */ VOID DrawTo(DOUBLE x1,DOUBLE y1) { Draw(RastPort,Fix(Add(x1,RUNDEN))+Abstand,Fix(Add(y1,RUNDEN))+Abstand); } /* Zeichnet Linie von (x1,y1) - (x2,y2) Parameter : DOUBLE */ VOID Line(DOUBLE x1,DOUBLE y1,DOUBLE x2,DOUBLE y2) { /* Zum Anfang bewegen und Linie ziehen */ Move(RastPort,Fix(Add(x1,RUNDEN))+Abstand,Fix(Add(y1,RUNDEN))+Abstand); Draw(RastPort,Fix(Add(x2,RUNDEN))+Abstand,Fix(Add(y2,RUNDEN))+Abstand); } /* Routine zum Beschriften des Koordinatenkreuzes */ VOID zeichne(VOID) { char buffer[11]; double i,dx,dy,x,y; char Zaehler; long xx,yy; SetDrMd(RastPort,JAM1); /* Bestimmt Abstand zwischen 2 Skalenunterteilungen */ dx=Div(Sub(xmp,xmn),10.0); dy=Div(Sub(ymp,ymn),10.0); /* Zeichnet Unterteilung der Achsen */ i=Sub(xmn,dx); yy=Fix(y0)+Abstand+12; for(Zaehler=0;Zaehler<=10;Zaehler++) { i=Add(i,dx); if(Cmp(Abs(i),Div(dx,1000.0))==-1)i=0.0000; x=Add(x0,Mul(i,xm)); Line(x,Sub(y0,3.0),x,Add(y0,3.0)); UmwFtoS(buffer,&i,2); xx=Fix(x)-(strlen(buffer)<<2)+Abstand; Print(RastPort,buffer,FARBE1,xx,yy); } i=Sub(ymn,dy); xx=Fix(x0)+Abstand+8; for(Zaehler=0;Zaehler<=10;Zaehler++) { i=Add(i,dy); if(Cmp(Abs(i),Div(dy,1000.0))==-1)i=0.0000; y=Sub(y0,Mul(i,ym)); Line(Sub(x0,5.0),y,Add(x0,5.0),y); UmwFtoS(buffer,&i,2); yy=Fix(y)+Abstand+3; Print(RastPort,buffer,FARBE1,xx,yy); } } /* Wertet Mausklick aus */ VOID MenuWahl(VOID) { struct MenuItem *Item; long menu,item; char ENDE=1; USHORT sub,menunr; while(ENDE) { /* Wartet auf Event */ Wait(1L<UserPort->mp_SigBit); /* Arbeitet ab, bis keine Events mehr */ while(EventAbfrage(Window,&msgInfo)) { /* Verzweigt entsprechend der Events */ switch(msgInfo.NachrichtenArt) { /* Menupunkt gewählt */ case MENUPICK: { menunr=msgInfo.code; /* Wurde wirklich ein Menu gewählt ? */ while(menunr!=MENUNULL) { /* Wenn ja, dann Menu-, Item- und SubItemNummer bestimmen */ menu=MENUNUM(menunr); item=ITEMNUM(menunr); sub =SUBNUM (menunr); /* Entsprechend des Menus verzweigen */ switch (menu) { case 0: { /* Ein Punkt des ersten Menus wurde gewählt */ switch(item) { /* Entsprechend des Items verzweigen */ case 0: { /* Bestimmung der neuen Zeichengenauigkeit */ GE=sub; break; } case 1: { /* Eingabe eines neuen Intervall */ do { TextFuerIntervall(); /* Gadget vorbereiten */ /* */ /* Grenzen abfragen */ Grenzen(xmnstring,ymnstring,xmpstring,ympstring); UmwandlungInIntervall(); /* Werte kopieren */ } while(Cmp(xmn,xmp)==1 || Cmp(ymn,ymp)==1); } case 2: { /* Schirm löschen */ /* Loeschen(); */ goto Einsprung_P2; } case 3: { /* Routine zum Drucken */ drucken(); /* Farben wieder zurücksetzen */ LoadRGB4(viep,Farb2,4L); break; } case 4: { ULONG OldIDCMP; if(KoordinatenKreuz_gezeichnet) { OldIDCMP=Window->IDCMPFlags; ModifyIDCMP(Window,MOUSEMOVE|MOUSEBUTTONS); /* */ /* Bereich mit Maus auswählen */ AusSchnitt(&xmn,&ymn,&xmp,&ymp); /* Funktion aufrufen */ ModifyIDCMP(Window,OldIDCMP); Einsprung_P2: Loeschen(); } break; } case 5: { /* Eingabe der Werte für die Konstanten */ TextFuerKonstanten(); /* Gadget vorbereiten */ /* */ /* Werte vom Anwender holen */ Grenzen(KonAString,KonCString,KonBString,KonDString); UmwandlungInKonstanten(); /* Werte kopieren */ break; } case 6: { /* About */ Einsprung_P3: About(); break; } case 7: { /* Beenden des Programms */ ENDE=1-request(PLOT_END,PLOT_CONT,PLOT_QUEST); } } break; } case 1: { /* Das nullte Menu wurde gewählt */ switch (item) { /* Entsprechend des Items verzweigen */ case 7: { Full_Discussion(sub); goto Einsprung_P3; } case 0: { /* Funktionsterm ändern */ do { Funktionseingabe(Formeln[sub]); /* Holen der neuen Vorschrift */ } while(AnzahlKlammern((char *)Formeln[sub])); UpdateMenuText(); /* SubItemText erneuern */ break; } case 1: case 2: case 3: { /* Entsprechend dem SubItem zeichnen */ ZeichneFunktion(sub,(int)item-1); break; } /* Item 4 ist ---------- */ case 5: { /* 1. Abl. symbolisch */ /* Entsprechend dem SubItem zeichnen */ strcpy(Formeln[10],Ableiten(Formeln[sub])); goto Einsprung_P1; } case 6: { /* 2. Abl. symbolisch */ strcpy(Formeln[10],Ableiten(Formeln[sub])); strcpy(Formeln[10],Ableiten(Formeln[10])); Einsprung_P1: ZeichneFunktion(10,0); } } break; } case 2: { switch(item) { case 1: { Groesse=GROSS; xx=969; /* Definiert, wie viele Punkte für Grafik */ yy=257; /* genutzt werden sollen */ break; } case 0: { Groesse=KLEIN; xx=609; /* Definiert, wie viele Punkte für Grafik */ yy=PLOT_Y; /* genutzt werden sollen */ } } goto Einsprung_P2; } } Item=ItemAddress(Menu,(LONG)menunr); menunr=Item->NextSelect; Item->NextSelect=MENUNULL; } } case RAWKEY: { if(Groesse) { TastaturAbfrage(); } } } } } } /* Öffnet Libraries, Screen, Window */ int oeffne() { int Failed=0; if((ToolBase=(struct ToolBase *)OpenLibrary("tool.library",0))) { IntuitionBase=ToolBase->IntuitionBase; GfxBase=ToolBase->GfxBase; MathIeeeDoubTransBase=ToolBase->MathIeeeDoubTransBase; MathIeeeDoubBasBase=ToolBase->MathIeeeDoubBasBase; if(Konstantenstart=Init_Konst()) { if((LayersBase = (struct LayersBase *)OpenLibrary("layers.library",0))) { if((Screen=(struct Screen *)OpenScreen(&Schirm))) { InitBitMap(&bitmap,2,1000,MAXPIXELY); if((bitmap.Planes[0]=AllocRaster(1000,MAXPIXELY))) { Delay(5); if((bitmap.Planes[1]=AllocRaster(1000,MAXPIXELY))) { Fenster.Screen=Screen; /* Fenster soll auf Screen erscheinen */ Fenster.BitMap=&bitmap; if((Window=(struct Window *)OpenWindow(&Fenster))) { /* Zuweisung von Variablen, Einfärben des Windows */ MakeMenu(); /* Menustrukturen erzeugen */ NewSetMenuStrip(Window,Menu); /* Menus verknüpfen */ viep=&Screen->ViewPort; /* ViewPort-Zeiger füllen */ RastPort=Window->RPort; /* Variablenzuweisung */ layer=RastPort->Layer; /* LayerPointer holen */ layerinfo=layer->LayerInfo; /* LayerInfo holen */ SetRast(RastPort,FARBE0); /* Schirm löschen */ Fenster2.Screen=Screen; /* Fenster2 auch auf Screen */ Fenster3.Screen=Screen; /* Fenster3 auch auf Screen */ Failed=1; /* Nur wenn alles geklappt hat */ } } } } } } } return(Failed); } /* Routine, die alles wieder schließt */ VOID ende(VOID) { LONG H; Delay(20); if(Konstantenstart)Free_Konst(Konstantenstart); /* Wenn offen -> schließen */ if(Window) { while(H=EventAbfrage(Window,&msgInfo)); ReMakeMenu(Window); CloseWindow(Window); }; if(bitmap.Planes[0]) { FreeRaster(bitmap.Planes[0],1000,MAXPIXELY); bitmap.Planes[0]=0; } if(bitmap.Planes[1]) { FreeRaster(bitmap.Planes[1],1000,MAXPIXELY); bitmap.Planes[1]=0; } if(Screen)CloseScreen(Screen); /* Schließt auch automatisch IntuitionBase etc. */ if(ToolBase)CloseLibrary((struct Library *)ToolBase); if(LayersBase)CloseLibrary((struct Library *)LayersBase); } /* Für Intervall */ VOID UmwandlungInIntervall(VOID) { /* Sollte nicht benutzt werden, darum ruhig undefinierter Wert */ berechnen(&xmp,xmpstring,&x0,(struct Konstanten *)Konstantenstart,&MatheFehler); berechnen(&xmn,xmnstring,&x0,(struct Konstanten *)Konstantenstart,&MatheFehler); berechnen(&ymp,ympstring,&x0,(struct Konstanten *)Konstantenstart,&MatheFehler); berechnen(&ymn,ymnstring,&x0,(struct Konstanten *)Konstantenstart,&MatheFehler); } /* Für Konstanten */ VOID UmwandlungInKonstanten(VOID) { /* Eine Konstante darf nicht aus dem Wert einer anderen Konstanten bestehen */ /* Also nicht A=1+B, da B zum Zeitpunkt der Bestimmung von A nicht unbe- */ /* dingt den richtigen Wert haben muß. */ /* Es ist zwar prinzipiell möglich, aber man sollte keine Rekursionen be- */ /* nutzen, wie a=d+1 und d=a*10 */ DOUBLE var; berechnen(&var,KonAString,&var,(struct Konstanten *)Konstantenstart,&MatheFehler); Set_Konst_P(Konstantenstart,1,&var); berechnen(&var,KonBString,&var,(struct Konstanten *)Konstantenstart,&MatheFehler); Set_Konst_P(Konstantenstart,2,&var); berechnen(&var,KonCString,&var,(struct Konstanten *)Konstantenstart,&MatheFehler); Set_Konst_P(Konstantenstart,3,&var); berechnen(&var,KonDString,&var,(struct Konstanten *)Konstantenstart,&MatheFehler); Set_Konst_P(Konstantenstart,4,&var); } /* Erneuert SubMenuTexte */ VOID UpdateMenuText(VOID) { /* Füllt die SubMenuTitel mit den aktuellen Funktionsdefinitionen */ USHORT i; ClearMenuStrip(Window); /* Menuverknüpfung aufheben */ for(i=0;i<=9;i++) { left(SubMenuTitle[i],Formeln[i],14L); /* Ans Ziel kopieren */ } SetMenuStrip(Window,Menu); /* Wieder verknüpfen */ } VOID SetRXOffset(VOID) { LONG dx,dy; if(YOffset<0)YOffset=0; if(XOffset<0)XOffset=0; if(YOffset>(MAXPIXELY-YSCREEN))YOffset=MAXPIXELY-YSCREEN; if(XOffset>(1000-640))XOffset=1000-640; dx=XOffset-(layer->Scroll_X); dy=YOffset-(layer->Scroll_Y); /* Mit der Abfrage geht es schneller. Auch ein ScrollLayer(..,..,0,0) */ /* braucht relativ viel Zeit. */ if(dx||dy)ScrollLayer(layerinfo,layer,dx,dy); } VOID TastaturAbfrage(VOID) { static short add=1; switch(msgInfo.code) { case 69: { /* ESC = Ursprung */ XOffset=YOffset=0; break; } case 76: { /* Cursor up */ YOffset-=add; goto Einsprung; } case 77: { /* Cursor down */ YOffset+=add; goto Einsprung; } case 78: { /* Cursor right */ XOffset+=add; goto Einsprung; } case 79: { /* Cursor left */ XOffset-=add; Einsprung: add++; break; } case 204: case 205: case 206: case 207: { /* Damit nicht zu schnell gescrollt wird... */ add=1; } } SetRXOffset(); if(add>10)add=10; } VOID Loeschen(VOID) { SetRast(RastPort,0); /* Koordinatenkreuz beim nächsten Mal neu zeichnen */ KoordinatenKreuz_gezeichnet=FALSE; ScrollLayer(layerinfo,layer,(LONG)-(layer->Scroll_X),(LONG)-(layer->Scroll_Y)); }