Annotation of OpenXM_contrib/pari-2.2/src/graph/plotport.c, Revision 1.1
1.1 ! noro 1: /* $Id: plotport.c,v 1.15 2001/03/26 13:52:07 karim Exp $
! 2:
! 3: Copyright (C) 2000 The PARI group.
! 4:
! 5: This file is part of the PARI/GP package.
! 6:
! 7: PARI/GP is free software; you can redistribute it and/or modify it under the
! 8: terms of the GNU General Public License as published by the Free Software
! 9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
! 10: ANY WARRANTY WHATSOEVER.
! 11:
! 12: Check the License for details. You should have received a copy of it, along
! 13: with the package; see the file 'COPYING'. If not, write to the Free Software
! 14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
! 15:
! 16: /*******************************************************************/
! 17: /* */
! 18: /* PLOT ROUTINES */
! 19: /* */
! 20: /*******************************************************************/
! 21: #include "pari.h"
! 22: #include "rect.h"
! 23:
! 24: extern void push_val(entree *ep, GEN a);
! 25: extern void pop_val(entree *ep);
! 26: extern void postdraw0(long *w, long *x, long *y, long lw);
! 27: extern void postdraw00(long *w, long *x, long *y, long lw, long scale);
! 28: extern void rectdraw0(long *w, long *x, long *y, long lw, long do_free);
! 29: static void PARI_get_psplot();
! 30:
! 31: static long current_color[NUMRECT];
! 32: PariRect **rectgraph = NULL;
! 33: PARI_plot pari_plot, pari_psplot;
! 34: long rectpoint_itype = 0;
! 35: long rectline_itype = 0;
! 36:
! 37: #define STRINGRECT (NUMRECT-2)
! 38: #define DRAWRECT (NUMRECT-1)
! 39:
! 40: #define PLOTH_NUMPOINTS 1000
! 41: #define PARAM_NUMPOINTS 1500
! 42: #define RECUR_NUMPOINTS 8
! 43:
! 44: #define RECUR_MAXDEPTH 10
! 45: #define RECUR_PREC 0.001
! 46: #define PARAMR_MAXDEPTH 10
! 47:
! 48: /********************************************************************/
! 49: /** **/
! 50: /** LOW-RES PLOT **/
! 51: /** **/
! 52: /********************************************************************/
! 53: #define ISCR 64
! 54: #define JSCR 22
! 55: #define BLANK ' '
! 56: #define ZERO1 ','
! 57: #define ZERO2 '-'
! 58: #define ZERO3 '`'
! 59: #define PICTZERO(j) ((j) % 3 ? ((j) % 3 == 2 ? ZERO3 : ZERO2) : ZERO1)
! 60: #define YY '|'
! 61: #define XX_UPPER '\''
! 62: #define XX_LOWER '.'
! 63: #define FF1 '_'
! 64: #define FF2 'x'
! 65: #define FF3 '"'
! 66: #define PICT(j) ((j) % 3 ? ((j) % 3 == 2 ? FF3 : FF2) : FF1)
! 67:
! 68: static char *
! 69: dsprintf9(double d, char *buf)
! 70: {
! 71: int i = 10;
! 72:
! 73: while (--i >= 0) {
! 74: sprintf(buf, "%9.*g", i, d);
! 75: if (strlen(buf) <= 9) return buf;
! 76: }
! 77: return buf; /* Should not happen? */
! 78: }
! 79:
! 80: typedef unsigned char screen[ISCR+1][JSCR+1];
! 81:
! 82: static void
! 83: fill_gap(screen scr, long i, int jnew, int jpre)
! 84: {
! 85: int mid, i_up, i_lo, up, lo;
! 86:
! 87: if (jpre < jnew - 2) {
! 88: up = jnew - 1; i_up = i;
! 89: lo = jpre + 1; i_lo = i - 1;
! 90: } else if (jnew < jpre - 2) {
! 91: up = jpre - 1; i_up = i - 1;
! 92: lo = jnew + 1; i_lo = i;
! 93: } else return; /* if gap < 2, leave it as it is. */
! 94:
! 95: mid = (jpre+jnew)/2;
! 96: if (mid>JSCR) mid=JSCR; else if (mid<0) mid=0;
! 97: if (lo<0) lo=0;
! 98: if (lo<=JSCR) while (lo <= mid) scr[i_lo][lo++] = ':';
! 99: if (up>JSCR) up=JSCR;
! 100: if (up>=0) while (up > mid) scr[i_up][up--] = ':';
! 101: }
! 102:
! 103: #define QUARK ((char*)NULL) /* Used as a special-case */
! 104: static GEN quark_gen;
! 105:
! 106: #define READ_EXPR(s) ((s)==QUARK? quark_gen : lisexpr(s))
! 107:
! 108: void
! 109: plot(entree *ep, GEN a, GEN b, char *ch,GEN ysmlu,GEN ybigu, long prec)
! 110: {
! 111: long av = avma, av2,limite,jz,j,i,sig;
! 112: int jnew, jpre = 0; /* for lint */
! 113: GEN p1,p2,ysml,ybig,x,diff,dyj,dx,y[ISCR+1];
! 114: screen scr;
! 115: char buf[80], z;
! 116:
! 117: sig=gcmp(b,a); if (!sig) return;
! 118: if (sig<0) { x=a; a=b; b=x; }
! 119: x = cgetr(prec); gaffect(a,x); push_val(ep, x);
! 120: for (i=1; i<=ISCR; i++) y[i]=cgetr(3);
! 121: p1 = gdivgs(gsub(b,a), ISCR-1);
! 122: dx = cgetr(prec); gaffect(p1, dx);
! 123: ysml=gzero; ybig=gzero;
! 124: for (j=1; j<=JSCR; j++) scr[1][j]=scr[ISCR][j]=YY;
! 125: for (i=2; i<ISCR; i++)
! 126: {
! 127: scr[i][1] = XX_LOWER;
! 128: scr[i][JSCR]=XX_UPPER;
! 129: for (j=2; j<JSCR; j++) scr[i][j]=BLANK;
! 130: }
! 131: av2=avma; limite=stack_lim(av2,1);
! 132: for (i=1; i<=ISCR; i++)
! 133: {
! 134: gaffect(READ_EXPR(ch),y[i]);
! 135: if (gcmp(y[i],ysml)<0) ysml=y[i];
! 136: if (gcmp(y[i],ybig)>0) ybig=y[i];
! 137: x = addrr(x,dx);
! 138: if (low_stack(limite, stack_lim(av2,1)))
! 139: {
! 140: long tetpil=avma;
! 141: if (DEBUGMEM>1) err(warnmem,"plot");
! 142: x = gerepile(av2,tetpil,rcopy(x));
! 143: }
! 144: ep->value = (void*)x;
! 145: }
! 146: if (ysmlu) ysml=ysmlu;
! 147: if (ybigu) ybig=ybigu;
! 148: avma=av2; diff=gsub(ybig,ysml);
! 149: if (gcmp0(diff)) { ybig=gaddsg(1,ybig); diff=gun; }
! 150: dyj = gdivsg((JSCR-1)*3+2,diff);
! 151: jz = 3-gtolong(gmul(ysml,dyj));
! 152: av2=avma; z = PICTZERO(jz); jz = jz/3;
! 153: for (i=1; i<=ISCR; i++)
! 154: {
! 155: if (0<=jz && jz<=JSCR) scr[i][jz]=z;
! 156: j = 3+gtolong(gmul(gsub(y[i],ysml),dyj));
! 157: jnew = j/3;
! 158: if (i > 1) fill_gap(scr, i, jnew, jpre);
! 159: if (0<=jnew && jnew<=JSCR) scr[i][jnew] = PICT(j);
! 160: avma = av2;
! 161: jpre = jnew;
! 162: }
! 163: p1=cgetr(3); gaffect(ybig,p1); pariputc('\n');
! 164: pariputsf("%s ", dsprintf9(rtodbl(p1), buf));
! 165: for (i=1; i<=ISCR; i++) pariputc(scr[i][JSCR]);
! 166: pariputc('\n');
! 167: for (j=(JSCR-1); j>=2; j--)
! 168: {
! 169: pariputs(" ");
! 170: for (i=1; i<=ISCR; i++) pariputc(scr[i][j]);
! 171: pariputc('\n');
! 172: }
! 173: p1=cgetr(3); gaffect(ysml,p1);
! 174: pariputsf("%s ", dsprintf9(rtodbl(p1), buf));
! 175: for (i=1; i<=ISCR; i++) pariputc(scr[i][1]);
! 176: pariputc('\n');
! 177: p1=cgetr(3); gaffect(a,p1);
! 178: p2=cgetr(3); gaffect(b,p2);
! 179: pariputsf("%10s%-9.7g%*.7g\n"," ",rtodbl(p1),ISCR-9,rtodbl(p2));
! 180: pop_val(ep); avma=av;
! 181: }
! 182:
! 183: /********************************************************************/
! 184: /** **/
! 185: /** RECTPLOT FUNCTIONS **/
! 186: /** **/
! 187: /********************************************************************/
! 188: void
! 189: init_graph()
! 190: {
! 191: int n;
! 192:
! 193: rectgraph = (PariRect**) gpmalloc(sizeof(PariRect*)*NUMRECT);
! 194: for (n=0; n<NUMRECT; n++)
! 195: {
! 196: PariRect *e = (PariRect*) gpmalloc(sizeof(PariRect));
! 197:
! 198: e->head = e->tail = NULL;
! 199: e->sizex = e->sizey = 0;
! 200: current_color[n] = DEFAULT_COLOR;
! 201: rectgraph[n] = e;
! 202: }
! 203: }
! 204:
! 205: void
! 206: free_graph()
! 207: {
! 208: int i;
! 209:
! 210: for (i=0; i<NUMRECT; i++)
! 211: {
! 212: PariRect *e=rectgraph[i];
! 213:
! 214: if (RHead(e)) killrect(i);
! 215: free((void *)e);
! 216: }
! 217: free((void *)rectgraph);
! 218: }
! 219:
! 220: static PariRect *
! 221: check_rect(long ne)
! 222: {
! 223: if (!GOODRECT(ne))
! 224: err(talker,"not an rplot vector type in graphic function");
! 225: return rectgraph[ne];
! 226: }
! 227:
! 228: static PariRect *
! 229: check_rect_init(long ne)
! 230: {
! 231: PariRect *e = check_rect(ne);
! 232: if (!RHead(e))
! 233: err(talker,"you must initialize the rectwindow first");
! 234: return e;
! 235: }
! 236:
! 237: void
! 238: initrect_gen(long ne, GEN x, GEN y, long flag)
! 239: {
! 240: long xi, yi;
! 241: if (flag) {
! 242: double xd = gtodouble(x), yd = gtodouble(y);
! 243:
! 244: PARI_get_plot(0);
! 245: xi = w_width - 1; yi = w_height - 1;
! 246: if (xd)
! 247: xi = (long)(xd*xi + 0.5);
! 248: if (yd)
! 249: yi = (long)(yd*yi + 0.5);
! 250: } else {
! 251: xi = itos(x); yi = itos(y);
! 252: if (!xi || !yi)
! 253: PARI_get_plot(0);
! 254: if (!xi)
! 255: xi = w_width - 1;
! 256: if (!yi)
! 257: yi = w_height - 1;
! 258: }
! 259: initrect(ne, xi, yi);
! 260: }
! 261:
! 262: void
! 263: initrect(long ne, long x, long y)
! 264: {
! 265: PariRect *e;
! 266: RectObj *z;
! 267:
! 268: if (x<=1 || y<=1) err(talker,"incorrect dimensions in initrect");
! 269: e = check_rect(ne); if (RHead(e)) killrect(ne);
! 270:
! 271: z = (RectObj*) gpmalloc(sizeof(RectObj));
! 272: RoNext(z) = NULL;
! 273: RoType(z) = ROt_NULL;
! 274: RHead(e)=RTail(e)=z;
! 275: RXsize(e)=x; RYsize(e)=y;
! 276: RXcursor(e)=0; RYcursor(e)=0;
! 277: RXscale(e)=1; RXshift(e)=0;
! 278: RYscale(e)=1; RYshift(e)=0;
! 279: RHasGraph(e) = 0;
! 280: }
! 281:
! 282: GEN
! 283: rectcursor(long ne)
! 284: {
! 285: PariRect *e = check_rect_init(ne);
! 286: GEN z=cgetg(3,t_VEC);
! 287:
! 288: z[1] = lstoi((long)RXcursor(e)); z[2] = lstoi((long)RYcursor(e));
! 289: return z;
! 290: }
! 291:
! 292: static void
! 293: rectscale0(long ne, double x1, double x2, double y1, double y2)
! 294: {
! 295: PariRect *e = check_rect_init(ne);
! 296: double p2,p3;
! 297:
! 298: p2 = RXshift(e) + RXscale(e) * RXcursor(e);
! 299: p3 = RYshift(e) + RYscale(e) * RYcursor(e);
! 300: RXscale(e) = RXsize(e)/(x2-x1); RXshift(e) = -x1*RXscale(e);
! 301: RYscale(e) = RYsize(e)/(y1-y2); RYshift(e) = -y2*RYscale(e);
! 302: RXcursor(e) = (p2 - RXshift(e)) / RXscale(e);
! 303: RYcursor(e) = (p3 - RYshift(e)) / RYscale(e);
! 304: }
! 305:
! 306: void
! 307: rectscale(long ne, GEN x1, GEN x2, GEN y1, GEN y2)
! 308: {
! 309: rectscale0(ne, gtodouble(x1), gtodouble(x2), gtodouble(y1), gtodouble(y2));
! 310: }
! 311:
! 312: /*
! 313: * #ifdef LONG_IS_64BIT
! 314: * # define MAXDTOL 9223372036854775807.0
! 315: * #else
! 316: * # define MAXDTOL 2147483647.0
! 317: * #endif
! 318: *
! 319: *
! 320: * long
! 321: * DTOL(double t)
! 322: * {
! 323: * if (fabs(t) > MAXDTOL) err(affer2);
! 324: * return (long)t;
! 325: * }
! 326: */
! 327:
! 328: static void
! 329: rectmove0(long ne, double x, double y, long relative)
! 330: {
! 331: PariRect *e = check_rect_init(ne);
! 332: RectObj *z = (RectObj*) gpmalloc(sizeof(RectObj1P));
! 333:
! 334: if (relative)
! 335: { RXcursor(e) += x; RYcursor(e) += y; }
! 336: else
! 337: { RXcursor(e) = x; RYcursor(e) = y; }
! 338: RoNext(z) = 0; RoType(z) = ROt_MV;
! 339: RoMVx(z) = RXcursor(e) * RXscale(e) + RXshift(e);
! 340: RoMVy(z) = RYcursor(e) * RYscale(e) + RYshift(e);
! 341: if (!RHead(e)) RHead(e)=RTail(e)=z;
! 342: else { RoNext(RTail(e))=z; RTail(e)=z; }
! 343: }
! 344:
! 345: void
! 346: rectmove(long ne, GEN x, GEN y)
! 347: {
! 348: rectmove0(ne,gtodouble(x),gtodouble(y),0);
! 349: }
! 350:
! 351: void
! 352: rectrmove(long ne, GEN x, GEN y)
! 353: {
! 354: rectmove0(ne,gtodouble(x),gtodouble(y),1);
! 355: }
! 356:
! 357: void
! 358: rectpoint0(long ne, double x, double y,long relative) /* code = ROt_MV/ROt_PT */
! 359: {
! 360: PariRect *e = check_rect_init(ne);
! 361: RectObj *z = (RectObj*) gpmalloc(sizeof(RectObj1P));
! 362:
! 363: if (relative)
! 364: { RXcursor(e) += x; RYcursor(e) += y; }
! 365: else
! 366: { RXcursor(e) = x; RYcursor(e) = y; }
! 367: RoNext(z)=0;
! 368: RoPTx(z) = RXcursor(e)*RXscale(e) + RXshift(e);
! 369: RoPTy(z) = RYcursor(e)*RYscale(e) + RYshift(e);
! 370: RoType(z) = ( DTOL(RoPTx(z)) < 0
! 371: || DTOL(RoPTy(z)) < 0 || DTOL(RoPTx(z)) > RXsize(e)
! 372: || DTOL(RoPTy(z)) > RYsize(e) ) ? ROt_MV : ROt_PT;
! 373: if (!RHead(e)) RHead(e)=RTail(e)=z;
! 374: else { RoNext(RTail(e))=z; RTail(e)=z; }
! 375: RoCol(z)=current_color[ne];
! 376: }
! 377:
! 378: void
! 379: rectpoint(long ne, GEN x, GEN y)
! 380: {
! 381: rectpoint0(ne,gtodouble(x),gtodouble(y),0);
! 382: }
! 383:
! 384: void
! 385: rectrpoint(long ne, GEN x, GEN y)
! 386: {
! 387: rectpoint0(ne,gtodouble(x),gtodouble(y),1);
! 388: }
! 389:
! 390: void
! 391: rectcolor(long ne, long color)
! 392: {
! 393: check_rect(ne);
! 394: if (!GOODCOLOR(color)) err(talker,"This is not a valid color");
! 395: current_color[ne]=color;
! 396: }
! 397:
! 398: void
! 399: rectline0(long ne, double gx2, double gy2, long relative) /* code = ROt_MV/ROt_LN */
! 400: {
! 401: double dx,dy,dxy,xmin,xmax,ymin,ymax,x1,y1,x2,y2;
! 402: PariRect *e = check_rect_init(ne);
! 403: RectObj *z = (RectObj*) gpmalloc(sizeof(RectObj2P));
! 404: const double c = 1 + 1e-10;
! 405:
! 406: x1 = RXcursor(e)*RXscale(e) + RXshift(e);
! 407: y1 = RYcursor(e)*RYscale(e) + RYshift(e);
! 408: if (relative)
! 409: { RXcursor(e)+=gx2; RYcursor(e)+=gy2; }
! 410: else
! 411: { RXcursor(e)=gx2; RYcursor(e)=gy2; }
! 412: x2 = RXcursor(e)*RXscale(e) + RXshift(e);
! 413: y2 = RYcursor(e)*RYscale(e) + RYshift(e);
! 414: xmin = max(min(x1,x2),0); xmax = min(max(x1,x2),RXsize(e));
! 415: ymin = max(min(y1,y2),0); ymax = min(max(y1,y2),RYsize(e));
! 416: dxy = x1*y2 - y1*x2; dx = x2-x1; dy = y2-y1;
! 417: if (dy)
! 418: {
! 419: if (dx*dy<0)
! 420: { xmin = max(xmin,(dxy+RYsize(e)*dx)/dy); xmax=min(xmax,dxy/dy); }
! 421: else
! 422: { xmin=max(xmin,dxy/dy); xmax=min(xmax,(dxy+RYsize(e)*dx)/dy); }
! 423: }
! 424: if (dx)
! 425: {
! 426: if (dx*dy<0)
! 427: { ymin=max(ymin,(RXsize(e)*dy-dxy)/dx); ymax=min(ymax,-dxy/dx); }
! 428: else
! 429: { ymin=max(ymin,-dxy/dx); ymax=min(ymax,(RXsize(e)*dy-dxy)/dx); }
! 430: }
! 431: RoNext(z)=0;
! 432: RoLNx1(z) = xmin; RoLNx2(z) = xmax;
! 433: if (dx*dy<0) { RoLNy1(z) = ymax; RoLNy2(z) = ymin; }
! 434: else { RoLNy1(z) = ymin; RoLNy2(z) = ymax; }
! 435: RoType(z) = (xmin>xmax*c || ymin>ymax*c) ? ROt_MV : ROt_LN;
! 436: if (!RHead(e)) RHead(e)=RTail(e)=z;
! 437: else { RoNext(RTail(e))=z; RTail(e)=z; }
! 438: RoCol(z)=current_color[ne];
! 439: }
! 440:
! 441: /* Given coordinates of ends of a line, and labels l1 l2 attached to the
! 442: ends, plot ticks where the label coordinate takes "round" values */
! 443:
! 444: static void
! 445: rectticks(PARI_plot *WW, long ne,
! 446: double dx1, double dy1, double dx2, double dy2,
! 447: double l1, double l2, long flags)
! 448: {
! 449: long dx,dy,dxy,dxy1,x1,y1,x2,y2,nticks,n,n1,dn;
! 450: double minstep, maxstep, step, l_min, l_max, minl, maxl, dl, dtx, dty, x, y;
! 451: double ddx, ddy;
! 452: const double mult[3] = { 2./1., 5./2., 10./5. };
! 453: PariRect *e = check_rect_init(ne);
! 454: int do_double = !(flags & TICKS_NODOUBLE);
! 455:
! 456: x1 = DTOL(dx1*RXscale(e) + RXshift(e));
! 457: y1 = DTOL(dy1*RYscale(e) + RYshift(e));
! 458: x2 = DTOL(dx2*RXscale(e) + RXshift(e));
! 459: y2 = DTOL(dy2*RYscale(e) + RYshift(e));
! 460: dx = x2 - x1;
! 461: dy = y2 - y1;
! 462: if (dx < 0) dx = -dx;
! 463: if (dy < 0) dy = -dy;
! 464: dxy1 = max(dx, dy);
! 465: if (WW) {
! 466: dx /= WW->hunit;
! 467: dy /= WW->vunit;
! 468: }
! 469: else {
! 470: PARI_get_plot(0);
! 471: dx /= h_unit;
! 472: dy /= v_unit;
! 473: }
! 474: dxy = (long)sqrt(dx*dx + dy*dy);
! 475: nticks = (long) ((dxy + 2.5)/4);
! 476: if (!nticks) return;
! 477:
! 478: /* Now we want to find nticks (or less) "round" numbers between l1 and l2.
! 479: For our purpose round numbers have "last significant" digit either
! 480: *) any;
! 481: *) even;
! 482: *) divisible by 5.
! 483: We need to choose which alternative is better.
! 484: */
! 485: if (l1 < l2)
! 486: l_min = l1, l_max = l2;
! 487: else
! 488: l_min = l2, l_max = l1;
! 489: minstep = (l_max - l_min)/(nticks + 1);
! 490: maxstep = 2.5*(l_max - l_min);
! 491: step = exp(log(10) * floor(log10(minstep)));
! 492: if (!(flags & TICKS_ENDSTOO)) {
! 493: double d = 2*(l_max - l_min)/dxy1; /* Two pixels off */
! 494:
! 495: l_min += d;
! 496: l_max -= d;
! 497: }
! 498: for (n = 0; ; n++) {
! 499: if (step >= maxstep) return;
! 500:
! 501: if (step >= minstep) {
! 502: minl = ceil(l_min/step);
! 503: maxl = floor(l_max/step);
! 504: if (minl <= maxl && maxl - minl + 1 <= nticks) {
! 505: nticks = (long) (maxl - minl + 1);
! 506: l_min = minl * step;
! 507: l_max = maxl * step; break;
! 508: }
! 509: }
! 510: step *= mult[ n % 3 ];
! 511: }
! 512: /* Where to position doubleticks, variants:
! 513: small: each 5, double: each 10 (n===2 mod 3)
! 514: small: each 2, double: each 10 (n===1 mod 3)
! 515: small: each 1, double: each 5 */
! 516: dn = (n % 3 == 2)? 2: 5;
! 517: n1 = ((long)minl) % dn; /* unused if do_double = FALSE */
! 518:
! 519: /* now l_min and l_max keep min/max values of l with ticks, and nticks is
! 520: the number of ticks to draw. */
! 521: if (nticks == 1) ddx = ddy = 0; /* unused: for lint */
! 522: else {
! 523: dl = (l_max - l_min)/(nticks - 1);
! 524: ddx = (dx2 - dx1) * dl / (l2 - l1);
! 525: ddy = (dy2 - dy1) * dl / (l2 - l1);
! 526: }
! 527: x = dx1 + (dx2 - dx1) * (l_min - l1) / (l2 - l1);
! 528: y = dy1 + (dy2 - dy1) * (l_min - l1) / (l2 - l1);
! 529: /* assume h_unit and v_unit form a square. For clockwise ticks: */
! 530: dtx = h_unit * dy/dxy * (y2 > y1 ? 1 : -1); /* y-coord runs down */
! 531: dty = v_unit * dx/dxy * (x2 > x1 ? 1 : -1);
! 532: for (n = 0; n < nticks; n++) {
! 533: RectObj *z = (RectObj*) gpmalloc(sizeof(RectObj2P));
! 534: double lunit = h_unit > 1 ? 1.5 : 2;
! 535: double l = (do_double && (n + n1) % dn == 0) ? lunit: 1;
! 536:
! 537: RoNext(z) = 0;
! 538: RoLNx1(z) = RoLNx2(z) = x*RXscale(e) + RXshift(e);
! 539: RoLNy1(z) = RoLNy2(z) = y*RYscale(e) + RYshift(e);
! 540:
! 541: if (flags & TICKS_CLOCKW) {
! 542: RoLNx1(z) += dtx*l;
! 543: RoLNy1(z) -= dty*l; /* y-coord runs down */
! 544: }
! 545: if (flags & TICKS_ACLOCKW) {
! 546: RoLNx2(z) -= dtx*l;
! 547: RoLNy2(z) += dty*l; /* y-coord runs down */
! 548: }
! 549: RoType(z) = ROt_LN;
! 550:
! 551: if (!RHead(e))
! 552: RHead(e)=RTail(e)=z;
! 553: else {
! 554: RoNext(RTail(e))=z; RTail(e)=z;
! 555: }
! 556: RoCol(z)=current_color[ne];
! 557: x += ddx;
! 558: y += ddy;
! 559: }
! 560: }
! 561:
! 562: void
! 563: rectline(long ne, GEN gx2, GEN gy2)
! 564: {
! 565: rectline0(ne, gtodouble(gx2), gtodouble(gy2),0);
! 566: }
! 567:
! 568: void
! 569: rectrline(long ne, GEN gx2, GEN gy2)
! 570: {
! 571: rectline0(ne, gtodouble(gx2), gtodouble(gy2),1);
! 572: }
! 573:
! 574: void
! 575: rectbox0(long ne, double gx2, double gy2, long relative)
! 576: {
! 577: double x1,y1,x2,y2,xmin,ymin,xmax,ymax;
! 578: double xx,yy;
! 579: PariRect *e = check_rect_init(ne);
! 580: RectObj *z = (RectObj*) gpmalloc(sizeof(RectObj2P));
! 581:
! 582: x1 = RXcursor(e)*RXscale(e) + RXshift(e);
! 583: y1 = RYcursor(e)*RYscale(e) + RYshift(e);
! 584: if (relative)
! 585: { xx = RXcursor(e)+gx2; yy = RYcursor(e)+gy2; }
! 586: else
! 587: { xx = gx2; yy = gy2; }
! 588: x2 = xx*RXscale(e) + RXshift(e);
! 589: y2 = yy*RYscale(e) + RYshift(e);
! 590: xmin = max(min(x1,x2),0); xmax = min(max(x1,x2),RXsize(e));
! 591: ymin = max(min(y1,y2),0); ymax = min(max(y1,y2),RYsize(e));
! 592:
! 593: RoNext(z)=0; RoType(z) = ROt_BX;
! 594: RoBXx1(z) = xmin; RoBXy1(z) = ymin;
! 595: RoBXx2(z) = xmax; RoBXy2(z) = ymax;
! 596: if (!RHead(e)) RHead(e)=RTail(e)=z;
! 597: else { RoNext(RTail(e))=z; RTail(e)=z; }
! 598: RoCol(z)=current_color[ne];
! 599: }
! 600:
! 601: void
! 602: rectbox(long ne, GEN gx2, GEN gy2)
! 603: {
! 604: rectbox0(ne, gtodouble(gx2), gtodouble(gy2), 0);
! 605: }
! 606:
! 607: void
! 608: rectrbox(long ne, GEN gx2, GEN gy2)
! 609: {
! 610: rectbox0(ne, gtodouble(gx2), gtodouble(gy2), 1);
! 611: }
! 612:
! 613: void
! 614: killrect(long ne)
! 615: {
! 616: RectObj *p1,*p2;
! 617: PariRect *e = check_rect_init(ne);
! 618:
! 619: current_color[ne]=DEFAULT_COLOR;
! 620: p1=RHead(e);
! 621: RHead(e) = RTail(e) = NULL;
! 622: RXsize(e) = RYsize(e) = 0;
! 623: RXcursor(e) = RYcursor(e) = 0;
! 624: RXscale(e) = RYscale(e) = 1;
! 625: RXshift(e) = RYshift(e) = 0;
! 626: while (p1)
! 627: {
! 628: if (RoType(p1)==ROt_MP || RoType(p1)==ROt_ML)
! 629: {
! 630: free(RoMPxs(p1)); free(RoMPys(p1));
! 631: }
! 632: if (RoType(p1)==ROt_ST) free(RoSTs(p1));
! 633: p2=RoNext(p1); free(p1); p1=p2;
! 634: }
! 635: }
! 636:
! 637: void
! 638: rectpoints0(long ne, double *listx, double *listy, long lx) /* code = ROt_MP */
! 639: {
! 640: double *ptx, *pty, x, y;
! 641: long i, cp=0;
! 642: PariRect *e = check_rect_init(ne);
! 643: RectObj *z = (RectObj*) gpmalloc(sizeof(RectObjMP));
! 644:
! 645: ptx=(double*) gpmalloc(lx*sizeof(double));
! 646: pty=(double*) gpmalloc(lx*sizeof(double));
! 647: for (i=0; i<lx; i++)
! 648: {
! 649: x = RXscale(e)*listx[i] + RXshift(e);
! 650: y = RYscale(e)*listy[i] + RYshift(e);
! 651: if ((x>=0)&&(y>=0)&&(x<=RXsize(e))&&(y<=RYsize(e)))
! 652: {
! 653: ptx[cp]=x; pty[cp]=y; cp++;
! 654: }
! 655: }
! 656: RoNext(z)=0; RoType(z) = ROt_MP;
! 657: RoMPcnt(z) = cp; RoMPxs(z) = ptx; RoMPys(z) = pty;
! 658: if (!RHead(e)) RHead(e)=RTail(e)=z;
! 659: else { RoNext(RTail(e))=z; RTail(e)=z; }
! 660: RoCol(z)=current_color[ne];
! 661: }
! 662:
! 663: void
! 664: rectpoints(long ne, GEN listx, GEN listy)
! 665: {
! 666: long i,lx, tx=typ(listx), ty=typ(listy);
! 667: double *px,*py;
! 668:
! 669: if (!is_matvec_t(tx) || !is_matvec_t(ty))
! 670: {
! 671: rectpoint(ne, listx, listy); return;
! 672: }
! 673: if (tx == t_MAT || ty == t_MAT) err(ploter4);
! 674: lx=lg(listx); if (lg(listy)!=lx) err(ploter5);
! 675: lx--; if (!lx) return;
! 676:
! 677: px = (double*) gpmalloc(lx*sizeof(double));
! 678: py = (double*) gpmalloc(lx*sizeof(double));
! 679: for (i=0; i<lx; i++)
! 680: {
! 681: px[i]=gtodouble((GEN)listx[i+1]); py[i]=gtodouble((GEN)listy[i+1]);
! 682: }
! 683: rectpoints0(ne,px,py,lx);
! 684: free(px); free(py);
! 685: }
! 686:
! 687: void
! 688: rectlines0(long ne, double *x, double *y, long lx, long flag) /* code = ROt_ML */
! 689: {
! 690: long i,I;
! 691: double *ptx,*pty;
! 692: PariRect *e = check_rect_init(ne);
! 693: RectObj *z = (RectObj*) gpmalloc(sizeof(RectObj2P));
! 694:
! 695: I = flag ? lx+1 : lx;
! 696: ptx = (double*) gpmalloc(I*sizeof(double));
! 697: pty = (double*) gpmalloc(I*sizeof(double));
! 698: for (i=0; i<lx; i++)
! 699: {
! 700: ptx[i] = RXscale(e)*x[i] + RXshift(e);
! 701: pty[i] = RYscale(e)*y[i] + RYshift(e);
! 702: }
! 703: if (flag)
! 704: {
! 705: ptx[i] = RXscale(e)*x[0] + RXshift(e);
! 706: pty[i] = RYscale(e)*y[0] + RYshift(e);
! 707: }
! 708: RoNext(z)=0; RoType(z)=ROt_ML;
! 709: RoMLcnt(z)=lx; RoMLxs(z)=ptx; RoMLys(z)=pty;
! 710: if (!RHead(e)) RHead(e)=RTail(e)=z;
! 711: else { RoNext(RTail(e))=z; RTail(e)=z; }
! 712: RoCol(z) = current_color[ne];
! 713: }
! 714:
! 715: void
! 716: rectlines(long ne, GEN listx, GEN listy, long flag)
! 717: {
! 718: long tx=typ(listx), ty=typ(listy), lx=lg(listx), i;
! 719: double *x, *y;
! 720:
! 721: if (!is_matvec_t(tx) || !is_matvec_t(ty))
! 722: {
! 723: rectline(ne, listx, listy); return;
! 724: }
! 725: if (tx == t_MAT || ty == t_MAT) err(ploter4);
! 726: if (lg(listy)!=lx) err(ploter5);
! 727: lx--; if (!lx) return;
! 728:
! 729: x = (double*) gpmalloc(lx*sizeof(double));
! 730: y = (double*) gpmalloc(lx*sizeof(double));
! 731: for (i=0; i<lx; i++)
! 732: {
! 733: x[i] = gtodouble((GEN)listx[i+1]); y[i] = gtodouble((GEN)listy[i+1]);
! 734: }
! 735: rectlines0(ne,x,y,lx,flag);
! 736: free(x); free(y);
! 737: }
! 738:
! 739: static void
! 740: put_string(long win, long x, long y, char *str, long dir)
! 741: {
! 742: rectmove0(win,(double)x,(double)y,0); rectstring3(win,str,dir);
! 743: }
! 744:
! 745: void
! 746: rectstring(long ne, char *str)
! 747: {
! 748: rectstring3(ne,str,RoSTdirLEFT);
! 749: }
! 750:
! 751: /* Allocate memory, then put string */
! 752: void
! 753: rectstring3(long ne, char *str, long dir) /* code = ROt_ST */
! 754: {
! 755: PariRect *e = check_rect_init(ne);
! 756: RectObj *z = (RectObj*) gpmalloc(sizeof(RectObjST));
! 757: long l = strlen(str);
! 758: char *s = (char *) gpmalloc(l+1);
! 759:
! 760: strcpy(s,str);
! 761: RoNext(z)=0; RoType(z) = ROt_ST;
! 762: RoSTl(z) = l; RoSTs(z) = s;
! 763: RoSTx(z) = RXscale(e)*RXcursor(e)+RXshift(e);
! 764: RoSTy(z) = RYscale(e)*RYcursor(e)+RYshift(e);
! 765: RoSTdir(z) = dir;
! 766: if (!RHead(e)) RHead(e)=RTail(e)=z;
! 767: else { RoNext(RTail(e))=z; RTail(e)=z; }
! 768: RoCol(z)=current_color[ne];
! 769: }
! 770:
! 771: void
! 772: rectpointtype(long ne, long type) /* code = ROt_PTT */
! 773: {
! 774: if (ne == -1) {
! 775: rectpoint_itype = type;
! 776: } else {
! 777: PariRect *e = check_rect_init(ne);
! 778: RectObj *z = (RectObj*) gpmalloc(sizeof(RectObjPN));
! 779:
! 780: RoNext(z) = 0; RoType(z) = ROt_PTT;
! 781: RoPTTpen(z) = type;
! 782: if (!RHead(e)) RHead(e)=RTail(e)=z;
! 783: else { RoNext(RTail(e))=z; RTail(e)=z; }
! 784: }
! 785: }
! 786:
! 787: void
! 788: rectpointsize(long ne, GEN size) /* code = ROt_PTS */
! 789: {
! 790: if (ne == -1) {
! 791: set_pointsize(gtodouble(size)); /* Immediate set */
! 792: } else {
! 793: PariRect *e = check_rect_init(ne);
! 794: RectObj *z = (RectObj*) gpmalloc(sizeof(RectObjPS));
! 795:
! 796: RoNext(z) = 0; RoType(z) = ROt_PTS;
! 797: RoPTSsize(z) = gtodouble(size);
! 798: if (!RHead(e)) RHead(e)=RTail(e)=z;
! 799: else { RoNext(RTail(e))=z; RTail(e)=z; }
! 800: }
! 801: }
! 802:
! 803: void
! 804: rectlinetype(long ne, long type)
! 805: {
! 806: if (ne == -1) {
! 807: rectline_itype = type;
! 808: } else {
! 809: PariRect *e = check_rect_init(ne);
! 810: RectObj *z = (RectObj*) gpmalloc(sizeof(RectObjPN));
! 811:
! 812: RoNext(z) = 0; RoType(z) = ROt_LNT;
! 813: RoLNTpen(z) = type;
! 814: if (!RHead(e)) RHead(e)=RTail(e)=z;
! 815: else { RoNext(RTail(e))=z; RTail(e)=z; }
! 816: }
! 817: }
! 818:
! 819: void
! 820: rectcopy_gen(long source, long dest, GEN xoff, GEN yoff, long flag)
! 821: {
! 822: long xi, yi;
! 823: if (flag & RECT_CP_RELATIVE) {
! 824: double xd = gtodouble(xoff), yd = gtodouble(yoff);
! 825:
! 826: PARI_get_plot(0);
! 827: xi = w_width - 1; yi = w_height - 1;
! 828: xi = (long)(xd*xi + 0.5);
! 829: yi = (long)(yd*yi + 0.5);
! 830: } else {
! 831: xi = itos(xoff); yi = itos(yoff);
! 832: }
! 833: if (flag & ~RECT_CP_RELATIVE) {
! 834: PariRect *s = check_rect_init(source), *d = check_rect_init(dest);
! 835:
! 836: switch (flag & ~RECT_CP_RELATIVE) {
! 837: case RECT_CP_NW:
! 838: break;
! 839: case RECT_CP_SW:
! 840: yi = RYsize(d) - RYsize(s) - yi;
! 841: break;
! 842: case RECT_CP_SE:
! 843: yi = RYsize(d) - RYsize(s) - yi;
! 844: /* FALL THROUGH */
! 845: case RECT_CP_NE:
! 846: xi = RXsize(d) - RXsize(s) - xi;
! 847: break;
! 848: }
! 849: }
! 850: rectcopy(source, dest, xi, yi);
! 851: }
! 852:
! 853: void
! 854: rectcopy(long source, long dest, long xoff, long yoff)
! 855: {
! 856: PariRect *s = check_rect_init(source), *d = check_rect_init(dest);
! 857: RectObj *p1 = RHead(s);
! 858: RectObj *tail = RTail(d);
! 859: RectObj *next;
! 860: int i;
! 861:
! 862: while (p1)
! 863: {
! 864: switch(RoType(p1))
! 865: {
! 866: case ROt_PT:
! 867: next = (RectObj*) gpmalloc(sizeof(RectObj1P));
! 868: memcpy(next,p1,sizeof(RectObj1P));
! 869: RoPTx(next) += xoff; RoPTy(next) += yoff;
! 870: RoNext(tail) = next; tail = next;
! 871: break;
! 872: case ROt_LN: case ROt_BX:
! 873: next = (RectObj*) gpmalloc(sizeof(RectObj2P));
! 874: memcpy(next,p1,sizeof(RectObj2P));
! 875: RoLNx1(next) += xoff; RoLNy1(next) += yoff;
! 876: RoLNx2(next) += xoff; RoLNy2(next) += yoff;
! 877: RoNext(tail) = next; tail = next;
! 878: break;
! 879: case ROt_MP: case ROt_ML:
! 880: next = (RectObj*) gpmalloc(sizeof(RectObjMP));
! 881: memcpy(next,p1,sizeof(RectObjMP));
! 882: RoMPxs(next) = (double*) gpmalloc(sizeof(double)*RoMPcnt(next));
! 883: RoMPys(next) = (double*) gpmalloc(sizeof(double)*RoMPcnt(next));
! 884: memcpy(RoMPxs(next),RoMPxs(p1),sizeof(double)*RoMPcnt(next));
! 885: memcpy(RoMPys(next),RoMPys(p1),sizeof(double)*RoMPcnt(next));
! 886: for (i=0; i<RoMPcnt(next); i++)
! 887: {
! 888: RoMPxs(next)[i] += xoff; RoMPys(next)[i] += yoff;
! 889: }
! 890: RoNext(tail) = next; tail = next;
! 891: break;
! 892: case ROt_ST:
! 893: next = (RectObj*) gpmalloc(sizeof(RectObjST));
! 894: memcpy(next,p1,sizeof(RectObjMP));
! 895: RoSTs(next) = (char*) gpmalloc(RoSTl(p1)+1);
! 896: memcpy(RoSTs(next),RoSTs(p1),RoSTl(p1)+1);
! 897: RoSTx(next) += xoff; RoSTy(next) += yoff;
! 898: RoNext(tail) = next; tail = next;
! 899: break;
! 900: case ROt_PTT: case ROt_LNT: case ROt_PTS:
! 901: next = (RectObj*) gpmalloc(sizeof(RectObjPN));
! 902: memcpy(next,p1,sizeof(RectObjPN));
! 903: RoNext(tail) = next; tail = next;
! 904: break;
! 905: }
! 906: p1=RoNext(p1);
! 907: }
! 908: RoNext(tail) = NULL; RTail(d) = tail;
! 909: }
! 910:
! 911: #define CLIPLINE_NONEMPTY 1
! 912: #define CLIPLINE_CLIP_1 2
! 913: #define CLIPLINE_CLIP_2 4
! 914:
! 915: /* A simpler way is to clip by 4 half-planes */
! 916: static int
! 917: clipline(double xmin, double xmax, double ymin, double ymax,
! 918: double *x1p, double *y1p, double *x2p, double *y2p)
! 919: {
! 920: int xy_exch = 0, rc = CLIPLINE_NONEMPTY;
! 921: double t, sl;
! 922: double xi, xmn, xmx;
! 923: double yi, ymn, ymx;
! 924: int x1_is_ymn, x1_is_xmn;
! 925: double x1 = *x1p, x2 = *x2p, y1 = *y1p, y2 = *y2p;
! 926:
! 927: if ((x1 < xmin && x2 < xmin) || (x1 > xmax && x2 > xmax))
! 928: return 0;
! 929: if (fabs(x1 - x2) < fabs(y1 - y2)) { /* Exchange x and y */
! 930: xy_exch = 1;
! 931: t = xmin; xmin = ymin; ymin = t;
! 932: t = xmax; xmax = ymax; ymax = t;
! 933: t = x1; x1 = y1; y1 = t;
! 934: t = x2; x2 = y2; y2 = t;
! 935: }
! 936:
! 937: /* Build y as a function of x */
! 938: xi = x1, yi = y1;
! 939: sl = ( (x1==x2) ? 0 : (y2 - yi)/(x2 - xi) );
! 940:
! 941: xmn = x1, xmx = x2;
! 942: if (x1 > x2) {
! 943: x1_is_xmn = 0;
! 944: xmn = x2, xmx = x1;
! 945: } else
! 946: x1_is_xmn = 1;
! 947:
! 948: if (xmn < xmin) {
! 949: xmn = xmin;
! 950: rc |= (x1_is_xmn ? CLIPLINE_CLIP_1 : CLIPLINE_CLIP_2);
! 951: }
! 952:
! 953: if (xmx > xmax) {
! 954: xmx = xmax;
! 955: rc |= (x1_is_xmn ? CLIPLINE_CLIP_2 : CLIPLINE_CLIP_1);
! 956: }
! 957:
! 958: if (xmn > xmx)
! 959: return 0;
! 960:
! 961: ymn = yi + (xmn - xi)*sl;
! 962: ymx = yi + (xmx - xi)*sl;
! 963:
! 964: if (sl < 0)
! 965: t = ymn, ymn = ymx, ymx = t;
! 966: if (ymn > ymax || ymx < ymin)
! 967: return 0;
! 968:
! 969: if (rc & CLIPLINE_CLIP_1)
! 970: x1 = (x1_is_xmn ? xmn : xmx);
! 971: if (rc & CLIPLINE_CLIP_2)
! 972: x2 = (x1_is_xmn ? xmx : xmn);
! 973:
! 974: /* Now we know there is an intersection, need to move x1 and x2 */
! 975: x1_is_ymn = ((sl >= 0) == (x1 < x2));
! 976: if (ymn < ymin) {
! 977: double x = (ymin - yi)/sl + xi; /* slope != 0 ! */
! 978:
! 979: if (x1_is_ymn)
! 980: x1 = x, rc |= CLIPLINE_CLIP_1;
! 981: else
! 982: x2 = x, rc |= CLIPLINE_CLIP_2;
! 983: }
! 984: if (ymx > ymax) {
! 985: double x = (ymax - yi)/sl + xi; /* slope != 0 ! */
! 986:
! 987: if (x1_is_ymn)
! 988: x2 = x, rc |= CLIPLINE_CLIP_2;
! 989: else
! 990: x1 = x, rc |= CLIPLINE_CLIP_1;
! 991: }
! 992: if (rc & CLIPLINE_CLIP_1)
! 993: y1 = yi + (x1 - xi)*sl;
! 994: if (rc & CLIPLINE_CLIP_2)
! 995: y2 = yi + (x2 - xi)*sl;
! 996: if (xy_exch) /* Exchange x and y */
! 997: *x1p = y1, *x2p = y2, *y1p = x1, *y2p = x2;
! 998: else
! 999: *x1p = x1, *x2p = x2, *y1p = y1, *y2p = y2;
! 1000: return rc;
! 1001: }
! 1002:
! 1003: void
! 1004: rectclip(long rect)
! 1005: {
! 1006: PariRect *s = check_rect_init(rect);
! 1007: RectObj *p1 = RHead(s);
! 1008: RectObj **prevp = &RHead(s);
! 1009: RectObj *next;
! 1010: double xmin = 0;
! 1011: double xmax = RXsize(s);
! 1012: double ymin = 0;
! 1013: double ymax = RYsize(s);
! 1014:
! 1015: while (p1) {
! 1016: int did_clip = 0;
! 1017:
! 1018: next = RoNext(p1);
! 1019: switch(RoType(p1)) {
! 1020: case ROt_PT:
! 1021: if ( DTOL(RoPTx(p1)) < xmin || DTOL(RoPTx(p1)) > xmax
! 1022: || DTOL(RoPTy(p1)) < ymin || DTOL(RoPTy(p1)) > ymax) {
! 1023: remove:
! 1024: *prevp = next;
! 1025: free(p1);
! 1026: break;
! 1027: }
! 1028: goto do_next;
! 1029: case ROt_BX:
! 1030: if (RoLNx1(p1) < xmin)
! 1031: RoLNx1(p1) = xmin, did_clip = 1;
! 1032: if (RoLNx2(p1) < xmin)
! 1033: RoLNx2(p1) = xmin, did_clip = 1;
! 1034: if (RoLNy1(p1) < ymin)
! 1035: RoLNy1(p1) = ymin, did_clip = 1;
! 1036: if (RoLNy2(p1) < ymin)
! 1037: RoLNy2(p1) = ymin, did_clip = 1;
! 1038: if (RoLNx1(p1) > xmax)
! 1039: RoLNx1(p1) = xmax, did_clip = 1;
! 1040: if (RoLNx2(p1) > xmax)
! 1041: RoLNx2(p1) = xmax, did_clip = 1;
! 1042: if (RoLNy1(p1) > ymax)
! 1043: RoLNy1(p1) = ymax, did_clip = 1;
! 1044: if (RoLNy2(p1) > ymax)
! 1045: RoLNy2(p1) = ymax, did_clip = 1;
! 1046: /* Remove zero-size clipped boxes */
! 1047: if ( did_clip
! 1048: && RoLNx1(p1) == RoLNx2(p1) && RoLNy1(p1) == RoLNy2(p1) )
! 1049: goto remove;
! 1050: goto do_next;
! 1051: case ROt_LN:
! 1052: if (!clipline(xmin, xmax, ymin, ymax,
! 1053: &RoLNx1(p1), &RoLNy1(p1), &RoLNx2(p1), &RoLNy2(p1)))
! 1054: goto remove;
! 1055: goto do_next;
! 1056: case ROt_MP:
! 1057: {
! 1058: int c = RoMPcnt(p1);
! 1059: int f = 0, t = 0;
! 1060:
! 1061: while (f < c) {
! 1062: if ( DTOL(RoMPxs(p1)[f]) >= xmin && DTOL(RoMPxs(p1)[f]) <= xmax
! 1063: && DTOL(RoMPys(p1)[f]) >= ymin
! 1064: && DTOL(RoMPys(p1)[f]) <= ymax) {
! 1065: if (t != f) {
! 1066: RoMPxs(p1)[t] = RoMPxs(p1)[f];
! 1067: RoMPys(p1)[t] = RoMPys(p1)[f];
! 1068: }
! 1069: t++;
! 1070: }
! 1071: f++;
! 1072: }
! 1073: if (t == 0)
! 1074: goto remove;
! 1075: RoMPcnt(p1) = t;
! 1076: goto do_next;
! 1077: }
! 1078: case ROt_ML:
! 1079: {
! 1080: /* Hard case. Here we need to break a multiline into
! 1081: several pieces if some part is clipped. */
! 1082: int c = RoMPcnt(p1) - 1;
! 1083: int f = 0, t = 0, had_lines = 0, had_hole = 0, rc;
! 1084: double ox = RoMLxs(p1)[0], oy = RoMLys(p1)[0], oxn, oyn;
! 1085:
! 1086: while (f < c) {
! 1087: /* Endpoint of this segment is the startpoint of the
! 1088: next one, so we need to preserve it if it is clipped. */
! 1089: oxn = RoMLxs(p1)[f + 1], oyn = RoMLys(p1)[f + 1];
! 1090: rc = clipline(xmin, xmax, ymin, ymax,
! 1091: /* &RoMLxs(p1)[f], &RoMLys(p1)[f], */
! 1092: &ox, &oy,
! 1093: &RoMLxs(p1)[f+1], &RoMLys(p1)[f+1]);
! 1094: RoMLxs(p1)[f] = ox; RoMLys(p1)[f] = oy;
! 1095: ox = oxn; oy = oyn;
! 1096: if (!rc) {
! 1097: if (had_lines)
! 1098: had_hole = 1;
! 1099: f++;
! 1100: continue;
! 1101: }
! 1102:
! 1103: if ( !had_lines || (!(rc & CLIPLINE_CLIP_1) && !had_hole) ) {
! 1104: /* Continuous */
! 1105: had_lines = 1;
! 1106: if (t != f) {
! 1107: if (t == 0) {
! 1108: RoMPxs(p1)[t] = RoMPxs(p1)[f];
! 1109: RoMPys(p1)[t] = RoMPys(p1)[f];
! 1110: }
! 1111: RoMPxs(p1)[t+1] = RoMPxs(p1)[f+1];
! 1112: RoMPys(p1)[t+1] = RoMPys(p1)[f+1];
! 1113: }
! 1114: t++;
! 1115: f++;
! 1116: if ( rc & CLIPLINE_CLIP_2)
! 1117: had_hole = 1, RoMLcnt(p1) = t + 1;
! 1118: continue;
! 1119: }
! 1120: /* Is not continuous, automatically p1 is not free()ed. */
! 1121: RoMLcnt(p1) = t + 1;
! 1122: if ( rc & CLIPLINE_CLIP_2) { /* Needs separate entry */
! 1123: RectObj *n = (RectObj*) gpmalloc(sizeof(RectObj2P));
! 1124:
! 1125: RoType(n) = ROt_LN;
! 1126: RoCol(n) = RoCol(p1);
! 1127: RoLNx1(n) = RoMLxs(p1)[f]; RoLNy1(n) = RoMLys(p1)[f];
! 1128: RoLNx2(n) = RoMLxs(p1)[f+1]; RoLNy2(n) = RoMLys(p1)[f+1];
! 1129: RoNext(n) = next;
! 1130: RoNext(p1) = n;
! 1131: /* Restore the unclipped value: */
! 1132: RoMLxs(p1)[f + 1] = oxn; RoMLys(p1)[f + 1] = oyn;
! 1133: f++;
! 1134: prevp = &RoNext(n);
! 1135: }
! 1136: if (f + 1 < c) { /* Are other lines */
! 1137: RectObj *n = (RectObj*) gpmalloc(sizeof(RectObjMP));
! 1138: RoType(n) = ROt_ML;
! 1139: RoCol(n) = RoCol(p1);
! 1140: RoMLcnt(n) = c - f;
! 1141: RoMLxs(n) = (double*) gpmalloc(sizeof(double)*(c - f));
! 1142: RoMLys(n) = (double*) gpmalloc(sizeof(double)*(c - f));
! 1143: memcpy(RoMPxs(n),RoMPxs(p1) + f, sizeof(double)*(c - f));
! 1144: memcpy(RoMPys(n),RoMPys(p1) + f, sizeof(double)*(c - f));
! 1145: RoMPxs(n)[0] = oxn; RoMPys(n)[0] = oyn;
! 1146: RoNext(n) = next;
! 1147: RoNext(p1) = n;
! 1148: next = n;
! 1149: }
! 1150: goto do_next;
! 1151: }
! 1152: if (t == 0)
! 1153: goto remove;
! 1154: goto do_next;
! 1155: }
! 1156: #if 0
! 1157: case ROt_ST:
! 1158: next = (RectObj*) gpmalloc(sizeof(RectObjMP));
! 1159: memcpy(next,p1,sizeof(RectObjMP));
! 1160: RoSTs(next) = (char*) gpmalloc(RoSTl(p1)+1);
! 1161: memcpy(RoSTs(next),RoSTs(p1),RoSTl(p1)+1);
! 1162: RoSTx(next) += xoff; RoSTy(next) += yoff;
! 1163: RoNext(tail) = next; tail = next;
! 1164: break;
! 1165: #endif
! 1166: default: {
! 1167: do_next:
! 1168: prevp = &RoNext(p1);
! 1169: break;
! 1170: }
! 1171: }
! 1172: p1 = next;
! 1173: }
! 1174: }
! 1175:
! 1176: /********************************************************************/
! 1177: /** **/
! 1178: /** HI-RES PLOT **/
! 1179: /** **/
! 1180: /********************************************************************/
! 1181:
! 1182: static void
! 1183: Appendx(dblPointList *f, dblPointList *l,double x)
! 1184: {
! 1185: (l->d)[l->nb++]=x;
! 1186: if (x < f->xsml) f->xsml=x;
! 1187: else if (x > f->xbig) f->xbig=x;
! 1188: }
! 1189:
! 1190: static void
! 1191: Appendy(dblPointList *f, dblPointList *l,double y)
! 1192: {
! 1193: (l->d)[l->nb++]=y;
! 1194: if (y < f->ysml) f->ysml=y;
! 1195: else if (y > f->ybig) f->ybig=y;
! 1196: }
! 1197:
! 1198: /* Convert data from GEN to double before we call rectplothrawin */
! 1199: static dblPointList*
! 1200: gtodblList(GEN data, long flags)
! 1201: {
! 1202: dblPointList *l;
! 1203: double xsml,xbig,ysml,ybig;
! 1204: long tx=typ(data), ty, nl=lg(data)-1, lx1,lx;
! 1205: register long i,j,u,v;
! 1206: long param=(flags & PLOT_PARAMETRIC);
! 1207: GEN x,y;
! 1208:
! 1209: if (! is_vec_t(tx)) err(talker,"not a vector in gtodblList");
! 1210: if (!nl) return NULL;
! 1211: lx1=lg(data[1]);
! 1212:
! 1213: /* Allocate memory, then convert coord. to double */
! 1214: l=(dblPointList*) gpmalloc(nl*sizeof(dblPointList));
! 1215: for (i=0; i<nl-1; i+=2)
! 1216: {
! 1217: u=i+1;
! 1218: x=(GEN)data[u]; tx = typ(x);
! 1219: y=(GEN)data[u+1]; ty = typ(y);
! 1220: if (!is_vec_t(tx) || !is_vec_t(ty)) err(ploter4);
! 1221: lx=lg(x); if (lg(y)!=lx) err(ploter5);
! 1222: if (!param && lx != lx1) err(ploter5);
! 1223: lx--;
! 1224:
! 1225: if (lx)
! 1226: {
! 1227: l[i].d = (double*) gpmalloc(lx*sizeof(double));
! 1228: l[u].d = (double*) gpmalloc(lx*sizeof(double));
! 1229:
! 1230: for (j=0; j<lx; j=v)
! 1231: {
! 1232: v=j+1;
! 1233: l[i].d[j]=gtodouble((GEN)x[v]);
! 1234: l[u].d[j]=gtodouble((GEN)y[v]);
! 1235: }
! 1236: }
! 1237: l[i].nb=l[u].nb=lx;
! 1238: }
! 1239:
! 1240: xsml=xbig=l[0].d[0]; ysml=ybig=l[1].d[0];
! 1241:
! 1242: /* Now compute extremas */
! 1243: if (param)
! 1244: {
! 1245: l[0].nb=nl/2;
! 1246: for (i=0; i<l[0].nb; i+=2)
! 1247: {
! 1248: u=i+1;
! 1249: for (j=0; j<l[u].nb; j++)
! 1250: {
! 1251: if (l[i].d[j]<xsml)
! 1252: xsml=l[i].d[j];
! 1253: else
! 1254: if (l[i].d[j]>xbig) xbig=l[i].d[j];
! 1255:
! 1256: if (l[u].d[j]<ysml)
! 1257: ysml=l[u].d[j];
! 1258: else
! 1259: if (l[u].d[j]>ybig) ybig=l[u].d[j];
! 1260: }
! 1261: }
! 1262: }
! 1263: else
! 1264: {
! 1265: l[0].nb=nl-1;
! 1266: for (j=0; j<l[1].nb; j++)
! 1267: {
! 1268: if (l[0].d[j]<xsml)
! 1269: xsml=l[0].d[j];
! 1270: else
! 1271: if (l[0].d[j]>xbig) xbig=l[0].d[j];
! 1272: }
! 1273: for (i=1; i<=l[0].nb; i++)
! 1274: {
! 1275: for (j=0; j<l[i].nb; j++)
! 1276: {
! 1277: if (l[i].d[j]<ysml)
! 1278: ysml=l[i].d[j];
! 1279: else
! 1280: if (l[i].d[j]>ybig) ybig=l[i].d[j];
! 1281: }
! 1282: }
! 1283: }
! 1284: l[0].xsml=xsml; l[0].xbig=xbig;
! 1285: l[0].ysml=ysml; l[0].ybig=ybig;
! 1286: return l;
! 1287: }
! 1288:
! 1289: static void
! 1290: single_recursion(dblPointList *pl,char *ch,entree *ep,GEN xleft,GEN yleft,
! 1291: GEN xright,GEN yright,long depth)
! 1292: {
! 1293: GEN xx,yy;
! 1294: long av=avma;
! 1295: double dy=pl[0].ybig - pl[0].ysml;
! 1296:
! 1297: if (depth==RECUR_MAXDEPTH) return;
! 1298:
! 1299: yy=cgetr(3); xx=gmul2n(gadd(xleft,xright),-1);
! 1300: ep->value = (void*) xx; gaffect(READ_EXPR(ch), yy);
! 1301:
! 1302: if (dy)
! 1303: {
! 1304: if (fabs(rtodbl(yleft)+rtodbl(yright)-2*rtodbl(yy))/dy < RECUR_PREC)
! 1305: return;
! 1306: }
! 1307: single_recursion(pl,ch,ep, xleft,yleft, xx,yy, depth+1);
! 1308:
! 1309: Appendx(&pl[0],&pl[0],rtodbl(xx));
! 1310: Appendy(&pl[0],&pl[1],rtodbl(yy));
! 1311:
! 1312: single_recursion(pl,ch,ep, xx,yy, xright,yright, depth+1);
! 1313:
! 1314: avma=av;
! 1315: }
! 1316:
! 1317: static void
! 1318: param_recursion(dblPointList *pl,char *ch,entree *ep, GEN tleft,GEN xleft,
! 1319: GEN yleft, GEN tright,GEN xright,GEN yright, long depth)
! 1320: {
! 1321: GEN tt,xx,yy, p1;
! 1322: long av=avma;
! 1323: double dy=pl[0].ybig - pl[0].ysml;
! 1324: double dx=pl[0].xbig - pl[0].xsml;
! 1325:
! 1326: if (depth==PARAMR_MAXDEPTH) return;
! 1327:
! 1328: xx=cgetr(3); yy=cgetr(3); tt=gmul2n(gadd(tleft,tright),-1);
! 1329: ep->value = (void*)tt; p1=READ_EXPR(ch);
! 1330: gaffect((GEN)p1[1],xx); gaffect((GEN)p1[2],yy);
! 1331:
! 1332: if (dx && dy)
! 1333: {
! 1334: if (fabs(rtodbl(xleft)+rtodbl(xright)-2*rtodbl(xx))/dx < RECUR_PREC &&
! 1335: fabs(rtodbl(yleft)+rtodbl(yright)-2*rtodbl(yy))/dy < RECUR_PREC)
! 1336: return;
! 1337: }
! 1338: param_recursion(pl,ch,ep, tleft,xleft,yleft, tt,xx,yy, depth+1);
! 1339:
! 1340: Appendx(&pl[0],&pl[0],rtodbl(xx));
! 1341: Appendy(&pl[0],&pl[1],rtodbl(yy));
! 1342:
! 1343: param_recursion(pl,ch,ep, tt,xx,yy, tright,xright,yright, depth+1);
! 1344:
! 1345: avma=av;
! 1346: }
! 1347:
! 1348: /*
! 1349: * Pure graphing. If testpoints is 0, it is set to the default.
! 1350: * Returns a dblPointList of (absolute) coordinates.
! 1351: */
! 1352: static dblPointList *
! 1353: rectplothin(entree *ep, GEN a, GEN b, char *ch, long prec, ulong flags,
! 1354: long testpoints)
! 1355: {
! 1356: long single_c;
! 1357: long param=flags & PLOT_PARAMETRIC;
! 1358: long recur=flags & PLOT_RECURSIVE;
! 1359: GEN p1,dx,x,xleft,xright,yleft,yright,tleft,tright;
! 1360: dblPointList *pl;
! 1361: long tx,av = avma,av2,i,j,sig,nc,nl,nbpoints;
! 1362: double xsml,xbig,ysml,ybig,fx,fy;
! 1363:
! 1364: if (!testpoints)
! 1365: {
! 1366: if (recur)
! 1367: testpoints = RECUR_NUMPOINTS;
! 1368: else
! 1369: testpoints = param? PARAM_NUMPOINTS : PLOTH_NUMPOINTS;
! 1370: }
! 1371: if (recur)
! 1372: nbpoints = testpoints << (param? PARAMR_MAXDEPTH : RECUR_MAXDEPTH);
! 1373: else
! 1374: nbpoints = testpoints;
! 1375:
! 1376: sig=gcmp(b,a); if (!sig) return 0;
! 1377: if (sig<0) { x=a; a=b; b=x; }
! 1378: dx=gdivgs(gsub(b,a),testpoints-1);
! 1379:
! 1380: x = cgetr(prec); gaffect(a,x); push_val(ep, x);
! 1381: av2=avma; p1=READ_EXPR(ch); tx=typ(p1);
! 1382: if (!is_matvec_t(tx))
! 1383: {
! 1384: xsml = gtodouble(a);
! 1385: xbig = gtodouble(b);
! 1386: ysml = ybig = gtodouble(p1);
! 1387: nc=1; nl=2; /* nc = nb of curves; nl = nb of coord. lists */
! 1388: if (param)
! 1389: err(warner,"flag PLOT_PARAMETRIC ignored");
! 1390: single_c=1; param=0;
! 1391: }
! 1392: else
! 1393: {
! 1394: if (tx != t_VEC) err(talker,"not a row vector in ploth");
! 1395: nl=lg(p1)-1; if (!nl) { avma=av; return 0; }
! 1396: single_c=0;
! 1397: if (param) nc=nl/2; else { nc=nl; nl++; }
! 1398: if (recur && nc > 1) err(talker,"multi-curves cannot be plot recursively");
! 1399:
! 1400: if (param)
! 1401: {
! 1402: xbig=xsml=gtodouble((GEN)p1[1]);
! 1403: ybig=ysml=gtodouble((GEN)p1[2]);
! 1404: for (i=3; i<=nl; i++)
! 1405: {
! 1406: fx=gtodouble((GEN)p1[i]); i++;
! 1407: fy=gtodouble((GEN)p1[i]);
! 1408: if (xsml>fx) xsml=fx; else if (xbig<fx) xbig=fx;
! 1409: if (ysml>fy) ysml=fy; else if (ybig<fy) ybig=fy;
! 1410: }
! 1411: }
! 1412: else
! 1413: {
! 1414: xsml=gtodouble(a); xbig=gtodouble(b);
! 1415: ysml=gtodouble(vecmin(p1)); ybig=gtodouble(vecmax(p1));
! 1416: }
! 1417: }
! 1418:
! 1419: pl=(dblPointList*) gpmalloc(nl*sizeof(dblPointList));
! 1420: for (i = 0; i < nl; i++)
! 1421: {
! 1422: pl[i].d = (double*) gpmalloc((nbpoints+1)*sizeof(dblPointList));
! 1423: pl[i].nb=0;
! 1424: }
! 1425: pl[0].xsml=xsml; pl[0].ysml=ysml; pl[0].xbig=xbig; pl[0].ybig=ybig;
! 1426:
! 1427: if (recur) /* recursive plot */
! 1428: {
! 1429: xleft=cgetr(3); xright=cgetr(3); yleft=cgetr(3); yright=cgetr(3);
! 1430: if (param)
! 1431: {
! 1432: tleft=cgetr(prec); tright=cgetr(prec);
! 1433: av2=avma;
! 1434: gaffect(a,tleft); ep->value = (void*)tleft; p1=READ_EXPR(ch);
! 1435: gaffect((GEN)p1[1],xleft); gaffect((GEN)p1[2],yleft);
! 1436: for (i=0; i<testpoints-1; i++)
! 1437: {
! 1438: if (i) {
! 1439: gaffect(tright,tleft); gaffect(xright,xleft); gaffect(yright,yleft);
! 1440: }
! 1441: gaddz(tleft,dx,tright); ep->value = (void*)tright;
! 1442: p1 = READ_EXPR(ch);
! 1443: if (lg(p1) != 3) err(talker,"inconsistent data in rectplothin");
! 1444: gaffect((GEN)p1[1],xright); gaffect((GEN)p1[2],yright);
! 1445:
! 1446: Appendx(&pl[0],&pl[0],rtodbl(xleft));
! 1447: Appendy(&pl[0],&pl[1],rtodbl(yleft));
! 1448:
! 1449: param_recursion(pl,ch,ep, tleft,xleft,yleft, tright,xright,yright, 0);
! 1450: avma=av2;
! 1451: }
! 1452: Appendx(&pl[0],&pl[0],rtodbl(xright));
! 1453: Appendy(&pl[0],&pl[1],rtodbl(yright));
! 1454: }
! 1455: else /* single_c */
! 1456: {
! 1457: av2=avma;
! 1458: gaffect(a,xleft); ep->value = (void*) xleft;
! 1459: gaffect(READ_EXPR(ch),yleft);
! 1460: for (i=0; i<testpoints-1; i++)
! 1461: {
! 1462: gaddz(xleft,dx,xright); ep->value = (void*) xright;
! 1463: gaffect(READ_EXPR(ch),yright);
! 1464:
! 1465: Appendx(&pl[0],&pl[0],rtodbl(xleft));
! 1466: Appendy(&pl[0],&pl[1],rtodbl(yleft));
! 1467:
! 1468: single_recursion(pl,ch,ep,xleft,yleft,xright,yright,0);
! 1469: avma=av2;
! 1470: gaffect(xright,xleft); gaffect(yright,yleft);
! 1471: }
! 1472: Appendx(&pl[0],&pl[0],rtodbl(xright));
! 1473: Appendy(&pl[0],&pl[1],rtodbl(yright));
! 1474: }
! 1475: }
! 1476: else /* non-recursive plot */
! 1477: {
! 1478: if (single_c)
! 1479: for (i=0; i<testpoints; i++)
! 1480: {
! 1481: p1 = READ_EXPR(ch);
! 1482: pl[0].d[i]=gtodouble(x);
! 1483: Appendy(&pl[0],&pl[1],gtodouble(p1));
! 1484: gaddz(x,dx,x); avma=av2;
! 1485: }
! 1486: else if (param)
! 1487: {
! 1488: long k;
! 1489: double z;
! 1490:
! 1491: for (i=0; i<testpoints; i++)
! 1492: {
! 1493: p1 = READ_EXPR(ch);
! 1494: if (lg(p1) != nl+1) err(talker,"inconsistent data in rectplothin");
! 1495: for (j=0; j<nl; j=k)
! 1496: {
! 1497: k=j+1; z=gtodouble((GEN)p1[k]);
! 1498: Appendx(&pl[0], &pl[j],z);
! 1499:
! 1500: j=k; k++; z=gtodouble((GEN)p1[k]);
! 1501: Appendy(&pl[0], &pl[j],z);
! 1502: }
! 1503: gaddz(x,dx,x); avma=av2;
! 1504: }
! 1505: }
! 1506: else /* plothmult */
! 1507: for (i=0; i<testpoints; i++)
! 1508: {
! 1509: p1 = READ_EXPR(ch);
! 1510: if (lg(p1) != nl) err(talker,"inconsistent data in rectplothin");
! 1511: pl[0].d[i]=gtodouble(x);
! 1512: for (j=1; j<nl; j++) { Appendy(&pl[0],&pl[j],gtodouble((GEN)p1[j])); }
! 1513: gaddz(x,dx,x); avma=av2;
! 1514: }
! 1515: }
! 1516: pl[0].nb=nc; pop_val(ep); avma = av;
! 1517: return pl;
! 1518: }
! 1519:
! 1520: extern GEN polint_i(GEN xa, GEN ya, GEN x, long n, GEN *ptdy);
! 1521:
! 1522: /* Uses highlevel plotting functions to implement splines as
! 1523: a low-level plotting function.
! 1524: Most probably one does not need to make varn==0 into pure variable,
! 1525: since plotting functions should take care of this. */
! 1526: static void
! 1527: rectsplines(long ne, double *x, double *y, long lx, long flag)
! 1528: {
! 1529: long i, j, oldavma = avma;
! 1530: GEN tas, xa = cgetg(lx+1, t_VEC), ya = cgetg(lx+1, t_VEC);
! 1531: entree *var0 = varentries[ordvar[0]];
! 1532:
! 1533: if (lx < 4)
! 1534: err(talker, "Too few points (%ld) for spline plot", lx);
! 1535: for (i = 1; i <= lx; i++) {
! 1536: xa[i] = (long) dbltor(x[i-1]);
! 1537: ya[i] = (long) dbltor(y[i-1]);
! 1538: }
! 1539: if (flag & PLOT_PARAMETRIC) {
! 1540: tas = new_chunk(4);
! 1541: for (j = 1; j <= 4; j++) tas[j-1] = lstoi(j);
! 1542: quark_gen = cgetg(2 + 1, t_VEC);
! 1543: }
! 1544: else tas = NULL; /* for lint */
! 1545: for (i = 0; i <= lx - 4; i++) {
! 1546: long oavma = avma;
! 1547:
! 1548: xa++; ya++;
! 1549: if (flag & PLOT_PARAMETRIC) {
! 1550: quark_gen[1] = (long)polint_i(tas, xa, polx[0], 4, NULL);
! 1551: quark_gen[2] = (long)polint_i(tas, ya, polx[0], 4, NULL);
! 1552: } else {
! 1553: quark_gen = polint_i(xa, ya, polx[0], 4, NULL);
! 1554: tas = xa;
! 1555: }
! 1556: rectploth(ne, var0,
! 1557: (GEN)(i==0 ? tas[0] : tas[1]),
! 1558: (GEN)(i==lx-4 ? tas[3] : tas[2]),
! 1559: QUARK,
! 1560: DEFAULTPREC, /* XXXX precision */
! 1561: PLOT_RECURSIVE
! 1562: | PLOT_NO_RESCALE
! 1563: | PLOT_NO_FRAME
! 1564: | PLOT_NO_AXE_Y
! 1565: | PLOT_NO_AXE_X
! 1566: | (flag & PLOT_PARAMETRIC),
! 1567: 2); /* Start with 3 points */
! 1568: avma = oavma;
! 1569: }
! 1570: avma = oldavma;
! 1571: }
! 1572:
! 1573: /*
! 1574: * Plot a dblPointList. Complete with axes, bounding box, etc.
! 1575: * We use two drawing rectangles: one for strings, another
! 1576: * for graphs.
! 1577: *
! 1578: * data is an array of structs. Its meaning depends on flags :
! 1579: *
! 1580: * + data[0] contains global extremas, the number of curves to plot
! 1581: * (data[0].nb) and a list of doubles (first set of x-coordinates).
! 1582: *
! 1583: * + data[i].nb (i>0) contains the number of points in the list
! 1584: * data[i].d (hopefully, data[2i].nb=data[2i+1].nb when i>0...)
! 1585: *
! 1586: * + If flags contain PLOT_PARAMETRIC, the array length should be
! 1587: * even, and successive pairs (data[2i].d, data[2i+1].d) represent
! 1588: * curves to plot.
! 1589: *
! 1590: * + If there is no such flag, the first element is an array with
! 1591: * x-coordinates and the following ones contain y-coordinates.
! 1592: *
! 1593: * Additional flags: PLOT_NO_AXE_X, PLOT_NO_AXE_Y, PLOT_NO_FRAME.
! 1594: */
! 1595:
! 1596: static GEN
! 1597: rectplothrawin(long stringrect, long drawrect, dblPointList *data,
! 1598: long flags, PARI_plot *WW)
! 1599: {
! 1600: GEN res;
! 1601: dblPointList y,x;
! 1602: double xsml,xbig,ysml,ybig,tmp;
! 1603: long ltype, ltop=avma;
! 1604: long i,nc,nbpoints, w[2], wx[2], wy[2];
! 1605:
! 1606: w[0]=stringrect; w[1]=drawrect;
! 1607: if (!data) return cgetg(1,t_VEC);
! 1608: x = data[0]; nc = x.nb;
! 1609: xsml = x.xsml; xbig = x.xbig;
! 1610: ysml = x.ysml; ybig = x.ybig;
! 1611: if (xbig-xsml < 1.e-9)
! 1612: {
! 1613: tmp=fabs(xsml)/10; if (!tmp) tmp=0.1;
! 1614: xbig+=tmp; xsml-=tmp;
! 1615: }
! 1616: if (ybig-ysml < 1.e-9)
! 1617: {
! 1618: tmp=fabs(ysml)/10; if (!tmp) tmp=0.1;
! 1619: ybig+=tmp; ysml-=tmp;
! 1620: }
! 1621:
! 1622: if (WW)
! 1623: { /* no rectwindow supplied ==> ps or screen output */
! 1624: char c1[16],c2[16],c3[16],c4[16];
! 1625: PARI_plot W = *WW;
! 1626: long lm = W.fwidth*10; /* left margin */
! 1627: long rm = W.hunit-1; /* right margin */
! 1628: long tm = W.vunit-1; /* top margin */
! 1629: long bm = W.vunit+W.fheight-1; /* bottom margin */
! 1630: long is = W.width - (lm+rm);
! 1631: long js = W.height - (tm+bm);
! 1632:
! 1633: wx[0]=wy[0]=0; wx[1]=lm; wy[1]=tm;
! 1634: /* Window size (W.width x W.height) is given in pixels, and
! 1635: * correct pixels are 0..w_width-1.
! 1636: * On the other hand, rect functions work with windows whose pixel
! 1637: * range is [0,width]. */
! 1638: initrect(stringrect, W.width-1, W.height-1);
! 1639: if (drawrect != stringrect) initrect(drawrect, is-1, js-1);
! 1640:
! 1641: /* draw labels on stringrect */
! 1642: sprintf(c1,"%.5g",ybig); sprintf(c2,"%.5g",ysml);
! 1643: sprintf(c3,"%.5g",xsml); sprintf(c4,"%.5g",xbig);
! 1644:
! 1645: rectlinetype(stringrect,-2); /* Frame */
! 1646: current_color[stringrect]=BLACK;
! 1647: put_string( stringrect, lm, 0, c1,
! 1648: RoSTdirRIGHT | RoSTdirHGAP | RoSTdirTOP);
! 1649: put_string(stringrect, lm, W.height - bm, c2,
! 1650: RoSTdirRIGHT | RoSTdirHGAP | RoSTdirVGAP);
! 1651: put_string(stringrect, lm, W.height - bm, c3,
! 1652: RoSTdirLEFT | RoSTdirTOP);
! 1653: put_string(stringrect, W.width - rm - 1, W.height - bm, c4,
! 1654: RoSTdirRIGHT | RoSTdirTOP);
! 1655: }
! 1656: RHasGraph(check_rect(drawrect)) = 1;
! 1657:
! 1658: if (!(flags & PLOT_NO_RESCALE))
! 1659: rectscale0(drawrect, xsml, xbig, ysml, ybig);
! 1660:
! 1661: if (!(flags & PLOT_NO_FRAME))
! 1662: {
! 1663: int do_double = (flags & PLOT_NODOUBLETICK) ? TICKS_NODOUBLE : 0;
! 1664:
! 1665: rectlinetype(drawrect, -2); /* Frame. */
! 1666: current_color[drawrect]=BLACK;
! 1667: rectmove0(drawrect,xsml,ysml,0);
! 1668: rectbox0(drawrect,xbig,ybig,0);
! 1669: if (!(flags & PLOT_NO_TICK_X)) {
! 1670: rectticks(WW, drawrect, xsml, ysml, xbig, ysml, xsml, xbig,
! 1671: TICKS_CLOCKW | do_double);
! 1672: rectticks(WW, drawrect, xbig, ybig, xsml, ybig, xbig, xsml,
! 1673: TICKS_CLOCKW | do_double);
! 1674: }
! 1675: if (!(flags & PLOT_NO_TICK_Y)) {
! 1676: rectticks(WW, drawrect, xbig, ysml, xbig, ybig, ysml, ybig,
! 1677: TICKS_CLOCKW | do_double);
! 1678: rectticks(WW, drawrect, xsml, ybig, xsml, ysml, ybig, ysml,
! 1679: TICKS_CLOCKW | do_double);
! 1680: }
! 1681: }
! 1682:
! 1683: if (!(flags & PLOT_NO_AXE_Y) && (xsml<=0 && xbig >=0))
! 1684: {
! 1685: rectlinetype(drawrect, -1); /* Axes. */
! 1686: current_color[drawrect]=BLUE;
! 1687: rectmove0(drawrect,0.0,ysml,0);
! 1688: rectline0(drawrect,0.0,ybig,0);
! 1689: }
! 1690:
! 1691: if (!(flags & PLOT_NO_AXE_X) && (ysml<=0 && ybig >=0))
! 1692: {
! 1693: rectlinetype(drawrect, -1); /* Axes. */
! 1694: current_color[drawrect]=BLUE;
! 1695: rectmove0(drawrect,xsml,0.0,0);
! 1696: rectline0(drawrect,xbig,0.0,0);
! 1697: }
! 1698:
! 1699: i = (flags & PLOT_PARAMETRIC)? 0: 1;
! 1700: for (ltype = 0; ltype < nc; ltype++)
! 1701: {
! 1702: current_color[drawrect] = ltype&1 ? SIENNA: RED;
! 1703: if (flags & PLOT_PARAMETRIC) x = data[i++];
! 1704:
! 1705: y=data[i++]; nbpoints=y.nb;
! 1706: if ((flags & PLOT_POINTS_LINES) || (flags & PLOT_POINTS)) {
! 1707: rectlinetype(drawrect, rectpoint_itype + ltype); /* Graphs. */
! 1708: rectpointtype(drawrect, rectpoint_itype + ltype); /* Graphs. */
! 1709: rectpoints0(drawrect,x.d,y.d,nbpoints);
! 1710: }
! 1711: if ((flags & PLOT_POINTS_LINES) || !(flags & PLOT_POINTS)) {
! 1712: if (flags & PLOT_SPLINES) {
! 1713: /* rectsplines will call us back with ltype == 0 */
! 1714: int old = rectline_itype;
! 1715:
! 1716: rectline_itype = rectline_itype + ltype;
! 1717: rectsplines(drawrect,x.d,y.d,nbpoints,flags);
! 1718: rectline_itype = old;
! 1719: } else {
! 1720: rectlinetype(drawrect, rectline_itype + ltype); /* Graphs. */
! 1721: rectlines0(drawrect,x.d,y.d,nbpoints,0);
! 1722: }
! 1723: }
! 1724: }
! 1725: for (i--; i>=0; i--) free(data[i].d);
! 1726: free(data);
! 1727:
! 1728: if (WW)
! 1729: {
! 1730: if (flags & PLOT_POSTSCRIPT)
! 1731: postdraw0(w,wx,wy,2);
! 1732: else
! 1733: rectdraw0(w,wx,wy,2, 0);
! 1734:
! 1735: killrect(drawrect); if (stringrect != drawrect) killrect(stringrect);
! 1736: }
! 1737:
! 1738: avma=ltop;
! 1739: res = cgetg(5,t_VEC);
! 1740: res[1]=(long)dbltor(xsml); res[2]=(long)dbltor(xbig);
! 1741: res[3]=(long)dbltor(ysml); res[4]=(long)dbltor(ybig);
! 1742: return res;
! 1743: }
! 1744:
! 1745: /*************************************************************************/
! 1746: /* */
! 1747: /* HI-RES FUNCTIONS */
! 1748: /* */
! 1749: /*************************************************************************/
! 1750:
! 1751: GEN
! 1752: rectploth(long drawrect,entree *ep,GEN a,GEN b,char *ch,
! 1753: long prec,ulong flags,long testpoints)
! 1754: {
! 1755: dblPointList *pl=rectplothin(ep, a,b, ch, prec, flags,testpoints);
! 1756: return rectplothrawin(0,drawrect, pl, flags,NULL);
! 1757: }
! 1758:
! 1759: GEN
! 1760: rectplothraw(long drawrect, GEN data, long flags)
! 1761: {
! 1762: dblPointList *pl=gtodblList(data,flags);
! 1763: return rectplothrawin(0,drawrect,pl,flags,NULL);
! 1764: }
! 1765:
! 1766: static PARI_plot*
! 1767: init_output(long flags)
! 1768: {
! 1769: if (flags & PLOT_POSTSCRIPT)
! 1770: { PARI_get_psplot(); return &pari_psplot; }
! 1771: else
! 1772: { PARI_get_plot(0); return &pari_plot; }
! 1773: }
! 1774:
! 1775: static GEN
! 1776: ploth0(long stringrect,long drawrect,entree *ep,GEN a,GEN b,char *ch,
! 1777: long prec,ulong flags,long testpoints)
! 1778: {
! 1779: PARI_plot *output = init_output(flags);
! 1780: dblPointList *pl=rectplothin(ep, a,b, ch, prec, flags,testpoints);
! 1781: return rectplothrawin(stringrect,drawrect, pl, flags, output);
! 1782: }
! 1783:
! 1784: static GEN
! 1785: plothraw0(long stringrect, long drawrect, GEN listx, GEN listy, long flags)
! 1786: {
! 1787: PARI_plot *output = init_output(flags);
! 1788: long data[] = {evaltyp(t_VEC) | m_evallg(3), 0, 0};
! 1789: dblPointList *pl;
! 1790:
! 1791: data[1] = (long) listx;
! 1792: data[2] = (long) listy;
! 1793: pl=gtodblList(data,PLOT_PARAMETRIC);
! 1794: if (!pl) return cgetg(1,t_VEC);
! 1795: return rectplothrawin(stringrect,drawrect,pl,flags | PLOT_PARAMETRIC,output);
! 1796: }
! 1797:
! 1798: GEN
! 1799: plothraw(GEN listx, GEN listy, long flags)
! 1800: {
! 1801: flags = (flags > 1 ? flags : (flags ? 0: PLOT_POINTS));
! 1802: return plothraw0(STRINGRECT, DRAWRECT, listx, listy, flags);
! 1803: }
! 1804:
! 1805: GEN
! 1806: ploth(entree *ep, GEN a, GEN b, char *ch, long prec,long flags,long numpoints)
! 1807: {
! 1808: return ploth0(STRINGRECT, DRAWRECT, ep,a,b,ch,prec,flags,numpoints);
! 1809: }
! 1810:
! 1811: GEN
! 1812: ploth2(entree *ep, GEN a, GEN b, char *ch, long prec)
! 1813: {
! 1814: return ploth0(STRINGRECT, DRAWRECT, ep,a,b,ch,prec,PLOT_PARAMETRIC,0);
! 1815: }
! 1816:
! 1817: GEN
! 1818: plothmult(entree *ep, GEN a, GEN b, char *ch, long prec)
! 1819: {
! 1820: return ploth0(STRINGRECT, DRAWRECT, ep,a,b,ch,prec,0,0);
! 1821: }
! 1822:
! 1823: GEN
! 1824: postplothraw(GEN listx, GEN listy, long flags)
! 1825: {
! 1826: flags=(flags)? 0: PLOT_POINTS;
! 1827: return plothraw0(STRINGRECT, DRAWRECT, listx, listy, flags|PLOT_POSTSCRIPT);
! 1828: }
! 1829:
! 1830: GEN
! 1831: postploth(entree *ep, GEN a, GEN b, char *ch, long prec,long flags,
! 1832: long numpoints)
! 1833: {
! 1834: return ploth0(STRINGRECT,DRAWRECT,ep,a,b,ch,prec,flags|PLOT_POSTSCRIPT,
! 1835: numpoints);
! 1836: }
! 1837:
! 1838: GEN
! 1839: postploth2(entree *ep, GEN a, GEN b, char *ch, long prec,
! 1840: long numpoints)
! 1841: {
! 1842: return ploth0(STRINGRECT,DRAWRECT,ep,a,b,ch,prec,
! 1843: PLOT_PARAMETRIC|PLOT_POSTSCRIPT,numpoints);
! 1844: }
! 1845:
! 1846: GEN
! 1847: plothsizes()
! 1848: {
! 1849: return plothsizes_flag(0);
! 1850: }
! 1851:
! 1852: GEN
! 1853: plothsizes_flag(long flag)
! 1854: {
! 1855: GEN vect = cgetg(1+6,t_VEC);
! 1856:
! 1857: PARI_get_plot(0);
! 1858: vect[1] = lstoi(w_width);
! 1859: vect[2] = lstoi(w_height);
! 1860: if (flag) {
! 1861: vect[3] = (long)dbltor(h_unit*1.0/w_width);
! 1862: vect[4] = (long)dbltor(v_unit*1.0/w_height);
! 1863: vect[5] = (long)dbltor(f_width*1.0/w_width);
! 1864: vect[6] = (long)dbltor(f_height*1.0/w_height);
! 1865: } else {
! 1866: vect[3] = lstoi(h_unit);
! 1867: vect[4] = lstoi(v_unit);
! 1868: vect[5] = lstoi(f_width);
! 1869: vect[6] = lstoi(f_height);
! 1870: }
! 1871: return vect;
! 1872: }
! 1873:
! 1874: /*************************************************************************/
! 1875: /* */
! 1876: /* POSTSCRIPT OUTPUT */
! 1877: /* */
! 1878: /*************************************************************************/
! 1879:
! 1880: typedef struct spoint {
! 1881: int x,y; } SPoint;
! 1882: typedef struct ssegment {
! 1883: int x1,y1,x2,y2; } SSegment;
! 1884: typedef struct srectangle {
! 1885: int x,y,width,height; } SRectangle;
! 1886:
! 1887: static void ps_point(FILE *psfile, int x, int y);
! 1888: static void ps_line(FILE *psfile, int x1, int y1, int x2, int y2);
! 1889: static void ps_rect(FILE *psfile, int x1, int y1, int x2, int y2);
! 1890: static void ps_string(FILE *psfile, int x, int y, char *c, long dir);
! 1891:
! 1892: #undef ISCR
! 1893: #undef JSCR
! 1894: #define ISCR 1120 /* 1400 en haute resolution */
! 1895: #define JSCR 800 /* 1120 en haute resolution */
! 1896:
! 1897: static void
! 1898: PARI_get_psplot()
! 1899: {
! 1900: pari_psplot.height = JSCR - 60;
! 1901: pari_psplot.width = ISCR - 40;
! 1902: pari_psplot.fheight = 15;
! 1903: pari_psplot.fwidth = 6;
! 1904: pari_psplot.hunit = 5;
! 1905: pari_psplot.vunit = 5;
! 1906: }
! 1907:
! 1908: static void
! 1909: gendraw(GEN list, long ps, long flag)
! 1910: {
! 1911: long i,n,ne,*w,*x,*y;
! 1912: GEN x0,y0,win;
! 1913:
! 1914: if (typ(list) != t_VEC) err(talker,"not a vector in rectdraw");
! 1915: n = lg(list)-1;
! 1916: if (n%3) err(talker,"incorrect number of components in rectdraw");
! 1917: n = n/3; if (!n) return;
! 1918: w = (long*)gpmalloc(n*sizeof(long));
! 1919: x = (long*)gpmalloc(n*sizeof(long));
! 1920: y = (long*)gpmalloc(n*sizeof(long));
! 1921: if (flag)
! 1922: PARI_get_plot(0);
! 1923: for (i=0; i<n; i++)
! 1924: {
! 1925: win=(GEN)list[3*i+1]; x0=(GEN)list[3*i+2]; y0=(GEN)list[3*i+3];
! 1926: if (typ(win)!=t_INT || (!flag && (typ(x0)!=t_INT || typ(y0)!= t_INT)))
! 1927: err(talker, "not an integer type in rectdraw");
! 1928: if (flag) {
! 1929: double xd = gtodouble(x0), yd = gtodouble(y0);
! 1930: long xi, yi;
! 1931:
! 1932: xi = w_width - 1; yi = w_height - 1;
! 1933: xi = (long)(xd*xi + 0.5);
! 1934: yi = (long)(yd*yi + 0.5);
! 1935: x[i] = xi; y[i] = yi;
! 1936: } else {
! 1937: x[i]=itos(x0); y[i]=itos(y0);
! 1938: }
! 1939: ne=itos(win); check_rect(ne);
! 1940: w[i]=ne;
! 1941: }
! 1942: if (ps) postdraw00(w,x,y,n,flag); else rectdraw0(w,x,y,n, 1);
! 1943: free(x); free(y); free(w);
! 1944: }
! 1945:
! 1946: void
! 1947: postdraw(GEN list) { gendraw(list, 1, 0); }
! 1948:
! 1949: void
! 1950: rectdraw(GEN list) { gendraw(list, 0, 0); }
! 1951:
! 1952: void
! 1953: postdraw_flag(GEN list, long flag) { gendraw(list, 1, flag); }
! 1954:
! 1955: void
! 1956: rectdraw_flag(GEN list, long flag) { gendraw(list, 0, flag); }
! 1957:
! 1958: static char*
! 1959: zmalloc(size_t x)
! 1960: {
! 1961: return x? gpmalloc(x): NULL;
! 1962: }
! 1963:
! 1964: void
! 1965: postdraw0(long *w, long *x, long *y, long lw)
! 1966: {
! 1967: postdraw00(w, x, y, lw, 0);
! 1968: }
! 1969:
! 1970: void
! 1971: postdraw00(long *w, long *x, long *y, long lw, long scale)
! 1972: {
! 1973: double *ptx,*pty;
! 1974: long *numpoints,*numtexts,*xtexts,*ytexts,*dirtexts;
! 1975: RectObj *p1;
! 1976: PariRect *e;
! 1977: long i,j,x0,y0;
! 1978: long a,b,c,d,nd[ROt_MAX+1];
! 1979: char **texts;
! 1980: FILE *psfile;
! 1981: double xscale = 0.65, yscale = 0.65;
! 1982: long fontsize = 16, xtick = 5, ytick = 5;
! 1983:
! 1984: SPoint *points, **lines, *SLine;
! 1985: SSegment *seg;
! 1986: SRectangle *rect, SRec;
! 1987:
! 1988: if (scale) {
! 1989: double postxsize, postysize;
! 1990:
! 1991: PARI_get_psplot();
! 1992: postxsize = pari_psplot.width;
! 1993: postysize = pari_psplot.height;
! 1994: PARI_get_plot(0);
! 1995: xscale *= postxsize * 1.0/w_width;
! 1996: fontsize = (long) (fontsize/(postxsize * 1.0/w_width));
! 1997: yscale *= postysize * 1.0/w_height;
! 1998: xtick = h_unit; ytick = v_unit;
! 1999: }
! 2000: psfile = fopen(current_psfile, "a");
! 2001: if (!psfile)
! 2002: err(openfiler,"postscript",current_psfile);
! 2003:
! 2004: for (i=0; i<=ROt_MAX; i++) nd[i]=0;
! 2005:
! 2006: for (i=0; i<lw; i++)
! 2007: {
! 2008: e = check_rect_init(w[i]); p1=RHead(e);
! 2009: while (p1)
! 2010: {
! 2011: if (RoType(p1) != ROt_MP) nd[RoType(p1)]++;
! 2012: else nd[ROt_PT]+=RoMPcnt(p1);
! 2013: p1=RoNext(p1);
! 2014: }
! 2015: }
! 2016: points=(SPoint*) zmalloc(nd[ROt_PT]*sizeof(SPoint));
! 2017: seg=(SSegment*) zmalloc(nd[ROt_LN]*sizeof(SSegment));
! 2018: rect=(SRectangle*) zmalloc(nd[ROt_BX]*sizeof(SRectangle));
! 2019: lines=(SPoint**) zmalloc(nd[ROt_ML]*sizeof(SPoint*));
! 2020: numpoints=(long*) zmalloc(nd[ROt_ML]*sizeof(long));
! 2021: texts=(char**) zmalloc(nd[ROt_ST]*sizeof(char*));
! 2022: numtexts=(long*) zmalloc(nd[ROt_ST]*sizeof(long));
! 2023: xtexts = (long*) zmalloc(nd[ROt_ST]*sizeof(long));
! 2024: ytexts = (long*) zmalloc(nd[ROt_ST]*sizeof(long));
! 2025: dirtexts = (long*) zmalloc(nd[ROt_ST]*sizeof(long));
! 2026: for (i=0; i<=ROt_MAX; i++) nd[i]=0;
! 2027:
! 2028: for (i=0; i<lw; i++)
! 2029: {
! 2030: e=rectgraph[w[i]]; p1=RHead(e); x0=x[i]; y0=y[i];
! 2031: while (p1)
! 2032: {
! 2033: switch(RoType(p1))
! 2034: {
! 2035: case ROt_PT:
! 2036: points[nd[ROt_PT]].x = DTOL(RoPTx(p1)+x0);
! 2037: points[nd[ROt_PT]].y = DTOL(RoPTy(p1)+y0);
! 2038: nd[ROt_PT]++; break;
! 2039: case ROt_LN:
! 2040: seg[nd[ROt_LN]].x1 = DTOL(RoLNx1(p1)+x0);
! 2041: seg[nd[ROt_LN]].y1 = DTOL(RoLNy1(p1)+y0);
! 2042: seg[nd[ROt_LN]].x2 = DTOL(RoLNx2(p1)+x0);
! 2043: seg[nd[ROt_LN]].y2 = DTOL(RoLNy2(p1)+y0);
! 2044: nd[ROt_LN]++; break;
! 2045: case ROt_BX:
! 2046: a=rect[nd[ROt_BX]].x = DTOL(RoBXx1(p1)+x0);
! 2047: b=rect[nd[ROt_BX]].y = DTOL(RoBXy1(p1)+y0);
! 2048: rect[nd[ROt_BX]].width = DTOL(RoBXx2(p1)+x0-a);
! 2049: rect[nd[ROt_BX]].height = DTOL(RoBXy2(p1)+y0-b);
! 2050: nd[ROt_BX]++; break;
! 2051: case ROt_MP:
! 2052: ptx = RoMPxs(p1); pty = RoMPys(p1);
! 2053: for (j=0; j<RoMPcnt(p1); j++)
! 2054: {
! 2055: points[nd[ROt_PT]+j].x = DTOL(ptx[j]+x0);
! 2056: points[nd[ROt_PT]+j].y = DTOL(pty[j]+y0);
! 2057: }
! 2058: nd[ROt_PT]+=RoMPcnt(p1); break;
! 2059: case ROt_ML:
! 2060: ptx=RoMLxs(p1); pty=RoMLys(p1);
! 2061: numpoints[nd[ROt_ML]]=RoMLcnt(p1);
! 2062: lines[nd[ROt_ML]]=(SPoint*)gpmalloc(RoMLcnt(p1)*sizeof(SPoint));
! 2063: for (j=0; j<RoMLcnt(p1); j++)
! 2064: {
! 2065: lines[nd[ROt_ML]][j].x = DTOL(ptx[j]+x0);
! 2066: lines[nd[ROt_ML]][j].y = DTOL(pty[j]+y0);
! 2067: }
! 2068: nd[ROt_ML]++; break;
! 2069: case ROt_ST:
! 2070: texts[nd[ROt_ST]] = RoSTs(p1);
! 2071: numtexts[nd[ROt_ST]] = RoSTl(p1);
! 2072: xtexts[nd[ROt_ST]] = DTOL(RoSTx(p1)+x0);
! 2073: ytexts[nd[ROt_ST]] = DTOL(RoSTy(p1)+y0);
! 2074: dirtexts[nd[ROt_ST]] = RoSTdir(p1);
! 2075: nd[ROt_ST]++; break;
! 2076: default: break;
! 2077: }
! 2078: p1=RoNext(p1);
! 2079: }
! 2080: }
! 2081: /* Definitions taken from post terminal of Gnuplot. */
! 2082: fprintf(psfile,"%%!\n50 50 translate\n/Times-Roman findfont %ld scalefont setfont\n%g %g scale\n", fontsize, yscale,xscale);
! 2083: fprintf(psfile,"/Lshow { moveto 90 rotate show -90 rotate } def\n/Rshow { 3 -1 roll dup 4 1 roll stringwidth pop sub Lshow } def\n/Cshow { 3 -1 roll dup 4 1 roll stringwidth pop 2 div sub Lshow } def\n");
! 2084: fprintf(psfile,"/Xgap %ld def\n/Ygap %ld def\n", xtick, ytick);
! 2085: fprintf(psfile,"/Bbox { gsave newpath 0 0 moveto true charpath pathbbox grestore } def\n");
! 2086: fprintf(psfile,"/Height { Bbox 4 1 roll pop pop pop } def\n");
! 2087: fprintf(psfile,"/TopAt { 3 -1 roll dup 4 1 roll Height 3 -1 roll add exch } def\n");
! 2088: fprintf(psfile,"/VCenter { 3 -1 roll dup 4 1 roll Height 2 div 3 -1 roll add exch } def\n");
! 2089: fprintf(psfile,"/Tgap { exch Ygap add exch } def\n");
! 2090: fprintf(psfile,"/Bgap { exch Ygap sub exch } def\n");
! 2091: fprintf(psfile,"/Lgap { Xgap add } def\n");
! 2092: fprintf(psfile,"/Rgap { Xgap sub } def\n");
! 2093:
! 2094: for (i=0; i<nd[ROt_PT]; i++)
! 2095: ps_point(psfile,points[i].x,points[i].y);
! 2096: for (i=0; i<nd[ROt_LN]; i++)
! 2097: ps_line(psfile,seg[i].x1,seg[i].y1,seg[i].x2,seg[i].y2);
! 2098: for (i=0; i<nd[ROt_BX]; i++)
! 2099: {
! 2100: SRec=rect[i]; a=SRec.x; b=SRec.y; c=a+SRec.width;
! 2101: d=b+SRec.height; ps_rect(psfile,a,b,c,d);
! 2102: }
! 2103: for (i=0; i<nd[ROt_ML]; i++)
! 2104: {
! 2105: SLine=lines[i];
! 2106: for (j=0; j<numpoints[i]; j++)
! 2107: {
! 2108: if (!j) fprintf(psfile,"%d %d moveto\n",SLine[0].y,SLine[0].x);
! 2109: else fprintf(psfile,"%d %d lineto\n",SLine[j].y,SLine[j].x);
! 2110: }
! 2111: }
! 2112: for (i=0; i<nd[ROt_ST]; i++)
! 2113: ps_string(psfile,xtexts[i],ytexts[i],texts[i], dirtexts[i]);
! 2114: fprintf(psfile,"stroke showpage\n"); fclose(psfile);
! 2115: #define xfree(pointer) if (pointer) free(pointer)
! 2116: xfree(points); xfree(seg); xfree(rect); xfree(numpoints);
! 2117: for (i=0; i<nd[ROt_ML]; i++) xfree(lines[i]);
! 2118: xfree(lines); xfree(texts); xfree(numtexts); xfree(xtexts); xfree(ytexts);
! 2119: #undef xfree
! 2120: }
! 2121:
! 2122: static void
! 2123: ps_point(FILE *psfile, int x, int y)
! 2124: {
! 2125: fprintf(psfile,"%d %d moveto\n0 2 rlineto 2 0 rlineto 0 -2 rlineto closepath fill\n",y,x);
! 2126: }
! 2127:
! 2128: static void
! 2129: ps_line(FILE *psfile, int x1, int y1, int x2, int y2)
! 2130: {
! 2131: fprintf(psfile,"%d %d moveto\n%d %d lineto\n",y1,x1,y2,x2);
! 2132: }
! 2133:
! 2134: static void
! 2135: ps_rect(FILE *psfile, int x1, int y1, int x2, int y2)
! 2136: {
! 2137: fprintf(psfile,"%d %d moveto\n%d %d lineto\n%d %d lineto\n%d %d lineto\nclosepath\n",y1,x1,y1,x2,y2,x2,y2,x1);
! 2138: }
! 2139:
! 2140: static void
! 2141: ps_string(FILE *psfile, int x, int y, char *s, long dir)
! 2142: {
! 2143: if (strpbrk(s, "(\\)")) {
! 2144: fprintf(psfile,"(");
! 2145: while (*s) {
! 2146: if ( *s=='(' || *s==')' || *s=='\\' )
! 2147: fputc('\\', psfile);
! 2148: fputc(*s, psfile);
! 2149: s++;
! 2150: }
! 2151: } else
! 2152: fprintf(psfile,"(%s", s);
! 2153: fprintf(psfile,") %d %d %s%s%s%sshow\n",
! 2154: y, x,
! 2155: ((dir & RoSTdirVGAP)
! 2156: ? ((dir & RoSTdirVPOS_mask) == RoSTdirTOP ? "Tgap " : "Bgap ")
! 2157: : ""),
! 2158: ((dir & RoSTdirHGAP)
! 2159: ? ((dir & RoSTdirHPOS_mask) == RoSTdirRIGHT ? "Rgap " : "Lgap ")
! 2160: : ""),
! 2161: ((dir & RoSTdirVPOS_mask) == RoSTdirBOTTOM ? ""
! 2162: : (dir & RoSTdirVPOS_mask) == RoSTdirTOP ? "TopAt " : "VCenter "),
! 2163: ((dir & RoSTdirHPOS_mask) == RoSTdirLEFT ? "L"
! 2164: : ((dir & RoSTdirHPOS_mask) == RoSTdirRIGHT ? "R" : "C")));
! 2165: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>