The R Project SVN R

Rev

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

Rev 29428 Rev 29897
Line 1... Line 1...
1
/*
1
/*
2
 *  R : A Computer Language for Statistical Data Analysis
2
 *  R : A Computer Language for Statistical Data Analysis
3
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
3
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
4
 *  Copyright (C) 1997--2001  Robert Gentleman, Ross Ihaka and the
4
 *  Copyright (C) 1997--2001  Robert Gentleman, Ross Ihaka and the
5
 *			      R Development Core Team
5
 *			      R Development Core Team
6
 *  Copyright (C) 2002--2003  The R Foundation
6
 *  Copyright (C) 2002--2004  The R Foundation
7
 *
7
 *
8
 *  This program is free software; you can redistribute it and/or modify
8
 *  This program is free software; you can redistribute it and/or modify
9
 *  it under the terms of the GNU General Public License as published by
9
 *  it under the terms of the GNU General Public License as published by
10
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  the Free Software Foundation; either version 2 of the License, or
11
 *  (at your option) any later version.
11
 *  (at your option) any later version.
Line 3239... Line 3239...
3239
    Rf_gpptr(dd)->cex = cexsave;
3239
    Rf_gpptr(dd)->cex = cexsave;
3240
    UNPROTECT(2);
3240
    UNPROTECT(2);
3241
    return ans;
3241
    return ans;
3242
}
3242
}
3243
 
3243
 
3244
static int dnd_n;
-
 
3245
static int *dnd_lptr;
3244
static int *dnd_lptr;
3246
static int *dnd_rptr;
3245
static int *dnd_rptr;
3247
static double *dnd_hght;
3246
static double *dnd_hght;
3248
static double *dnd_xpos;
3247
static double *dnd_xpos;
3249
static double dnd_hang;
3248
static double dnd_hang;
Line 3251... Line 3250...
3251
static SEXP *dnd_llabels;
3250
static SEXP *dnd_llabels;
3252
 
3251
 
3253
 
3252
 
3254
static void drawdend(int node, double *x, double *y, DevDesc *dd)
3253
static void drawdend(int node, double *x, double *y, DevDesc *dd)
3255
{
3254
{
-
 
3255
/* Recursive function for 'hclust' dendrogram drawing:
-
 
3256
 * Do left + Do right + Do myself
-
 
3257
 * "do" : 1) label leafs (if there are) and __
-
 
3258
 *        2) find coordinates to draw the  | |
-
 
3259
 *        3) return (*x,*y) of "my anchor"
-
 
3260
 */
3256
    double xl, xr, yl, yr;
3261
    double xl, xr, yl, yr;
3257
    double xx[4], yy[4];
3262
    double xx[4], yy[4];
3258
    int k;
3263
    int k;
-
 
3264
 
3259
    *y = dnd_hght[node-1];
3265
    *y = dnd_hght[node-1];
-
 
3266
    /* left part  */
3260
    k = dnd_lptr[node-1];
3267
    k = dnd_lptr[node-1];
3261
    if (k > 0) drawdend(k, &xl, &yl, dd);
3268
    if (k > 0) drawdend(k, &xl, &yl, dd);
3262
    else {
3269
    else {
3263
	xl = dnd_xpos[-k-1];
3270
	xl = dnd_xpos[-k-1];
3264
	if (dnd_hang >= 0) yl = *y - dnd_hang;
3271
	yl = (dnd_hang >= 0) ? *y - dnd_hang : 0;
3265
	else yl = 0;
-
 
3266
	if(dnd_llabels[-k-1] != NA_STRING)
3272
	if(dnd_llabels[-k-1] != NA_STRING)
3267
	    GText(xl, yl-dnd_offset, USER, CHAR(dnd_llabels[-k-1]),
3273
	    GText(xl, yl-dnd_offset, USER, CHAR(dnd_llabels[-k-1]),
3268
		  1.0, 0.3, 90.0, dd);
3274
		  1.0, 0.3, 90.0, dd);
3269
    }
3275
    }
-
 
3276
    /* right part */
3270
    k = dnd_rptr[node-1];
3277
    k = dnd_rptr[node-1];
3271
    if (k > 0) drawdend(k, &xr, &yr, dd);
3278
    if (k > 0) drawdend(k, &xr, &yr, dd);
