Skip to content

Instantly share code, notes, and snippets.

@shspage
Last active April 1, 2017 07:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shspage/9bee40d7f4edd507c7a49a61994253c2 to your computer and use it in GitHub Desktop.
Save shspage/9bee40d7f4edd507c7a49a61994253c2 to your computer and use it in GitHub Desktop.
Illustrator script 3つの(半径が同じ)円の隙間に円を描く
// ----------------------------------------------
function Point(x, y){
this.x = x;
this.y = y;
}
// ----------------------------------------------
function Circle(path){ // path: PathItem(円とする)
var w = 0;
if(path.stroked) w = path.strokeWidth / 2;
this.center = new Point(
path.left + w + path.width / 2,
path.top - w - path.height / 2);
this.radius = path.width / 2;
}
// ----------------------------------------------
// Point p1, p2 の間の距離を返す
function dist(p1, p2) {
var dx = p1.x - p2.x;
var dy = p1.y - p2.y;
return Math.sqrt(dx*dx + dy*dy);
}
// ----------------------------------------------
// Point p1, p2 の中点を返す
function midPnt(p1, p2){
return new Point((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
}
// ----------------------------------------------
// Point p1, p2 を通る直線をax+by+c=0と表したときの
// [a, b, c] を返す
function defline(p1, p2){
var a = p1.y - p2.y;
var b = p1.x - p2.x;
return [a, -b, b * p1.y - a * p1.x];
}
// ----------------------------------------------
// Point p1, p2 を結ぶ線分の垂直二等分線を
// ax+by+c=0 と表したときの [a, b, c] を返す
function perpendicularBisector(p1, p2){
var mp = midPnt(p1, p2);
return defline(new Point(mp.x - (p1.y - mp.y),
mp.y + (p1.x - mp.x)),
new Point(mp.x - (p2.y - mp.y),
mp.y + (p2.x - mp.x)));
}
// ----------------------------------------------
// 直線 p, q の交点を返す。2直線が平行な場合は undefined を返す。
// p, q: ax+by+c=0 の係数 [a, b, c]
function intersection(p, q){
var d = p[0] * q[1] - p[1] * q[0];
if(d==0) return;
return new Point((q[2] * p[1] - p[2] * q[1]) / d,
(p[2] * q[0] - q[2] * p[0]) / d);
}
// ----------------------------------------------
// メイン処理
function main(){
// これより小さい半径はゼロと見なす
var ALMOST_ZERO_RADIUS = 0.1;
var sel = activeDocument.selection;
// c1~c3は同じ大きさの円とする
var c1 = new Circle(sel[0]);
var c2 = new Circle(sel[1]);
var c3 = new Circle(sel[2]);
// 中心を結ぶ線の垂直二等分線
var pb1 = perpendicularBisector(c1.center, c2.center);
var pb2 = perpendicularBisector(c2.center, c3.center);
// 求める円の中心と半径
var center = intersection(pb1, pb2);
if(center == undefined){
alert("描けません");
return;
}
var radius = dist(c1.center, center) - c1.radius;
// 3円が1点で交わっている場合の例外的処理
if(radius < ALMOST_ZERO_RADIUS){
alert("半径が小さすぎるので3円が1点で交わっていると見なします\r"
+ "半径=" + radius);
radius = c1.radius * 2;
}
// 円を描画
sel[0].layer.pathItems.ellipse(
center.y + radius, center.x - radius,
radius * 2, radius * 2);
}
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment