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