flash on 2013-6-27
followup to: http://wonderfl.net/c/4xB4
a better triangle cutting (by plane) function
/**
* Copyright mutantleg ( http://wonderfl.net/user/mutantleg )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/jr9W
*/
package {
import flash.events.Event;
import flash.display.Sprite;
public class FlashTest extends Sprite {
public function FlashTest() {
myTri = new xFace();
myTri.a.setValue(10,10, 0);
myTri.b.setValue(100,100, 0);
myTri.c.setValue(10,250, 0);
stage.addEventListener(Event.ENTER_FRAME, onEnter);
}//ctor
public var cx:Number = 200;
public var cy:Number = 200;
public var ang:Number = 0;
public var myTri:xFace;
public var temp1:xFace = new xFace();
public var temp2:xFace = new xFace();
public function onEnter(e:Event):void
{
graphics.clear();
graphics.lineStyle(2, 0);
graphics.drawCircle(cx, cy, 8);
var dx:Number;
var dy:Number;
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);
ny = Math.sin(ang);
drawTri(myTri);
var ret:int;
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 );
ret = cutTri2(myTri, cx,cy, 0, -ny, nx, 0 , temp1, temp2);
graphics.lineStyle(2, 0xFF0000);
if (ret >= 1) { drawTri(temp1); }
graphics.lineStyle(2, 0x00FF00);
if (ret >= 2) { drawTri(temp2);}
}//onenter
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);
}//drawtri
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 ad:Number;
var bd:Number;
var cd:Number;
it = 0;
va = tri.a;
vs = tri.c;
//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;
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
//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
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; }
retb.a.copyVert(vecOut[1]);
retb.b.copyVert(vecOut[2]);
retb.c.copyVert(vecOut[3]);
return 2;
}//cuttri2
}//classend
}
internal class xFace
{
public var a:xVert = new xVert();
public var b:xVert = new xVert();
public var c:xVert = new xVert();
}//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