Vector Perpendicular Projection
http://jccc-mpg.wikidot.com/vector-projection
/**
* Copyright WLAD ( http://wonderfl.net/user/WLAD )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/4Zft
*/
package {
import flash.display.Sprite;
public class FlashTest extends Sprite {
private var A:DP;
private var B:DP;
private var C:DP;
private var tV:T;
private var tU:T;
private var tPV:T;
private var tPer:T;
private var V:Vec;
private var U:Vec;
private var pV:Vec;
private var per:Vec;
public function FlashTest() {
// write as3 code here..
A = new DP( update, "A", 0xB4C2D3, this, 50, 300 );
B = new DP( update, "B", 0x79CD1D, this, 300, 250 );
C = new DP( update, "C", 0xE18B17, this, 100, 130 );
tV = new T("V", 0,0, 0x79CD1D, true ); addChild( tV );
tU = new T("U", 0,0, 0xE18B17, true ); addChild( tU );
tPV = new T("Proj v.u", 0,0, 0xD623D6 ); addChild( tPV );
tPer = new T("Perpendicular", 0,0, 0x1D95DC ); addChild( tPer );
update(null);
}
private function update( P:DP ):void
{
graphics.clear();
// Calc vectors
V = Vec.PP2V( A.point, B.point );
V.lenght -= 12;
U = Vec.PP2V( A.point, C.point );
U.lenght -= 12;
pV = V.projection( U );
per = U.clone().subtract( pV );
//Draw vectors
V.render( graphics, A.point, 0x79CD1D, 4 );
U.render( graphics, A.point, 0xE18B17, 4 );
pV.render( graphics, A.point, 0xD623D6, 2 );
per.render( graphics, pV.point.add( A.point ), 0x1D95DC, 2 );
// Update labels
V.lenght /= 2; tV.x = A.x + V.x; tV.y = A.y + V.y;
U.lenght /= 2; tU.x = A.x + U.x; tU.y = A.y + U.y;
per.lenght /= 2;
tPer.x = A.x + per.x + pV.x;
tPer.y = A.y + per.y + pV.y;
pV.lenght /= 2; tPV.x = A.x + pV.x; tPV.y = A.y + pV.y;
}
}
}
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.text.TextField;
import flash.text.TextFormat;
class DP extends Sprite
{
public function get point():Point{ return new Point(x,y) };
private var onChange:Function;
private var color:uint;
public function DP(
onChange:Function = null,
label:String = "P",
color:uint = 0xF3CE5C,
parent:Sprite = null,
x:Number = 0,
y:Number = 0)
{
buttonMode = useHandCursor = true;
this.x = x;
this.y = y;
if ( parent ) parent.addChild( this );
alpha = 0.8;
this.color = color;
this.onChange = onChange;
draw( 9 );
addChild( new T(label) );
addEventListener(MouseEvent.MOUSE_DOWN, onMD);
}
private function onMU(e:MouseEvent):void
{
draw( 9 );
alpha = 0.8;
stopDrag();
if ( onChange != null ) onChange( this );
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMM);
stage.removeEventListener(MouseEvent.MOUSE_UP, onMU);
}
private function onMD(e:MouseEvent):void
{
draw( 14 , true );
alpha = 1;
startDrag(true);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMM);
stage.addEventListener(MouseEvent.MOUSE_UP, onMU);
}
private function onMM(e:MouseEvent):void
{
if ( onChange != null ) onChange( this );
}
private function draw( r:Number, b:Boolean = false ):void
{
graphics.clear();
if ( b ) graphics.lineStyle(3, 0x666666);
graphics.beginFill(color);
graphics.drawCircle(0, 0, r);
graphics.endFill();
}
}
class T extends TextField
{
/** @author http://wonderfl.net/user/Vladik */
public function T(txt:String = "Text", x:Number = 0, y:Number = 0,c:uint = 0x0,b:Boolean = false)
{
var tf:TextFormat = new TextFormat("_sans", 12, c, b);
this.setTextFormat(tf);
this.defaultTextFormat = tf;
this.autoSize = 'left';
this.text = txt;
this.textColor = c;
this.selectable = this.wordWrap = this.multiline = this.mouseEnabled = false;
this.x = x - this.width / 2;
this.y = y - this.height / 2;
}
}
class Vec
{
// Convert a line between two point into a vector
static public function PP2V(a:Point, b:Point):Vec{return new Vec(b.x - a.x, b.y - a.y);}
// Convert line 2 point
static public function P2V(p:Point):Vec{return new Vec(p.x,p.y);}
// Angle between two vectors in radians
static public function RadiansBetween( A:Vec, B:Vec):Number
{
return Math.acos( A.clone().normalise().dot( B.clone().normalise() ) );
//return Math.acos( A.dot(B) / ( A.lenght + B.lenght );
}
public function normalise():Vec
{
lenght = 1;
return this;
}
//http://jccc-mpg.wikidot.com/vector-projection
public function projection( u:Vec ):Vec
{
var l:Number = lenght;
return clone().scale( u.dot( this ) / (l * l) );
}
/** @author http://wonderfl.net/user/Vladik */
public var x:Number, y:Number;
public function Vec(x:Number = 0, y:Number = 0){this.x = x;this.y = y;}
public function get lenght():Number{return Math.sqrt(x * x + y * y);}
public function set lenght(value:Number):void{lenght == 0 ? scale(0) : scale(value / lenght);}
public function set degrees(value:Number):void{radians = value * Math.PI / 180;}
public function get degrees():Number{return radians * 180 / Math.PI;}
public function set radians(value:Number):void{var f:Number = lenght;x = Math.cos(value) * f;y = Math.sin(value) * f;}
public function scale(n:Number):Vec { x *= n; y *= n; return this; }
public function clone():Vec{return new Vec(x, y);}
public function get radians():Number { return Math.atan2(y, x); }
public function dot( v:Vec ):Number { return x * v.x + y * v.y; }
public function get point():Point { return new Point(x, y); }
public function distToPoint( p:Point ):Number
{
return p.length * Math.sin( Vec.RadiansBetween( this, Vec.P2V(p) ) );
}
public function toString():String{return "["+x.toFixed(2)+","+y.toFixed(2)+"]";}
public function render( g:Graphics, o:Point = null, color:uint = 0xFF0000, thikness:uint = 3 ):void
{
g.beginFill( color );
g.lineStyle( thikness, color);
g.moveTo( o.x, o.y);
var B:Point = new Point(o.x + x, o.y + y);
g.lineTo( B.x, B.y);
var v:Vec = Vec.PP2V( o, B );
v.lenght = 7;
v.degrees -= 45 + 180;
g.lineTo( B.x + v.x, B.y + v.y );
v.degrees += 90;
g.lineTo( B.x + v.x, B.y + v.y );
g.lineTo( B.x, B.y );
g.endFill();
}
public function add( V:Vec ):Vec
{
this.x += V.x;
this.y += V.y;
return this;
}
public function subtract(V:Vec):Vec
{
this.x -= V.x;
this.y -= V.y;
return this;
}
}