The R Project SVN R

Rev

Rev 59267 | Rev 59282 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 59267 Rev 59276
Line 196... Line 196...
196
	    }
196
	    }
197
	}
197
	}
198
    } /* linear / log */
198
    } /* linear / log */
199
    return at;
199
    return at;
200
}
200
}
201
 
-
 
202
    /* GRAPHICS FUNCTION ENTRY POINTS */
-
 
203
 
-
 
204
 
-
 
205
SEXP attribute_hidden do_plot_new(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
206
{
-
 
207
    /* plot.new() - create a new plot "frame" */
-
 
208
 
-
 
209
    pGEDevDesc dd;
-
 
210
 
-
 
211
    checkArity(op, args);
-
 
212
 
-
 
213
    dd = GEcurrentDevice();
-
 
214
    /*
-
 
215
     * If user is prompted before new page, user has opportunity
-
 
216
     * to kill current device.  GNewPlot returns (potentially new)
-
 
217
     * current device.
-
 
218
     */
-
 
219
    dd = GNewPlot(GRecording(call, dd));
-
 
220
 
-
 
221
    dpptr(dd)->xlog = gpptr(dd)->xlog = FALSE;
-
 
222
    dpptr(dd)->ylog = gpptr(dd)->ylog = FALSE;
-
 
223
 
-
 
224
    GScale(0.0, 1.0, 1, dd);
-
 
225
    GScale(0.0, 1.0, 2, dd);
-
 
226
    GMapWin2Fig(dd);
-
 
227
    GSetState(1, dd);
-
 
228
 
-
 
229
    if (GRecording(call, dd))
-
 
230
	GErecordGraphicOperation(op, args, dd);
-
 
231
    return R_NilValue;
-
 
232
}
-
 
233
 
-
 
234
static void drawPointsLines(double xp, double yp, double xold, double yold,
-
 
235
			    char type, int first, pGEDevDesc dd)
-
 
236
{
-
 
237
    if (type == 'p' || type == 'o')
-
 
238
	GSymbol(xp, yp, DEVICE, gpptr(dd)->pch, dd);
-
 
239
    if ((type == 'l' || type == 'o') && !first)
-
 
240
	GLine(xold, yold, xp, yp, DEVICE, dd);
-
 
241
}
-
 
242
 
-
 
243
 
-
 
244
SEXP attribute_hidden do_locator(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
245
{
-
 
246
    SEXP x, y, nobs, ans, saveans, stype = R_NilValue;
-
 
247
    int i, n;
-
 
248
    char type = 'p';
-
 
249
    double xp, yp, xold=0, yold=0;
-
 
250
    pGEDevDesc dd = GEcurrentDevice();
-
 
251
 
-
 
252
    /* If replaying, just draw the points and lines that were recorded */
-
 
253
    if (call == R_NilValue) {
-
 
254
	x = CAR(args); args = CDR(args);
-
 
255
	y = CAR(args); args = CDR(args);
-
 
256
	nobs = CAR(args); args = CDR(args);
-
 
257
	n = INTEGER(nobs)[0];
-
 
258
	stype = CAR(args); args = CDR(args);
-
 
259
	type = CHAR(STRING_ELT(stype, 0))[0];
-
 
260
	if (type != 'n') {
-
 
261
	    GMode(1, dd);
-
 
262
	    for (i = 0; i < n; i++) {
-
 
263
		xp = REAL(x)[i];
-
 
264
		yp = REAL(y)[i];
-
 
265
		GConvert(&xp, &yp, USER, DEVICE, dd);
-
 
266
		drawPointsLines(xp, yp, xold, yold, type, i==0, dd);
-
 
267
		xold = xp;
-
 
268
		yold = yp;
-
 
269
	    }
-
 
270
	    GMode(0, dd);
-
 
271
	}
-
 
272
	return R_NilValue;
-
 
273
    } else {
-
 
274
	GCheckState(dd);
-
 
275
 
-
 
276
	checkArity(op, args);
-
 
277
	n = asInteger(CAR(args));
-
 
278
	if (n <= 0 || n == NA_INTEGER)
-
 
279
	    error(_("invalid number of points in locator()"));
-
 
280
	args = CDR(args);
-
 
281
	if (isString(CAR(args)) && LENGTH(CAR(args)) == 1)
-
 
282
	    stype = CAR(args);
-
 
283
	else
-
 
284
	    error(_("invalid plot type"));
-
 
285
	type = CHAR(STRING_ELT(stype, 0))[0];
-
 
286
	PROTECT(x = allocVector(REALSXP, n));
-
 
287
	PROTECT(y = allocVector(REALSXP, n));
-
 
288
	PROTECT(nobs=allocVector(INTSXP,1));
-
 
289
 
-
 
290
	GMode(2, dd);
-
 
291
	for (i = 0; i < n; i++) {
-
 
292
	    if (!GLocator(&(REAL(x)[i]), &(REAL(y)[i]), USER, dd)) break;
-
 
293
	    if (type != 'n') {
-
 
294
		GMode(1, dd);
-
 
295
		xp = REAL(x)[i];
-
 
296
		yp = REAL(y)[i];
-
 
297
		GConvert(&xp, &yp, USER, DEVICE, dd);
-
 
298
		drawPointsLines(xp, yp, xold, yold, type, i==0, dd);
-
 
299
		GMode(0, dd);
-
 
300
		GMode(2, dd);
-
 
301
		xold = xp; yold = yp;
-
 
302
	    }
-
 
303
	}
-
 
304
	GMode(0, dd);
-
 
305
	INTEGER(nobs)[0] = i;
-
 
306
	for (; i < n; i++) {
-
 
307
	    REAL(x)[i] = NA_REAL;
-
 
308
	    REAL(y)[i] = NA_REAL;
-
 
309
	}
-
 
310
	PROTECT(ans = allocList(3));
-
 
311
	SETCAR(ans, x);
-
 
312
	SETCADR(ans, y);
-
 
313
	SETCADDR(ans, nobs);
-
 
314
	PROTECT(saveans = allocList(4));
-
 
315
	SETCAR(saveans, x);
-
 
316
	SETCADR(saveans, y);
-
 
317
	SETCADDR(saveans, nobs);
-
 
318
	SETCADDDR(saveans, CAR(args));
-
 
319
	/* Record the points and lines that were drawn in the display list */
-
 
320
	GErecordGraphicOperation(op, saveans, dd);
-
 
321
	UNPROTECT(5);
-
 
322
	return ans;
-
 
323
    }
-
 
324
}
-
 
325
 
-
 
326
static void drawLabel(double xi, double yi, int pos, double offset,
-
 
327
		      const char *l, cetype_t enc, pGEDevDesc dd)
-
 
328
{
-
 
329
    switch (pos) {
-
 
330
    case 4:
-
 
331
	xi = xi+offset;
-
 
332
	GText(xi, yi, INCHES, l, enc, 0.0,
-
 
333
	      dd->dev->yCharOffset, 0.0, dd);
-
 
334
	break;
-
 
335
    case 2:
-
 
336
	xi = xi-offset;
-
 
337
	GText(xi, yi, INCHES, l, enc, 1.0,
-
 
338
	      dd->dev->yCharOffset, 0.0, dd);
-
 
339
	break;
-
 
340
    case 3:
-
 
341
	yi = yi+offset;
-
 
342
	GText(xi, yi, INCHES, l, enc, 0.5,
-
 
343
	      0.0, 0.0, dd);
-
 
344
	break;
-
 
345
    case 1:
-
 
346
	yi = yi-offset;
-
 
347
	GText(xi, yi, INCHES, l, enc, 0.5,
-
 
348
	      1-(0.5-dd->dev->yCharOffset),
-
 
349
	      0.0, dd);
-
 
350
	break;
-
 
351
    case 0:
-
 
352
	GText(xi, yi, INCHES, l, enc, 0.0, 0.0, 0.0, dd);
-
 
353
	break;
-
 
354
    }
-
 
355
}
-
 
356
 
-
 
357
/* This manages R_Visible */
-
 
358
SEXP attribute_hidden do_identify(SEXP call, SEXP op, SEXP args, SEXP env)
-
 
359
{
-
 
360
    SEXP ans, x, y, l, ind, pos, Offset, draw, saveans;
-
 
361
    double xi, yi, xp, yp, d, dmin, offset, tol;
-
 
362
    int atpen, i, imin, k, n, nl, npts, plot, posi, warn;
-
 
363
    pGEDevDesc dd = GEcurrentDevice();
-
 
364
 
-
 
365
    /* If we are replaying the display list, then just redraw the
-
 
366
       labels beside the identified points */
-
 
367
    if (call == R_NilValue) {
-
 
368
	ind = CAR(args); args = CDR(args);
-
 
369
	pos = CAR(args); args = CDR(args);
-
 
370
	x = CAR(args); args = CDR(args);
-
 
371
	y = CAR(args); args = CDR(args);
-
 
372
	Offset = CAR(args); args = CDR(args);
-
 
373
	l = CAR(args); args = CDR(args);
-
 
374
	draw = CAR(args);
-
 
375
	n = LENGTH(x);
-
 
376
	nl = LENGTH(l);
-
 
377
	/*
-
 
378
	 * Most of the appropriate settings have been set up in
-
 
379
	 * R code by par(...)
-
 
380
	 * Hence no GSavePars() or ProcessInlinePars() here
-
 
381
	 * (also because this function is unusual in that it does
-
 
382
	 *  different things when run by a user compared to when
-
 
383
	 *  run from the display list)
-
 
384
	 * BUT par(cex) only sets cexbase, so here we set cex from cexbase
-
 
385
	 */
-
 
386
	gpptr(dd)->cex = gpptr(dd)->cexbase;
-
 
387
	offset = GConvertXUnits(asReal(Offset), CHARS, INCHES, dd);
-
 
388
	for (i = 0; i < n; i++) {
-
 
389
	    plot = LOGICAL(ind)[i];
-
 
390
	    if (LOGICAL(draw)[0] && plot) {
-
 
391
		xi = REAL(x)[i];
-
 
392
		yi = REAL(y)[i];
-
 
393
		GConvert(&xi, &yi, USER, INCHES, dd);
-
 
394
		posi = INTEGER(pos)[i];
-
 
395
		drawLabel(xi, yi, posi, offset,
-
 
396
			  CHAR(STRING_ELT(l, i % nl)),
-
 
397
			  getCharCE(STRING_ELT(l, i % nl)), dd);
-
 
398
	    }
-
 
399
	}
-
 
400
	return R_NilValue;
-
 
401
    }
-
 
402
    else {
-
 
403
	GCheckState(dd);
-
 
404
 
-
 
405
	checkArity(op, args);
-
 
406
	x = CAR(args); args = CDR(args);
-
 
407
	y = CAR(args); args = CDR(args);
-
 
408
	l = CAR(args); args = CDR(args);
-
 
409
	npts = asInteger(CAR(args)); args = CDR(args);
-
 
410
	plot = asLogical(CAR(args)); args = CDR(args);
-
 
411
	Offset = CAR(args); args = CDR(args);
-
 
412
	tol = asReal(CAR(args)); args = CDR(args);
-
 
413
	atpen = asLogical(CAR(args));
-
 
414
	if (npts <= 0 || npts == NA_INTEGER)
-
 
415
	    error(_("invalid number of points in identify()"));
-
 
416
	if (!isReal(x) || !isReal(y) || !isString(l) || !isReal(Offset))
-
 
417
	    error(_("incorrect argument type"));
-
 
418
	if (tol <= 0 || ISNAN(tol))
-
 
419
	    error(_("invalid '%s' value"), "tolerance");
-
 
420
	if (plot == NA_LOGICAL)
-
 
421
	    error(_("invalid '%s' value"), "plot");
-
 
422
	if (atpen == NA_LOGICAL)
-
 
423
	    error(_("invalid '%s' value"), "atpen");
-
 
424
	nl = LENGTH(l);
-
 
425
	if (nl <= 0)
-
 
426
	    error(_("zero length 'labels'"));
-
 
427
	n = LENGTH(x);
-
 
428
	if (n != LENGTH(y))
-
 
429
	    error(_("different argument lengths"));
-
 
430
	if (nl > n)
-
 
431
	    warning(_("more 'labels' than points"));
-
 
432
	if (n <= 0) {
-
 
433
	    R_Visible = FALSE;
-
 
434
	    return NULL;
-
 
435
	}
-
 
436
 
-
 
437
	/*
-
 
438
	 * Most of the appropriate settings have been set up in
-
 
439
	 * R code by par(...)
-
 
440
	 * Hence no GSavePars() or ProcessInlinePars() here
-
 
441
	 * (also because this function is unusual in that it does
-
 
442
	 *  different things when run by a user compared to when
-
 
443
	 *  run from the display list)
-
 
444
	 * BUT par(cex) only sets cexbase, so here we set cex from cexbase
-
 
445
	 */
-
 
446
	gpptr(dd)->cex = gpptr(dd)->cexbase;
-
 
447
	offset = GConvertXUnits(asReal(Offset), CHARS, INCHES, dd);
-
 
448
	PROTECT(ind = allocVector(LGLSXP, n));
-
 
449
	PROTECT(pos = allocVector(INTSXP, n));
-
 
450
	for (i = 0; i < n; i++) LOGICAL(ind)[i] = 0;
-
 
451
 
-
 
452
	k = 0;
-
 
453
	GMode(2, dd);
-
 
454
	PROTECT(x = duplicate(x));
-
 
455
	PROTECT(y = duplicate(y));
-
 
456
	while (k < npts) {
-
 
457
	    if (!GLocator(&xp, &yp, INCHES, dd)) break;
-
 
458
	    /*
-
 
459
	     * Repeat cex setting from cexbase within loop
-
 
460
	     * so that if window is redrawn
-
 
461
	     * (e.g., conver/uncover window)
-
 
462
	     * during identifying (i.e., between clicks)
-
 
463
	     * we reset cex properly.
-
 
464
	     */
-
 
465
	    gpptr(dd)->cex = gpptr(dd)->cexbase;
-
 
466
	    dmin = DBL_MAX;
-
 
467
	    imin = -1;
-
 
468
	    for (i = 0; i < n; i++) {
-
 
469
		xi = REAL(x)[i];
-
 
470
		yi = REAL(y)[i];
-
 
471
		GConvert(&xi, &yi, USER, INCHES, dd);
-
 
472
		if (!R_FINITE(xi) || !R_FINITE(yi)) continue;
-
 
473
		d = hypot(xp-xi, yp-yi);
-
 
474
		if (d < dmin) {
-
 
475
		    imin = i;
-
 
476
		    dmin = d;
-
 
477
		}
-
 
478
	    }
-
 
479
	    /* can't use warning because we want to print immediately  */
-
 
480
	    /* might want to handle warn=2? */
-
 
481
	    warn = asInteger(GetOption1(install("warn")));
-
 
482
	    if (dmin > tol) {
-
 
483
		if(warn >= 0) {
-
 
484
		    REprintf(_("warning: no point within %.2f inches\n"), tol);
-
 
485
		    R_FlushConsole();
-
 
486
		}
-
 
487
	    }
-
 
488
	    else if (LOGICAL(ind)[imin]) {
-
 
489
		if(warn >= 0 ) {
-
 
490
		    REprintf(_("warning: nearest point already identified\n"));
-
 
491
		    R_FlushConsole();
-
 
492
		}
-
 
493
	    }
-
 
494
	    else {
-
 
495
		k++;
-
 
496
		LOGICAL(ind)[imin] = 1;
-
 
497
 
-
 
498
		if (atpen) {
-
 
499
		    xi = xp;
-
 
500
		    yi = yp;
-
 
501
		    INTEGER(pos)[imin] = 0;
-
 
502
		    /* now record where to replot if necessary */
-
 
503
		    GConvert(&xp, &yp, INCHES, USER, dd);
-
 
504
		    REAL(x)[imin] = xp; REAL(y)[imin] = yp;
-
 
505
		} else {
-
 
506
		    xi = REAL(x)[imin];
-
 
507
		    yi = REAL(y)[imin];
-
 
508
		    GConvert(&xi, &yi, USER, INCHES, dd);
-
 
509
		    if (fabs(xp-xi) >= fabs(yp-yi)) {
-
 
510
			if (xp >= xi)
-
 
511
			    INTEGER(pos)[imin] = 4;
-
 
512
			else
-
 
513
			    INTEGER(pos)[imin] = 2;
-
 
514
		    } else {
-
 
515
			if (yp >= yi)
-
 
516
			    INTEGER(pos)[imin] = 3;
-
 
517
			else
-
 
518
			    INTEGER(pos)[imin] = 1;
-
 
519
		    }
-
 
520
		}
-
 
521
		if (plot) {
-
 
522
		    drawLabel(xi, yi, INTEGER(pos)[imin], offset,
-
 
523
			      CHAR(STRING_ELT(l, imin % nl)),
-
 
524
			      getCharCE(STRING_ELT(l, imin % nl)), dd);
-
 
525
		    GMode(0, dd);
-
 
526
		    GMode(2, dd);
-
 
527
		}
-
 
528
	    }
-
 
529
	}
-
 
530
	GMode(0, dd);
-
 
531
	PROTECT(ans = allocList(2));
-
 
532
	SETCAR(ans, ind);
-
 
533
	SETCADR(ans, pos);
-
 
534
	PROTECT(saveans = allocList(7));
-
 
535
	SETCAR(saveans, ind);
-
 
536
	SETCADR(saveans, pos);
-
 
537
	SETCADDR(saveans, x);
-
 
538
	SETCADDDR(saveans, y);
-
 
539
	SETCAD4R(saveans, Offset);
-
 
540
	SETCAD4R(CDR(saveans), l);
-
 
541
	SETCAD4R(CDDR(saveans), ScalarLogical(plot));
-
 
542
 
-
 
543
	/* If we are recording, save enough information to be able to
-
 
544
	   redraw the text labels beside identified points */
-
 
545
	if (GRecording(call, dd))
-
 
546
	    GErecordGraphicOperation(op, saveans, dd);
-
 
547
	UNPROTECT(6);
-
 
548
 
-
 
549
	R_Visible = TRUE;
-
 
550
	return ans;
-
 
551
    }
-
 
552
}
-