/**
* 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;
}
}