ガイド用に作成したポリラインをベジェ曲線用に分割していく。ループにも対応しています。

2次ベジェ曲線(3点の制御点)

最初と最後以外の直線を分割して、3点ずつカーブをつくり、つないでいく。
//
// ポリラインをベジェ曲線(2次)の制御点ラインへ分割する(2025/05/05)
//
// Run Over: Primitives
// input0: Polyline
//
int pts[] = primpoints(0, @primnum);
// 描画には最低3点必要(2点以下なら直線のままにする)
if(len(pts) > 2)
{
// Polylineがループしているか否かは始点と終点の距離で判断する
int isClosed = 0;
vector start_pos = point(0, "P", pts[0]);
vector end_pos = point(0, "P", pts[-1]);
if(length(end_pos - start_pos) < 0.001)
isClosed = 1;
// ループしている場合
if(isClosed)
{
// 分割点を追加していく
int midpoint[];
for(int i = 0; i < len(pts)-1; i++)
{
vector p0 = point(0, "P", pts[i]);
vector p1 = point(0, "P", pts[i+1]);
vector p2 = lerp(p0, p1, 0.5);
int pt = addpoint(0, p2);
append(midpoint, pt);
}
for(int i = 0; i < len(pts)-1; i++)
{
// 始点
if(i == 0)
{
int prim = addprim(0, "polyline");
addvertex(0, prim, midpoint[0]);
addvertex(0, prim, pts[1]);
addvertex(0, prim, midpoint[1]);
}
else if(i > 0 && i < len(pts)-2)
{
int prim = addprim(0, "polyline");
addvertex(0, prim, midpoint[i]);
addvertex(0, prim, pts[i+1]);
addvertex(0, prim, midpoint[i+1]);
}
// 終点
else
{
int prim = addprim(0, "polyline");
addvertex(0, prim, midpoint[-1]);
addvertex(0, prim, pts[-1]);
addvertex(0, prim, midpoint[0]);
}
}
}
// ループしていない場合
else
{
// 分割点を追加していく
int midpoint[];
for(int i = 1; i < len(pts)-2; i++)
{
vector p0 = point(0, "P", pts[i]);
vector p1 = point(0, "P", pts[i+1]);
vector p2 = lerp(p0, p1, 0.5);
int pt = addpoint(0, p2);
append(midpoint, pt);
}
// 分割されたポリラインを生成していく
for(int i = 0; i < len(pts) - 2; i++)
{
// 始点
if(i == 0)
{
int prim = addprim(0, "polyline");
addvertex(0, prim, pts[0]);
addvertex(0, prim, pts[1]);
addvertex(0, prim, midpoint[0]);
}
else if(i > 0 && i < len(pts)-3)
{
int prim = addprim(0, "polyline");
addvertex(0, prim, midpoint[i-1]);
addvertex(0, prim, pts[i+1]);
addvertex(0, prim, midpoint[i]);
}
// 終点
else
{
int prim = addprim(0, "polyline");
addvertex(0, prim, midpoint[i-1]);
addvertex(0, prim, pts[i+1]);
addvertex(0, prim, pts[i+2]);
}
}
}
// 元のポリラインを削除
removeprim(0, @primnum, 1);
}
3次ベジェ曲線(4点の制御点)

