In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

2つの円を円弧で繋ぐ

2つの円を円弧で繋ぐ
* リアルな水滴の表現に向けて目玉焼きみたいな
* 例外処理は未実装
Get Adobe Flash player
by Kay 02 Mar 2009
/*
 * 2つの円を円弧で繋ぐ
 * リアルな水滴の表現に向けて目玉焼きみたいな
 * 例外処理は未実装
 */
package {
	import flash.display.Sprite;
	import flash.geom.Point;
	import flash.events.Event;
	[SWF(width=400, height=400, backgroundColor=0x333366)]
	public class Take05 extends Sprite {
		private const SW:Number = stage.stageWidth;
		private const SH:Number = stage.stageHeight;
		private var circleA:Circle;
		private var circleB:Circle;
		private var nA:Number = 0;
		private var nB:Number = 0;
		public function Take05():void {
			circleA = new Circle();
			circleA.x = SW/2-55;
			circleA.y = SH/2+55;
			circleA.radius = 120;
			circleB = new Circle();
			circleB.x = SW/2+90;
			circleB.y = SH/2-90;
			circleB.radius = 90;
			// circleA,Bの位置を常時移動する
			addEventListener(Event.ENTER_FRAME, moveCircleB);
		}
		private function moveCircleB(eventObject:Event):void {
			nA+=0.07;
			circleA.y = SH/2 + 60*Math.sin(nA);
			nB+=0.15;
			circleB.y = SH/2 + 100*Math.sin(nB);
			graphics.clear();
			// 2つの円を曲線で繋ぐ
			getConectCenter(circleA, circleB, (circleA.radius+circleB.radius)/3);
			// オマケ
			graphics.beginFill(0xffcc00);
			graphics.drawCircle(circleA.x, circleA.y, circleA.radius/2);
			graphics.endFill();
			graphics.beginFill(0xffcc00);
			graphics.drawCircle(circleB.x, circleB.y, circleB.radius/2);
			graphics.endFill();
			graphics.lineStyle(16, 0xffffff);
			var pA:Point = new Point(circleA.x, circleA.y);
			graphics.moveTo(pA.x-circleA.radius*0.3, pA.y);
			drawArc(pA, circleA.radius*0.3, Math.PI*1, Math.PI*1.4)
			var pB:Point = new Point(circleB.x, circleB.y);
			graphics.moveTo(pB.x-circleB.radius*0.25, pB.y);
			drawArc(pB, circleB.radius*0.25, Math.PI*1, Math.PI*1.4)
		}
		// 2つの円を繋ぐ接続円を描く
		private function getConectCenter(circleA:Circle, circleB:Circle, radiusC:Number):void {
			// 3辺の長さを求める
			var pointA:Point = new Point(circleA.x,circleA.y);
			var pointB:Point = new Point(circleB.x,circleB.y);
			var distAC:Number = circleA.radius+radiusC;
			var distBC:Number = circleB.radius+radiusC;
			var distAB:Number = Point.distance(pointA,pointB);
			if (distAB < distBC+distAC) {
				// ヘロンの公式で三角形の高さを求める
				var nABC:Number = (distAB+distAC+distBC)/2;
				var area:Number = Math.sqrt(nABC*(nABC-distAB)*(nABC-distAC)*(nABC-distBC));
				var nH:Number = area/distAB*2;
				// ∠CABを求める
				var radianCAB:Number = Math.asin(nH / distAC);
				// pointAとpointBの角度を求める
				var radianAB:Number = Math.atan2((pointB.y-pointA.y),(pointB.x-pointA.x));
				// 交点C座標を求める
				var pointC:Point = Point.polar(distAC, radianCAB+radianAB);
				pointC.offset(pointA.x, pointA.y);
				if (radianCAB != 0) {
					// もう1つの交点D座標を求める
					var pointD:Point = Point.polar(distAC, -radianCAB+radianAB);
					pointD.offset(pointA.x, pointA.y);
					// 2つの円を円弧で繋いだ線を描画
					graphics.beginFill(0xffffff);
					graphics.lineStyle(16,0xffff99);
					var vAC:Number = Math.atan2((pointC.y-pointA.y),(pointC.x-pointA.x));
					var vAD:Number = Math.atan2((pointD.y-pointA.y),(pointD.x-pointA.x));
					var vBC:Number = Math.atan2((pointC.y-pointB.y),(pointC.x-pointB.x));
					var vBD:Number = Math.atan2((pointD.y-pointB.y),(pointD.x-pointB.x));
					var pointBegin:Point = Point.polar(circleA.radius,vAC);
					pointBegin.offset(pointA.x, pointA.y);
					graphics.moveTo(pointBegin.x, pointBegin.y);
					drawArc(pointA,circleA.radius,vAC,vAD+Math.PI*2);
					drawArc(pointD,radiusC,vAD+Math.PI,vBD+Math.PI);
					drawArc(pointB,circleB.radius,vBD,vBC);
					drawArc(pointC,radiusC,vBC+Math.PI,vAC+Math.PI);
					graphics.endFill();
					// オマケ
					graphics.beginFill(0xff6666);
					graphics.drawCircle(pointC.x, pointC.y, radiusC/2);
					graphics.endFill();
					graphics.beginFill(0xff6666);
					graphics.drawCircle(pointD.x, pointD.y, radiusC/2);
					graphics.endFill();
					graphics.lineStyle(16,0xffffff);
					graphics.moveTo(pointC.x-radiusC*0.2,pointC.y);
					drawArc(pointC,radiusC*0.2,Math.PI,Math.PI*1.3);
					graphics.moveTo(pointD.x-radiusC*0.2,pointD.y);
					drawArc(pointD,radiusC*0.2,Math.PI,Math.PI*1.3);
				}
			}
		}
		private function drawArc(center:Point, radius:Number, begin:Number, end:Number):void {
			// 描画範囲を取得
			var diffRadian:Number=end-begin;
			// 描画開始点を取得
			var pBegin:Point=Point.polar(radius,begin);
			pBegin.offset(center.x, center.y);
			var pEnd:Point=Point.polar(radius,end);
			pEnd.offset(center.x, center.y);
			// 中間点の数を求める
			var nStep:uint=Math.ceil(Math.abs(diffRadian)/Math.PI*4)-1;
			// 分割する角度を求める
			var stepRadian:Number = diffRadian / (nStep+1);
			// 開始点を求める
			var nY:Number=radius*Math.tan(stepRadian/2);
			var nDist:Number=Math.sqrt(Math.pow(radius,2)+Math.pow(nY,2));
			var currentRadian:Number=begin;
			for (var i:uint = 0; i < nStep; i++) {
				// 到達点
				var targetRadian:Number=currentRadian+stepRadian;
				var pTarget:Point=Point.polar(radius,targetRadian);
				pTarget.offset(center.x, center.y);
				// コントロールポイント(pControl)を求める
				var pControl:Point=Point.polar(nDist,currentRadian+stepRadian/2);
				pControl.offset(center.x, center.y);
				graphics.curveTo(pControl.x, pControl.y, pTarget.x, pTarget.y);
				// 開始点を更新
				currentRadian=targetRadian;
			}
			// 最終到達点までを描く
			stepRadian=end-currentRadian;
			nY=radius*Math.tan(stepRadian/2);
			nDist=Math.sqrt(Math.pow(radius,2)+Math.pow(nY,2));
			pControl=Point.polar(nDist,currentRadian+stepRadian/2);
			pControl.offset(center.x, center.y);
			graphics.curveTo(pControl.x, pControl.y, pEnd.x, pEnd.y);
		}
	}
}
import flash.display.Sprite;
class Circle extends Sprite {
	public var radius:Number = 100;
	public var color:uint = 0;
	public var nX:Number = 0;
	public var nY:Number = 0;
	public function Circle() {
	}
}