forked from: Circle Packing Algorithm
using linked lists and 'while' statements
/**
* Copyright nhubben ( http://wonderfl.net/user/nhubben )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/3eLt
*/
///////////////////////////////////////////////////////////
//
// forked from onedayitwillmake's Circle Packing Algorithm
// using linked lists and 'while' statements
//
///////////////////////////////////////////////////////////
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Vector3D;
import frocessing.color.ColorHSV;
import frocessing.core.F5Graphics;
import net.hires.debug.Stats;
[SWF(frameRate = '60', backgroundColor='0x000000',width='400', height='400' )]
public class TestTest extends Sprite {
protected var _nodes : Vector.<Node> = new Vector.<Node>;
private var iterationCounter : int = 0;
private var CENTER : Point;
private var v : Vector3D;
public var _view : F5Graphics;
private var dragCircle : Node = null;
public function TestTest() {
this.addEventListener(Event.ADDED_TO_STAGE, initCirclePacking)
_view = new F5Graphics(graphics);
}
public function initCirclePacking(e : Event) : void {
CENTER = new Point(stage.stageWidth / 2, stage.stageHeight / 2);
_view.clear();
var maxSize : Number = 30;
var color : ColorHSV = new ColorHSV(0, 0.8, 1.0);
var max : Number = 100;
var n : Node;
var size : Number;
for(var i : int = 0; i < max; i++) {
n = new Node();
addChild(n);
n.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
size = 4 + Math.random() * maxSize;
color.h = size / maxSize * 180 + 120;
n.draw(size, color.value);
n.setPosition(i * 8, 200 + Math.random() * 200) ;
_nodes.push(n);
if( i > 0 ) {
_nodes[i - 1]._next = n;
}
}
var stats:Stats = new Stats();
//stats.scaleX = stats.scaleY = .25;
addChild(stats);
addEventListener(Event.ENTER_FRAME, packCircles);
}
private function startDragging(e : MouseEvent) : void {
dragCircle = e.target as Node;
dragCircle._radius = dragCircle._originalRadius * 1.5;
dragCircle.startDrag(false);
stage.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
}
private function stopDragging(e : MouseEvent) : void {
dragCircle._radius = dragCircle._originalRadius;
stopDrag();
dragCircle = null;
stage.removeEventListener(MouseEvent.MOUSE_UP, stopDragging);
}
private function packCircles(e : Event) : void {
//_nodes = _nodes.sort(sortOnDistanceToCenter);
v = new Vector3D();
var n:Node = _nodes[0];
var next:Node;
var dx:Number, dy:Number, r:Number, d:Number;
while( n ){
if( n._next ){
next = n._next;
while( next ) {
dx = next.x - n.x;
dy = next.y - n.y;
r = n._radius + next._radius;
d = (dx*dx) + (dy*dy);
if (d < (r * r) - 0.01 ){
v.x = dx;
v.y = dy;
v.normalize();
v.scaleBy((r - Math.sqrt(d)) * 0.5);
if( next !== dragCircle) {
next.x += v.x;
next.y += v.y;
}
if(n !== dragCircle) {
n.x -= v.x;
n.y -= v.y;
}
}
next = ( next._next ) ? next._next : null;
}
}
n = ( n._next ) ? n._next : null;
}
//return;
// push toward center
var damping:Number = 0.01;
n = _nodes[0];
while( n ) {
if(n != dragCircle){
v.x = n.x - CENTER.x;
v.y = n.y - CENTER.y;
v.scaleBy(damping);
n.x -= v.x;
n.y -= v.y;
}
n = ( n._next ) ? n._next : null;
}
}
/*
private function sortOnDistanceToCenter(a:Node, b:Node):int
{
var valueA:int = a.distanceToCenter(CENTER);
var valueB:int = b.distanceToCenter(CENTER);
var comparisonValue:int = 0;
if(valueA > valueB) comparisonValue = -1;
else if(valueA < valueB) comparisonValue = 1;
return comparisonValue;
}
*
*/
}
}
import frocessing.core.F5Graphics2D;
import flash.display.Sprite;
import flash.geom.Point;
//import gs.TweenMax;
//import gs.easing.*;
class Node extends Sprite
{
private var _view:F5Graphics2D;
public var _originalRadius:Number, _radius:Number, _radiusSquared:Number;
public var _color:uint;
public var _next:Node;
public function Node()
{
}
public function draw(nodeSize:Number, color:uint = 0xff0000):void
{
size = nodeSize;
_color = color;
_view = new F5Graphics2D(this.graphics);
_view.noStroke();
_view.beginDraw();
_view.fillColor = color;
_view.fillAlpha = 0.75;
_view.circle(0,0, _radius*0.8);
_view.circle(0,0, _radius * 0.9);
_view.fillAlpha = 0.3;
_view.circle(0,0, _radius);
_view.endDraw();
}
public function setPosition(xpos:Number, ypos:Number):void
{
x = xpos;
y = ypos;
}
/**
* A few circle helper mathematical functions
*/
public function containsPoint(xpos:Number, ypos:Number):Boolean
{
var dx:Number = x - ypos;
var dy:Number = y - ypos;
var distance:Number = Math.sqrt(dx*dx + dy*dy);
// if it's shorter than either radi, we intersect
return distance <= _radius;
}
public function distanceToCenter(centerPoint:Point):Number
{
var dx:Number = x - centerPoint.x;
var dy:Number = y - centerPoint.y;
var distance:Number = dx*dx + dy*dy;
return distance;
}
public function intersects(otherNode:Node):Boolean
{
var dx:Number = otherNode.x - x;
var dy:Number = otherNode.y - y;
var distance:Number = dx*dx + dy * dy;
// if it's shorter than either radi, we intersect
return (distance < _radiusSquared || distance < otherNode._radiusSquared);
}
public function dealloc():void
{
_next = null;
_view = null;
}
public function set size(value:Number):void
{
_radius = value;
_originalRadius = value;
_radiusSquared = _radius * _radius;
}
}