Illustratorでジェネラティブアートを作ってみる12
ペアノ曲線
ペアノ曲線というのは空間充填曲線の最初に発見されたものです。以前にヒルベルト曲線をやってみましたが、雰囲気的には似た感じのものになります。ヒルベルト曲線と同様に1次元の線を折り曲げるだけなんですけど、極限において単位平面を充填するため、フラクタル次元は2に近くなります。
ヒルベルト曲線では単位矩形を4分割して接続しましたが、このペアノ曲線では単位矩形を3×3に分割することにより層を成しますので負荷は高くなります、単位形状における制御点は9個になるためIllustratorの限界である1つのパスあたり32768個のアンカーポイント数制限の影響を受けやすいためにアンカーポイント数が16000コを超えたあたりで新しいパスに引き継ぐようにしました。なので、depthiを深く設定してもエラーは生じにくいです。depth=6までテストしていますが、相当時間がかかりました。
var lyr = app.activeDocument.activeLayer;
var depth = 5;
var size = 300;
var startX = 100;
var startY = 100;
var pathPoints = [];
var orders = [
makeOrder("down", "up", "down", false),
makeOrder("down", "up", "down", true),
makeOrder("up", "down", "up", false),
makeOrder("up", "down", "up", true)
];
var patterns = [
[0,1,0,2,3,2,0,1,0],
[1,0,1,3,2,3,1,0,1],
[2,3,2,0,1,0,2,3,2],
[3,2,3,1,0,1,3,2,3]
];
function drawPeano(x, y, sz, d, orderId, ps)
{
if (d==0)
{
if (ps==1||ps==4||ps==7) return;
pathPoints.push([x+sz/2, y+sz/2]);
return;
}
var sub = sz / 3;
var ord = orders[orderId];
var pat = patterns[orderId];
for (var i=0; i<9; i++)
{
var dx = ord[i][0] * sub;
var dy = ord[i][1] * sub;
drawPeano(x+dx, y+dy, sub, d-1, pat[i], i);
}
}
drawPeano(startX, startY, size, depth, 0, 0);
var pth = lyr.pathItems.add();
pth.closed = false;
pth.stroked = true;
pth.filled = false;
pth.strokeWidth = 0.3;
for (var i=0; i<pathPoints.length; i++)
{
if (pth.pathPoints.length>16000)
{
pth = lyr.pathItems.add();
pth.closed = false;
pth.stroked = true;
pth.filled = false;
pth.strokeWidth = 0.3;
p = pth.pathPoints.add();
p.anchor = pathPoints[i-1];
p.leftDirection = p.anchor;
p.rightDirection = p.anchor;
}
var p = pth.pathPoints.add();
p.anchor = pathPoints[i];
p.leftDirection = p.anchor;
p.rightDirection = p.anchor;
}
function makeOrder(leftDir, centerDir, rightDir, reverseCols)
{
function col(x, dir)
{
var arr = [];
for (var y=0; y<3; y++)
{
arr.push([x, (dir=="up")? y : 2-y]);
}
return arr;
}
var cols = [col(0, leftDir), col(1, centerDir), col(2, rightDir)];
if (reverseCols) cols.reverse();
return [].concat(cols[0], cols[1], cols[2]);
}
処理手順を追ってみましょう。
まず、単位矩形を用意します。
これを9分割し…
出来た9個の矩形をS字になるようにピックアップし、各矩形の中心点を結んでいきます。
同様にこれらの分割された矩形を、それぞれ9個に分割しS字を描くようにピックアップします。その際、正しい順序でピックアップする必要があるため、分割した際の位置によって進行方向を選択する必要があります。
さらに深く再帰を行うと曲線がだんだんと空間を埋めていく様子が見えてきます。
さらに深く…
さらに深く…
形状が複雑な分、5段階ほど回せばそれなりに空間が埋められるのがよくわかります。
ヒルベルト曲線と比較すると配置パターンが複雑になるため再帰の際の開始点の選択に注意が必要です。そういった処理のためにヒルベルト曲線と比較するとコード量は膨らみます。