triangle fractall
forked from flash on 2014-12-24 (diff: 157)
let's do this http://2.bp.blogspot.com/-58NYJwX1hHw/TteOnR72WGI/AAAAAAAAA-w/0OrOFZrCQ24/s640/Mountain+Fractal.jpg
ActionScript3 source code
/**
* Copyright Cheshir ( http://wonderfl.net/user/Cheshir )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/hpcw
*/
// forked from Cheshir's flash on 2014-12-24
package {
import flash.filters.GlowFilter;
import flash.events.TimerEvent;
import flash.utils.Timer;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.events.Event;
import flash.text.TextField;
// let's do this http://www.flashandmath.com/advanced/simple3d/
import flash.display.Sprite;
public class FlashTest extends Sprite {
private var multyY_1:Number = Math.random()-.5; // this values must set facture of fractall // funny but 0 height steel be 0
private var multyY_2:Number = Math.random()-.5; // разрывы возникают, так как треугольники переворачиваются, и у разных сторон
private var multyY_3:Number = Math.random()-.5; // оказываются разные значения
private var isRotate:Boolean = false;
private var needPointDraw:Boolean = false;
private var canvas:Sprite = new Sprite(); //
private var vertexArray:Array = [new Point3D(120,Math.random()*-180,0), new Point3D(-100,Math.random()*100,100), new Point3D(-100,Math.random()*100,-100),
new Point3D(120,Math.random()*120,-200), new Point3D(120,Math.random()*120,200)];
private var facesArray:Array = [[0,1,2,0],[2,3,0,0],[0,1,4,0]]; // last value is iteration of this face
// face hold iteration value, i need find in facesArray all faces where (iterate == nowIterate), and make them fractall !
private var nowIterate:int = 0;
// private var sequenceFace:Array = [0,1,2,0,0,1,0,2,3,5,6,7,8,0,1,2,3,0,1,0,0]; // 2 iteration // old age
private var maxIterate:int = 3; // 3 iteration normal implementation.
public function FlashTest() {
drawGrid(); // I need more time... 15 minutes I did not get
addChild(coordinates);
addChild(canvas);
stage.addEventListener(Event.ENTER_FRAME, rotate);
var timeUpdate:Timer = new Timer(50);
timeUpdate.addEventListener(TimerEvent.TIMER, nextFace);
timeUpdate.start();
stage.addEventListener(MouseEvent.MOUSE_DOWN, startRotate);
stage.addEventListener(MouseEvent.MOUSE_UP, stopRotate);
trace.textColor = 0xffee00;
trace.filters = [new GlowFilter(0)];
trace.x = 30;
trace.y = 30;
addChild(trace);
}
private var trace:TextField = new TextField();
private var nowFace:int = 0;
private function nextFace(e:TimerEvent):void{
nowFace = findFace(nowIterate);
if(nowFace >= 0){
fractallFace(facesArray[nowFace], nowFace);
} else if(nowIterate < maxIterate){
nowIterate++;
}
trace.text = 'total faces: '+facesArray.length.toString();
//fractallFace(facesArray[sequenceFace[faceI]],sequenceFace[faceI]);
//if(faceI<sequenceFace.length)
// faceI++;
}
private function findFace(iterate:int=0):int {
for(var i:int = 0; i<facesArray.length; i++){
if(facesArray[i][3] == iterate){
return i;
}
}
return -1;
}
private function approximatelyEqual(a:Number, b:Number, error:Number = 0.1):Boolean{
if(a==b) return true;
if(a>b){
if(a-b > error) return true;
} else {
if(b-a > error) return true;
}
return false;
}
private function startRotate(e:MouseEvent):void{isRotate = true;}
private function stopRotate(e:MouseEvent):void{isRotate = false;}
private var speedZ:Number = 0;
private var speedY:Number = 0;
private var mX:Number = 0;
private var mY:Number = 0;
private function rotate(e:Event):void{
if(isRotate){
speedZ = (mY - mouseY)/100;
speedY = (mouseX - mX)/100;
theta += speedZ;
phi += speedY;
}
mX = mouseX;
mY = mouseY;
canvas.graphics.clear();
for(var i:int=0; i<vertexArray.length; i++){
drawPoint(vertexArray[i]);
}
for(i=0; i<facesArray.length; i++){
drawFace(facesArray[i]);
}
drawGrid();
}
// this must make this http://2.bp.blogspot.com/-58NYJwX1hHw/TteOnR72WGI/AAAAAAAAA-w/0OrOFZrCQ24/s640/Mountain+Fractal.jpg 1 time
private function fractallFace(face:Array, faceId:uint):void{
// одна грань должна превратиться в 4
// первым делом нужно добавить новую точку (всего их будет 3)
// за высоту отвечает Y остальные точки должны быть строго по середине // in this case Y = 0 and multy is not work...
var id_1:int = vertexArray.length; // будущие id новых точек
var id_2:int = id_1+1;
var id_3:int = id_2+1;
var id_a:int = face[0]; // id старых точек на грани
var id_b:int = face[1];
var id_c:int = face[2];
var nextIterate:int = face[3]+1; // это определенно более сглаженно, но блин (((
var p_1:Point3D = new Point3D((vertexArray[face[0]].x+vertexArray[face[1]].x)/2, getNewY(vertexArray[face[0]], vertexArray[face[1]], multyY_1), (vertexArray[face[0]].z+vertexArray[face[1]].z)/2);
var p_2:Point3D = new Point3D((vertexArray[face[1]].x+vertexArray[face[2]].x)/2, getNewY(vertexArray[face[1]], vertexArray[face[2]], multyY_2), (vertexArray[face[1]].z+vertexArray[face[2]].z)/2);
var p_3:Point3D = new Point3D((vertexArray[face[2]].x+vertexArray[face[0]].x)/2, getNewY(vertexArray[face[2]], vertexArray[face[0]], multyY_3), (vertexArray[face[2]].z+vertexArray[face[0]].z)/2);
vertexArray.push(p_1, p_2, p_3);
facesArray.splice(faceId,1); // delete old face
facesArray.push( [ id_2, id_3, id_1, nextIterate ], [id_a, id_1, id_3, nextIterate], [id_1, id_b, id_2, nextIterate ],
[id_3, id_2, id_c, nextIterate] );
// abc - to - a13 - 32c - 1b2 - 231
// where 1 in ab, 2 in bc, 3 in ca
}
private function getNewY(pointA:Point3D, pointB:Point3D, multy:Number):Number{
var length:Number = Math.sqrt(Math.pow(pointA.x-pointB.x, 2) + Math.pow(pointA.z-pointB.z, 2));
return (pointA.y+pointB.y)/2 + length*multy ;
}
private var coordinates:Sprite = new Sprite();
public function drawGrid():void{
coordinates.graphics.clear();
var w:Number = stage.stageWidth;
var h:Number = stage.stageHeight;
var point_0:Point3D = new Point3D(0,0,0);
point_0.calcVisual(theta, phi);
var point_X:Point3D = new Point3D(100,0,0);
var point_Y:Point3D = new Point3D(0,100,0);
var point_Z:Point3D = new Point3D(0,0,100);
point_X.calcVisual(theta, phi);
point_Y.calcVisual(theta, phi);
point_Z.calcVisual(theta, phi);
this.graphics.beginFill(0xcccccc);
this.graphics.drawRect(0,0,w,h);
this.graphics.endFill();
coordinates.graphics.lineStyle(1,0xdd3333,0.4);
coordinates.graphics.moveTo(point_0.visualX, point_0.visualY);
coordinates.graphics.lineTo(point_X.visualX, point_X.visualY);
coordinates.graphics.lineStyle(1,0x33dd33,0.4);
coordinates.graphics.moveTo(point_0.visualX, point_0.visualY);
coordinates.graphics.lineTo(point_Y.visualX, point_Y.visualY);
coordinates.graphics.lineStyle(1,0x3333dd,0.4);
coordinates.graphics.moveTo(point_0.visualX, point_0.visualY);
coordinates.graphics.lineTo(point_Z.visualX, point_Z.visualY);
canvas.x = w/2; canvas.y = h/2;
coordinates.x = 100; coordinates.y = 100;
}
// Создание подписей
private function createSignature(x:Number,y:Number,signature:String,scale:Number = 1.5):void{
var sig:TextField = new TextField();
sig.text = signature;
sig.textColor = 0xdd3333;
sig.scaleX = sig.scaleY = scale;
sig.autoSize = 'left';
sig.x = x;
sig.y = y;
addChild(sig);
}
private var theta:Number = 0;
private var phi:Number = 0;
private function drawPoint(p:Point3D):void{
if(needPointDraw){
canvas.graphics.beginFill(0x33dd33+p.z*0xdd); // I can draw point, but I need calculate offset before;
// похоже, что это позволяет производить сещение для осей Y и Z и это выглядит правильно, но ось Х у меня выпадает
p.calcVisual(theta,phi);
canvas.graphics.drawCircle(p.visualX, p.visualY, 3);
canvas.graphics.endFill();
} else {
p.calcVisual(theta,phi);
}
}
private var averageY:Number=0;
private function drawFace(face:Array):void{
averageY = (vertexArray[face[0]].y + vertexArray[face[1]].y + vertexArray[face[2]].y)/3;
canvas.graphics.beginFill(averageY,0.4); // z-sorting? phhhhfffff!....
canvas.graphics.lineStyle(1,0x333333);
canvas.graphics.moveTo(vertexArray[face[0]].visualX, vertexArray[face[0]].visualY);
canvas.graphics.lineTo(vertexArray[face[1]].visualX, vertexArray[face[1]].visualY);
canvas.graphics.lineTo(vertexArray[face[2]].visualX, vertexArray[face[2]].visualY);
canvas.graphics.endFill();
}
}
}
import flash.geom.Point;
Class {
class Point3D extends Point{
public var visualX:Number;
public var visualY:Number;
public var z:Number;
public var color:uint;
public function Point3D(x:Number=0, y:Number=0, z:Number=0, color:uint=0xdd3333){
this.x = x; this.color = color;
this.y = y;
this.z = z;
}
// нужно бы еще создать точку схождения...
public function calcVisual(theta:Number, phi:Number):void{
this.visualX = x*Math.cos(theta)*Math.sin(phi) + y*Math.sin(theta)*Math.sin(phi) + z*Math.cos(phi);
this.visualY = -x*Math.sin(theta)+y*Math.cos(theta);
}
}
}