보로노이 다이어그램을 이용하여 오각형 Type 5 테셀레이션을 그려보았다.
(1) 사잇각이 60도인 기준점들을 찍는다.
(2) 기준점을 중심으로 하여 일정한 각도로 6개의 시드 점을 찍는다.
(3) 시드점을 기준으로 시드점에서 가장 가까운 거리에 있는 픽셀들끼리 묶어서 평면을 분할한다.
(4) 완성된 테셀레이션
소스코드
https://github.com/tibyte/visual/blob/master/tessellation
캔버스의 크기가 작아서 외접원을 구하지 않고 단순 반복문으로 구현...
|
var ctx; |
| var width; | var height; |
| var pixels = []; | var points = []; |
| var numPoints = 0; |
| function init() | { | canvas = document.getElementById("canvas"); | ctx = canvas.getContext("2d"); |
| width = canvas.width; | height = canvas.height; |
| for(var i=0; i<height; i++) { | for(var j=0; j<width; j++) { | pixels[i*width + j] = 0; | } | } |
|
| for(var i=0; i<10; i++) { | for(var j=0; j<10; j++) { | var cx = j*80-100; | var cy = i*92+j*46-250; | for(var k=0; k<6; k++) { | points[numPoints] = {}; | points[numPoints].x = cx + 36*Math.cos(k*Math.PI/3+11/180*Math.PI); | points[numPoints].y = cy + 36*Math.sin(k*Math.PI/3+11/180*Math.PI); |
| var rr = (points[numPoints].y+points[numPoints].x)/8; | var rg = (points[numPoints].y*2+points[numPoints].x*4)/8; | var rb = (points[numPoints].y*4+points[numPoints].x*8)/8; |
| rr = Math.floor(rr); | rg = Math.floor(rg); | rb = Math.floor(rb); |
| points[numPoints].c = "rgb("+rr+","+rg+","+rb+")"; |
| ++numPoints; | } | } | } |
| fill(ctx); | edge(ctx); | //point(ctx); |
| } |
| function fill(ctx) | { | for(var i=0; i<height; i++) { | for(var j=0; j<width; j++) { | var min = width*width+height*height; | var minK = 0; | for(var k=0; k<numPoints; k++) { | var dy = i-points[k].y; | var dx = j-points[k].x; | var dist = dx*dx+dy*dy; | if(dist < min) { | min = dist; | minK = k; | } | } | pixels[i*width + j] = points[minK].c; | ctx.fillStyle = points[minK].c; | ctx.fillRect(j, i, 1, 1); | }//end j loop | } | } |
| function edge(ctx) | { | for(var i=0; i<height; i++) { | for(var j=0; j<width; j++) { | if(pixels[i*width + j] != pixels[i*width + j-1] || | pixels[i*width + j] != pixels[i*width + j+1] || | pixels[i*width + j] != pixels[(i-1)*width + j] || | pixels[i*width + j] != pixels[(i+1)*width + j]) { | ctx.fillStyle = "#000000"; | ctx.fillRect(j, i, 1, 1); | } | } | } | } |
| function point(ctx) | { | for(var k=0; k<numPoints; k++) { | console.log("aa"); | ctx.fillStyle = "#000000"; | ctx.fillRect(points[k].x, points[k].y, 2, 2); | } | } |
|