Browse the notebook

Category: Math

Closest Point on a Line

// from
// http://www.gamedev.net/topic/444154-closest-point-on-a-line/

function getClosestPoint(A:*, B:*, P:*, segmentClamp:Boolean=true):Point {
	var AP:Point = new Point(P.x - A.x, P.y - A.y),
	    AB:Point = new Point(B.x - A.x, B.y - A.y);
	var ab2:Number=AB.x*AB.x+AB.y*AB.y;
	var ap_ab:Number=AP.x*AB.x+AP.y*AB.y;
	var t:Number=ap_ab/ab2;
	if (segmentClamp) {
		if (t<0.0) {
			t=0.0;
		} else if (t > 1.0) {
			t=1.0;
		}

	}
	return new Point(A.x + AB.x * t, A.y + AB.y * t);
}


var point:Sprite = Sprite(addChild(new Sprite()));
point.x = 50;
point.y = 50;
with(point.graphics) beginFill(0), drawCircle(0,0, 3);

var line:MovieClip = MovieClip(addChild(new MovieClip()));
line.a = new Point(20, 100);
line.b = new Point(300, 60);
with(line.graphics) lineStyle(0), moveTo(line.a.x, line.a.y), lineTo(line.b.x, line.b.y);

var closestPoint:Point = getClosestPoint(line.a, line.b, point);

var closest:Sprite = Sprite(addChild(new Sprite()));
closest.x = closestPoint.x;
closest.y = closestPoint.y;
with(closest.graphics) beginFill(0xFF0000), drawCircle(0,0, 3);
Read snippet: Closest Point on a Line

Fish Curve

var xp:Number = 0;
var yp:Number = 0;
var t:Number = 0;
var a:Number = 200;
x = stage.stageWidth / 2;
y = stage.stageHeight / 2;

graphics.lineStyle(0,0x000000);
addEventListener(Event.ENTER_FRAME, onRun);
function onRun(evt:Event):void {
	xp = a * Math.cos(t) - (a * Math.pow(Math.sin(t),2))/Math.sqrt(2);
	yp = a * Math.cos(t) * Math.sin(t);
	if (t == 0){
	  graphics.moveTo(xp, yp);
	}else{
	  graphics.lineTo(xp, yp);
	}
	t += 0.05;
}

While surfing mathworld I stumbled upon the equation for something called the Fish Curve. This snippet will draw something like this:

Read snippet: Fish Curve

Astroid Pedal Curve Variation

var xp:Number = 0;
var yp:Number = 0;
var t:Number = 0;
var r:Number = 200;
x = stage.stageWidth / 2;
y = stage.stageHeight / 2;

graphics.lineStyle(0,0x000000);
addEventListener(Event.ENTER_FRAME, onRun);
function onRun(evt:Event):void {
	r = 200 * Math.cos(t / 10);
	xp = r * Math.pow(Math.cos(t), 3);
	yp = r * Math.pow(Math.sin(t), 3);
	if (t == 0){
	  graphics.moveTo(xp, yp);
	}else{
	  graphics.lineTo(xp, yp);
	}
	t += 0.1;
}

While browsing mathworld I decided to do a variation on this curve . The above snippet will draw something like this:

Read snippet: Astroid Pedal Curve Variation

Logistic Map Play

var offX:Number = 100;
var offY:Number = 300;
var scalarX:Number = 6;
var scalarY:Number = 200;
addEventListener(Event.ENTER_FRAME, onLoop);
function onLoop(evt:Event):void{
	var r:Number = mouseY / 100;
	var xn:Number = (mouseX - 100) / 650;
	var xn1:Number = 0;
	graphics.clear();
	graphics.lineStyle(0,0);
	for (var i:int = 0; i<100; i++){
	  xn1 = r * xn * (1 - xn);
	  xn = xn1;
	  if (i == 0){
		graphics.moveTo(offX+i*scalarX,offY+xn1*scalarY);  
	  }else{
		graphics.lineTo(offX+i*scalarX, offY+xn1*scalarY);
	  }
	}
}

