重複なし行のみの抽出

  • データレコードが行列状になっているときに、重複行を見つけて、ダブっている分を除いて、1行分にして出すのがunique()
  • 今、ダブっているレコードは1行残らず、破棄したい
  • unique()関数は、上からスキャンして、初出はTRUE、既出分とダブったらFALSEを返す関数 duplicate()を基準にしているので、スキャンを上下の2方向からやって、どちらでもTRUEな行は、重複に関わらない行
my.onlyone <- function(x){
	n <- length(x[,1])
	a <- !duplicated(x)
	b <- !duplicated(x[n:1,])[n:1]
	return(x[a & b,])
}
x <- matrix(c(0,0,0,1,0,1,1,1),byrow=TRUE,ncol=2)
my.onlyone(x)
  • これを使って、『図形』がブロックで出来ているときに、内部点・内部面などを取り除いて表面要素だけにすることができるだろう
# ボクセルはその座標最小頂点(x,y,z)座標で登録する

# 各ボクセルは6面を持つ
# 面(正方形)はその座標最小頂点(x,y,z)と、面の方向で区別する
# xy平面、yz平面、zx平面に広がるものを、1,2,3と呼び分ける

# 各頂点は4頂点を持つ

Vox.list <- as.matrix(expand.grid(0:2,0:2,0:2))

my.vox.faces <- function(xyz){
	rbind(c(xyz,1),c(xyz,2),c(xyz,3),c(xyz+c(1,0,0),2),c(xyz+c(0,1,0),3),c(xyz+c(0,0,1),1))
}

my.face.nodes <- function(xyzw){
	xyz <- xyzw[1:3]
	w <- xyzw[4]
	if(w==1){
		ret <- rbind(xyz,xyz+c(1,0,0),xyz+c(0,1,0),xyz+c(1,1,0))
	}else if(w==2){
		ret <- rbind(xyz,xyz+c(0,1,0),xyz+c(0,0,1),xyz+c(0,1,1))
	}else{
		ret <- rbind(xyz,xyz+c(0,0,1),xyz+c(1,0,0),xyz+c(1,0,1))
	}
	return(ret)
}

my.onlyone <- function(x){
	n <- length(x[,1])
	a <- !duplicated(x)
	b <- !duplicated(x[n:1,])[n:1]
	return(x[a & b,])
}

my.vox.surface <- function(Vlist){
	faces <- matrix(0,0,4)
	for(i in 1:length(Vlist[,1])){
		faces <- rbind(faces,my.vox.faces(Vlist[i,]))
	}
	return(my.onlyone(faces))
	
}

faces <- my.vox.surface(Vox.list)

my.surface.nodes <- function(faces){
	vs <- matrix(0,0,3)
	for(i in 1:length(faces[,1])){
		vs <- rbind(vs,my.face.nodes(faces[i,]))
	}
	return(unique(vs))
}

nodes <- my.surface.nodes(faces)

library(rgl)
plot3d(nodes)