/**
* Copyright mutantleg ( http://wonderfl.net/user/mutantleg )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/a8vY
*/
package {
import flash.text.TextField;
import flash.ui.Keyboard;
import flash.events.KeyboardEvent;
import flash.events.Event;
import flash.display.Sprite;
public class FlashTest extends Sprite {
public function FlashTest() {
myFace = new xFace();
myFace.a.setValue(20,20,0);
//myFace.a.setValue(400,400,0);
myFace.b.setValue(20,400,0);
myFace.c.setValue(400,20,0);
/*
myFace.a.setValue(200,400,0);
myFace.b.setValue(20,400,0);
myFace.c.setValue(400,20,0);
*/
deb = new TextField();
deb.mouseEnabled = false;
deb.width = 320;
deb.height = 240;
addChild(deb);
xCutter.deb = deb;
stage.addEventListener(KeyboardEvent.KEY_DOWN, kdown);
stage.addEventListener(KeyboardEvent.KEY_UP, kup);
stage.addEventListener(Event.ENTER_FRAME, onEnter);
}//ctor
public var vecKey:Vector.<Boolean> = new Vector.<Boolean>(512, false);
public function kdown(e:KeyboardEvent):void { if (e.keyCode >511){ return;} vecKey[e.keyCode]=true;}
public function kup(e:KeyboardEvent):void { if (e.keyCode>511) { return;} vecKey[e.keyCode] =false;}
public var deb:TextField;
public var cx:Number = 300;
public var cy:Number = 300;
public var ang:Number = 0;
public var myFace:xFace = new xFace();
/*
public var ret1:xFace = new xFace();
public var ret2:xFace = new xFace();
public var ret3:xFace = new xFace();
public var ret4:xFace = new xFace();
public var ret5:xFace = new xFace();
public var ret6:xFace = new xFace();
public var ret7:xFace = new xFace();
public var ret8:xFace = new xFace();
*/
public var cut1:xCutter = new xCutter();
public var cut2:xCutter = new xCutter();
public var cut3:xCutter = new xCutter();
public function onEnter(e:Event):void
{
graphics.clear();
graphics.lineStyle(2, 0);
graphics.drawCircle(cx, cy, 8);
var dx:Number;
var dy:Number;
if (vecKey[Keyboard.UP]) { cy -= 4; }
if (vecKey[Keyboard.DOWN]) { cy += 4; }
if (vecKey[Keyboard.LEFT]) { cx -= 4; }
if (vecKey[Keyboard.RIGHT]) { cx += 4; }
dx = stage.mouseX-cx;
dy = stage.mouseY-cy;
ang = Math.atan2(dy, dx);
graphics.moveTo(cx, cy);
graphics.lineTo(cx+Math.cos(ang)*8,cy+ Math.sin(ang)*8);
var nx:Number;
var ny:Number;
nx = Math.cos(ang-0.7);
ny = Math.sin(ang-0.7);
graphics.moveTo(cx,cy);
graphics.lineTo(cx+nx*256,cy+ny*256);
graphics.moveTo(cx+nx*128,cy+ny*128);
graphics.lineTo(cx+(nx*128)-ny*8,cy+(ny*128)+nx*8 );
nx = Math.cos(ang+0.7);
ny = Math.sin(ang+0.7);
graphics.moveTo(cx,cy);
graphics.lineTo(cx+nx*256,cy+ny*256);
graphics.moveTo(cx+nx*128,cy+ny*128);
graphics.lineTo(cx+(nx*128)+ny*8,cy+(ny*128)-nx*8 );
nx = Math.cos(ang);
ny = Math.sin(ang);
graphics.moveTo(cx+nx-ny*64,cy+ny+nx*64 );
graphics.lineTo(cx+nx+ny*64,cy+ny-nx*64 );
var num1:int;
var num2:int;
var num3:int;
var num3b:int;
var fc:xFace;
var fc2:xFace;
var fc3:xFace;
drawTri(myFace);
//i keep screwing up the cutting function but not sure where
//edit //2013/6/30
//ok now i think i figured out
//or at least it seem to work now ok
cut1.setPlane(cx,cy, 0, Math.cos(ang), Math.sin(ang), 0);
cut2.setPlane(cx,cy, 0, -Math.sin(ang-0.7), Math.cos(ang-0.7), 0);
cut3.setPlane(cx,cy, 0, Math.sin(ang+0.7), -Math.cos(ang+0.7), 0);
num1 = cut1.cutFace(myFace);
if (num1 == 0) { fc = myFace;} else { fc = cut1.ret1; }
graphics.lineStyle(4,0xFF0000);
drawTri(fc);
if (num1 > 1) { graphics.lineStyle(3,0x880000);
drawTri(cut1.ret2);}
/*
graphics.lineStyle(2,0);
num2 = cut2.cutFace(fc);
if (num2 == 0) { fc2 = fc;} else { fc2 = cut2.ret1; }
graphics.lineStyle(4,0x00FF00);
drawTri(fc2);
graphics.lineStyle(2,0);
if (num2>1) { fillTri(cut2.ret2, 0x808080,0.5) };
num3 = cut3.cutFace(fc2);
if (num3 == 0) { fc3 = fc2;} else { fc3 = cut3.ret1; }
fillTri(fc3, 0xFF,0.5);
if (num3 > 1) { fillTri(cut3.ret2, 0xF0F0, 0.5); }
if (num2 > 1)
{
fc2 = cut2.ret2;
drawTri(fc2);
num3 = cut3.cutFace(fc2);
if (num3 == 0) { fc3 = fc2;} else { fc3 = cut3.ret1; }
fillTri(fc3,0xFF0000, 0.5);
// if (num3 > 1) { fillTri(cut3.ret2, 0xFFF000, 0.5); }
}
*/
/*
nx = Math.cos(ang);
ny = Math.sin(ang);
num1 = cutTri2(myFace, cx, cy, 0, nx, ny, 0, ret1, ret2);
if (num1 < 0) { return; }
if (num1 == 0) { ret1.copyFace(myFace); }
graphics.lineStyle(2, 0xFF0000);
drawTri(ret1);
if (num1>1) { drawTri(ret2); }
nx = -Math.sin(ang-0.7);
ny = Math.cos(ang-0.7);
num2 = cutTri2(ret1, cx,cy,0, nx, ny, 0, ret3, ret4);
if (num2 < 0) { return; }
if (num2 == 0) { ret3.copyFace(ret1); }
graphics.lineStyle(2, 0x00FF00);
drawTri(ret3);
if (num2>1) {drawTri(ret4);}
nx = Math.sin(ang+0.7);
ny = -Math.cos(ang+0.7);
num3 = cutTri2(ret3, cx, cy, 0, nx, ny, 0, ret5, ret6);
graphics.lineStyle(2, 0x0000FF);
if (num3 < 0) { return; }
if (num3 == 0) { ret5.copyFace(ret3); }
drawTri(ret5);
if (num3 >1) { drawTri(ret6);}
*/
}//onenter
public function fillTri(f:xFace, c:uint, a:Number=1.0):void
{
graphics.beginFill(c, a);
graphics.moveTo(f.a.cx, f.a.cy);
graphics.lineTo(f.b.cx, f.b.cy);
graphics.lineTo(f.c.cx, f.c.cy);
graphics.lineTo(f.a.cx, f.a.cy);
graphics.endFill();
}//filltri
public function drawTri(f:xFace):void
{
graphics.moveTo(f.a.cx, f.a.cy);
graphics.lineTo(f.b.cx, f.b.cy);
graphics.lineTo(f.c.cx, f.c.cy);
graphics.lineTo(f.a.cx, f.a.cy);
graphics.drawCircle(f.a.cx, f.a.cy, 4);
graphics.drawCircle(f.b.cx, f.b.cy, 7);
graphics.drawCircle(f.c.cx, f.c.cy, 10);
}//drawtri
}//classend
}
import flash.text.TextField;
internal class xCutter
{
public static var deb:TextField;
public var ret1:xFace = new xFace();
public var ret2:xFace = new xFace();
public var num:int = 0;
public var cx:Number = 0;
public var cy:Number = 0;
public var cz:Number = 0;
public var cnx:Number = 0;
public var cny:Number = 0;
public var cnz:Number = 0;
public function xCutter():void
{}//ctor
public function setPlane( px:Number, py:Number, pz:Number,
nx:Number, ny:Number, nz:Number):void
{
cx = px; cy = py; cz = pz;
cnx = nx; cny =ny; cnz = nz;
}//setplane
public function cutFace(f:xFace):int
{
num = cutTri2(f, cx,cy,cz, cnx,cny,cnz, ret1, ret2);
return num;
}//cutface
public var vecOut:Vector.<xVert> = Vector.<xVert>([new xVert(), new xVert(), new xVert(), new xVert()]);
//cut triangle by plane
//copies new tris into reta and retb
//returns the number of tris created
//note -- only returns the triangles on the front
public function cutTri2(tri:xFace,
px:Number, py:Number, pz:Number, //plane position
nx:Number, ny:Number, nz:Number, //plane normal
reta:xFace, retb:xFace):int
{
var it:int;
var t:Number;
var va:xVert;
var vs:xVert;
var dv:xVert;
var da:Number;
var ds:Number;
var ccw:Number;
var ad:Number;
var bd:Number;
var cd:Number;
//todo -- optimisation
//distance only need to be calculated ONCE per vertex
ad = (tri.a.cx - px)*nx + (tri.a.cy - py)*ny + (tri.a.cz - pz)*nz;
bd = (tri.b.cx - px)*nx + (tri.b.cy - py) * ny + (tri.b.cz - pz) * nz;
cd = (tri.c.cx - px) * nx + (tri.c.cy - py) * ny + (tri.c.cz - pz) * nz;
if (ad > 0 && bd > 0 && cd > 0) { return 0; }
it = 0;
//copy paste iminent
vs = tri.a;
va = tri.b;
da = (va.cx - px)*nx + (va.cy - py)*ny + (va.cz - pz)*nz;
ds = (vs.cx - px) * nx + (vs.cy - py) * ny + (vs.cz - pz) * nz;
if (da > 0)
{
vecOut[it].copyVert(va);
it += 1;
if (ds <= 0)
{
t = da / (nx * (va.cx - vs.cx) + ny * (va.cy - vs.cy) + nz * (va.cz - vs.cz) );
dv = vecOut[it];
dv.cx = va.cx + (vs.cx - va.cx) * t;
dv.cy = va.cy + (vs.cy - va.cy) * t;
dv.cz = va.cz + (vs.cz - va.cz) * t;
it += 1;
}//endif2
}
else if (ds > 0)
{
t = da / (nx * (va.cx - vs.cx) + ny * (va.cy - vs.cy) + nz * (va.cz - vs.cz) );
dv = vecOut[it];
dv.cx = va.cx + (vs.cx - va.cx) * t;
dv.cy = va.cy + (vs.cy - va.cy) * t;
dv.cz = va.cz + (vs.cz - va.cz) * t;
it += 1;
}//endif2
va = tri.a;
vs = tri.c;
da = (va.cx - px)*nx + (va.cy - py)*ny + (va.cz - pz)*nz;
ds = (vs.cx - px)*nx + (vs.cy - py)*ny + (vs.cz - pz)*nz;
if (da > 0)
{
vecOut[it].copyVert(va);
it += 1;
if (ds <= 0)
{
t = da / (nx * (va.cx - vs.cx) + ny * (va.cy - vs.cy) + nz * (va.cz - vs.cz) );
dv = vecOut[it];
dv.cx = va.cx + (vs.cx - va.cx) * t;
dv.cy = va.cy + (vs.cy - va.cy) * t;
dv.cz = va.cz + (vs.cz - va.cz) * t;
it += 1;
}//endif2
}
else if (ds > 0)
{
t = da / (nx * (va.cx - vs.cx) + ny * (va.cy - vs.cy) + nz * (va.cz - vs.cz) );
dv = vecOut[it];
dv.cx = va.cx + (vs.cx - va.cx) * t;
dv.cy = va.cy + (vs.cy - va.cy) * t;
dv.cz = va.cz + (vs.cz - va.cz) * t;
it += 1;
}//endif2
vs = tri.b;
va = tri.c;
da = (va.cx - px)*nx + (va.cy - py)*ny + (va.cz - pz)*nz;
ds = (vs.cx - px) * nx + (vs.cy - py) * ny + (vs.cz - pz) * nz;
if (da > 0)
{
vecOut[it].copyVert(va);
it += 1;
if (ds <= 0)
{
t = da / (nx * (va.cx - vs.cx) + ny * (va.cy - vs.cy) + nz * (va.cz - vs.cz) );
dv = vecOut[it];
dv.cx = va.cx + (vs.cx - va.cx) * t;
dv.cy = va.cy + (vs.cy - va.cy) * t;
dv.cz = va.cz + (vs.cz - va.cz) * t;
it += 1;
}//endif2
}
else if (ds > 0)
{
t = da / (nx * (va.cx - vs.cx) + ny * (va.cy - vs.cy) + nz * (va.cz - vs.cz) );
dv = vecOut[it];
dv.cx = va.cx + (vs.cx - va.cx) * t;
dv.cy = va.cy + (vs.cy - va.cy) * t;
dv.cz = va.cz + (vs.cz - va.cz) * t;
it += 1;
}//endif2
if (it < 3) { return -1; }
reta.a.copyVert(vecOut[0]);
reta.b.copyVert(vecOut[1]);
reta.c.copyVert(vecOut[2]);
if (it == 3) { return 1; }
/*
ccw = (tri.b.cx - tri.a.cx)*(tri.c.cy - tri.a.cy)
- (tri.b.cy - tri.a.cy)*(tri.c.cx - tri.a.cx);
*/
ccw = getCcw(tri.a, tri.b, tri.c);
deb.text = "ccw " + ccw;
var ccw2:Number;
var ccw3:Number;
ccw2 = getCcw(vecOut[1], vecOut[2], vecOut[3]);
deb.appendText( "\n ccw2 " + ccw2);
if ((ccw < 0 && ccw2 <0) || (ccw > 0 && ccw2 >0) )
{
retb.a.copyVert(vecOut[1]);
retb.b.copyVert(vecOut[2]);
retb.c.copyVert(vecOut[3]);
}
else
{
retb.a.copyVert(vecOut[2]);
retb.b.copyVert(vecOut[0]);
retb.c.copyVert(vecOut[3]);
}
return 2;
}//cuttri2
//http://en.wikipedia.org/wiki/Graham_scan#Pseudocode
public function getCcw(p1:xVert, p2:xVert, p3:xVert):Number
{
return (p2.cx - p1.cx)*(p3.cy - p1.cy) - (p2.cy - p1.cy)*(p3.cx - p1.cx);
}//gettccw
}//xcutter
internal class xFace
{
public var a:xVert = new xVert();
public var b:xVert = new xVert();
public var c:xVert = new xVert();
public function copyFace(vf:xFace):void
{
a.copyVert(vf.a);
b.copyVert(vf.b);
c.copyVert(vf.c);
}
// public function isSame(a:xFace):void
// {}
}//xface
internal class xVert
{
public var cx:Number = 0;
public var cy:Number = 0;
public var cz:Number = 0;
public function copyVert(va:xVert):void
{ cx = va.cx; cy = va.cy; cz = va.cz; }
public function setValue(x:Number, y:Number, z:Number):void
{ cx = x; cy = y; cz = z; }
}//xvert