Poisson Disc Sampling
Reference - http://www.cnblogs.com/pulas/archive/2013/04/02/2994922.html
/**
* Copyright greentec ( http://wonderfl.net/user/greentec )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/MMGa
*/
package {
import com.bit101.components.Label;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
public class FlashTest extends Sprite {
public var bitmapData:BitmapData;
public var shape:Shape;
public var emptyShape:Shape;
public var shapeArray:Array;
public var gridWidth:int = 10;//33
public var gridHeight:int = 10;
public var minWidth:int = gridWidth * Math.sqrt(2);
public var grid:Array;
public var processArray:Array;
public var sampleArray:Array;
public var tryCount:int = 30;
public var label:Label;
public var colorSwitch:Boolean = true;
public function FlashTest() {
// write as3 code here..
var back:BitmapData = new BitmapData(465, 465, false, 0x292929);
addChild(new Bitmap(back));
bitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0x00ffffff);
addChild(new Bitmap(bitmapData));
shape = new Shape();
shape.graphics.beginFill(0xdddddd, 0.5);
shape.graphics.drawCircle(0, 0, 10);
shape.graphics.endFill();
emptyShape = new Shape();
emptyShape.graphics.lineStyle(1, 0xdddddd, 0.5);
emptyShape.graphics.drawCircle(0, 0, 10);
shapeArray = [shape, emptyShape];
//init Grid
var i:int;
var j:int;
grid = [];
var len:int = stage.stageWidth / gridWidth;
for (i = 0; i <= len; i += 1)
{
grid[i] = [];
for (j = 0; j <= len; j += 1)
{
grid[i].push(null);
}
}
var point:Point;
point = new Point(stage.stageWidth * Math.random(), stage.stageHeight * Math.random());
processArray = [];
sampleArray = [];
processArray.push(point);
sampleArray.push(point);
grid[int(point.x / gridWidth)][int(point.y / gridHeight)] = point;
drawPoint(point);
//drawGrid(grid);
label = new Label(this, 10, 10, "");
label.scaleX = label.scaleY = 2;
label.transform.colorTransform = new ColorTransform(0, 0, 0, 1, 255, 0, 0, 0);
stage.addEventListener(Event.ENTER_FRAME, onLoop);
}
private function onReset(e:Event = null):void
{
stage.removeEventListener(MouseEvent.CLICK, onReset);
colorSwitch = !colorSwitch;
label.text = "";
bitmapData.fillRect(bitmapData.rect, 0x00ffffff);
var i:int;
var j:int;
var len:int = stage.stageWidth / gridWidth;
for (i = 0; i <= len; i += 1)
{
for (j = 0; j <= len; j += 1)
{
grid[i][j] = null;
}
}
sampleArray = [];
var point:Point;
point = new Point(stage.stageWidth * Math.random(), stage.stageHeight * Math.random());
processArray = [];
sampleArray = [];
processArray.push(point);
sampleArray.push(point);
grid[int(point.x / gridWidth)][int(point.y / gridHeight)] = point;
drawPoint(point);
//drawGrid(grid);
stage.addEventListener(Event.ENTER_FRAME, onLoop);
}
private function drawPoint(point:Point):void
{
var colT:ColorTransform;
colT = new ColorTransform();
//var index:int;
if (colorSwitch == true)
{
colT.color = HSV2RGB(point.x / stage.stageWidth * 360, 1, 1);
}
//index = (int(point.x / gridWidth) + int(point.y / gridWidth)) % 2;
bitmapData.draw(shapeArray[int(Math.random() * 2)], new Matrix(1, 0, 0, 1, point.x, point.y), colT);
//bitmapData.draw(shapeArray[index], new Matrix(1, 0, 0, 1, point.x, point.y), colT);
}
private function onLoop(e:Event):void
{
if (processArray.length == 0)
{
stage.removeEventListener(Event.ENTER_FRAME, onLoop);
label.text = "Click - Reset";
stage.addEventListener(MouseEvent.CLICK, onReset);
}
else
{
var point:Point;
var randIndex:int = int(Math.random() * processArray.length);
point = processArray.splice(randIndex, 1)[0];
var newPoint:Point;
var i:int;
for (i = 0; i < tryCount; i += 1)
{
newPoint = new Point(point.x + Math.cos(Math.PI * 2 * Math.random()) * (minWidth * (1 + Math.random())),
point.y + Math.sin(Math.PI * 2 * Math.random()) * (minWidth * (1 + Math.random())));
if (newPoint.x >= 0 && newPoint.x <= stage.stageWidth &&
newPoint.y >= 0 && newPoint.y <= stage.stageHeight &&
inNeighbor(grid, newPoint) == false)
{
processArray.push(newPoint);
sampleArray.push(newPoint);
grid[int(newPoint.x / gridWidth)][int(newPoint.y / gridHeight)] = newPoint;
drawPoint(newPoint);
}
}
//drawGrid(grid);
}
}
private function inNeighbor(grid:Array, newPoint:Point):Boolean
{
var gridPoint:Point = new Point(int(newPoint.x / gridWidth), int(newPoint.y / gridWidth));
var i:int;
var j:int;
var point:Point;
for (i = gridPoint.x - 2; i <= 2 + gridPoint.x; i += 1)
{
if (i >= 0 && i <= int(stage.stageWidth / gridWidth))
{
for (j = gridPoint.y - 2; j <= 2 + gridPoint.y; j += 1)
{
if (j >= 0 && j <= int(stage.stageHeight / gridWidth))
{
if (grid[i][j] != null)
{
point = grid[i][j];
//distance calc;
if (Math.pow((point.x - newPoint.x), 2) + Math.pow((point.y - newPoint.y), 2) <= minWidth * minWidth)
{
return true;
}
}
}
}
}
}
return false;
}
private function HSV2RGB(h:Number, s:Number, v:Number):uint
{
if (s == 0)
{
return uint(v*255<<16) | uint(v*255<<8) | uint(v*255);
}
else
{
var rgb:uint = 0xffffff;
var hi:int = (h/60)>>0;
var f:Number = (h/60 - hi);
var p:Number = v*(1 - s);
var q:Number = v*(1 - f*s);
var t:Number = v*(1-(1-f)*s);
if (hi == 0)
{
rgb = uint(v * 255 << 16) | uint(t * 255 << 8) | uint(p * 255);
}
else if(hi==1) rgb = uint(q*255<<16) | uint(v*255<<8) | uint(p*255);
else if(hi==2) rgb = uint(p*255<<16) | uint(v*255<<8) | uint(t*255);
else if(hi==3) rgb = uint(p*255<<16) | uint(q*255<<8) | uint(v*255);
else if(hi==4) rgb = uint(t*255<<16) | uint(p*255<<8) | uint(v*255);
else if(hi==5) rgb = uint(v*255<<16) | uint(p*255<<8) | uint(q*255);
return rgb;
}
}
}
}