2つの円に共通する接線を求めてみようと思います。接線は、それぞれの円の接点を求めることと同じになりますが、この接点は、Math.acos でわりと単純に求めることができます。
上の図のように、2つの円の中心を結ぶベクトルをvとします。接線ができるのは、2つの円について、vからの角度が同じθの場合と、θとθ+Math.PI の場合です。どちらも、vの角度から±θのところが接点になります。また、θとθ+Math.PIの場合は、2つの接線が交差します。
cosθは、上図のような関係になるので、θは、
a1 = Math.acos( (r0-r1)/v.length ); a2 = Math.acos( (r0+r1)/v.length );
で求めることができます。θは、(r0-r1)、(r0+r1)が、v.lengthより大きい場合は成立しませんから、その場合、接線はないことになります。
接点の座標は、vの角度から±θになるので、
/**
* 円0: 中心( x0, y0 ) 半径 r0
* 円1: 中心( x1, y1 ) 半径 r1
*
*/
dr:Number = r0-r1;
if( Math.abs(dr)<=v.length ){
//接線あり
//vの角度
var a0:Number = Math.atan2( v.y, v.x );
//接点の角度1
var a1:Number = Math.acos( dr/v.length );
//円0の接点
var tp01:Point = new Point( x0 + r0*Math.cos(a0+a1), y0 + r0*Math.sin(a0+a1) );
var tp02:Point = new Point( x0 + r0*Math.cos(a0-a1), y0 + r0*Math.sin(a0-a1) );
//円1の接点
var tp11:Point = new Point( x1 + r1*Math.cos(a0+a1), y1 + r1*Math.sin(a0+a1) );
var tp12:Point = new Point( x1 + r1*Math.cos(a0-a1), y1 + r1*Math.sin(a0-a1) );
dr = r0+r1;
if( dr<v.length ){
//接点の角度2
var a2:Number = Math.acos( dr/v.length );
//円0の接点
var tp03:Point = new Point( x0 + r0*Math.cos(a0+a2), y0 + r0*Math.sin(a0+a2) );
var tp04:Point = new Point( x0 + r0*Math.cos(a0-a2), y0 + r0*Math.sin(a0-a2) );
//円1の接点
var tp13:Point = new Point( x1 + r1*Math.cos(a0+a2+Math.PI), y1 + r1*Math.sin(a0+a2+Math.PI) );
var tp14:Point = new Point( x1 + r1*Math.cos(a0-a2+Math.PI), y1 + r1*Math.sin(a0-a2+Math.PI) );
}else if( dr==v.length ){
//円が接している 接点
var tp05:Point = new Point( x0 + r0*Math.cos(a0), y0 + r0*Math.sin(a0) );
}
}
//追記:2010/10/17修正しました
のようになります。
接線だけなら、a0、a1、a2を求めて、円1についての接線を求めればよいことになります。