Last active
April 1, 2017 07:28
-
-
Save shspage/9bee40d7f4edd507c7a49a61994253c2 to your computer and use it in GitHub Desktop.
Illustrator script 3つの(半径が同じ)円の隙間に円を描く
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ---------------------------------------------- | |
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