カーブのポイント数から2を引き、
2で割った商→3次ベジェ曲線の数
余りがあれば→最後の組が2次のベジェ曲線
//
// ポリラインをベジェ曲線(3次)のガイドラインへ分割する
// Run Over: Primitives
// input0: Polyline
//
int pts[] = primpoints(0, @primnum);
// 描画には最低3点必要(2点以下なら直線のままにする)
if(len(pts) > 2)
{
// Polylineが連環しているか否か
int isClosed = primintrinsic(0, "closed", 0);
if(isClosed)
{
// ポイント総数N(N角形)から2で割った数がベジェ3次曲線の組数
int div = len(pts) / 2;
// 2で割った余りがあれば最後の組みがベジェ2次曲線になる
int mod = len(pts) % 2;
if (mod > 0)
div += 1;
for(int i = 0; i < div; i++)
{
if(i == div-1 && mod > 0)
{
// ベジェ2次曲線のための3点を選ぶ
vector p0 = point(0, "P", pts[i*2]);
vector p1 = point(0, "P", pts[(i*2+1)%len(pts)]);
vector p2 = point(0, "P", pts[(i*2+2)%len(pts)]);
p0 = (p0 + p1) / 2;
p2 = (p1 + p2) / 2;
// ポリラインを生成
int prim = addprim(0, "polyline");
int pt = addpoint(0, p0);
addvertex(0, prim, pt);
pt = addpoint(0, p1);
addvertex(0, prim, pt);
pt = addpoint(0, p2);
addvertex(0, prim, pt);
float hue = (i / (float)((len(pts)-2) * 2)) * -1 + 0.6;
setprimattrib(0, "Cd", prim, hsvtorgb(hue, 1, 1));
}
else
{
// ベジェ曲線のための4点を選ぶ
vector p0 = point(0, "P", pts[i*2]);
vector p1 = point(0, "P", pts[(i*2+1)%len(pts)]);
vector p2 = point(0, "P", pts[(i*2+2)%len(pts)]);
vector p3 = point(0, "P", pts[(i*2+3)%len(pts)]);
p0 = (p0 + p1) / 2;
p3 = (p2 + p3) / 2;
// ポリラインを生成
int prim = addprim(0, "polyline");
int pt = addpoint(0, p0);
addvertex(0, prim, pt);
pt = addpoint(0, p1);
addvertex(0, prim, pt);
pt = addpoint(0, p2);
addvertex(0, prim, pt);
pt = addpoint(0, p3);
addvertex(0, prim, pt);
float hue = (i / (float)((len(pts)-2) * 2)) * -1 + 0.6;
setprimattrib(0, "Cd", prim, hsvtorgb(hue, 1, 1));
}
}
}
// ポリラインが連環していない
else
{
// ポイント総数から-2して2で割った数がベジェ3次曲線の組数
int div = (len(pts) - 2) / 2;
// 2で割った余りがあれば最後の組みがベジェ2次曲線になる
int mod = (len(pts) - 2) % 2;
if (mod > 0)
div += 1;
for(int i = 0; i < div; i++)
{
// ポイントが3つ、または
// 余りがあれば最後はベジェ2次曲線にする
if( (i == 0 && div == 1 && mod > 0) || (i == div-1 && mod > 0))
{
// ベジェ2次曲線のための3点を選ぶ
vector p0 = point(0, "P", pts[i*2]);
vector p1 = point(0, "P", pts[i*2+1]);
vector p2 = point(0, "P", pts[i*2+2]);
if(i > 0)
p0 = (p0 + p1) / 2;
// ポリラインを生成
int prim = addprim(0, "polyline");
int pt = addpoint(0, p0);
addvertex(0, prim, pt);
pt = addpoint(0, p1);
addvertex(0, prim, pt);
pt = addpoint(0, p2);
addvertex(0, prim, pt);
float hue = (i / (float)((len(pts)-2) * 2)) * -1 + 0.6;
setprimattrib(0, "Cd", prim, hsvtorgb(hue, 1, 1));
}
else
{
// 3次ベジェ曲線のための4点を選ぶ
vector p0 = point(0, "P", pts[i*2]);
vector p1 = point(0, "P", pts[i*2+1]);
vector p2 = point(0, "P", pts[i*2+2]);
vector p3 = point(0, "P", pts[i*2+3]);
// 始点
if(i == 0)
{
if(len(pts) > 4)
p3 = (p2 + p3) / 2;
}
// 中間のポイント
else if(i > 0 && i < div-1)
{
p0 = (p0 + p1) / 2;
p3 = (p2 + p3) / 2;
}
// 終点(の2つ前)
else
{
p0 = (p0 + p1) / 2;
}
// ポリラインを生成
int prim = addprim(0, "polyline");
int pt = addpoint(0, p0);
addvertex(0, prim, pt);
pt = addpoint(0, p1);
addvertex(0, prim, pt);
pt = addpoint(0, p2);
addvertex(0, prim, pt);
pt = addpoint(0, p3);
addvertex(0, prim, pt);
float hue = (i / (float)((len(pts)-2) * 2)) * -1 + 0.6;
setprimattrib(0, "Cd", prim, hsvtorgb(hue, 1, 1));
}
}
}
// 元のポリラインを削除
removeprim(0, @primnum, 1);
}
カーブの長さの比でラインを分割する

