朝わん2日目:枠情報からポリゴンを作る(あとでつづき)
朝ワン2日目
未完です
/**
* Copyright nyamogera ( http://wonderfl.net/user/nyamogera )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/sw1u
*/
// forked from mogera's forked from: 朝わん1日目
// forked from mogera's 朝わん1日目
package {
// 朝ワン2日目
//
//未完です
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.display.Shape;
import flash.geom.Point;
public class FlashTest extends Sprite {
[SWF(width="465", height="465", backgroundColor="0xffffff", framerate="20")]
private var _tmpLine:Line; // 一時保管ライン
private var _lineStartAndLast:Line;// 最初と最後をつなぐ
private var _tmpBuffer:Shape; // 描画ライン一時保存用
private var _backBuffer:Shape; // 描画ライン(もう動かさないよう)
private var _tmpOldPoint:Point;
private var _tmpStartPoint:Point;
private var _debug:DebugTest;
private var _trace:DebugTest;
private var _traceStr:String;
private var _isCreatePolygon:Boolean;
private var _lineCount:int;
private var _createPolygonButton:TestButton;
private var _createPolygon:CreatePolygon;
public function FlashTest() {
// write as3 code here..
var background:Sprite = createBackGround()
var asaWon:AsaWon = new AsaWon( 2, 0x000000);
asaWon.x = 100;
addChild(asaWon);
// トレース用
_trace= new DebugTest( "trace");
_trace.x = 350;
addChild( _trace);
// デバッグ用(残らない)
_debug = new DebugTest( "debug");
_debug.x = 300;
addChild( _debug );
///////////////////////////////////////// まだなので。
_debug.x = (stage.stageWidth - _debug.width ) / 2;
_debug.y = (stage.stageHeight - _debug.height) / 2;
_debug.add("atode", "あとで続き")
///////////////////////////////////////// まだなので。
// return;
_lineStartAndLast = new Line();
_tmpLine = new Line();
addChild( _tmpBuffer = new Shape() ); // 保存用のバッファと
addChild( _backBuffer = new Shape() ); // 表示用のバッファ
addChild( _createPolygonButton = new TestButton("Create!"));
_createPolygonButton.enabled = false;
_createPolygonButton.addEventListener( MouseEvent.CLICK, createPolygonHandler);
_createPolygon = new CreatePolygon();
addChild(_createPolygon.debugShape );
var resetButton:TestButton;
addChild( resetButton = new TestButton("Reset!"));
resetButton.addEventListener( MouseEvent.CLICK, resetHandler );
resetButton.y = 20;
// イベント取り付ける
background.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
background.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
background.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
}
private function resetHandler(event:MouseEvent) : void
{
// ここでリセットする
_createPolygon.reset();
_isCreatePolygon = false;
_tmpBuffer.graphics.clear();
_backBuffer.graphics.clear();
_traceStr = "";
_trace.add("trace", _traceStr );
}
private function createPolygonHandler(event:MouseEvent) : void
{
keepLine(_tmpOldPoint.x, _tmpOldPoint.y);
_tmpBuffer.graphics.clear();
_tmpLine.draw(_tmpBuffer, 0x000000);
_lineStartAndLast.draw(_tmpBuffer, 0x000000);
// ここからポリゴン作る!
_isCreatePolygon = false;
_createPolygon.calc();
}
// トレースを追加する
private function addTrace(str:String) : void
{
_traceStr = _traceStr + "\n" + str;
_trace.add("trace", _traceStr );
}
// マウスが移動したとき
private function mouseMoveHandler(event:MouseEvent) : void
{
_debug.add("mouse", "mouse move ->" + _tmpLine);
_debug.add("pos x:", event.stageX.toString() + ", y:"+ event.stageY.toString() );
if( ! _isCreatePolygon ) return ; // 作成フラグがないのでリターンする
keepLine(mouseX, mouseY);
_tmpBuffer.graphics.clear();
_tmpLine.draw(_tmpBuffer, 0xff0000);
_lineStartAndLast.draw(_tmpBuffer, 0xff0000);
// 最初と最後をつなぐ用の描画
_lineStartAndLast.draw(_tmpBuffer, 0x00ff00);
}
// マウスが押されたとき
private function mouseDownHandler(event:MouseEvent) : void
{
_debug.add("mouse", "mouse down");
_debug.add("pos put x:", event.stageX.toString() + ", y:"+ event.stageY.toString() );
if( !_isCreatePolygon)
{
_tmpStartPoint = _tmpOldPoint = new Point(mouseX, mouseY);
//_createPolygon.addFramePos(new Point(mouseX, mouseY));
//addTrace("addFramePos x:" + mouseX.toString() + ",y:" + mouseY.toString() );
}
_isCreatePolygon = true;
}
// マウスがUP!
private function mouseUpHandler(event:MouseEvent) : void
{
_lineCount++;
_debug.add("mouse", "mouse up");
_tmpBuffer.graphics.clear(); // バッファクリア
keepLine(mouseX, mouseY);
// 最初と最後をつなぐ用の描画
_lineStartAndLast.draw(_tmpBuffer, 0x00ff00);
// バッファに書き込む
_tmpLine.draw(_backBuffer, 0x000000);
_createPolygon.addFramePos(_tmpOldPoint = new Point(mouseX, mouseY));
addTrace("addFramePos x:" + mouseX.toString() + ",y:" + mouseY.toString() );
if( _lineCount >= 3 ) _createPolygonButton.enabled = true;
addTrace("mou up2")
}
private function keepLine(mouseX:Number, mouseY:Number) : void
{
// ラスト・ラスト一歩手前
_tmpLine.p0.x = _tmpOldPoint.x;
_tmpLine.p0.y = _tmpOldPoint.y;
_tmpLine.p1.x = mouseX;
_tmpLine.p1.y = mouseY;
// スタート・ラスト
_lineStartAndLast.p0.x = _tmpStartPoint.x;
_lineStartAndLast.p0.y = _tmpStartPoint.y;
_lineStartAndLast.p1.x = mouseX;
_lineStartAndLast.p1.y = mouseY;
}
// 背景表示用
private function createBackGround(color:uint=0xffffff):Sprite
{
var sprite:Sprite = new Sprite();
addChild( sprite );
var shape:Shape = new Shape();
shape.graphics.beginFill(color, 1);
shape.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
sprite.addChild(shape);
return sprite;
}
/*
private function crossCheck() : void
{
var length:int = _lines.length;
for(var i:int = 0; i < length -1; i ++ )
{
for( var j:int = i; j < length; j++)
{
if( Line.intersection(_lines[i], _lines[j]))
{
addTrace( i.toString() + "x" + j.toString() + " is cross");
}
else
{
addTrace( i.toString() + "x" + j.toString() + " is not cross");
}
}
}
}
*/
}
}
internal class TestButton extends Sprite
{
private var _enabled:Boolean;
private var _textField:TextField = new TextField();
public function TestButton(str:String) : void
{
_textField.text = str;
_textField.height = _textField.textHeight + 4;
_textField.width = _textField.textWidth + 4;
_textField.background = true;
_textField.backgroundColor = 0x000000;
_textField.textColor = 0xffffff;
addChild(_textField);
}
public function set enabled(val:Boolean) : void
{
if( val )
{
_textField.backgroundColor = 0x333333;
}
else
{
_textField.backgroundColor = 0x0888888;
}
mouseEnabled = val;
_enabled = val;
}
public function get enabled() : Boolean { return _enabled; }
}
// ポリゴン作成クラス
internal class CreatePolygon
{
private var _frame:Vector.<Point>;
private var _tmpLines:Vector.<Line>;
private var _polygon:Vector.<Polygon>;
private var _isCreated:Boolean;
public function get isCreated() : Boolean { return isCreated; }
public var debugShape:Shape = new Shape();
// 枠の点を追加する
public function addFramePos(p:Point) : void
{
_frame.push(p);
}
//
public function CreatePolygon()
{
_frame = new Vector.<Point>();
_tmpLines = new Vector.<Line>();
_polygon = new Vector.<Polygon>;
}
// todo:情報をリセットする
public function reset() : void
{
debugShape.graphics.clear();
_frame.splice(0, _frame.length );
_tmpLines.splice(0, _tmpLines.length );
_polygon.splice(0, _polygon.length );
}
// デバッグチェック用
public function traceDebug() : String
{
var str:String;
var length:int = _frame.length;
for( var i:int ; i < length; i ++)
{
str += i.toString() + " x:" + _frame[i].x + ",y:" + _frame[i].y;
}
return str;
}
// todo:枠情報からポリゴンを作成する
public function calc() : void
{
// 3つ点が無ければ、ポリゴン作れない・・・。
if( _frame.length <= 3 ) return;
var tmpFrameLines:Vector.<Line> = getFrameLines();
var tmpCrossLines:Vector.<Line> = getCrossLines(tmpFrameLines);
}
// 枠情報から交差チェック用のlineを作成する
public function getFrameLines() : Vector.<Line>
{
var tmpFrameLines:Vector.<Line> = new Vector.<Line>();
var length:int = _frame.length;
for( var i:int = 0; i < length -1; i ++ )
{
var tmpLine:Line = new Line();
tmpLine.p0 = _frame[i];
tmpLine.p1 = _frame[i+1];
tmpFrameLines.push( tmpLine );
}
tmpLine.p0 = _frame[_frame.length -1];
tmpLine.p1 = _frame[0];
tmpFrameLines.push( tmpLine );
return tmpFrameLines;
}
// 枠情報から交差チェック用のlineを作成する
private function getCrossLines(tmpFrameLines:Vector.<Line>) : Vector.<Line>
{
var tmpCrossLines:Vector.<Line> = new Vector.<Line>();
var tmpLine:Line = new Line();
var length : int = _frame.length;
for( var i:int = 0; i < length - 2; i ++ )
{
for( var j:int = i+2; j < length ; j ++ )
{
tmpLine.p0 = _frame[i];
tmpLine.p1 = _frame[j];
var sj:int = (i - 1 + length ) % length;
var cj:int = (i + length ) % length;
var ej:int = (i + 1 + length ) % length;
var si:int = (j - 1 + length ) % length;
var ci:int = (j + length ) % length;
var ei:int = (j + 1 + length ) % length;
if( !isCrossLines( tmpLine, tmpFrameLines ))
{
var tj:int = j;
var ti:int = i;
if( !inside( _frame[sj], _frame[cj] ,_frame[ej], _frame[tj]))
{
trace("continue")
continue;
}
// if( !inside( _frame[si], _frame[ci] ,_frame[ei], _frame[ti])) continue;
var line:Line = new Line();
line.p0 = _frame[i];
line.p1 = _frame[j];
line.draw(debugShape, 0xff00ff);
tmpCrossLines.push( line );
}
}
}
return tmpCrossLines;
}
private function inside(start:Point, center:Point, end:Point, to:Point) : Boolean
{
var poly:Polygon = new Polygon();
poly.p0 = start;
poly.p1 = center;
poly.p2 = to;
var n1:Number = poly.normalize();
poly.p0 = to;
poly.p1 = center;
poly.p2 = end;
var n2:Number = poly.normalize();
trace( n1, n2 );
//if( n1 > 0 && n2 > 0 ) return true;
if( n1 < 0 && n2 < 0 ) return true;
return false;
}
// 交差チェックを行う。linesの配列の中身すべてのラインに交差していなければ false
// ひとつでも交差していれば true
private function isCrossLines( line:Line, lines:Vector.<Line>) : Boolean
{
var length:int = lines.length;
trace("intersect", length)
for( var i:int = 0; i < length; i ++ )
{
var result:Boolean = Line.intersection(lines[i], line)
trace("lines",line.p0, line.p1, lines[i].p0, lines[i].p1, result)
if( result )
{
trace("result" , result)
return true;
}
}
return false;
}
}
// ライン
import flash.display.Graphics;
import flash.geom.Point;
import flash.display.Shape;
internal class Line
{
public var p0:Point = new Point();
public var p1:Point = new Point();
public function draw( shape:Shape, color:uint ) : void
{
var g:Graphics = shape.graphics;
g.lineStyle(1,color,1.0);
g.moveTo(p0.x,p0.y);
g.lineTo(p1.x,p1.y);
}
// 交差しているか
public static function intersection(line0:Line, line1:Line) : Boolean
{
if(intersectFunc(line0, line1) && intersectFunc(line1, line0))
{
return true;
}
return false;
}
private static function intersectFunc(line0:Line, line1:Line) : Boolean
{
if(
((line0.p0.x - line0.p1.x) * (line1.p0.y - line0.p0.y) +
(line0.p0.y - line0.p1.y) * (line0.p0.x - line1.p0.x)) *
((line0.p0.x - line0.p1.x) * (line1.p1.y - line0.p0.y) +
(line0.p0.y - line0.p1.y) * (line0.p0.x - line1.p1.x)) < 0)
{
return true;
}
return false;
}
public function isDot() : Boolean
{
return (( p0.x == p1.x) && (p0.y == p1.y));
}
private static function sameLine(line0:Line, line1:Line) : Boolean
{
if(( (
( line0.p0.x == line1.p0.x ) &&
( line0.p0.y == line1.p0.y ) ) &&
(( line0.p1.x == line1.p1.x ) &&
( line0.p1.y == line1.p1.y ) ) )||
( (( line0.p0.x == line1.p1.x ) &&
( line0.p0.y == line1.p1.y ) ) &&
(( line0.p1.x == line1.p0.x ) &&
( line0.p1.y == line1.p0.y ) ) ))
{
return true;
}
return false;
}
}
internal class Polygon
{
public var p0:Point;
public var p1:Point;
public var p2:Point;
public function draw(shape:Shape, color:uint) : void
{
var g:Graphics = shape.graphics;
g.lineStyle(1,color,1.0);
g.moveTo(p0.x,p0.y);
g.lineTo(p1.x,p1.y);
g.lineTo(p2.x,p2.y);
g.lineTo(p0.x,p0.y);
}
// 法線方向を求める
// 2dなので、おもてむきか裏向きかだけしりたい
public function normalize() : Number
{
var tmp01:Point = new Point();
var tmp02:Point = new Point();
var n:Number;
tmp01.x = p1.x - p0.x;
tmp01.y = p1.y - p0.y;
tmp02.x = p2.x - p0.x;
tmp02.y = p2.y - p0.y;
n = tmp01.x * tmp02.y + tmp01.y * tmp02.x;
return n ;
}
}
// (U^ω^) <わん
import flash.text.TextField;
import flash.display.Sprite;
internal class AsaWon extends Sprite
{
private var textField:TextField;
function AsaWon(day:int, color:uint)
{
textField = new TextField();
textField.text = "朝 (U^ω^) <わん " + day + "日め";
textField.textColor = color;
textField.width = textField.textWidth + 4;
textField.height = textField.textHeight + 4;
addChild( textField );
}
}
// デバッグ用のコード
// http://wonderfl.net/code/c4bf78ae758a71c3a7bdcdc26fcf79383b2c2f7a/edit
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.utils.Dictionary;
class DebugTest extends Sprite
{
private var barField:TextField;
private var openField:TextField;
private var debugField:TextField;
private var dictionary:Dictionary;
public function DebugTest(title:String)
{
dictionary = new Dictionary(true);
barField = new TextField();
openField = new TextField();
debugField = new TextField();
barField.text = title;
openField.text = "▲"; // 上三角
barField.background = true;
barField.backgroundColor = 0x00000;
barField.textColor = 0xffffff;
barField.x = 20;
barField.height = 20;
barField.addEventListener( MouseEvent.MOUSE_DOWN, startMove);
barField.addEventListener( MouseEvent.MOUSE_UP, endMove);
barField.border = true;
barField.selectable= false;
openField.background = true;
openField.backgroundColor = 0x00000;
openField.textColor = 0xffffff;
openField.height = 20;
openField.width = 20;
openField.selectable= false;
openField.border = true;
openField.mouseEnabled = true;
openField.addEventListener( MouseEvent.CLICK, switchVisible);
debugField.border = true;
debugField.background = true;
debugField.y = 20;
addChild( barField );
addChild( openField );
addChild( debugField );
update();
}
// すいっち
private function switchVisible(e:MouseEvent):void
{
debugField.visible = !debugField.visible;
if ( debugField.visible )
{
openField.text = "▲"
}
else
{
openField.text = "▼"
}
}
//
private function endMove(e:MouseEvent):void
{
stopDrag();
}
//
private function startMove(e:MouseEvent):void
{
startDrag();
}
// 更新
private function update():void
{
var w:Number = Math.max( barField.textWidth + 20, debugField.textWidth ) + 4 ;
barField.width = w - 20;
debugField.width = w;
debugField.height = debugField.textHeight + 4;
}
public function add(key:String, str:String) : void
{
dictionary[key] = str;
debugField.text = "";
for ( var s:String in dictionary )
{
debugField.appendText( s + ":" + dictionary[s] + "\n" );
}
update();
}
public function remove(key:String) : void
{
dictionary[key] = null;
delete dictionary[key];
update();
}
}