以前作成したバージョンの曲線対応版です。
main();
function main() {
if (app.documents.length == 0) {
alert("ドキュメントを開いてください");
return;
}
var doc = app.activeDocument;
if (doc.selection.length == 0) {
alert("パスを選択してください");
return;
}
var path = doc.selection[0];
if (!(path instanceof PathItem)) {
alert("PathItemを選択してください");
return;
}
var targetCount = Number(
prompt("アンカーポイント数", 30)
);
if (targetCount < 2) {
return;
}
var samples = buildSamples(path, 20);
var totalLength =
samples[samples.length - 1].dist;
var newPts = [];
for (var i = 0; i < targetCount; i++) {
var tdist;
if (path.closed) {
tdist =
totalLength * (i / targetCount);
} else {
tdist =
totalLength *
(i / (targetCount - 1));
}
newPts.push(
getPointAtDistance(samples, tdist)
);
}
createSmoothPath(doc, newPts, path.closed);
alert("完了");
}
// サンプル生成
function buildSamples(path, divs) {
var pts = path.pathPoints;
var result = [];
var accum = 0;
for (var i = 0; i < pts.length; i++) {
var next;
if (i == pts.length - 1) {
if (!path.closed) break;
next = 0;
} else {
next = i + 1;
}
var p0 = pts[i].anchor;
var p1 = pts[i].rightDirection;
var p2 = pts[next].leftDirection;
var p3 = pts[next].anchor;
var prev = null;
for (var j = 0; j <= divs; j++) {
var t = j / divs;
var p = cubicBezier(
p0, p1, p2, p3, t
);
if (prev) {
accum += distance(prev, p);
}
result.push({
pt: p,
dist: accum
});
prev = p;
}
}
return result;
}
// ベジェ評価
function cubicBezier(p0,p1,p2,p3,t){
var mt = 1 - t;
var x =
mt*mt*mt*p0[0] + 3*mt*mt*t*p1[0] + 3*mt*t*t*p2[0] +
t*t*t*p3[0];
var y =
mt*mt*mt*p0[1] + 3*mt*mt*t*p1[1] + 3*mt*t*t*p2[1] +
t*t*t*p3[1];
return [x,y];
}
// 距離
function distance(a,b){
var dx = b[0]-a[0];
var dy = b[1]-a[1];
return Math.sqrt(dx*dx+dy*dy);
}
// 距離位置取得
function getPointAtDistance(samples, d){
for (var i=1; i<samples.length; i++){
if (samples[i].dist >= d){
var prev = samples[i-1];
var curr = samples[i];
var span =
curr.dist - prev.dist;
var ratio =
(d - prev.dist) / span;
var x =
prev.pt[0] + (curr.pt[0]-prev.pt[0])*ratio;
var y =
prev.pt[1] + (curr.pt[1]-prev.pt[1])*ratio;
return [x,y];
}
}
return samples[samples.length-1].pt;
}
// 新規スムーズパス生成
function createSmoothPath(doc, pts, closed){
var p = doc.pathItems.add();
p.setEntirePath(pts);
p.closed = closed;
p.stroked = true;
p.filled = false;
var pp = p.pathPoints;
for (var i=0; i<pp.length; i++){
pp[i].pointType = PointType.SMOOTH;
var prev =
pts[(i-1+pts.length)%pts.length];
var next =
pts[(i+1)%pts.length];
var dx = (next[0]-prev[0]) * 0.18;
var dy = (next[1]-prev[1]) * 0.18;
pp[i].leftDirection = [
pts[i][0]-dx,
pts[i][1]-dy
];
pp[i].rightDirection = [
pts[i][0]+dx,
pts[i][1]+dy
];
}
}

調整したいオブジェクトを選択して実行すると・・・
ちなみに極端に少ないポイント数を指定すると形状は崩れます。


















































