Actionscript:
-
[SWF(width=600,height=500,frameRate=30)]
-
var canvas:BitmapData=new BitmapData(400,400,false,0x000000);
-
addChild(new Bitmap(canvas));
-
-
var size:Number=canvas.width*canvas.height;
-
var w:Number=canvas.width;
-
var pix:Vector.<uint> = new Vector.<uint>(size);
-
-
addEventListener(Event.ENTER_FRAME, onLoop);
-
function onLoop(evt:Event):void {
-
canvas.lock();
-
-
var i:int = size;
-
var x1:Number=mouseX;
-
var y1:Number=mouseY;
-
var x2:Number=250;
-
var y2:Number=250;
-
var dx:Number=x2-x1;
-
var dy:Number=y2-y1;
-
var denom:Number = 1/(dx * dx + dy * dy);
-
if (dx==0&&dy==0) {
-
x2+=1;
-
y2+=1;
-
dx=dy=1;
-
}
-
-
while( --i> -1 ){
-
var xp:int= i % w;
-
var yp:int = i / w;
-
var u:Number = ((xp - x1) * dx + (yp - y1) * dy) * denom;
-
-
var closestX:Number;
-
var closestY:Number;
-
if (u<0) {
-
closestX=x1;
-
closestY=y1;
-
} else if (u> 1) {
-
closestX=x2;
-
closestY=y2;
-
} else {
-
closestX=x1+u*dx;
-
closestY=y1+u*dy;
-
}
-
var dfx:Number=closestX-xp;
-
var dfy:Number=closestY-yp;
-
var d:Number=255-Math.sqrt(dfx*dfx+dfy*dfy);
-
if (d<0) d=0;
-
pix[i]=uint(d);
-
}
-
canvas.setVector(canvas.rect, pix);
-
canvas.unlock();
-
}
This didn't come out as interesting as I thought it would for some reason - just used the technique from the last two posts to draw a gradient. Event though it's visually boring, it does show how I went about inlining the function from yesterday... so I figured I'd post it.
Actionscript:
-
/**
-
Original function by Pieter Iserbyt:
-
http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/DistancePoint.java
-
from Paul Bourke's website:
-
http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/
-
*/
-
function pointToLineDist(x1:Number, y1:Number, x2:Number, y2:Number,x3:Number, y3:Number):Number {
-
var dx:Number=x2-x1;
-
var dy:Number=y2-y1;
-
if (dx==0&&dy==0) {
-
x2+=1;
-
y2+=1;
-
dx=dy=1;
-
}
-
var u:Number = ((x3 - x1) * dx + (y3 - y1) * dy) / (dx * dx + dy * dy);
-
-
var closestX:Number;
-
var closestY:Number;
-
if (u<0) {
-
closestX=x1;
-
closestY=y1;
-
} else if (u> 1) {
-
closestX=x2;
-
closestY=y2;
-
} else {
-
closestX=x1+u*dx;
-
closestY=y1+u*dy;
-
}
-
dx=closestX-x3;
-
dy=closestY-y3;
-
return Math.sqrt(dx * dx + dy * dy);
-
}
-
-
/**
-
Test out the function
-
*/
-
-
var dotA:Sprite = dot(100, 100);
-
var dotB:Sprite = dot(200, 200);
-
var dotC:Sprite = dot(150, 100, 0x0000FF);
-
var txt:TextField = TextField(dotC.addChild(new TextField()));
-
with(txt) x = 5, y = 5, autoSize = "left", selectable = false, mouseEnabled = false;
-
-
addEventListener(Event.ENTER_FRAME, onLoop);
-
function onLoop(evt:Event):void {
-
graphics.clear();
-
graphics.lineStyle(0,0x000000);
-
graphics.moveTo(dotA.x, dotA.y);
-
graphics.lineTo(dotB.x, dotB.y);
-
txt.text = pointToLineDist(dotA.x, dotA.y, dotB.x, dotB.y, dotC.x, dotC.y).toFixed(2);
-
}
-
-
// draggable dot
-
function dot(xp:Number, yp:Number, col:uint = 0xFF0000, rad:Number=4):Sprite {
-
var s:Sprite = Sprite(addChild(new Sprite));
-
s.x = xp;
-
s.y = yp;
-
with(s.graphics) beginFill(col), drawCircle(0,0,rad);
-
s.buttonMode = true;
-
s.addEventListener(MouseEvent.MOUSE_DOWN, onDrag);
-
return s;
-
}
-
function onDrag(evt:MouseEvent):void { evt.currentTarget.startDrag() }
-
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
-
function onUp(evt:MouseEvent):void{stopDrag() }
This is the same as yesterdays post about the distance between a point and a line segment. I just took a few minutes to optimize the function - it runs close to 3X faster now. For more info see yesterdays post.
Actionscript:
-
/**
-
Original function by Pieter Iserbyt:
-
http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/DistancePoint.java
-
from Paul Bourke's website:
-
http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/
-
*/
-
function pointToLineDistance(p1:Sprite, p2:Sprite, p3:Sprite):Number {
-
var xDelta:Number = p2.x - p1.x;
-
var yDelta:Number = p2.y - p1.y;
-
if ((xDelta == 0) && (yDelta == 0)) {
-
// p1 and p2 cannot be the same point
-
p2.x += 1;
-
p2.y += 1;
-
xDelta = 1;
-
yDelta = 1;
-
}
-
var u:Number = ((p3.x - p1.x) * xDelta + (p3.y - p1.y) * yDelta) / (xDelta * xDelta + yDelta * yDelta);
-
var closestPoint:Point;
-
if (u <0) {
-
closestPoint = new Point(p1.x, p1.y);
-
} else if (u> 1) {
-
closestPoint = new Point(p2.x, p2.y);
-
} else {
-
closestPoint = new Point(p1.x + u * xDelta, p1.y + u * yDelta);
-
}
-
return Point.distance(closestPoint, new Point(p3.x, p3.y));
-
}
-
-
/**
-
Test out the function
-
*/
-
-
var dotA:Sprite = dot(100, 100);
-
var dotB:Sprite = dot(200, 200);
-
var dotC:Sprite = dot(150, 100, 0x0000FF);
-
var txt:TextField = TextField(dotC.addChild(new TextField()));
-
with(txt) x = 5, y = 5, autoSize = "left", selectable = false, mouseEnabled = false;
-
-
addEventListener(Event.ENTER_FRAME, onLoop);
-
function onLoop(evt:Event):void {
-
graphics.clear();
-
graphics.lineStyle(0,0x000000);
-
graphics.moveTo(dotA.x, dotA.y);
-
graphics.lineTo(dotB.x, dotB.y);
-
txt.text = pointToLineDistance(dotA, dotB, dotC).toFixed(2);
-
}
-
-
// draggable dot
-
function dot(xp:Number, yp:Number, col:uint = 0xFF0000, rad:Number=4):Sprite {
-
var s:Sprite = Sprite(addChild(new Sprite));
-
s.x = xp;
-
s.y = yp;
-
with(s.graphics) beginFill(col), drawCircle(0,0,rad);
-
s.buttonMode = true;
-
s.addEventListener(MouseEvent.MOUSE_DOWN, onDrag);
-
return s;
-
}
-
function onDrag(evt:MouseEvent):void { evt.currentTarget.startDrag() }
-
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
-
function onUp(evt:MouseEvent):void{stopDrag() }
Last night I was working late and found myself in need of a way to calculate the distance between a point and a line. After a quick google search I found myself once again on Paul Bourke's extremely useful website. I was in a rush, so I just quickly ported the java code (by Pieter Iserbyt) and wrote this test snippet to make sure it works.
This code could be optimized a bit, but it works nicely.
I needed this for a commercial project, but as I was porting the code I thought of an interesting way to use this code to draw a gradient - may write and post that tomorrow.
Actionscript:
-
// calculate the slope of a line
-
function calculateSlope(x1:Number, y1:Number, x2:Number, y2:Number):Number {
-
// rise over run
-
var s:Number = (y1 - y2) / (x1 - x2);
-
/*if (x1==x2) {
-
// slope is Infinity or -Infinity
-
}*/
-
return s;
-
}
-
-
/**
-
Test it out
-
*/
-
function draw(x1:Number, y1:Number, x2:Number, y2:Number):void {
-
graphics.moveTo(x1, y1);
-
graphics.lineTo(x2, y2)
-
var txt:TextField =TextField(addChild(new TextField()));
-
txt.text = calculateSlope(x1, y1, x2, y2).toFixed(2);
-
txt.x = x2, txt.y = y2;
-
}
-
-
graphics.lineStyle(0,0xFF0000);
-
draw (100, 100, 200, 200);
-
-
draw(100, 100, 200, 150);
-
-
draw(100, 100, 200, 100);
-
-
draw(100, 100, 99, 200);
This snippet shows how to calculate the slope of a line ... It demos the function by drawing a few lines and showing the corresponding slope of each.
It will draw this:
If (x1 == x2), the slope will be -Infinity or Infinity... depending on where you're using this calculation you may want to reset the s variable to something else, return null etc... I commented it out for simplicity.
Posted in Math, misc | Tagged actionscript, as3, flash |