PQ torus

drawing 3D lines in flash algorithmically

PQ torus

src/PQtorus.mxml


<?xml version="1.0" encoding="utf-8"?>
<mx:Application 
	pageTitle=" P Q . t o r u s "
	backgroundColor="#000000" backgroundAlpha="1"
	backgroundGradientColors="[#535353, #000000]"
	backgroundGradientAlphas="[1.0, 1.0]" 
	xmlns:mx="http://www.adobe.com/2006/mxml"
	xmlns:xx="nu.xero.flex.*"
	layout="absolute"
	applicationComplete="init3D()">
<mx:Script>
<![CDATA[/*
           .  .  P Q . t o r u s . k n o t  .  .
      
           respect due to the infamous blackpawn
          thanx for sharing all your math skills!
          http://www.blackpawn.com/texts/pqtorus/
                                                        */
//________________________________________________________
//                                                 imports
	import org.papervision3d.core.geom.renderables.*;
	import org.papervision3d.materials.special.*;
	import org.papervision3d.materials.*;
	import org.papervision3d.core.geom.*;
	import nu.xero.flex.*;
//________________________________________________________
//                                                    vars		
	//enviorment vars
	private var fps			:FlexFPS;
	private var speed		:Number  = .02;
	private var count		:Number  = 0;
	private var draw		:Boolean = true;
	private var theColor1	:uint    = 0xff00ff;
	private var theColor2	:uint    = 0x00ff00;
	private var theMix		:Number  = 0;
	private var dir			:Boolean = false;
	//line vars
	private var linez		:Lines3D;
	private var firstX		:Number  = 0;
	private var firstY		:Number  = 0;
	private var firstZ		:Number  = 0;
	private var lastX		:Number  = 0;
	private var lastY		:Number  = 0;
	private var lastZ		:Number  = 0;
	private var nextX		:Number  = 0;
	private var nextY		:Number  = 0;
	private var nextZ		:Number  = 0;
	//math vars
	private var r			:Number  = 0;
	private var p			:Number  = 4;
	private var q			:Number  = 5;
	private var phi			:Number  = 0;
//________________________________________________________
//                                             constructor
	private function init3D():void {
		//create framerate display
		fps = new FlexFPS(0x000000, 0x535353, 0xFFFFFF, 0, "kb");
		addChild(fps);
		
		//setup camera
		paperCanvas.view.camera.z = -400;
		
		//create line object
		linez = new Lines3D(new LineMaterial(theColor1));
		paperCanvas.view.scene.addChild(linez);				
		
		//add render loop
		addEventListener(Event.ENTER_FRAME, loop3D);
	}
//________________________________________________________
//                                             render loop	
	private function loop3D(e:Event):void {
		//update framerate display
		fps.update("lines.rendered: " + linez.lines.length); 

		//rotation
		if(autoRot.selected){
			linez.rotationY = count++;
		}
		if(mouseControl.selected){
			linez.rotationX -= (mouseY-(stage.height*.5))/100;
		}
				
		if(count<315){
			//calculate torus knot
			phi += speed;
			r = .5 * (2 + Math.sin(q * phi)) * 10;
			nextX = r * Math.cos(p * phi) * 10;
			nextY = r * Math.cos(q * phi) * 10;
			nextZ = r * Math.sin(p * phi) * 10;
			//starting positions
			if(count==1){
				firstX = nextX;
				firstY = nextY;
				firstZ = nextZ;
				lastX = nextX;
				lastY = nextY;
				lastZ = nextZ;					
			}
			if(theColor2 == 0x00000f){
				//add solid line
				linez.addLine(new Line3D(linez, new LineMaterial(theColor1), 10, new Vertex3D(lastX, lastY, lastZ), new Vertex3D(nextX, nextY, nextZ)));
			} else {
				//color transition
				if(!dir){
				 	if(theMix<=250){
				  		theMix+=5;
				  	} else {
				  		dir=true;
				  	}
				} else {
				  	if(theMix>5){
				  	 	theMix-=5;
				  	} else {
				  	 	dir=false;
					}
				}
				//add gradient line
				linez.addLine(new Line3D(linez, new LineMaterial(theColor1*theMix), 10, new Vertex3D(lastX, lastY, lastZ), new Vertex3D(nextX, nextY, nextZ)));
			}				
			//update last positions
			lastX = nextX;
			lastY = nextY;
			lastZ = nextZ;
		} else if(count == 315) {
			//connect the final line
			if(theColor2 == 0x00000f){
				linez.addLine(new Line3D(linez, new LineMaterial(theColor1), 10, new Vertex3D(lastX, lastY, lastZ), new Vertex3D(firstX, firstY, firstZ)));									
			} else {
				linez.addLine(new Line3D(linez, new LineMaterial(theColor1*theMix), 10, new Vertex3D(lastX, lastY, lastZ), new Vertex3D(firstX, firstY, firstZ)));
			}			
		}
		//render		
		paperCanvas.view.singleRender(); 
	}
//________________________________________________________
//                                             reset linez	
	private function setupLinez():void {
		linez.material.destroy();
		linez.removeAllLines();
		linez.lines = [];
		phi = 0;
		count = 0;	
		p = theP.value;
		q = theQ.value;
	}
//________________________________________________________
//                                                     gui
	private function switchMenu(dir:String):void {
		if(dir == "open"){
			currentState = "customColor";
			colorPanel.x = btnColor.x - 40;
		} else {
			currentState = "";
		}
	}
//________________________________________________________
//                                       change line color
	private function setColor(color1:uint, color2:uint = 0x00000f):void {
		theColor1 = color1;
		theColor2 = color2;
		setupLinez();
		currentState = "";
	}
//________________________________________________________
//                                             move camera
	private function fov():void {
		paperCanvas.view.camera.z = theZoom.value;
	}	
]]>
</mx:Script>
	<mx:states>
		<mx:State name="customColor">
			<mx:AddChild position="lastChild">
				<mx:Panel x="653" width="86" height="437" layout="absolute" id="colorPanel" bottom="31" borderStyle="solid" borderColor="#c3c3c3" borderThickness="1" headerHeight="3" backgroundAlpha=".59" backgroundColor="#303030" dropShadowEnabled="false">
					<mx:Button x="7" y="24" label=" " width="55" fillAlphas="[1.0, 1.0]" fillColors="[#1EFF00, #1EFF00]" id="btnLime" click="setColor(0x00ff00, 0x000000f)"/>
					<mx:Button x="7" y="50" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#FF0000, #FF0000]" id="btnRed" click="setColor(0xff0000, 0x000000f)"/>
					<mx:Button x="7" y="77" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#0000FF, #0000FF]" id="btnBlue" click="setColor(0x0000ff, 0x000000f)"/>
					<mx:Button x="7" y="104" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#FF00CC, #FF00FF]" id="btnPink" click="setColor(0xff00ff, 0x000000f)"/>
					<mx:Button x="7" y="132" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#FFF000, #FFF000]" id="btnYellow" click="setColor(0xfff000, 0x000000f)"/>
					<mx:Button x="7" y="159" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#006600, #006600]" id="btnGreen" click="setColor(0x006600, 0x000000f)"/>
					<mx:Button x="7" y="186" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#FFFFFF, #FFFFFF]" id="btnWhile" click="setColor(0xffffff, 0x000000f)"/>
					<mx:Button x="7" y="227" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#FF00FF, #00FF00]" id="btnMix1" click="setColor(0xff00ff, 0x00ff00)"/>
					<mx:Button x="7" y="254" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#00FFFF, #FFF000]" id="btnMix2" click="setColor(0x00ffff, 0xfff00)"/>
					<mx:Button x="7" y="333" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#FF0000, #FFF000]" id="btnMix5" click="setColor(0xffff00, 0xfff00)"/>
					<mx:Button x="7" y="306" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#0000FF, #00FF00]" id="btnMix4" click="setColor(0x0000ff, 0x00ff00)"/>
					<mx:Button x="7" y="280" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#00FF00, #FF0000]" id="btnMix3" click="setColor(0x00ff00, 0xff0000)"/>
					<mx:Button x="7" y="362" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#FF0000, #000000]" id="btnMix6" click="setColor(0xff0000, 0x000000)"/>
					<mx:Button x="7" y="389" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#FFFFFF, #FFF000]" id="btnMix7" click="setColor(0xffffff, 0xfff00)"/>
					<mx:Label x="15" y="209" text="mixed" color="#FFFFFF"/>
					<mx:Label x="18" y="5" text="solid" color="#FFFFFF"/>
				</mx:Panel>
			</mx:AddChild>
			<mx:SetProperty target="{btnColor}" name="label" value="v"/>
			<mx:SetProperty target="{btnColor}" name="width" value="34"/>
			<mx:SetEventHandler target="{btnColor}" name="click" handler="switchMenu(&quot;close&quot;)"/>
			<mx:SetStyle target="{btnColor}" name="textRollOverColor" value="#ffffff"/>
			<mx:SetStyle target="{btnColor}" name="textSelectedColor" value="#ffffff"/>
			<mx:RemoveChild target="{btnColor}"/>
			<mx:AddChild position="lastChild" target="{btnColor}"/>
			<mx:SetStyle target="{btnColor}" name="right" value="27"/>
			<mx:SetStyle target="{btnColor}" name="bottom" value="4"/>
			<mx:RemoveChild target="{label1}"/>
			<mx:AddChild position="lastChild" target="{label1}"/>
			<mx:SetProperty target="{label1}" name="text" value="color"/>
			<mx:SetStyle target="{label1}" name="bottom" value="6"/>
			<mx:SetStyle target="{label1}" name="right" value="71"/>
		</mx:State>
	</mx:states>
	<xx:CanvasView3D id="paperCanvas" top="0" bottom="0" left="0" right="0"/>
	<mx:ApplicationControlBar right="0" left="0" bottom="0">
		<mx:Label text="  torus ( P =" color="#FFFFFF"/>
		<mx:NumericStepper width="45" id="theP" value="4" minimum="-50" maximum="50" change="setupLinez()" backgroundColor="#333333" color="#FFFFFF" borderColor="#000000"/>
		<mx:Label text=", Q = " color="#FFFFFF"/>
		<mx:NumericStepper width="45" id="theQ" value="5" minimum="-50" maximum="50" change="setupLinez()" color="#FFFFFF" backgroundColor="#333333" borderColor="#000000"/>
		<mx:Text text=")       " color="#FFFFFF"/>
		<mx:Label text="       "/>
	</mx:ApplicationControlBar>
	<mx:Label text="color" color="#FFFFFF" id="label1" right="71" bottom="6"/>
	<mx:Button label="^" width="35" color="#FFFFFF" fillAlphas="[1.0, 1.0]" fillColors="[#000000, #8B8B8B, #464646, #000000]" id="btnColor" click="switchMenu(&quot;open&quot;)" right="27" bottom="4" themeColor="#8B8B8B" textRollOverColor="#ffffff" textSelectedColor="#ffffff"/>
	<mx:HSlider id="theZoom" liveDragging="true" change="fov()" maximum="0" value="-400" minimum="-800" allowTrackClick="true" width="116" horizontalCenter="-38" bottom="10"/>
	<mx:Label text="camera:" color="#FCFCFC" id="label2" horizontalCenter="-116" bottom="8"/>
	<mx:CheckBox label="mouse controlled" id="mouseControl" selected="false" color="#FFFFFF" bottom="4" horizontalCenter="226"/>
	<mx:CheckBox label="auto rotate" id="autoRot" selected="true" color="#FFFFFF" horizontalCenter="90" bottom="5"/>
</mx:Application>

Download

raw zip tar