Random Planar Figure Generator
Select what space figure you want in combobox and click "Draw" button. You can also determine the size of planar figure.
If you want to make your own text to parse, see attached file.
(Number of face) / (list of edge's number in each face)
/**
* Copyright Qwaz ( http://wonderfl.net/user/Qwaz )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/rh5O
*/
package
{
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import com.bit101.components.InputText;
import com.bit101.components.PushButton;
import com.bit101.components.ComboBox;
[SWF (width="500", height="500")]
public class Main extends Sprite
{
public const p4:String = '4/1,2,3/2,5,4/3,4,6/5,1,6';
public const p6:String = '6/1,4,3,2/3,9,8,7/2,7,6,5/1,5,12,11/9,4,11,10/6,8,10,12';
public const p8:String = '8/1,2,3/1,9,4/2,5,6/3,7,8/6,11,7/9,8,12/4,10,5/10,12,11';
public const p12:String = '12/1,2,3,4,5/1,10,19,20,6/2,6,11,12,7/3,7,13,14,8/4,8,15,16,9/5,9,17,18,10/20,25,26,21,11/12,21,27,22,13/14,22,28,23,15/16,23,29,24,17/18,24,30,25,19/26,30,29,28,27';
public const p20:String = '20/1,2,3/1,9,10/2,4,5/3,6,7/10,18,11/4,11,12/5,13,14/6,14,15/8,7,16/9,8,17/12,19,20/13,20,21/23,15,22/16,23,24/26,17,25/26,27,18/27,28,19/21,29,22/25,24,30/28,30,29';
public const p6_8:String = '14/1,2,3/1,8,15,9/2,4,11,5/3,6,13,7/9,10,4/5,12,6/8,7,14/15,20,21/11,16,17/13,18,19/10,21,22,16/12,17,23,18/14,19,24,20/22,24,23';
public var myParser:Parser;
public var canvas:Sprite;
public var radiusInput:InputText;
public var dataInput:InputText;
public var generateBtn:PushButton;
public var copyComboBox:ComboBox;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
Face.beginFill(0xFFFFFF);
Face.lineStyle(1, 0, 1, false, "none");
myParser = new Parser();
radiusInput = new InputText(this, 5, 5, "50");
radiusInput.width = 30;
radiusInput.restrict = '0-9';
dataInput = new InputText(this, 5, radiusInput.y + radiusInput.height + 5);
dataInput.width = 490;
generateBtn = new PushButton(this, radiusInput.x + radiusInput.width + 5, 5, "Draw", drawHandler);
generateBtn.width = 50;
generateBtn.height = radiusInput.height;
copyComboBox = new ComboBox(this, generateBtn.x + generateBtn.width + 5, 5, "", ["Tetrahedron", "Cube", "Octahedron", "Dodecahedron", "Icosahedron", "Cuboctahedron"]);
copyComboBox.height = radiusInput.height;
copyComboBox.addEventListener(Event.SELECT, copyData);
copyComboBox.selectedIndex = 0;
copyComboBox.numVisibleItems = 6;
}
private function copyData(e:Event):void {
var now:int = copyComboBox.selectedIndex;
switch(now) {
case 0:
dataInput.text = p4;
break;
case 1:
dataInput.text = p6;
break;
case 2:
dataInput.text = p8;
break;
case 3:
dataInput.text = p12;
break;
case 4:
dataInput.text = p20;
break;
case 5:
dataInput.text = p6_8;
break;
}
}
private function drawHandler(e:MouseEvent):void {
var face:Face;
if (canvas == null) {
canvas = new Sprite();
this.addChild(canvas);
canvas.x = stage.stageWidth / 2;
canvas.y = stage.stageHeight / 2;
} else {
for each (face in myParser.faceArr) {
canvas.removeChild(face);
}
}
myParser.radius = Number(radiusInput.text);
myParser.parse(dataInput.text, canvas);
}
}
}
import flash.utils.Dictionary;
import flash.display.DisplayObjectContainer;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Point;
class Face extends Sprite
{
private var _vertices:Vector.<Point>;
private var _edges:Vector.<Edge> = new Vector.<Edge>();
private var _canvas:Shape = new Shape();
public function Face () {
this.addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init (e:Event):void {
this.removeEventListener(Event.ADDED_TO_STAGE, init);
this.addChild(_canvas);
}
public function attachToOtherFace (target:Edge, to:Edge):void {
if (target.parent != this) {
throw new ArgumentError("target must be the child of caller");
}
var fiStart:Point = this.localToGlobal(target.start);
var fiEnd:Point = this.localToGlobal(target.end);
var fiDistance:Number = Point.distance(fiStart, fiEnd);
var seStart:Point = to.parent.localToGlobal(to.start);
var seEnd:Point = to.parent.localToGlobal(to.end);
var seDistance:Number = Point.distance(seStart, seEnd);
this.scaleX *= seDistance / fiDistance;
this.scaleY *= seDistance / fiDistance;
var targetAngle:Number = Math.atan2(seEnd.y - seStart.y, seEnd.x - seStart.x) * 180 / Math.PI;
var nowAngle:Number = Math.atan2(fiStart.y - fiEnd.y, fiStart.x - fiEnd.x) * 180 / Math.PI;
if (targetAngle > nowAngle) {
targetAngle += 360;
}
this.rotation += targetAngle - nowAngle;
fiStart = this.localToGlobal(target.start);
fiEnd = this.localToGlobal(target.end);
this.x += seEnd.x - fiStart.x;
this.y += seEnd.y - fiStart.y;
target._linked = to;
to._linked = target;
}
public static function makeRegularPolygon(n:uint, length:Number):Face {
var vertices:Vector.<Point> = new Vector.<Point>();
var i:int;
for (i = 0; i < n; i++) {
vertices.push(Point.polar(Math.sqrt((length * length) / (2 - 2 * Math.cos(2 * Math.PI / n))), 2 * Math.PI / n * i - Math.PI / 2));
}
return makeByVertices(vertices);
}
public static function makeByVertices(vertices:Vector.<Point>):Face {
if (vertices.length < 3) {
throw new ArgumentError("Require more than 3 vertices");
}
var face:Face = new Face();
var point:Point;
var i:int;
with (face._canvas.graphics) {
if (_nowFilling) {
beginFill(_fillColor, _fillAlpha);
}
if (_lineInitialized) {
lineStyle(_thickness, _lineColor, _lineAlpha, _pixelHinting, _scaleMode, _caps, _joints, _miterLimit);
}
moveTo(vertices[0].x, vertices[0].y);
}
for (i = 1; i < vertices.length; i++) {
face._canvas.graphics.lineTo(vertices[i].x, vertices[i].y);
face._edges.push(new Edge(vertices[i - 1], vertices[i], face));
}
face._edges.push(new Edge(vertices[i - 1], vertices[0], face));
face._canvas.graphics.lineTo(vertices[0].x, vertices[0].y);
face._vertices = vertices;
return face;
}
private static var _fillColor:uint;
private static var _fillAlpha:Number;
private static var _nowFilling:Boolean = false;
public static function beginFill(color:uint, alpha:Number = 1):void {
_fillColor = color;
_fillAlpha = alpha;
_nowFilling = true;
}
public static function endFill():void {
_nowFilling = false;
}
private static var _thickness:Number;
private static var _lineColor:uint;
private static var _lineAlpha:Number;
private static var _pixelHinting:Boolean;
private static var _scaleMode:String;
private static var _caps:String;
private static var _joints:String;
private static var _miterLimit:Number;
private static var _lineInitialized:Boolean = false;
public static function lineStyle(
thickness:Number = 0,
color:uint = 0,
alpha:Number = 1,
pixelHinting:Boolean = false,
scaleMode:String = "normal",
caps:String = null,
joints:String = null,
miterLimit:Number = 3):void {
_thickness = thickness;
_lineColor = color;
_lineAlpha = alpha;
_pixelHinting = pixelHinting;
_scaleMode = scaleMode;
_caps = caps;
_joints = joints;
_miterLimit = miterLimit;
_lineInitialized = true;
}
public function get vertices():Vector.<Point> {
return _vertices;
}
public function get edges():Vector.<Edge> {
return _edges;
}
}
class Edge
{
public var start:Point;
public var end:Point;
private var _parent:Face;
internal var _linked:Edge;
public function Edge(start:Point, end:Point, parent:Face) {
this.start = start;
this.end = end;
this._parent = parent;
}
internal function get parent():Face {
return _parent;
}
public function get linked():Edge {
return _linked;
}
//Delete If You are not using Parser
public function set linked(e:Edge):void {
_linked = e;
}
}
class Parser
{
private var _edgeArr:Array;
private var _faceArr:Vector.<Face>;
private var _array:Array;
private var sNum:int;
public var radius:Number = 20;
public function parse (data:String, canvas:DisplayObjectContainer):void {
var fClone:Vector.<Face> = new Vector.<Face>;
_array = data.split('/');
var length:int = int(_array[0]);
var i:int;
var j:int;
for (i = 1; i <= length; i++) {
_array[i] = String(_array[i]).split(',');
}
_faceArr = new Vector.<Face>;
_edgeArr = new Array();
for (i = 1; i <= length; i++) {
_faceArr.push(Face.makeRegularPolygon(_array[i].length, radius));
fClone.push(_faceArr[i - 1]);
canvas.addChild(_faceArr[i - 1]);
}
var start:int = Math.floor(Math.random() * length);
start = Math.floor(Math.random() * length);
process(_faceArr[start]);
while(_edgeArr.length > 0) {
_edgeArr.sort(randomSort);
_edgeArr.sort(randomSort);
for (i = 1; i < _array.length; i++) {
for (j = 0; j < _array[i].length; j++) {
if (_array[i][j] == _edgeArr[0][1]) {
_faceArr[i - 1].attachToOtherFace(_faceArr[i - 1].edges[j], _edgeArr[0][0]);
process(_faceArr[i - 1]);
break;
}
}
}
}
var face:Face;
for each (face in fClone) {
_faceArr.push(face);
}
}
private function process(target:Face):void {
var index:int = _faceArr.indexOf(target);
var i:int;
var j:int;
var chk:Boolean;
for (i = 0; i < target.edges.length; i++) {
chk = false;
for (j = 0; j < _edgeArr.length; j++) {
if (_array[index + 1][i] == _edgeArr[j][1]) {
target.edges[i].linked = _edgeArr[j][0];
_edgeArr[j][0].linked = target.edges[i];
_edgeArr.splice(j, 1);
chk = true;
break;
}
}
if (!chk) {
_edgeArr.push([target.edges[i], _array[index + 1][i]]);
}
}
_faceArr.splice(index, 1);
_array.splice(index + 1, 1);
}
private function randomSort(x:Object, y:Object):int {
if (Math.random() < 0.5) {
return -1;
}
return 1;
}
public function get faceArr():Vector.<Face> {
return _faceArr;
}
}