home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
449a.lha
/
Plotter
/
src
/
Plot.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-02
|
21KB
|
615 lines
/********************************************************************/
/**** ****/
/**** ****/
/**** 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 <exec/types.h>
#include <proto/tool.h>
#include "Plotter.h"
#endif
#include <string.h>
#include <devices/printer.h>
#include <intuition/intuitionbase.h>
#include <graphics/regions.h>
#include <proto/mathieeedoubbas.h>
#include <proto/mathieeedoubtrans.h>
#include <proto/layers.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <exec/memory.h>
#include <exec/tasks.h>
#include <libraries/dosextens.h>
#include <dos.h>
/* 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<<Window->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));
}