Whenever I can’t decide what kind of snippet to make, I simply go to wikipedia or mathworld for a bit and I always end up with something. I’ve messed with Logistic Maps before (when learning about strange attractors). This is a simple rendering where the x and y axis change the biotic potential (r) and the starting value for x.

Here is the link I used for reference.


Have a look at the swf (just move your mouse around).

Read snippet: Logistic Map Play

Connect The Dots E8

[SWF(width = 500, height = 500)]
const TWO_PI:Number = Math.PI * 2;
var centerX:Number = stage.stageWidth / 2;
var centerY:Number = stage.stageHeight / 2;
addEventListener(Event.ENTER_FRAME, onLoop);
function onLoop(evt:Event):void{
	// data
	var points:Array = [];
	var i:int = 0;
	var pointNum : int = Math.max(2,int(mouseX / 12))
	
	var radius:Number = 200;
	var step:Number = TWO_PI / pointNum;
	var theta:Number = step / 2;
	for (i = 0; i<pointNum; i++){
		var xp:Number = centerX + radius * Math.cos(theta);
		var yp:Number = centerY + radius * Math.sin(theta);
		points[i] = new Point(xp, yp);
		theta += step;
	}
	// render
	graphics.clear();
	graphics.lineStyle(0,0);
	for ( i = 0; i<pointNum; i++){
     var a:Point = points[i];
     for (var j:int = 0; j<pointNum; j++){
        var b:Point = points[j];
        if (a != b){
		   graphics.drawCircle(a.x, a.y, 10);
		   graphics.moveTo(a.x, a.y);
	       graphics.lineTo(b.x, b.y);
        }
     }
   }
}

I’ve been using this geometric shape for lots of different things recently. Including during consulting gigs as a helpful visualization. Just move your mouse left and right… I particularly like the simpler forms you get by moving your mouse to the left (triangles squares and simple polygons):

Connect The Dots – wonderfl build flash online

While not entirely related this wikipedia article is interesting.

[EDIT : Thanks to martin for reminding me that I can do away with the if statement here in the above code ]

graphics.clear();
graphics.lineStyle(0,0);
for (i = 0; i<pointNum; i++) {
	var a:Point=points[i];
	for (var j:int = i+1; j<pointNum; j++) {
		var b:Point=points[j];
		graphics.drawCircle(a.x, a.y, 10);
		graphics.moveTo(a.x, a.y);
		graphics.lineTo(b.x, b.y);
	}
}
graphics.drawCircle(a.x, a.y, 10);

I implemented that change over at wonderfl and it works nicely

Read snippet: Connect The Dots E8

Polar Coordinates Distribution

If you’re at all interested in watching me free from code. I recorded a video of me coding this snippet (which is about 11 minutes long or so).

In the video I create a few functions that allow you to draw shapes like these:

Mathematically this stuff is really simple … the free form nature of the video takes a less technical perspective as you’ll see (I even made a few funny mistakes).



[SWF(width = 600, height = 600)]
var dotNum:int = 1000;
var dotRad:Number = 0.5;

x = 120
y = 100;

// extra stuff to display what the functions can do
stage.addEventListener(MouseEvent.CLICK, onDrawAll);

function onDrawAll(evt:Event):void{
	graphics.clear();
	for (var i:int = 0; i<16; i++){
		var m:Number;
	
		var rad:Number = 120;
		var xp:Number = i % 4 * rad
		var yp:Number = int(i / 4) * rad
	
		var type:int = int(Math.random() * 4);
		if (type == 0){
		  makeShape(xp, yp, rad-60, Math.random() , 1);
		}else if (type == 1){
		   makeShape(xp, yp, rad-60, 1,  Math.random());
		}
		else if (type == 2){
		   m = Math.random() * 2;
		   makeShape(xp, yp, rad-Math.random()*120, m, m);
		}
		else if (type == 3){
		   m = Math.random() * 2;
		   makeShape(xp, yp, rad-Math.random()*120, m, m/2);
		}
	}
}

