| 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;