[Rd] GCircle(): fails for non-clippable devices under certain circumstances (see below) (PR#940)

thoffman@zappa.sax.de thoffman@zappa.sax.de
Tue, 15 May 2001 23:36:37 +0200 (MET DST)


The following code snippet from graphics.c: GCircle() (around line 3100) fails for devices which 
can not clip (dd->dp.canClip==0) and try to plot a circle that does not fit into the plot region, but
fits into the device region, see inserted comments:

....
    result = clipCircleCode(x, y, coords, ir, dd);
// result>0, because circle does not fit into plot region (for dd->gp.xpd=0)

    switch (result) {
    case -2: /* No clipping;  draw all of circle */
        dd->dp.circle(x, y, coords, ir, bg, fg, dd);
        break;
    case -1: /* Total clipping; draw nothing */
        break;
    default: /* Partial clipping; draw poly[line|gon] */
// we proceed here:
        dd->gp.xpd = 2;
// check clipping for the device region:
        result = clipCircleCode(x, y, coords, ir, dd);
// ...if it fits, result=-2: ouch, we have thrown away the result from the 1st check!
        dd->gp.xpd = xpdsaved;
        if (dd->dp.canClip && result == -2) {
// ...but it does not matter if we can clip!
            GClip(dd);
            dd->dp.circle(x, y, coords, ir, bg, fg, dd);
        }
        else {
//...BUT if we can not clip, then we call for trouble:
            vmax = vmaxget();$

....
    default: /* Partial clipping; draw poly[line|gon] */
      if (dd->dp.canClip) {
	dd->gp.xpd = 2;
	result = clipCircleCode(x, y, coords, ir, dd);
	dd->gp.xpd = xpdsaved;
	if (result == -2) {
	    GClip(dd);
	    dd->dp.circle(x, y, coords, ir, bg, fg, dd);
	    break;
	}
      }
      vmax = vmaxget();
      xc = (double*)R_alloc(result+1, sizeof(double));
      yc = (double*)R_alloc(result+1, sizeof(double));
      GConvert(&x, &y, coords, DEVICE, dd);
      convertCircle(x, y, ir, result, xc, yc, dd);
      if (bg == NA_INTEGER) {
	dd->gp.col = fg;
	GPolyline(result+1, xc, yc, DEVICE, dd);
      }
      else {
	int npts;
	double *xcc, *ycc;
	xcc = ycc = 0;	/* -Wall */
	npts = GClipPolygon(xc, yc, result, DEVICE, 0, xcc, ycc, dd);
	if (npts > 1) {
	  xcc = (double*)R_alloc(npts, sizeof(double));
	  ycc = (double*)R_alloc(npts, sizeof(double));
	  npts = GClipPolygon(xc, yc, result, DEVICE, 1,
			      xcc, ycc, dd);
	  dd->dp.polygon(npts, xcc, ycc, DEVICE, bg, fg, dd);
	}
      }
      vmaxset(vmax);
    }
}


This works at least in my test case at

> version
         _
platform i386-pc-os2_emx
arch     i386
os       os2_emx
system   i386, os2_emx
status
major    1
minor    2.2
year     2001
month    02
day      26
language R


Thomas Hoffmann.


-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-devel-request@stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._