Forked from: fuck's forked from: Circle Packing Algorithm diff:1 forked from: forked from: Circle Packing Algorithm Sundev.Lohr forked:0favorite:1lines:184license : MIT License modified : 2012-04-14 06:18:29 Embed Tweet // forked from fuck's forked from: Circle Packing Algorithm // forked from onedayitwillmake's Circle Packing Algorithm 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; [SWF(frameRate = '60', backgroundColor='0x000000')] public class FlashTest 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; public function FlashTest() { 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 = 40 var color:ColorHSV = new ColorHSV(1, 1.10, 10.20); var currentX:int = 35; var max:Number = 10; for(var i:int = 0; i < max; i++) { var node:Node = new Node(); addChild(node); node.addEventListener(MouseEvent.MOUSE_DOWN, startDragging); var size:Number; if(i<30) size = Math.random()* maxSize/10 + 5; else size = Math.random()* maxSize + 5; color.h = size/maxSize * 180 + 200; node.draw(size, color.value); node.setPosition(i*8, 200 + Math.random()) _nodes.push(node); } addEventListener(Event.ENTER_FRAME, packCircles) } private function startDragging(e:MouseEvent):void { dragCircle = e.target as Node; dragCircle._radius = dragCircle._originalRadius * 1.5; stage.addEventListener(MouseEvent.MOUSE_UP, stopDragging); } private function stopDragging(e:MouseEvent):void { dragCircle._radius = dragCircle._originalRadius; dragCircle = null; stage.removeEventListener(MouseEvent.MOUSE_UP, stopDragging); } private var dragCircle:Node; private function packCircles(e:Event):void { _nodes = _nodes.sort(sortOnDistanceToCenter); v = new Vector3D(); // Push them away from each other for(var i:int = 0; i < _nodes.length; i++) { var ci:Node = _nodes[i]; for (var j:int = i + 1; j<_nodes.length; j++) { var cj:Node = _nodes[j]; if(i == j) continue; //cj.alpha = Math.random() var dx:Number = cj.x - ci.x; var dy:Number = cj.y - ci.y; var r:Number = ci._radius + cj._radius; var d:Number = (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(cj != dragCircle) { cj.x += v.x; cj.y += v.y; } if(ci != dragCircle) { ci.x -= v.x; ci.y -= v.y; } } } } //return; // push toward center var damping:Number = 0.01;///Number(iterationCounter); //trace(damping) for(i = 0; i < _nodes.length; i++) { var c:Node = _nodes[i]; if(c == dragCircle) continue; v.x = c.x - CENTER.x; v.y = c.y - CENTER.y; v.scaleBy(damping); c.x -= v.x; c.y -= v.y; } if(dragCircle) { dragCircle.x = stage.mouseX dragCircle.y = stage.mouseY } } private function sortOnRandom(a:Node, b:Node):int { return Math.random() < 0.5 ? -1 : 1; } 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 _relative: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, animationTime:Number = 0.0, delay:Number = 0.0):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 { _relative = null; _view = null; } public function set size(value:Number):void { _radius = value; _originalRadius = value; _radiusSquared = _radius * _radius; } } Code Fullscreen Preview Fullscreen idleworks Point.distance fillAlpha value fillColor ColorHSV MouseEvent.MOUSE_UP Math.sqrt sort normalize graphics length target MouseEvent.ADDED_TO_STAGE MouseEvent Math.max removeEventListener mouseY mouseX MouseEvent.MOUSE_DOWN MouseEvent.ENTER_FRAME