// WAVES.C - Program to draw summations of sinewaves under user control #include #include #include #include #include "n:/course/elec/include/gfxlib1.h" // define number of data points to calculate (= no of pixels on graphs) #define DATAPOINTS 460 // main linked-list structure made global typedef struct wave_parameters { double amplitude; double frequency; double phase; struct wave_parameters *next; struct wave_parameters *previous; } WAVE; // function to draw axes and other stuff on the screen void draw_screen(void) { cleardevice(); // clear the screen // draw screen divisions, in green setcolor(BLUE); line(0,240,640,240); line(500,0,500,480); // draw axes setcolor(YELLOW); line(20,120,480,120); line(20,10,20,230); line(20,360,480,360); line(20,250,20,469); // Write graph labels and control panel options setcolor(WHITE); outtextxy(200,5, "Current Wave:"); outtextxy(200,245, "Sum of all waves:"); outtextxy(510,245, "Control Panel"); outtextxy(510,260, "A= add wave"); outtextxy(510,280, "D= delete wave"); outtextxy(510,300, "E= edit wave"); outtextxy(510,320, "N= next wave"); outtextxy(510,340, "P= previous wave"); outtextxy(510,450, "Q= quit program"); return; } void print_wave_parameters(WAVE *current, char title[20]) { char tempstring[40]; // clear the "wave parameters" area of the screen, using a flood fill setfillstyle(SOLID_FILL,BLACK); floodfill(510,20,BLUE); setcolor(WHITE); outtextxy(510,5,title); sprintf(tempstring,"Amplitude=%.2lf", current->amplitude); outtextxy(510,40, tempstring); sprintf(tempstring,"Frequency=%.2lf", current->frequency); outtextxy(510,60, tempstring); sprintf(tempstring,"Phase=%.2lf", current->phase); outtextxy(510,80, tempstring); return; } void add_wave(WAVE **first, WAVE **current) { WAVE *new_wave; WAVE *tempstore; new_wave=malloc(sizeof(WAVE)); new_wave->amplitude=0; new_wave->frequency=0; new_wave->phase=0; new_wave->next=NULL; new_wave->previous=NULL; if (*first==NULL) { *first=new_wave; *current=new_wave; return; } tempstore=NULL; if (current!=NULL) { tempstore=(*current)->next; } (*current)->next=new_wave; new_wave->next=tempstore; if (new_wave->next) new_wave->next->previous=new_wave; new_wave->previous=(*current); (*current)=new_wave; return; } /* graphical_input_number allows the user to enter numbers whilst in graphics mode: it takes a string array and x and y co-ordinates; and returns the double-precision floating-point value entered. */ double graphical_input_number(char* string,int xpos,int ypos) { char tempstring[40],kbchar,kbstring[4], numberstring[40]; double return_val; strcpy(tempstring,string); outtextxy(xpos,ypos,tempstring); /* get characters from keyboard, if they're valid, add to string and print to screen */ do { kbchar=getch(); if (isdigit(kbchar) || kbchar=='.') { sprintf(kbstring,"%c",kbchar); strcat(tempstring, kbstring); } outtextxy(xpos,ypos,tempstring); } while (kbchar!=13); strcpy(numberstring,tempstring+strlen(string)); return_val=atof(numberstring); // convert string to floating-point number return(return_val); } void edit_wave(WAVE *current) { print_wave_parameters(current,"Editing wave"); setcolor(RED); outtextxy(510,100,"New values:"); current->amplitude=graphical_input_number("A=",510,125); current->frequency=graphical_input_number("F=",510,145); current->phase=graphical_input_number("P=",510,165); setcolor(WHITE); return; } void delete_wave(WAVE **first, WAVE **current) { WAVE *item; item=*current; if (item==NULL) return; if (item->next ==NULL) { // end of list (*current)=item->previous; (*current)->next=NULL; if (item->previous==NULL) { // only item in list (*first)=(*current)=NULL; } } else if (item->previous == NULL) { // start of list (*current)=item->next; (*current)->previous=NULL; (*first)=(*current); } else { item->previous->next=item->next; item->next->previous=item->previous; (*current)=item->next; } free(item); return; } double calculate_yval(WAVE *wave_data, double xval, double xscale) { double return_val; // formula is A*cos(2*pi*F*t+P) NB- xval is normalised to give t between 0 and 1 return_val=wave_data->amplitude * cos((2 * M_PI * wave_data->frequency * xval / xscale) + (wave_data->phase / 180 * M_PI)); return(return_val); } double findscalefactor(WAVE *first) { WAVE *this_wave; double lowfreq=HUGE_VAL; this_wave=first; while (this_wave) { if (this_wave->frequencyfrequency>0) lowfreq=this_wave->frequency; this_wave=this_wave->next; } return(0.5*lowfreq*DATAPOINTS); } void calculate_single(WAVE *first, WAVE *current, double *single_wave) { int i; double xscale; if (current->frequency==0) return; xscale=findscalefactor(first); for(i=0; ifrequency==0) { this_wave=this_wave->next; continue;} for(i=0; inext; } } void plot_waves(double *single_wave, double *total_wave, WAVE *first) { int i; double plotx,ploty; double maxval=0; double xscale=0; double lowfreq=0; double time=0; char label[20]; xscale=findscalefactor(first); lowfreq=2*xscale/DATAPOINTS; time=1/lowfreq; for(i=0; i0) lineto(plotx, ploty); else moveto(plotx, ploty); } setcolor(WHITE); moveto(20,360); setcolor(GREEN); for(i=0; i0) lineto(plotx, ploty); else moveto(plotx, ploty); } setcolor(WHITE); sprintf(label, "%2.2E", maxval); outtextxy(5,10, label); outtextxy(5,120, "0"); outtextxy(5,250, label); outtextxy(5,360,"0"); sprintf(label, "%2.2E", time); outtextxy(DATAPOINTS/2,125, label); outtextxy(DATAPOINTS/2,365, label); sprintf(label, "%2.2E", time*2); outtextxy(DATAPOINTS,125, label); outtextxy(DATAPOINTS,365, label); } // main function int main(void) { WAVE *first=NULL; WAVE *current=NULL; char keypress; double single_wave[DATAPOINTS]; double total_wave[DATAPOINTS]; graphics_on(); add_wave(&first, ¤t); draw_screen(); print_wave_parameters(current, "Wave parameters"); do { //printf("F=%lf C=%lf\n",first->frequency, current->frequency); keypress=getch(); switch(keypress) { case 'a': case 'A': add_wave(&first, ¤t); edit_wave(current);break; case 'e': case 'E': edit_wave(current); break; case 'n': case 'N': if(current->next) current=current->next; break; case 'p': case 'P': if(current->previous) current=current->previous; break; case 'd': case 'D': delete_wave(&first, ¤t); break; } draw_screen(); if (current!=NULL && first!=NULL) { print_wave_parameters(current, "Wave parameters"); if (current->frequency!=0) { calculate_single(first, current, single_wave); calculate_total(first, total_wave); plot_waves(single_wave, total_wave, first); } } } while (keypress!='q' && keypress!='Q'); graphics_off(); return(0); }