// main part from the video 
function makeShape(xp:Number, yp:Number, 
				   maxRad:Number = 100,m0:Number=1, 
				   m1:Number=1):void{
	var polarX:Number;
	var polarY:Number;
	var radius:Number;
	graphics.lineStyle(0, 0);
	var theta:Number = Math.random() * Math.PI * 2;
	for (var i:int = 0; i<dotNum; i++){
		radius = Math.random() * maxRad
		polarX = xp + radius * Math.cos(theta * m0);
		polarY = yp + radius * Math.sin(theta * m1);
		theta += 0.1;
		 
		makeDot(polarX, polarY);
		
	}
}

function makeDot(xp:Number, yp:Number, fillColor:uint = 0x000000):void{
	graphics.beginFill(fillColor);
	graphics.drawCircle(xp, yp, dotRad);
	graphics.endFill();
}

Here it is over at wonderf:

Polar Distribution – wonderfl build flash online
Read snippet: Polar Coordinates Distribution

Prefix Notation (Lisp Style)

Today’s quiz is not multiple choice. Instead, your task is to write a lisp style math parser. This may sound tricky, but it’s surprisingly simple. (well… not simple exactly, it’s just simple compared to what one might assume).

Lisp uses prefix notation… where the operator is placed before the operands:

10 * 10

becomes:

* 10 10

You could think of this as a function “*” with two arguments (10, 10). In Lisp this is enclosed with parens:

(* 10 10)

Let’s see a few more examples:

100 / 2 + 10

becomes:

(+ (/ 100 2) 10)

…
2 * 4 * 6 * 7

becomes:

(* 2 4 6 7)

…

(2 + 2) * (10 – 2) * 2

becomes

(* (+ 2 2) (- 10 2) 2)

Remember, thinking “functions” really helps. The above can be though of as:

multiply( add(2, 2), subtract(10 , 2), 2)

You should create a function called parsePrefix() that takes a string and returns a number:

Here is some code to test if your parser works properly:

trace(parsePrefix("(* 10 10)"));

trace(parsePrefix("(* 1 (+ 20 2 (* 2 7) 1) 2)"));

trace(parsePrefix("(/ 22 7)"));

trace(parsePrefix("(+ (/ 1 1) (/ 1 2) (/ 1 3) (/ 1 4))"));

/* Should trace out:
100
74
3.142857142857143
2.083333333333333
*/

I highly recommend giving this a try, it was one of those cases where I assumed it would be much trickier than it was.

I’ve posted my solution here.

Read snippet: Prefix Notation (Lisp Style)

Float as a Fraction

// print some floats as fractions
printFraction(0.5);
printFraction(0.75);
printFraction(0.48);

// try something a little more complex
var float:Number = 0.98765432;
trace("na more complex example:");
printFraction(float);
var frac:Array = asFraction(float);
trace("double check it:");
trace(frac[0] + "/" + frac[1] +" = " + frac[0] / frac[1]);

/* outputs:
0.5 = 1/2
0.75 = 3/4
0.48 = 12/25

a more complex example:
0.98765432 = 12345679/12500000
double check it:
12345679/12500000 = 0.98765432
*/


function printFraction(n:Number):void{
	var frac:Array = asFraction(n);
	trace(n + " = " + frac[0] + "/" + frac[1]);
}

// takes any value less than one and returns an array 
// with the numerator at index 0 and the denominator at index 1
function asFraction(num:Number):Array{
    var decimalPlaces:int = num.toString().split(".")[1].length;
	var denom:Number = Math.pow(10, decimalPlaces);
	return reduceFraction(num * denom, denom);
}

// divide the numerator and denominator by the GCF
function reduceFraction(numerator:int, denominator:Number):Array{
	// divide by the greatest common factor
	var divisor:int = gcf(numerator, denominator);
	if (divisor){
		numerator /= divisor;
		denominator /= divisor;
	}
	return [numerator, denominator];
}
					
// get the greatest common factor of two integers
function gcf(a:int, b:int):int{
	var remainder:int;
	var factor:Number = 0;
	var maxIter:int = 100;
	var i:int = 0;
	while (1){
		if (b > a){
		   var swap:int = a;
		   a = b;
		   b = swap;
		}
		remainder = a % b;
		a = b;
		b = remainder
		if (remainder == 0){
			factor = a;
			break;
		}else if (remainder==1){
			break;
		}else if (i > maxIter){
			trace("failed to calculate gcf");
			break;
		}
		i++;
	}
	return factor;
}

