チャーノフの顔グラフ     Last modified: Apr 13, 2004

目的

チャーノフの顔グラフを描く

使用法

face.plot(x, size=480)

引数

x       18 個の要素を持つベクトル
	データベクトルからこのベクトルを用意するために,face.data という関数を使うとよい
size    顔の大きさ

ソース

インストールは,以下の 1 行をコピーし,R コンソールにペーストする
source("http://aoki2.si.gunma-u.ac.jp/R/src/face_plot.R", encoding="euc-jp")

# チャーノフの顔グラフ
face.plot <- function(x, size=480)
{
        # 円弧を描く
        arc1 <- function(x1, y1, r, l)
        {
                sign <- ifelse(l > 0, -1, 1)
                theta <- sign*acos(x1/r)
                y1 <- y1-sign*sqrt(r^2-x1^2)
                if (l <= 0) {
                        arc(0, y1, r, theta, pi-theta)
                }
                else {
                        arc(0, y1, r, pi-theta, pi*2+theta)
                }
        }
        # 円(の一部)を描く
        arc <- function(ox, oy, r, theta.start, theta.end)
        {
                step <- min(0.1, (theta.end-theta.start)*0.1)
                interval <- c(seq(theta.start, theta.end, step), theta.end)
                lines(r*cos(interval)+ox, r*sin(interval)+oy)
        }
        # 楕円(の一部)を描く
        ellipse <- function(ox, oy, r.a, r.b, theta.axis, theta.start, theta.end)
        {
                theta.end <- theta.end+(theta.end <= theta.start)*pi*2
                temp1 <- r.a*r.b
                temp2 <- 30/(r.a+r.b)
                k <- (theta.end-theta.start)/temp2+2
                x <- y <- numeric(k)
                for (i in 1:(k-1)) {
                        factor <- temp1/sqrt((r.a*sin(theta.start))^2+(r.b*cos(theta.start))^2)
                        x[i] <- factor*cos(theta.axis+theta.start)
                        y[i] <- factor*sin(theta.axis+theta.start)
                        theta.start <- theta.start+temp2
                }
                factor <- temp1/sqrt((r.a*sin(theta.end))^2+(r.b*cos(theta.end))^2)
                x[k] <- factor*cos(theta.axis+theta.end)
                y[k] <- factor*sin(theta.axis+theta.end)
                lines(ox+x, oy+y)
        }

        pi2 <- 2*pi
        plot(c(-500, 500), c(-500, 500), type="n", xlab="", xaxt="n", ylab="", yaxt="n", bty="n")
        size2 <- size*(1+x[1])/2
        theta <- (pi/4)*(2*x[2]-1)
        h <- size*(1+x[3])/2
        x1 <- size2*cos(theta)
        y1 <- size2*sin(theta)
# 顔の上半分 
        ak <- 1-x[4]^2
        oy1 <- (ak*x1^2+y1^2-h^2)/(2*(y1-h))
        r.b1 <- h-oy1
        r.a1 <- r.b1/sqrt(ak)
        theta.start <- atan((y1-oy1)/x1)
        theta.end <- pi-theta.start
        ellipse(0, oy1, r.a1, r.b1, 0, theta.start, theta.end)
# 顔の下半分 
        ak <- 1-x[5]^2
        oy2 <- (ak*x1^2+y1^2-h^2)/(2*(y1+h))
        r.b2 <- h+oy2
        r.a2 <- r.b2/sqrt(ak)
        theta.end <- atan((y1-oy2)/x1)
        theta.start <- pi-theta.end
        ellipse(0, oy2, r.a2, r.b2, 0, theta.start, theta.end)
# 鼻 
        y <- h*x[6]
        lines(c(0, 0), c(y, -y))
# 口 
        pm <- -h*(x[7]+(1-x[7])*x[6])
        wm <- sqrt(r.a2^2*(1-(pm-oy2)^2/r.b2^2))
        if (x[8] == 0) {
                lines(c(-wm/2, wm/2), c(pm, pm))
        }
        else {
                r <- h/abs(x[8])
                am <- x[9]*r
                x1 <- ifelse(am > wm, x[9]*wm, am)
                l <- ifelse(x[8] <= 0, -1, 1)
                y1 <- pm-l*(r-sqrt(r^2-x1^2))
                arc1(x1, y1, r, l)
        }
# 目 
        ye <- h*(x[10]+(1-x[10])*x[6])
        we <- sqrt(r.a1^2*(1-(ye-oy1)^2/r.b1^2))
        xe <- we*(1+2*x[11])/4
        theta <- (2*x[12]-1)*pi/5
        r.a3 <- x[14]*min(xe, we-xe)
        r.b3 <- sqrt(r.a3^2*(1-x[13]^2))
        ellipse(xe, ye, r.a3, r.b3, theta, 0, pi2)
        ellipse(-xe, ye, r.a3, r.b3, pi-theta, 0, pi2)
# 瞳 
        re <- r.a3/sqrt(cos(theta)^2+sin(theta)^2/x[13]^2)
        shift <- re*(2*x[15]-1)
        sapply(c(xe, -xe)-shift, function(arg) arc(arg, ye, 3, 0, pi2))
# 眉 
        theta2 <- 2*(1-x[17])*(pi/5)
        theta3 <- ifelse(theta >= 0, theta+theta2, theta-theta2)
        len <- re*(2*x[18]+1)/2
        x0 <- len*cos(theta3)
        x1 <- xe-c(x0, -x0)
        y0 <- len*sin(theta3)
        y1 <- ye+2*(x[16]+0.3)*r.a3*x[13]-c(y0, -y0)
        lines(x1-shift, y1)
        lines(-x1-shift, y1)
}


使用例

> nv <- 18
> d <- matrix(rnorm(9*nv), ncol=nv)
> x <- face.data(d)
> old <- par(mar=c(1,1,1,1), mfrow=c(3, 3))	# 図を3行3列に描く
> for(i in 1:9) {
+ 	face.plot(x[i,])
+ }
> par(old)	# パラメータを元に戻す

出力結果例

graph

・ 解説ページ
脇本和昌,垂水共之,田中豊編「パソコン統計解析ハンドブック I 基礎統計編」共立出版株式会社株式会社


・ 直前のページへ戻る  ・ E-mail to Shigenobu AOKI

Made with Macintosh