Ilya Zakharevich on Sun, 5 Mar 2000 01:42:21 -0500 (EST) |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
[PATCH 2.0.15] ticks in plotting |
What I have here is a pretty old version of PARI, but I hope that the patch still applies. This patch adds ticks to plots, and allows new flags: 512 to plot no x-ticks, 1024 to plot no y-ticks, and 2048 to plot all ticks of the same length. Enjoy, Ilya --- ./src/graph/plotport.c-ppp Sun Oct 10 21:40:06 1999 +++ ./src/graph/plotport.c Sat Mar 4 23:58:50 2000 @@ -419,6 +419,127 @@ rectline0(long ne, double gx2, double gy RoCol(z)=current_color[ne]; } +/* Given coordinates of ends of a line, and labels l1 l2 attached to the + ends, plot ticks where the label coordinate takes "round" values */ + +static void +rectticks(long ne, double dx1, double dy1, double dx2, double dy2, double l1, double l2, long flags) +{ + long dx,dy,dxy,dxy1,x1,y1,x2,y2,nticks,n,n1,dn; + double minstep, maxstep, step, l_min, l_max, minl, maxl, dl, dtx, dty, x, y; + double ddx, ddy; + const double mult[3] = { 2./1., 5./2., 10./5. }; + PariRect *e = check_rect_init(ne); + + x1 = DTOL(dx1*RXscale(e) + RXshift(e)); + y1 = DTOL(dy1*RYscale(e) + RYshift(e)); + x2 = DTOL(dx2*RXscale(e) + RXshift(e)); + y2 = DTOL(dy2*RYscale(e) + RYshift(e)); + dx = x2 - x1; + dy = y2 - y1; + if (dx < 0) + dx = -dx; + if (dy < 0) + dy = -dy; + if (dx < dy) + dxy1 = dy; + else + dxy1 = dx; + dx /= h_unit; + dy /= v_unit; + dxy = sqrt(dx*dx + dy*dy); + nticks = (dxy + 2.5)/4; + if (!nticks) + return; + /* Now we want to find nticks (or less) "round" numbers between l1 and l2. + For our purpose round numbers have "last significant" digit either + *) any; + *) even; + *) divisible by 5. + We need to choose which alternative is better. + */ + if (l1 < l2) + l_min = l1, l_max = l2; + else + l_min = l2, l_max = l1; + minstep = (l_max - l_min)/(nticks + 1); + maxstep = 2.5*(l_max - l_min); + step = exp(log(10) * floor(log10(minstep))); + if (!(flags & TICKS_ENDSTOO)) { + double d = 2*(l_max - l_min)/dxy1; /* Two pixels off */ + + l_min += d; + l_max -= d; + } + for (n = 0; ; n++) { + if (step >= maxstep) + return; + if (step >= minstep) { + minl = ceil(l_min/step); + maxl = floor(l_max/step); + if (minl <= maxl && maxl - minl + 1 <= nticks) { + nticks = maxl - minl + 1; + l_min = minl * step; + l_max = maxl * step; + if (!(flags & TICKS_NODOUBLE)) { + /* Where to position doubleticks, variants: + small: each 5, double: each 10 (n===2 mod 3) + small: each 2, double: each 10 (n===1 mod 3) + small: each 1, double: each 5 */ + if (n % 3 == 2) + dn = 2; + else + dn = 5; + n1 = ((long)minl) % dn; + } + break; + } + } + step *= mult[ n % 3 ]; + } + /* now l_min and l_max keep min/max values of l with ticks, and nticks is + the number of ticks to draw. */ + if (nticks > 1) { + dl = (l_max - l_min)/(nticks - 1); + ddx = (dx2 - dx1) * dl / (l2 - l1); + ddy = (dy2 - dy1) * dl / (l2 - l1); + } + x = dx1 + (dx2 - dx1) * (l_min - l1) / (l2 - l1); + y = dy1 + (dy2 - dy1) * (l_min - l1) / (l2 - l1); + /* assume h_unit and v_unit form a square. For clockwise ticks: */ + dtx = h_unit * dy/dxy * (y2 > y1 ? 1 : -1); /* y-coord runs down */ + dty = v_unit * dx/dxy * (x2 > x1 ? 1 : -1); + for (n = 0; n < nticks; n++) { + RectObj *z = (RectObj*) gpmalloc(sizeof(RectObj2P)); + double lunit = h_unit > 1 ? 1.5 : 2; + double l; + + RoNext(z) = 0; + RoLNx1(z) = RoLNx2(z) = x*RXscale(e) + RXshift(e); + RoLNy1(z) = RoLNy2(z) = y*RYscale(e) + RYshift(e); + l = ((flags & TICKS_NODOUBLE) || (n + n1) % dn != 0) ? 1 : lunit; + + if (flags & TICKS_CLOCKW) { + RoLNx1(z) += dtx*l; + RoLNy1(z) -= dty*l; /* y-coord runs down */ + } + if (flags & TICKS_ACLOCKW) { + RoLNx2(z) -= dtx*l; + RoLNy2(z) += dty*l; /* y-coord runs down */ + } + RoType(z) = ROt_LN; + + if (!RHead(e)) + RHead(e)=RTail(e)=z; + else { + RoNext(RTail(e))=z; RTail(e)=z; + } + RoCol(z)=current_color[ne]; + x += ddx; + y += ddy; + } +} + void rectline(long ne, GEN gx2, GEN gy2) { @@ -1497,10 +1618,24 @@ rectplothrawin(long stringrect, long dra if (!(flags & PLOT_NO_FRAME)) { + int do_double = (flags & PLOT_NODOUBLETICK) ? TICKS_NODOUBLE : 0; + rectlinetype(drawrect, -2); /* Frame. */ current_color[drawrect]=BLACK; rectmove0(drawrect,xsml,ysml,0); rectbox0(drawrect,xbig,ybig,0); + if (!(flags & PLOT_NO_TICK_X)) { + rectticks(drawrect, xsml, ysml, xbig, ysml, xsml, xbig, + TICKS_CLOCKW | do_double); + rectticks(drawrect, xbig, ybig, xsml, ybig, xbig, xsml, + TICKS_CLOCKW | do_double); + } + if (!(flags & PLOT_NO_TICK_Y)) { + rectticks(drawrect, xbig, ysml, xbig, ybig, ysml, ybig, + TICKS_CLOCKW | do_double); + rectticks(drawrect, xsml, ybig, xsml, ysml, ybig, ysml, + TICKS_CLOCKW | do_double); + } } if (!(flags & PLOT_NO_AXE_Y) && (xsml<=0 && xbig >=0)) --- ./src/graph/rect.h-ppp Sun Oct 10 20:44:06 1999 +++ ./src/graph/rect.h Sat Mar 4 23:55:48 2000 @@ -204,6 +204,9 @@ typedef struct RectObjPS { #define PLOT_POINTS 0x00040 #define PLOT_POINTS_LINES 0x00080 #define PLOT_SPLINES 0x00100 +#define PLOT_NO_TICK_X 0x00200 +#define PLOT_NO_TICK_Y 0x00400 +#define PLOT_NODOUBLETICK 0x00800 #define PLOT_POSTSCRIPT 0x80000 @@ -212,6 +215,15 @@ typedef struct RectObjPS { #define RECT_CP_SW 0x2 #define RECT_CP_SE 0x4 #define RECT_CP_NE 0x6 + +#define TICKS_CLOCKW 1 /* Draw in clockwise direction */ +#define TICKS_ACLOCKW 2 /* Draw in anticlockwise direction */ +#define TICKS_ENDSTOO 4 /* Draw at endspoints if needed */ +#define TICKS_NODOUBLE 8 /* Do not draw double-length ticks */ + +/* Not implemented yet */ +#define TICKS_COORD 16 /* Output [x,y,l,isdbl] for each tick */ +#define TICKS_RELATIVE 32 /* x,y-coordinates are relative */ extern PariRect **rectgraph; extern long rectpoint_itype;