This snippet contains a few functions for calculating fractions based on float values. Writing this brought back some memories from grade school math.

Read snippet: Float as a Fraction

Greatest Common Factor (divisor)

trace(gcf(75,145));

// outputs 5

function gcf(a:int, b:int):int{
	var remainder:int;
	var factor:Number = 0;
	while (1){
		if (b > a){
		   var swap:int = a;
		   a = b;
		   b = swap;
		}
		remainder = a % b;
		a = b;
		b = remainder
		if (remainder == 0){
			factor = a;
			break;
		}else if (remainder==1){
          
			break;
		}
	}
	return factor;
}

I was messing around with Egyptian Fractions and found myself in need of some interesting functions. The first function I realized I would be needing was for a greatest common factor (GCF or GCD).

The above snippet is a quick implementation of Euclid’s algorithm. It will return 0 if no GCF is found…

I wrote a few helper functions while working with Egyptian fractions… will post them over the next few days.

Read snippet: Greatest Common Factor (divisor)

Ancient Egyptian Multiplication

egyptianMultiply(12, 99);

// trace(12 * 99) // test to make sure it works

/* outputs:
/64 768
/32 384
 16 192
 8 96
 4 48
/2 24
/1 12
---
1188
*/
 

function egyptianMultiply(valueA:Number, valueB:Number):void {
	
	var left:Array = [];
	var right:Array = []
	
	// swap if valueB is smaller than value A
	if (valueB < valueA){
		var swap:int = valueB;
		valueB = valueA;
		valueA = swap; 
	}
	
	// create left and right columns
	var currentLeft:int = 1;
	var currentRight:int = valueA;
	
	while (currentLeft < valueB){
		left.push(currentLeft);
		right.push(currentRight);
		currentRight += currentRight;
		currentLeft += currentLeft; 
	}
	
	
	// add up the right column based on the left
	currentLeft = 0;
	var rightSum:int;
	var leftSum:int;
	var i:int = left.length - 1;
	
	while (currentLeft != valueB){
	 
	  leftSum = currentLeft + left[i];
	  // if the next number causes the sum
	  // to go above valueB, skip it
	  if (leftSum <= valueB){
		currentLeft = leftSum;
		rightSum += right[i];
		trace("/" + left[i]  + " " + right[i]);
	  } else {
		trace(" " + left[i]  + " " + right[i]);
	  }
	  i--;
	}
	trace("---");
	trace(rightSum);
}

Someone mentioned egyptian multiplication to me yesterday… So read a little about it here and whipped up this example. For some reason I decided to do it in processing … once it worked I ported it to ActionScript.

The above link describing the technique I used is from http://www.jimloy.com/… I haven’t spent much time digging around the site, but it appears to have some pretty nice stuff on it…

If you’re curious, here is the original processing version:

Vector left = new Vector();
Vector right = new Vector();

int valueA = 10;
int valueB = 8;

if (valueB < valueA){
    int swap = valueB;
    valueB = valueA;
    valueA = swap; 
}

int currentLeft = 1;
int currentRight = valueA;
while (currentLeft < valueB){
    left.add(currentLeft);
    right.add(currentRight);
    currentRight += currentRight;
    currentLeft += currentLeft; 
}
 
currentLeft = 0;
 
int result = 0;
int i = left.size() - 1;
while (currentLeft != valueB){
 
  int temp = currentLeft + (Integer) left.get(i);
  if (temp <= valueB){
    
    currentLeft = temp;
    result += (Integer) right.get(i);
    println("/" + left.get(i) + " " + right.get(i));
  } else {
    println(" " + left.get(i)  + " " + right.get(i));
  }
    
  i--;
}
println("---");
println(result);

After writing, this I took a look at the wikipedia entry… I also found myself on this short page about a scribe called Ahmes. (I recommend reading this if you are interested in PI)

Read snippet: Ancient Egyptian Multiplication