plloop

start event loop

parametertypeunitsdescription
--void--
returns:void

Description

plloop, if the plotter driver is X, starts an event loop, testing whether a key or a mouse button was hit. If so, plevent is called, with information about the key that was hit and the current position of the mouse pointer. The user is responsible for delivering the plevent routine. See plevent. If the plotter driver is PostScript (PS or PSL) then plloop is equivalent to calling pldraw and plend. The user is responsible for supplying the pldraw-routine. This facility has been built in for users who want to temporarily convert an X-windows program into a PostScript plotting program without having to make it dynamically switchable .

Examples

The following program is a relatively simple example of the use of plloop, yet it is very illustrative for many features of simplot. It plots MIRA-fractals for which the user can change the parameters interactively. The program sets up a loop recognizing several events:
F1
shows help information about the key recognized
q
quits the program
p
plots the current fractal to the plotter
0-9.-
these keys enter a number. The current number becomes visible in the top centre of the window
n
set the number of iterations to the current number and redraws the fractal
a
sets fractal parameter a to the current number and draws the new fractal
b
sets fractal parameter b to the current number and draws the new fractal
mouse
left button may be pressed and dragged to expand a subrectangle
mouse
right button undoes the expansion, returning the fractal to its original dimensions
mouse
middle button displays two crosshairs, annotated with the x,y position of their intersection
The following page shows the initial plot (a=0.4, b=0.999).
// plloop example - basic X-windows program plotting fractals

#include <stdio.h>
#include <simplot.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#define NONE 0
#define EXPANDING 1
#define MARKING 2
#define BW 16
#define SIZE 150

float number=0.,a=.40002,b=.999;
//float number=0.,a=.399,b=.999;
float ymin=-8,ymax=8,xmin=-8,xmax=8;
float xmn=-8,ymn=-8,xmx=8,ymx=8;
float xl=SIZE,yl=SIZE;
int num=100000,mode=NONE;
float dot=.3;

void pldraw(void) {
   int i;
   double w,x,y,z;
   float c;
   if (plget(PLOTTER)==X)
      plpage();      // clear the window
   plaxes(xmn,ymn,xmx,ymx,xl,yl,"X","Y","MIRA - fractal (F1=help)");
   if (plget(PLOTTER)!=X)
      plframe(5,3);
   plset(RECTFILL,TRUE);
   plrect(xmn,ymn,xmx,ymx);
   plset(RECTFILL,FALSE);

   x=12;
   y=0;
   c=2*(1-a);
   w=a*x+c*x*x/(1+x*x);
   if (plget(PLOTTER)==X)
      plcolor(Red);
   for (i=1;i<num;i++) {                 // plot the fractal
      z=x;
      x=b*y+w;
      w=a*x+c*x*x/(1+x*x);
      y=w-z;
      if (x<xmn)
         continue;
      if (x>xmx)
         continue;
      if (y<ymn)
         continue;
      if (y>ymx)
         continue;
      pldot(x,y,dot);
   }
   plcolor(Blue);
   plmess("MIRA fractal  %d iterations  a=%g  b=%g\n",num,a,b);
   plcolor(Black);
}

void expand(float xmi, float ymi, float xma, float yma)
// expand a rectangle opened with the mouse
{ xmn=xmi;
   ymn=ymi;
   xmx=xma;
   ymx=yma;
   pldraw();
}

void unexpand(void) {
   expand(xmin,ymin,xmax,ymax);
}

