Draw curve with hint
点と点を曲線で繋ぐ(こんなふうに描きました)
* Please drag red Circle and confirm the change.
// forked from Kay's Draw curve
/*
* 点と点を曲線で繋ぐ(こんなふうに描きました)
* Please drag red Circle and confirm the change.
*/
package {
import flash.display.Sprite;
import flash.display.Shape;
import flash.geom.Point;
[SWF(width=465, height=465, backgroundColor=0x000000, frameRate=30)]
public class Take03 extends Sprite {
private const PNUM:uint = 12;
private const ANGLE:Number = 360/PNUM;
private const RADIUS:uint = 150;
private const SW:uint = stage.stageWidth;
private const SH:uint = stage.stageHeight;
private var points:Vector.<Sprite> = new Vector.<Sprite>();
private var controlStage:Sprite;
private var hintLineStage:Shape;
private var hintPointStage:Shape;
private var drawStage:Shape;
public function Take03():void {
controlStage = new Sprite();
for (var i:uint = 0; i < PNUM; i++) {
var cp:ControlPoint = new ControlPoint();
var myP:Point = Point.polar(RADIUS,ANGLE*i/180*Math.PI);
myP.offset(SW/2,SH/2);
cp.x = myP.x;
cp.y = myP.y;
controlStage.addChild(cp);
points.push(cp);
}
hintLineStage = new Shape();
hintPointStage = new Shape();
drawStage = new Shape();
drawLine();
addChild(drawStage);
addChild(hintLineStage);
addChild(hintPointStage);
addChild(controlStage);
}
public function drawLine():void {
drawStage.graphics.clear();
drawStage.graphics.lineStyle(5,0xffffff);
drawStage.graphics.moveTo(points[1].x,points[1].y);
hintLineStage.graphics.clear();
hintLineStage.graphics.lineStyle(0,0x00ffff);
hintLineStage.graphics.moveTo(points[1].x,points[1].y);
hintPointStage.graphics.clear();
for (var i:uint = 0; i < PNUM; i++) {
var pA:uint = (i+PNUM)%PNUM;
var pB:uint = (pA+1)%PNUM;
var pC:uint = (pB+1)%PNUM;
var pD:uint = (pC+1)%PNUM;
var cp:Array = getCurvePoint(points[pA],points[pB],points[pC],points[pD]);
drawStage.graphics.curveTo(cp[0].x,cp[0].y,cp[1].x,cp[1].y);
drawStage.graphics.curveTo(cp[2].x,cp[2].y,points[pC].x,points[pC].y);
hintLineStage.graphics.lineTo(cp[0].x, cp[0].y);
hintLineStage.graphics.lineTo(cp[1].x, cp[1].y);
hintLineStage.graphics.lineTo(cp[2].x, cp[2].y);
hintLineStage.graphics.lineTo(points[pC].x, points[pC].y);
hintPointStage.graphics.beginFill(0xff00ff);
hintPointStage.graphics.drawCircle(cp[0].x,cp[0].y,2);
for (var j:uint = 0; j < 3; j++) {
hintPointStage.graphics.endFill();
hintPointStage.graphics.beginFill(0xff00ff);
hintPointStage.graphics.drawCircle(cp[j].x,cp[j].y,2.5);
}
}
}
// 与えられた4点からその中間2点(A0,B0)を曲線で繋ぐための位置(controlPointA,mp,controlPointB)を求める
private function getCurvePoint(a:Sprite, b:Sprite, c:Sprite, d:Sprite):Array {
// Point targetA,targetBの距離
var beforeA:Point = new Point(a.x, a.y);
var targetA:Point = new Point(b.x, b.y);
var targetB:Point = new Point(c.x, c.y);
var afterB :Point = new Point(d.x, d.y);
var connectL:Number = Point.distance(targetA,targetB);
//var connectR:Number = getRadian(targetB,targetA);
// コントロールポイント(controlPoint)の要素
var controlPointA:Object = new Object();
controlPointA.r = getRadian(targetB, beforeA);
controlPointA.p = Point.distance(targetA, beforeA); // この線にかかる力(接続線の距離)
var controlPointB:Object = new Object();
controlPointB.r = getRadian(targetA, afterB);
controlPointB.p = Point.distance(targetB, afterB); // この線にかかる力(接続線の距離)
// 力のかかる比率
var ratio:Number = controlPointA.p/(controlPointA.p+controlPointB.p);
// コントロールポイント(controlPoint)の位置を求める
if (targetA.equals(beforeA)) {
controlPointA.x = beforeA.x;
controlPointA.y = beforeA.y;
} else {
controlPointA.l = connectL/2*ratio; //*Math.tan(getRadianDiff(connectR,controlPointA.r));
controlPointA.x = targetA.x + controlPointA.l*Math.cos(controlPointA.r);
controlPointA.y = targetA.y + controlPointA.l*Math.sin(controlPointA.r);
}
if (targetB.equals(afterB)) {
controlPointB.x = afterB.x;
controlPointB.y = afterB.y;
} else {
controlPointB.l = connectL/2*(1-ratio); //*Math.tan(getRadianDiff(controlPointB.r,connectR));
controlPointB.x = targetB.x + controlPointB.l*Math.cos(controlPointB.r);
controlPointB.y = targetB.y + controlPointB.l*Math.sin(controlPointB.r);
}
// 中間点(centerPoint)
var centerPoint:Point = new Point();
centerPoint.x = controlPointA.x + (controlPointB.x-controlPointA.x)*ratio;
centerPoint.y = controlPointA.y + (controlPointB.y-controlPointA.y)*ratio;
// 中間点と2つのコントロールポイントとを返す
return ([controlPointA,centerPoint,controlPointB]);
}
private function getRadian(a:Point,b:Point):Number {
var dx:Number = (a.x - b.x);
var dy:Number = (a.y - b.y);
var radian:Number = Math.atan2(dy,dx);
return (radian);
}
}
}
import flash.display.Sprite;
import flash.display.Shape;
import flash.events.MouseEvent;
import flash.events.Event;
class ControlPoint extends Sprite {
private var dFlag:Boolean = false;
public function ControlPoint():void {
graphics.beginFill(0xff0000);
graphics.drawCircle(0,0,10);
graphics.endFill();
addEventListener(MouseEvent.MOUSE_DOWN, beginDrag);
addEventListener(MouseEvent.MOUSE_UP, finishDrag);
addEventListener(MouseEvent.MOUSE_MOVE, movePoint);
buttonMode = true;
}
private function movePoint(e:Event):void {
if (dFlag) e.target.parent.parent.drawLine();
}
private function beginDrag(e:MouseEvent):void {
dFlag = true;
this.startDrag();
}
private function finishDrag(e:MouseEvent):void {
dFlag = false;
this.stopDrag();
}
}