/********************************************************************/ /**** ****/ /**** ****/ /**** Program : BerechnungsRoutinen.c ****/ /**** ****/ /**** Version : 03.71 ****/ /**** ****/ /**** Erstversion : 14.08.1988 ****/ /**** ****/ /**** Letzte Änderung : 05.08.1990 ****/ /**** ****/ /**** Compiliert mit : siehe MAKEFILE ****/ /**** ****/ /**** Gelinkt mit : siehe MAKEFILE ****/ /**** ****/ /********************************************************************/ /**** ****/ /**** ****/ /**** Copyright by Rüdiger Dreier ****/ /**** ****/ /**** ****/ /********************************************************************/ /* Einbinden der Include-Files */ #ifdef DEBUG #include "Plotter.h" #include #endif #include #include #include #include #include #include #include LONG MatheFehler; char flagg; SHORT Genauigkeiten[3]= { 8,4,1 }; /* Funktion testet, ob ein Fehler aufgetreten ist */ VOID FehlerAbfrage(VOID) { /* Abfrage auf Mathe-Fehler */ if (MatheFehler) { request("OK","OK",BE_ERROR); } MatheFehler=0; } /* Zeichnet die n-te Ableitung der Funktion nr */ VOID __asm ZeichneFunktion(register __d0 USHORT nr, register __d1 int Ableitung) { USHORT ZEICHNEN=TRUE; double i,xalt,yalt,y; ULONG OldIDCMP; SHORT MaxXPos,Pos; LONG H; MaxXPos=(SHORT)(xx-Genauigkeiten[GE]); SetAPen(RastPort,FARBE1); /* Berechnet Position der x/y-Achse */ x0=Add(Mul(Div(Neg(xmn),Sub(xmp,xmn)),Flt(xx-1)),1.0); y0= Add(Mul(Div(ymp,Sub(ymp,ymn)),Flt(yy-1)),1.0); /* Bestimmt Zeichenmaßstab */ xm=Div(Flt(xx-1),Sub(xmp,xmn)); ym=Div(Flt(yy-1),Sub(ymp,ymn)); OldIDCMP=Window->IDCMPFlags; ModifyIDCMP(Window,MOUSEBUTTONS); if(!KoordinatenKreuz_gezeichnet)Loeschen(); SetAPen(RastPort,FARBE3); flagg=1; /* ersten Punkt nur setzen */ StartBlock=Init_Mem(Formeln[nr]); MatheFehler=Init_Block(StartBlock); MatheFehler|=PreCalc(StartBlock,Konstantenstart); if(MatheFehler) { FehlerAbfrage(); /* Es ist ein Fehler aufgetreten ! */ } else { yalt=FunktionsWert(nr,xmn,Ableitung); if(StartBlock->Fehler)flagg=2; /* NICHT MatheFehler */ xalt=xmn; Verbinden(xalt,yalt); for (Pos=1+Genauigkeiten[GE];Pos<=MaxXPos;Pos+=Genauigkeiten[GE]) { i=Div(Sub(Flt(Pos),x0),xm); /* Berechnet für einige x-Werte den Funktionswert und zeichnet ihn */ y=FunktionsWert(nr,i,Ableitung); if(StartBlock->Fehler) { flagg=2; } Plotte(nr,xalt,i,yalt,y,0,Ableitung); /* Zeichnet den Punkt */ xalt=i; yalt=y; /* Abfrage auf Unterbrechnung */ H=EventAbfrage(Window,&msgInfo); if (H==MOUSEBUTTONS) { if(request(BE_JA,BE_NEIN,BE_QUEST)) { Pos=MaxXPos; ZEICHNEN=FALSE; } } } if(ZEICHNEN) { y=FunktionsWert(nr,xmp,Ableitung); Plotte(nr,xalt,xmp,yalt,y,0,Ableitung); /* Zeichnet den letzten Punkt */ } /* Alles, was in FARBE3 über den Rand hinausgezeichnet wurde, wird hier gelöscht.*/ /* Dabei wird auch alles FARBE1 gelöscht. Beim Überschreiben wird darauf */ /* geachtet, daß FARBE3 nicht beeinträchtigt wird. Es wird nur ein Bit in der */ /* ersten BitPlane gesetzt, wenn dort FARBE3 erscheinen soll. Die zweite */ /* BitPlane wird nicht berührt. */ WaitBlit(); Forbid(); SetAPen(RastPort,FARBE0); RectFill(RastPort,0,yy+Abstand+1,999,299); RectFill(RastPort,0,0,1000,Abstand); SetAPen(RastPort,FARBE1); /* Und neu zeichnen */ SetWrMsk(RastPort,1); if(Cmp(x0,0.0)>=0 && (Fix(x0)<(xx))) { Line(x0,1.0,x0,Flt(yy)); } if(Cmp(y0,0.0)>=0 && Cmp(y0,Flt(yy))<1) { Line(1.0,y0,Flt(xx),y0); } zeichne(); SetWrMsk(RastPort,0xff); Permit(); KoordinatenKreuz_gezeichnet=TRUE; FehlerAbfrage(); /* Ist ein Fehler aufgetreten ? */ } while(H=EventAbfrage(Window,&msgInfo)); ModifyIDCMP(Window,OldIDCMP); Free_Block(StartBlock); } /* Arbeitet rekursiv, bis y-Abstand zweier Punkte klein genug */ VOID Plotte(nr,xl,xr,yl,yr,st,Ableitung) unsigned short nr; double xl,xr,yr,yl; int st,Ableitung; { double x,y,a; SHORT a1; long Sprung; /* GE liegt zwischen 1 und 3 */ Sprung=4-GE; a=Sub(yl,yr); if(Cmp(Abs(a),MAXLONG)==1) { a1=0; } else { a1=(abs(Fix(a))>Sprung); } /* Großer Sprung zwischen 2 Werten (z.B. Pole) */ if(a1) { /* Rekursionstiefe aufgrund der Zeichengenauigkeit */ if(st<=10 && Cmp(Min(yl,yr),Flt(yy))==-1 && Tst(Max(yr,yl))==1) { x=Div((Add(xl,xr)),2.0); /* x-Wert zwischen den beiden Stellen */ /* Berechnen des Funktionswertes */ y=FunktionsWert(nr,x,Ableitung); Plotte(nr,xl,x,yl,y,st+1,Ableitung); Plotte(nr,x,xr,y,yr,st+1,Ableitung); } else { flagg=1; /* 2 Punkte werden nicht verbunden */ /* z. B. 1/x bei x um 0 */ Verbinden(xr,yr); } } else { Verbinden(xr,yr); } } double FunktionsWert(nr,i,Ableitung) int Ableitung; unsigned short nr; double i; { double ywert; double y; switch(Ableitung) { case 0: { MatheFehler|=Calc_P(&ywert,StartBlock,&i); goto Einsprung_B1; } case 1: { double H1,H2,Help1; if(Ableitung==1) { Help1=(Add(i,deltah)); MatheFehler|=Calc_P(&H1,StartBlock,&Help1); MatheFehler|=Calc_P(&H2,StartBlock,&i); ywert=Div(Sub(H1,H2),deltah); Einsprung_B1: y=Sub(y0,Mul(ym,ywert)); break; } case 2: { Help1=Add(i,deltahh); H1=FunktionsWert(nr,i,1); H2=FunktionsWert(nr,Help1,1); ywert=Div(Sub(H1,H2),deltahh); y=Sub(y0,ywert); break; } } } return(y); } VOID Verbinden(xr,yr) double xr,yr; { xr=Add(x0,Mul(xm,xr)); if(Cmp(Abs(yr),MAXLONG)==-1) { /* Wenn zu zeichen (innerhalb Zeichenbereichs) */ switch(flagg) { /* 2 Punkte nicht verbinden */ case 1: { Pset(xr,yr); flagg=0; break; } case 2: { flagg=1; break; } case 0: { /* Zum nächsten Punkt zeichnen. Wenn Koordinaten wie bei Pset, dann */ /* wird nur ein Punkt gesetzt. */ DrawTo(xr,yr); break; } } } else { flagg=1; } } DOUBLE Max(a,b) DOUBLE a,b; { if(a>b) { return(a); } else { return(b); } } DOUBLE Min(a,b) DOUBLE a,b; { if(a>b) { return(b); } else { return(a); } } /* Hier kommen die Stub-Routinen, die für dieses Programm nicht */ /* gebraucht werden. Dadurch werden sie nicht angelinkt. */ VOID MemCleanup(VOID) { } VOID chkabort(VOID) { }