void plevent(float xpointer,float ypointer,int key) {
   static int numpos=0,help=TRUE;
   static char numstring[100]="";
   int toplotter=FALSE;

   // for non-mouse events look at key down only:
   if (!plget(EVENT_BUTTON))
      if (key<0)
         return;

   switch(key) {
      case 'a':
         a=number;
         number=numpos=0;
         unexpand();
         break;
      case 'b':
         b=number;
         number=numpos=0;
         unexpand();
         break;
      case 'd':
         dot=number;
         number=numpos=0;
         pldraw();
         break;
      case 'n':
         num=(int)number;
         number=numpos=0;
         pldraw();
         break;
      case F1:    // F1 function key: help
         if (!help)
            pldraw();
         else {
            plpage();
            plu(xmn,ymx);
            plformat(.5,-1, "F1 : help (press again to continue)\n"
                     "[0-9.-] : build number\n"
                     "a : set parameter (now %g) a to current number\n"
                     "b : set parameter (now %g) a to current number\n"
                     "d : set dotsize in mm\n"
                     "n : set number of iterations (now %d)\n"
                     "P : print to plotfile and plotter\n"
                     "p : print to plotfile only\n"
                     "q : quit\n"
                     "Mouse:\n"
                     "Leftdrag : expand\n"
                     "Right    : unexpand\n"
                     "Middle   : track position\n",a,b,num);
         }
         help=!help;
         break;
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5': // build number
      case '6':
      case '7':
      case '8':
      case '9':
      case '-':
      case '.':
         numstring[numpos++]=key;
         numstring[numpos]=0;
         sscanf(numstring,"%g",&number);
         plmess("current number: %g",number);
         return;
      case Delete:
         if (numpos)
            numstring[--numpos]=0;
         sscanf(numstring,"%g",&number);
         plmess("current number: %g",number);
         return;
      case Escape:
         number=numpos=0;
         plmess("");
         break;
      case 'P':                           // plot to plotter
         toplotter=TRUE;
      case 'p':				// plot to file only
         plmess("");
         plend();
         plinit(PS,"plloop",A4,30,30,"","");
         pldraw();
         plend();
         if (toplotter)
            system("plot plloop&");
         plinit(X,"",SIZE+20,SIZE+20,10,10,"","");
         plloop();
         break;
      case 'q':                           // Quit
         plend();
         exit(0);
      case MouseLeftDown:                 // initialize rectangle
         plmess("expanding");
         mode=EXPANDING;
         xmn=xpointer>xmin?xpointer:xmin;
         ymn=ypointer>ymin?ypointer:ymin;
         xmx=xmn;
         ymx=ymn;
         plset(PLOTMODE,GXxor);
         break;
      case MouseLeftUp:                   // expand part in rect
         plset(PLOTMODE,GXcopy);
         if ((xmx-xmn)*plget(XU2P)<10||(ymx-ymn)*plget(YU2P)<10)
            unexpand();
         else
            expand(xmn,ymn,xmx,ymx);
         mode=NONE;
         break;
      case MouseMiddleDown:
         plhairs(xpointer,ypointer,TRUE,TRUE);
         mode=MARKING;
         break;
      case MouseMiddleUp:
         mode=NONE;
         plhairs(xpointer,ypointer,FALSE,FALSE);   // erase last hairs
         plmess("MIRA fractal  %d iterations  a=%g  b=%g\n",num,a,b);
         break;
      case MouseRightUp:                  	// restore full plot
         unexpand();
         break;
      case MouseDrag:                             // change rectangle
         if (xpointer<xmn)
            break;
         if (ypointer<ymn)
            break;
         if (xpointer>xmax)
            break;
         if (ypointer>ymax)
            break;
         switch(mode) {
            case EXPANDING:
               plrect(xmn,ymn,xmx,ymx);              // replot previous rect, erasing it
               xmx=xpointer;
               ymx=ypointer;
               plrect(xmn,ymn,xmx,ymx);              // plot new rect
               break;
            case MARKING:
               plmess("x=%g y=%g",xpointer,ypointer);
               plhairs(xpointer,ypointer,TRUE,TRUE);
               break;
         }
         break;
   }
}

int main(int argc,char *argv[]) { // without an argument, just make a PostScript plotfile and quit
   // with an argument, run under X
   if (argc==1) {
      plinit(PS,"plloop",A4,50,50,"","");
      plset(PENDIA,1);
      plset(HEIGHT,5);
      plfcolor(Aquamarine);
      pldraw();
      plend();
   } else {
      plinit(X,"",SIZE+50,SIZE+50,25,25,"","");
      plset(HEIGHT,5);
      plset(PENDIA,.3);
      plfcolor(Aquamarine);
      plloop();
   }
   exit(0);
}

plloop

See also

plfill plfunc plevent