2次ベジェ曲線用と同じ3点の制御点で分割していくが、中間点の位置を隣の辺の長さの比にしている。
//
// ポリラインをベジェ曲線(2次)の制御点ラインへ分割する
// 両隣のエッジの長さの比で分割する(2025/05/05)
// Run Over: Primitives
// input0: Polyline
//
int pts[] = primpoints(0, @primnum);
// 描画には最低3点必要(2点以下なら直線のままにする)
if(len(pts) > 2)
{
// Polylineがループしているか否かは始点と終点の距離で判断する
int isClosed = 0;
vector start_pos = point(0, "P", pts[0]);
vector end_pos = point(0, "P", pts[-1]);
if(length(end_pos - start_pos) < 0.001)
isClosed = 1;
// ループしている場合
if(isClosed)
{
// 分割点を追加していく
int midpoint[];
for(int i = 0; i < len(pts)-1; i++)
{
vector p0 = point(0, "P", pts[i]);
vector p1 = point(0, "P", pts[i+1]);
vector prev = point(0, "P", pts[i-1]);
vector next = point(0, "P", pts[i+2]);
// 始点
if(i == 0)
{
p0 = point(0, "P", pts[0]);
p1 = point(0, "P", pts[1]);
prev = point(0, "P", pts[-2]);
next = point(0, "P", pts[2]);
}
// 終点
else if(i == len(pts)-2)
{
p0 = point(0, "P", pts[-2]);
p1 = point(0, "P", pts[0]);
prev = point(0, "P", pts[-3]);
next = point(0, "P", pts[1]);
}
float t = length(p0-prev) / (length(p0-prev) + length(next-p1));
vector p2 = lerp(p0, p1, t);
int pt = addpoint(0, p2);
append(midpoint, pt);
}
for(int i = 0; i < len(pts)-1; i++)
{
// 始点
if(i == 0)
{
int prim = addprim(0, "polyline");
addvertex(0, prim, midpoint[0]);
addvertex(0, prim, pts[1]);
addvertex(0, prim, midpoint[1]);
}
else if(i > 0 && i < len(pts)-2)
{
int prim = addprim(0, "polyline");
addvertex(0, prim, midpoint[i]);
addvertex(0, prim, pts[i+1]);
addvertex(0, prim, midpoint[i+1]);
}
// 終点
else
{
int prim = addprim(0, "polyline");
addvertex(0, prim, midpoint[-1]);
addvertex(0, prim, pts[-1]);
addvertex(0, prim, midpoint[0]);
}
}
}
// ループしていない場合
else
{
int midpoint[];
for(int i = 1; i < len(pts)-2; i++)
{
vector p0 = point(0, "P", pts[i]);
vector p1 = point(0, "P", pts[i+1]);
vector p2 = point(0, "P", pts[i+2]);
vector prev = point(0, "P", pts[i-1]);
vector next = point(0, "P", pts[i+3]);
float t = length(p1 - p0) / (length(p1-p0) + length(next-p2));
vector p3 = lerp(p0, p1, t);
int pt = addpoint(0, p3);
append(midpoint, pt);
}
for(int i = 0; i < len(pts) - 2; i++)
{
// 始点
if(i == 0)
{
int prim = addprim(0, "polyline");
addvertex(0, prim, pts[0]);
addvertex(0, prim, pts[1]);
addvertex(0, prim, midpoint[0]);
}
else if(i > 0 && i < len(pts)-3)
{
int prim = addprim(0, "polyline");
addvertex(0, prim, midpoint[i-1]);
addvertex(0, prim, pts[i+1]);
addvertex(0, prim, midpoint[i]);
}
// 終点
else
{
int prim = addprim(0, "polyline");
addvertex(0, prim, midpoint[i-1]);
addvertex(0, prim, pts[i+1]);
addvertex(0, prim, pts[i+2]);
}
}
}
// 元のポリラインを削除
removeprim(0, @primnum, 1);
}