Forked from: Kay's 円弧を描く diff:110 2つの円を円弧で繋ぐ 2つの円を円弧で繋ぐ * リアルな水滴の表現に向けて目玉焼きみたいな * 例外処理は未実装 Kay forked:1favorite:11lines:127license : All rights reserved modified : 2009-03-02 13:48:16 Embed Tweet /* * 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() { } } Code Fullscreen Preview Fullscreen alexnotkin y_tti matacat yoshifuto paq plankton OneInchPunch.. tatsuhisa clockmaker shaktool 024t910 Point.polar Math.PI Math.atan2 Math.pow Math.tan Math.sqrt Math.asin Point Math.ceil Point.distance offset Math.abs addEventListener Math.sin Event.ENTER_FRAME uint Event Sprite Number sort new page view favorite forked pv5027 forked from: 2つの円を円弧で繋ぐ tatsuhisa forked:4 favorite:53lines:166 (diff:166) tag: BetweenAS3 balls beautyfl effect metaball sticky 勉強 水