Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Illustrator で2円をつなぐ線を描く
// 座標や範囲を配列で表すと見にくいのでクラスのようなものにします。
function Point(x, y){ //
this.x = x;
this.y = y;
}
function Rect(bounds){ // 範囲 bounds:[left, top, right, bottom]
this.left = bounds[0];
this.top = bounds[1];
this.right = bounds[2];
this.bottom = bounds[3];
this.center = new Point((this.right + this.left) / 2,
(this.top + this.bottom) / 2);
this.width = this.right - this.left;
this.height = this.top - this.bottom;
}
// O1を中心とした半径R1の円と、
// O2を中心とした半径R2の円をつなぐ線(2つのうちの片方)
// の接点を取得してP1, P2に設定する。
// 接線が描けない場合 false を返す。
function getTangentPoint(O1, R1, O2, R2, P1, P2){
//2円の中心の距離を d とする。
var dx = O1.x - O2.x;
var dy = O1.y - O2.y;
var d = Math.sqrt(dx*dx + dy*dy);
// 2円が重なっているか、接しているか、包囲している
if(d <= R1 + R2) return false;
var t = Math.acos((R1 + R2) / d);
//O1を原点とした場合、中心を結ぶ線の角度は
var T = Math.atan2(O2.y - O1.y, O2.x - O1.x);
//従って
P1.x = O1.x + R1 * Math.cos(T + t);
P1.y = O1.y + R1 * Math.sin(T + t);
T += Math.PI; // O2を原点とした角度に直す
P2.x = O2.x + R2 * Math.cos(T + t);
P2.y = O2.y + R2 * Math.sin(T + t);
// もう片方の接線の接点は -t とすると求められます。
return true;
}
// メイン処理
function main(){
// 選択オブジェクトを取得
// 選択物はパスか?などの確認は省略
var sel = activeDocument.selection;
var C1 = sel[0]; // 円1
var C2 = sel[1]; // 円2
// それぞれを囲む範囲の情報を取得
var C1_rect = new Rect(C1.geometricBounds);
var C2_rect = new Rect(C2.geometricBounds);
var O1 = C1_rect.center; // 円1の中心
var R1 = C1_rect.width / 2; // 円1の半径
var O2 = C2_rect.center;
var R2 = C2_rect.width / 2;
var P1 = new Point(); // 接点1
var P2 = new Point(); // 接点2
// result: 接線が描けない場合 false
var result = getTangentPoint(O1, R1, O2, R2, P1, P2);
// 接線を作成
if(result){
var path = C1.duplicate(); // 属性を継承するために複製
path.closed = false; // ただしクローズパスではない
path.filled = false; // 一応塗りもリセットしておく
path.setEntirePath([[P1.x, P1.y],[P2.x, P2.y]]);
} else {
alert("接線は描けません");
}
}
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment