Illustratorでジェネラティブアートを作ってみる3
コッホ曲線
コッホ曲線ていうのがあるんですけど、曲線と言いつつ直線上に三角形を作るようにポキポキ折って作るような感じのものです。
ちょっとやってみましょう。
はい、曲線のアンカーポイント間をコッホ曲線に変換しました。深度は4で設定してあります。これにグラデーションを適用して色々重ねると印象的な表現になったりするんですけど、そこには今回触れません。
var dp = 4;
var positive = true;
applyKoch (4, true);
function applyKoch(dp, positive)
{
var dc =app.document;
var pth = app.activeDocument.selection;
var clr = new CMYKColor;
clr.cyan = 0;
clr.magenta = 0;
clr.yellow = 0;
clr.black = 100;
var pt = new Array();
var ln;
for (var j=0;j<pth.length;j++)
{
if (pth[j].typename!="PathItem") continue;
pt = [];
for (var i=0;i<pth[j].pathPoints.length;i++)
pt.push(pth[j].pathPoints[i].anchor);
ln = app.activeDocument.pathItems.add();
ln.stroke = true;
ln.strokeColor = clr;
ln.strokeWidth = 0.3;
ln.filled =false;
for (i=0;i<pt.length;i++)
{
if (i==pt.length-1)
{
if(pth[j].closed) koch(pt[i], pt[0], dp, ln);
}
else
{
koch(pt[i], pt[i+1], dp, ln);
}
}
if (pth[j].closed) ln.closed = true;
}
}
function koch(a, b, dpth, ln)
{
var e;
if (dpth==0)
{
addPoint(b, ln);
return;
}
var c = dv(ad(mlt(a, 2), b), 3);
var d = dv(ad(mlt(b, 2), a), 3);
var f = dv(ad(a, b), 2);
var v0 = dv(sb(f, a), len(f, a));
var v1 = [v0[1], -v0[0]];
if (positive)
e = sb(f, mlt(v1, Math.sqrt(3) / 6 * len(b, a)));
else
e = ad(f, mlt(v1, Math.sqrt(3) / 6 * len(b, a)));
koch(a, c, dpth-1, ln);
koch(c, e, dpth-1, ln);
koch(e, d, dpth-1, ln);
koch(d, b, dpth-1, ln);
}
function mlt(v, n)
{
return [v[0]*n, v[1]*n];
}
function dv(v, n)
{
return [v[0]/n, v[1]/n];
}
function ad(a, b)
{
return [a[0]+b[0], a[1]+b[1]];
}
function sb(a, b)
{
return [a[0]-b[0], a[1]-b[1]];
}
function len(a, b)
{
return Math.sqrt(Math.pow(a[0] - b[0], 2)
+ Math.pow(a[1] - b[1], 2));
}
function addPoint(p, ln)
{
var pts = ln.pathPoints.add();
pts.anchor = p;
pts.leftDirection = pts.anchor;
pts.rightDirection = pts.anchor;
}
コードを見ていただくとわかるんですけどアンカーポイント間を分割して中央の部分が正三角形になるように折り曲げるというのがパターンです。深度設定により新たに出来た辺を再帰で同様に折り曲げることでこの特徴的な変形を生成しています。
コード自体の記述も再帰の部分を除けば、上で書いたとおり直線を折り曲げていく処理がストレートに書かれている状態だというのがおわかりいただけるものと思います。
コッホスノーフレーク
で、ですね、このコッホ曲線を正三角形の各辺に適用するとコッホスノーフレークっていうものができます。
var lyr = app.activeDocument.layers.add();
lyr.name = "Koch Snowflake";
var gray = new GrayColor();
gray.gray = 60;
drawKochSnowflake(lyr, 200, 300, 300, 5);
function drawKochSnowflake(ly, x, y, size, depth)
{
var h = size * Math.sqrt(3) / 2;
var p1 = [x, -y];
var p2 = [x + size, -y];
var p3 = [x + size / 2, -y - h];
var path = ly.pathItems.add();
path.stroked = true;
path.strokeColor = gray;
path.strokeWidth = 1;
path.filled = false;
path.closed = true;
koch(p1, p2, depth, path);
koch(p2, p3, depth, path);
koch(p3, p1, depth, path);
}
function koch(a, b, dpth, path)
{
if (dpth == 0)
{
addPoint(b, path);
return;
}
var c = dv(ad(mlt(a, 2), b), 3);
var d = dv(ad(mlt(b, 2), a), 3);
var f = dv(ad(a, b), 2);
var v0 = dv(sb(f, a), len(f, a));
var v1 = [v0[1], -v0[0]];
var e = sb(f, mlt(v1, Math.sqrt(3) / 6 * len(b, a)));
koch(a, c, dpth - 1, path);
koch(c, e, dpth - 1, path);
koch(e, d, dpth - 1, path);
koch(d, b, dpth - 1, path);
}
function mlt(v, n)
{
return [v[0] * n, v[1] * n];
}
function dv(v, n)
{
return [v[0] / n, v[1] / n];
}
function ad(a, b)
{
return [a[0] + b[0], a[1] + b[1]];
}
function sb(a, b)
{
return [a[0] - b[0], a[1] - b[1]];
}
function len(a, b)
{
return Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2));
}
function addPoint(p, path)
{
var pt = path.pathPoints.add();
pt.anchor = p;
pt.leftDirection = pt.anchor;
pt.rightDirection = pt.anchor;
}
こ〜んな感じのコードです。まず、ど〜んと大きな正三角形を描画して、その各辺をコッホ曲線に置き換えていきます。
こんな具合になるんですけど、直線1本あたり4つに分割するのであ〜っと言う間にアンカーポイントの数がひどいことになります。
このスクリプトでは1パスでどんどん分割するような処理になっていますので、Illustratorがハングする前に仕様である1パスアイテムあたり32000個のアンカーポイントの制限がやってきます。これはdepthを7に設定していただけば体感できると思います。是非お試しください。