3272
    else {
3279
    else {
3273
	xr = dnd_xpos[-k-1];
3280
	xr = dnd_xpos[-k-1];
3274
	if (dnd_hang >= 0) yr = *y - dnd_hang;
3281
	yr = (dnd_hang >= 0) ? *y - dnd_hang : 0;
3275
	else yr = 0;
-
 
3276
	if(dnd_llabels[-k-1] != NA_STRING)
3282
	if(dnd_llabels[-k-1] != NA_STRING)
3277
	    GText(xr, yr-dnd_offset, USER, CHAR(dnd_llabels[-k-1]),
3283
	    GText(xr, yr-dnd_offset, USER, CHAR(dnd_llabels[-k-1]),
3278
		  1.0, 0.3, 90.0, dd);
3284
		  1.0, 0.3, 90.0, dd);
3279
    }
3285
    }
3280
    xx[0] = xl; yy[0] = yl;
3286
    xx[0] = xl; yy[0] = yl;
Line 3287... Line 3293...
3287
 
3293
 
3288
 
3294
 
3289
SEXP do_dend(SEXP call, SEXP op, SEXP args, SEXP env)
3295
SEXP do_dend(SEXP call, SEXP op, SEXP args, SEXP env)
3290
{
3296
{
3291
    double x, y;
3297
    double x, y;
-
 
3298
    int n;
-
 
3299
 
3292
    SEXP originalArgs;
3300
    SEXP originalArgs;
3293
    DevDesc *dd;
3301
    DevDesc *dd;
3294
 
3302
 
3295
    dd = CurrentDevice();
3303
    dd = CurrentDevice();
3296
    GCheckState(dd);
3304
    GCheckState(dd);
3297
 
3305
 
3298
    originalArgs = args;
3306
    originalArgs = args;
3299
    if (length(args) < 6)
3307
    if (length(args) < 6)
3300
	errorcall(call, "too few arguments");
3308
	errorcall(call, "too few arguments");
3301
 
3309
 
-
 
3310
    /* n */
3302
    dnd_n = asInteger(CAR(args));
3311
    n = asInteger(CAR(args));
3303
    if (dnd_n == NA_INTEGER || dnd_n < 2)
3312
    if (n == NA_INTEGER || n < 2)
3304
	goto badargs;
3313
	goto badargs;
3305
    args = CDR(args);
3314
    args = CDR(args);
3306
 
3315
 
-
 
3316
    /* merge */
3307
    if (TYPEOF(CAR(args)) != INTSXP || length(CAR(args)) != 2*dnd_n)
3317
    if (TYPEOF(CAR(args)) != INTSXP || length(CAR(args)) != 2*n)
3308
	goto badargs;
3318
	goto badargs;
3309
    dnd_lptr = &(INTEGER(CAR(args))[0]);
3319
    dnd_lptr = &(INTEGER(CAR(args))[0]);
3310
    dnd_rptr = &(INTEGER(CAR(args))[dnd_n]);
3320
    dnd_rptr = &(INTEGER(CAR(args))[n]);
3311
    args = CDR(args);
3321
    args = CDR(args);
3312
 
3322
 
-
 
3323
    /* height */
3313
    if (TYPEOF(CAR(args)) != REALSXP || length(CAR(args)) != dnd_n)
3324
    if (TYPEOF(CAR(args)) != REALSXP || length(CAR(args)) != n)
3314
	goto badargs;
3325
	goto badargs;
3315
    dnd_hght = REAL(CAR(args));
3326
    dnd_hght = REAL(CAR(args));
3316
    args = CDR(args);
3327
    args = CDR(args);
3317
 
3328
 
-
 
3329
    /* ord = order(x$order) */
3318
    if (TYPEOF(CAR(args)) != REALSXP || length(CAR(args)) != dnd_n+1)
3330
    if (length(CAR(args)) != n+1)
3319
	goto badargs;
3331
	goto badargs;
3320
    dnd_xpos = REAL(CAR(args));
3332
    dnd_xpos = REAL(coerceVector(CAR(args),REALSXP));
3321
    args = CDR(args);
3333
    args = CDR(args);
3322
 
3334
 
-
 
3335
    /* hang */
3323
    dnd_hang = asReal(CAR(args));
3336
    dnd_hang = asReal(CAR(args));
3324
    if (!R_FINITE(dnd_hang))
3337
    if (!R_FINITE(dnd_hang))
3325
	goto badargs;
3338
	goto badargs;
3326
    dnd_hang = dnd_hang * (dnd_hght[dnd_n-1] - dnd_hght[0]);
3339
    dnd_hang = dnd_hang * (dnd_hght[n-1] - dnd_hght[0]);
3327
    args = CDR(args);
3340
    args = CDR(args);
3328
 
3341
 
-
 
3342
    /* labels */
3329
    if (TYPEOF(CAR(args)) != STRSXP || length(CAR(args)) != dnd_n+1)
3343
    if (TYPEOF(CAR(args)) != STRSXP || length(CAR(args)) != n+1)
3330
	goto badargs;
3344
	goto badargs;
3331
    dnd_llabels = STRING_PTR(CAR(args));
3345
    dnd_llabels = STRING_PTR(CAR(args));
3332
    args = CDR(args);
3346
    args = CDR(args);
3333
 
3347
 
3334
    GSavePars(dd);
3348
    GSavePars(dd);
Line 3340... Line 3354...
3340
    /* NOTE: don't override to _reduce_ clipping region */
3354
    /* NOTE: don't override to _reduce_ clipping region */
3341
    if (Rf_gpptr(dd)->xpd < 1)
3355
    if (Rf_gpptr(dd)->xpd < 1)
3342
	Rf_gpptr(dd)->xpd = 1;
3356
	Rf_gpptr(dd)->xpd = 1;
3343
 
3357
 
3344
    GMode(1, dd);
3358
    GMode(1, dd);
3345
    drawdend(dnd_n, &x, &y, dd);
3359
    drawdend(n, &x, &y, dd);
3346
    GMode(0, dd);
3360
    GMode(0, dd);
3347
    GRestorePars(dd);
3361
    GRestorePars(dd);
3348
    /* NOTE: only record operation if no "error"  */
3362
    /* NOTE: only record operation if no "error"  */
3349
    if (GRecording(call))
3363
    if (GRecording(call))
3350
	recordGraphicOperation(op, originalArgs, dd);
3364
	recordGraphicOperation(op, originalArgs, dd);
Line 3364... Line 3378...
3364
    DevDesc *dd;
3378
    DevDesc *dd;
3365
 
3379
 
3366
    dd = CurrentDevice();
3380
    dd = CurrentDevice();
3367
    GCheckState(dd);
3381
    GCheckState(dd);
3368
    originalArgs = args;
3382
    originalArgs = args;
3369
    if (length(args) < 6)
3383
    if (length(args) < 5)
3370
	errorcall(call, "too few arguments");
3384
	errorcall(call, "too few arguments");
3371
    n = asInteger(CAR(args));
3385
    n = asInteger(CAR(args));
3372
    if (n == NA_INTEGER || n < 2)
3386
    if (n == NA_INTEGER || n < 2)
3373
	goto badargs;
3387
	goto badargs;
3374
    args = CDR(args);
3388
    args = CDR(args);
3375
    if (TYPEOF(CAR(args)) != INTSXP || length(CAR(args)) != 2 * n)
3389
    if (TYPEOF(CAR(args)) != INTSXP || length(CAR(args)) != 2 * n)
3376
	goto badargs;
3390
	goto badargs;
3377
    merge = CAR(args);
3391
    merge = CAR(args);
-
 
3392
 
3378
    args = CDR(args);
3393
    args = CDR(args);
3379
    if (TYPEOF(CAR(args)) != REALSXP || length(CAR(args)) != n)
3394
    if (TYPEOF(CAR(args)) != REALSXP || length(CAR(args)) != n)
3380
	goto badargs;
3395
	goto badargs;
3381
    height = CAR(args);
3396
    height = CAR(args);
3382
    args = CDR(args);
-
 
3383
    if (TYPEOF(CAR(args)) != REALSXP || length(CAR(args)) != n + 1)
-
 
3384
	goto badargs;
3397
 
3385
    dnd_xpos = REAL(CAR(args));
-
 
3386
    args = CDR(args);
3398
    args = CDR(args);
3387
    dnd_hang = asReal(CAR(args));
3399
    dnd_hang = asReal(CAR(args));
3388
    if (!R_FINITE(dnd_hang))
3400
    if (!R_FINITE(dnd_hang))
3389
	goto badargs;
3401
	goto badargs;
-
 
3402
 
3390
    args = CDR(args);
3403
    args = CDR(args);
3391
    if (TYPEOF(CAR(args)) != STRSXP || length(CAR(args)) != n + 1)
3404
    if (TYPEOF(CAR(args)) != STRSXP || length(CAR(args)) != n + 1)
3392
	goto badargs;
3405
	goto badargs;
3393
 
-
 
3394
    llabels = CAR(args);
3406
    llabels = CAR(args);
-
 
3407
 
3395
    args = CDR(args);
3408
    args = CDR(args);
3396
    GSavePars(dd);
3409
    GSavePars(dd);
3397
    ProcessInlinePars(args, dd, call);
3410
    ProcessInlinePars(args, dd, call);
3398
    Rf_gpptr(dd)->cex = Rf_gpptr(dd)->cexbase * Rf_gpptr(dd)->cex;
3411
    Rf_gpptr(dd)->cex = Rf_gpptr(dd)->cexbase * Rf_gpptr(dd)->cex;
3399
    dnd_offset = GStrWidth("m", INCHES, dd);
3412
    dnd_offset = GStrWidth("m", INCHES, dd);
Line 3414... Line 3427...
3414
    for (i = 0; i < n; i++) {
3427
    for (i = 0; i < n; i++) {
3415
	str = STRING_ELT(llabels, i);
3428
	str = STRING_ELT(llabels, i);
3416
	ll[i] = (str == NA_STRING) ? 0.0 :
3429
	ll[i] = (str == NA_STRING) ? 0.0 :
3417
	    GStrWidth(CHAR(str), INCHES, dd) + dnd_offset;
3430
	    GStrWidth(CHAR(str), INCHES, dd) + dnd_offset;
3418
    }
3431
    }
-
 
3432
 
-
 
3433
    imax = -1; yval = -DBL_MAX;
3419
    if (dnd_hang >= 0) {
3434
    if (dnd_hang >= 0) {
3420
	ymin = ymax - (1 + dnd_hang) * (ymax - ymin);
3435
	ymin = ymax - (1 + dnd_hang) * (ymax - ymin);
3421
	yrange = ymax - ymin;
3436
	yrange = ymax - ymin;
3422
	/* determine leaf heights */
3437
	/* determine leaf heights */
3423
	for (i = 0; i < n; i++) {
3438
	for (i = 0; i < n; i++) {
Line 3427... Line 3442...
3427
		y[-dnd_rptr[i] - 1] = REAL(height)[i];
3442
		y[-dnd_rptr[i] - 1] = REAL(height)[i];
3428
	}
3443
	}
3429
	/* determine the most extreme label depth */
3444
	/* determine the most extreme label depth */
3430
	/* assuming that we are using the full plot */
3445
	/* assuming that we are using the full plot */
3431
	/* window for the tree itself */
3446
	/* window for the tree itself */
3432
	imax = -1;
-
 
3433
	yval = -DBL_MAX;
-
 
3434
	for (i = 0; i < n; i++) {
3447
	for (i = 0; i < n; i++) {
3435
	    tmp = ((ymax - y[i]) / yrange) * pin + ll[i];
3448
	    tmp = ((ymax - y[i]) / yrange) * pin + ll[i];
3436
	    if (tmp > yval) {
3449
	    if (tmp > yval) {
3437
		yval = tmp;
3450
		yval = tmp;
3438
		imax = i;
3451
		imax = i;
3439
	    }
3452
	    }
3440
	}
3453
	}
3441
    }
3454
    }
3442
    else {
3455
    else {
3443
	ymin = 0;
-
 
3444
	yrange = ymax;
3456
	yrange = ymax;
3445
	imax = -1;
-
 
3446
	yval = -DBL_MAX;
-
 
3447
	for (i = 0; i < n; i++) {
3457
	for (i = 0; i < n; i++) {
3448
	    tmp = pin + ll[i];
3458
	    tmp = pin + ll[i];
3449
	    if (tmp > yval) {
3459
	    if (tmp > yval) {
3450
		yval = tmp;
3460
		yval = tmp;
3451
		imax = i;
3461
		imax = i;
3452
	    }
3462
	    }
3453
	}
3463
	}
3454
    }
3464
    }
3455
    /* now determine how much to scale */
3465
    /* now determine how much to scale */
3456
    ymin = ymax - (pin/(pin - ll[imax])) * (ymax - ymin);
3466
    ymin = ymax - (pin/(pin - ll[imax])) * yrange;
3457
    GScale(1.0, n+1.0, 1, dd);
3467
    GScale(1.0, n+1.0, 1 /* x */, dd);
3458
    GScale(ymin, ymax, 2, dd);
3468
    GScale(ymin, ymax, 2 /* y */, dd);
3459
    GMapWin2Fig(dd);
3469
    GMapWin2Fig(dd);
3460
    GRestorePars(dd);
3470
    GRestorePars(dd);
3461
    /* NOTE: only record operation if no "error"  */
3471
    /* NOTE: only record operation if no "error"  */
3462
    if (GRecording(call))
3472
    if (GRecording(call))
3463
	recordGraphicOperation(op, originalArgs, dd);
3473
	recordGraphicOperation(op, originalArgs, dd);