city planner
click to update;
Cell -> http://wonderfl.net/c/200s @wh0
/**
* Copyright zob ( http://wonderfl.net/user/zob )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/zx7L
*/
package
{
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.geom.Point;
/**
* ...
* @author zonnbe
*/
public class city extends Sprite
{
private var cell:Cell;
private var gwidth:Number = 465;
private var gheight:Number = 465;
public function city()
{
stage.addEventListener( MouseEvent.MOUSE_DOWN, onMouseDown);
onMouseDown();
}
private function onMouseDown( e:MouseEvent = null ):void
{
var i:int = 0, j:int = 0;
cell = new Cell(new Point(0 , 0), new Point(gwidth, 0), new Point(0, gheight), new Point(gwidth, gheight));
cell.setOriginal( cell.tl, cell.tr, cell.bl, cell.br );
cell.setPatterns(
function(c:*):Boolean { return c < 5; }, // chose
null, // slope
function(c:Number = 1):Number { return 0.99 - Math.random() * 0.001 * c * c; } // size
);
for (i = 560; i; i--) cell.leaf(new Point(Math.random() * gwidth, Math.random() * gheight)).divide();
var newRegions:Vector.<Vector.<Point>> = new Vector.<Vector.<Point>>();
newRegions = cell.checkOut();
var g:Graphics = this.graphics;
g.clear();
g.lineStyle( 0.1, 0x222222 );
for each( var region:Vector.<Point> in newRegions)
{
for ( i = 0; i < region.length; i++)
{
j = ( i + 1 ) % region.length;
g.moveTo( region[i].x, region[i].y );
g.lineTo( region[j].x, region[j].y );
}
}
var highways:Vector.<Vector.<Point>> = cell.checkOutHighway();
g.lineStyle( 0.1, 0xff7755 );
for each( var highway:Vector.<Point> in highways)
{
if (highway.length > 0)
{
g.moveTo( highway[0].x, highway[0].y );
g.lineTo( highway[1].x, highway[1].y );
}
}
}
}
}
class city3d
{
}
import flash.geom.Point;
class Cell {
public var tl:Point;
public var tr:Point;
public var bl:Point;
public var br:Point;
private var _tl:Point;
private var _tr:Point;
private var _bl:Point;
private var _br:Point;
private var d0:Point;
private var d1:Point;
private var hw0:Point;
private var hw1:Point;
private var c0:Cell;
private var c1:Cell;
private var margin:Number = 0.2;
private var hmargin:Number = margin / 2;
private var chosePattern:Function;
private var slopePattern:Function;
private var sizePattern:Function;
public var level:int = 0;
public function Cell( tl:Point, tr:Point, bl:Point, br:Point, r:Number = 1, l:int = 0 ) {
this.level = ++l;
this.tl = tl.clone();
this.tr = tr.clone();
this.bl = bl.clone();
this.br = br.clone();
if ( r != 1 ) resizeCell( this.tl, this.tr, this.br, this.bl, r );
}
public function setOriginal( otl:Point, otr:Point, obl:Point, obr:Point ):void
{
this._tl = otl.clone();
this._tr = otr.clone();
this._bl = obl.clone();
this._br = obr.clone();
}
private function get width():Number {
return (tr.subtract(tl).length + br.subtract(bl).length) / 2;
}
private function get height():Number {
return (bl.subtract(tl).length + br.subtract(tr).length) / 2;
}
private function get ratio():Number {
var w:Number = width;
var h:Number = height;
return w * w / (w * w + h * h);
}
public function leaf(p:Point):Cell {
if (!c0) return this;
var dp:Point = p.subtract(d0);
var dd:Point = d1.subtract(d0);
if (dd.x * dp.y - dd.y * dp.x >= 0) return c0.leaf(p);
else return c1.leaf(p);
}
public function divide():void {
var i0:Number = 0.5 + Math.random() * margin - hmargin;
var i1:Number = (Math.random() < 0.5)? i0: 0.5 + Math.random() * margin - hmargin;
var thw0:Point;
var thw1:Point;
if (Math.random() < ratio) {
// vertical
d0 = interpolate( tl, tr, i0 );
d1 = interpolate( bl, br, i1 );
thw0 = intersection( d0, d1, _tl, _tr );
thw1 = intersection( d0, d1, _bl, _br );
c0 = new Cell( tl, d0, bl, d1, (sizePattern != null)? sizePattern( level ): 1, level );
c1 = new Cell( d0, tr, d1, br, (sizePattern != null)? sizePattern( level ): 1, level );
c0.setOriginal( _tl, thw0, _bl, thw1 );
c1.setOriginal( thw0, _tr, thw1, _br );
} else {
// horizontal
d0 = interpolate( br, tr, i0 );
d1 = interpolate( bl, tl, i1 );
thw0 = intersection( d0, d1, _br, _tr );
thw1 = intersection( d0, d1, _bl, _tl );
c0 = new Cell( tl, tr, d1, d0, (sizePattern != null)? sizePattern( level ): 1, level );
c1 = new Cell( d1, d0, bl, br, (sizePattern != null)? sizePattern( level ): 1, level );
c0.setOriginal( _tl, _tr, thw1, thw0 );
c1.setOriginal( thw1, thw0, _bl, _br );
}
if ( chosePattern != null && chosePattern( level ) ) { hw0 = thw0.clone(); hw1 = thw1.clone(); }
c0.setPatterns( this.chosePattern, this.slopePattern, this.sizePattern );
c1.setPatterns( this.chosePattern, this.slopePattern, this.sizePattern );
}
public function checkOut():Vector.<Vector.<Point>> {
var arr:Vector.<Vector.<Point>> = new Vector.<Vector.<Point>>();
pump(arr);
return arr;
}
public function checkOutHighway():Vector.<Vector.<Point>> {
var arr:Vector.<Vector.<Point>> = new Vector.<Vector.<Point>>();
pumpHighway( arr );
return arr;
}
public function setPatterns( chose_pattern:Function, slope_pattern:Function, size_pattern:Function ):void
{
this.chosePattern = chose_pattern;
this.slopePattern = slope_pattern;
this.sizePattern = size_pattern;
}
public function pump( arr:Vector.<Vector.<Point>> ):void
{
if(c0) {
c0.pump(arr); c1.pump(arr);
} else {
var ar:Vector.<Point> = new Vector.<Point>();
ar.push(tl,tr,br,bl);
arr.push(ar);
}
}
public function pumpHighway( arr:Vector.<Vector.<Point>> ):void
{
if(c0) {
c0.pumpHighway(arr); c1.pumpHighway(arr);
}
if ( hw0 )
{
var ar:Vector.<Point> = new Vector.<Point>();
ar.push( hw0, hw1 );
arr.push( ar );
}
}
public function intersection( p1:Point, p2:Point, p3:Point, p4:Point ):Point
{
var p21x:Number = p2.x - p1.x;
var p21y:Number = p2.y - p1.y;
var p43x:Number = p4.x - p3.x;
var p43y:Number = p4.y - p3.y;
var d:Number = p21x * p43y - p21y * p43x;
if ( d == 0 ) return null;
var p31x:Number = p3.x - p1.x;
var p31y:Number = p3.y - p1.y;
var m1:Number = ( p31x * p43y - p31y * p43x ) / d;
//if ( ( p31x * p43y - p31y * p43x ) / d < 0 || m1 > 1 ) return null;
//var m2:Number = (p31x * p21y - p31y * p21x) / d;
//if ( ( p31x * p21y - p31y * p21x ) / d < 0 || m2 > 1 ) return null;
return new Point( p1.x + m1 * p21x, p1.y + m1 * p21y );
}
private static function interpolate( p0:Point, p1:Point, i:Number ):Point {
var j:Number = 1 - i;
return new Point( p0.x * j + p1.x * i, p0.y * j + p1.y * i );
}
private function resizeCell( p1:Point, p2:Point, p3:Point, p4:Point, r:Number ):void
{
var center:Point = com( p1, p2, p3, p4 );
resizePoint( p1, center, r );
resizePoint( p2, center, r );
resizePoint( p3, center, r );
resizePoint( p4, center, r );
}
private function resizePoint( p:Point, ct:Point, r:Number ):void
{
p.x = ct.x + ( p.x - ct.x ) * r;
p.y = ct.y + ( p.y - ct.y ) * r;
}
private function com( p1:Point, p2:Point, p3:Point, p4:Point ):Point
{
var arr:Vector.<Point> = new Vector.<Point>();
arr.push( p1, p2, p3, p4 );
var cm:Point = new Point();
var tx:Number = 0;
var ty:Number = 0;
var a:Number = area( arr );
var i:int = 0;
var j:int = 0;
var d:Number = 0;
i = 0;
while ( i < arr.length )
{
j = ( i + 1 ) % arr.length;
d = arr[i].x * arr[j].y - arr[j].x * arr[i].y;
tx = tx + ( arr[i].x + arr[j].x ) * d;
ty = ty + ( arr[i].y + arr[j].y ) * d;
i++;
}
a = a * 6;
d = 1 / a;
tx = tx * d;
ty = ty * d;
cm.x = tx;
cm.y = ty;
return cm;
}
private function area( p:Vector.<Point> ):Number
{
var i:int = 0;
var j:int = 0;
var a:Number = 0;
i = 0;
while ( i < p.length )
{
j = ( i + 1 ) % p.length;
a = a + p[i].x * p[j].y;
a = a - p[i].y * p[j].x;
i++;
}
a = a / 2;
return a;
}
}