In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

papervision3dで地形と等高線を表示

* papervision3dで地形と等高線を表示。
* 地形データは「標高データ 立山カルデラ周辺](http://www.vector.co.jp/soft/data/home/se021130.html)
* を利用させていただいている。
* シフトキーを押しながら、画面をクリックすると、等高線が表示される。
* ドラッグで、カメラ位置を変更できる。
Get Adobe Flash player
by termat 20 Mar 2010
    Embed
/**
 * Copyright termat ( http://wonderfl.net/user/termat )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/z5Nc
 */

/*
 * papervision3dで地形と等高線を表示。
 * 地形データは「標高データ 立山カルデラ周辺](http://www.vector.co.jp/soft/data/home/se021130.html)
 * を利用させていただいている。
 * シフトキーを押しながら、画面をクリックすると、等高線が表示される。
 * ドラッグで、カメラ位置を変更できる。
 */
package 
{

	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
    import flash.geom.ColorTransform;
	import flash.system.Security;
	import org.papervision3d.core.geom.Lines3D;
	import org.papervision3d.core.geom.renderables.Line3D;
    import org.papervision3d.materials.ColorMaterial;
	import org.papervision3d.materials.special.LineMaterial;
    import org.papervision3d.view.BasicView;
	import org.papervision3d.core.geom.TriangleMesh3D;
	import org.papervision3d.core.geom.renderables.Vertex3D;
	import org.papervision3d.core.geom.renderables.Triangle3D;
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.core.math.NumberUV;
	import org.papervision3d.materials.utils.MaterialsList;
		
   [SWF(width = "500", height = "500", backgroundColor = "0x000000", fps = "30")] 
	public class Mountain extends BasicView
	{
		private var loader:URLLoader;
		private var node:Array;
		private var elem:Vector.<Array>;
		private var map:Vector.<Array>;
		private var mx:int;
		private var my:int;
		private var rangeZ:Number;
		private var minZ:Number;
		private var mesh:TriangleMesh3D;
		private var rootNode:DisplayObject3D;
		private var contour:DisplayObject3D;	
		private var isPress:Boolean=false;
		private var cameraPitch:Number = 61.75;
		private var cameraYaw:Number = 21;
		private var cameraTarget:DisplayObject3D = DisplayObject3D.ZERO;
		private var preX:Number;
		private var preY:Number;

		public function Mountain():void{
			super(500, 500, false, false);
			rootNode = new DisplayObject3D();
			scene.addChild(rootNode);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
			stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
			stage.addEventListener(Event.ENTER_FRAME, update);
			/*5iVESTAR.ORGさん(http://5ivestar.org/blog/)のプロキシを利用させていただいている。*/
			Security.loadPolicyFile("http://termat.sakura.ne.jp/crossdomain.xml");
			loader = new URLLoader();
			loader.addEventListener(Event.COMPLETE,onCompleted);
			loader.load(new URLRequest("http://termat.sakura.ne.jp/air/data.csv"));
		}
	
		private function update(e:Event):void {
			if (!isPress) {
				cameraYaw += 2;
				cameraYaw %= 360;
				camera.orbit(cameraPitch, cameraYaw, true, cameraTarget);
			}
		}
		
		private function onMouseDown(e:MouseEvent):void{
			isPress = true;
			preX = e.stageX;
			preY = e.stageY;
			if (e.shiftKey) {
				if (contour == null) {
					contour = new DisplayObject3D();
					rootNode.addChild(contour);
					var num:Number = Math.round(minZ / 10) * 10;
					for (; num < minZ + rangeZ; num += 10) {
						if (num % 200 == 0) {
							drawContour(num);
						}
					}
				}else {
					if (contour.parent == rootNode) {
						rootNode.removeChild(contour);
					}else {
						rootNode.addChild(contour);
					}
				}
			}
		}
 
		private function onMouseUp(e:MouseEvent):void{
			isPress = false;
		}
 
		private function onMouseMove(e:MouseEvent):void{
			if(isPress){
				cameraPitch += (e.stageY - preY) * 0.25;
				cameraYaw += (e.stageX - preX) * 0.25;
				cameraPitch %= 360;
				cameraYaw %= 360;
				cameraPitch = cameraPitch > 0 ? cameraPitch : 0.0001;
				cameraPitch = cameraPitch < 180 ? cameraPitch : 179.9999;
				preX = e.stageX;
				preY = e.stageY;
				camera.orbit(cameraPitch, cameraYaw, true, cameraTarget);
			}
		}
		
		private function onCompleted(e:Event):void {
			node = new Array();
			var data:Array = parseCSV(loader.data);
			my = (data[0] as Array).length;
			mx = data.length;
			var maxZ:Number = -1e12;
			minZ = 1e12;
			var centerX:Number = mx * 100 / 2;
			var centerY:Number = my * 100 / 2;
			for (var i:int = 0; i < data.length; i++) {
				for (var j:int = 0; j < data[i].length; j++) {
					var z:Number = parseFloat(data[i][j]);
					var p:Vertex3D = new Vertex3D(i * 100 - centerX, z, (my-j-1) * 100 - centerY);
					node.push(p);
					minZ = Math.min(minZ, z);
					maxZ = Math.max(maxZ, z);
				}
			}
			camera.z = -my * 100 * 1.2;
			rangeZ = maxZ - minZ;
			createMap();
			mesh = new TriangleMesh3D(new ColorMaterial( 0x006699, 1 ), node, new Array(), null );
			rootNode.addChild(mesh);
			for (i = 0; i < elem.length; i++) {
				createTriMesh(node[elem[i][0]], node[elem[i][1]], node[elem[i][2]]);
			}
			startRendering();
		}
		
		private function parseCSV(str:String):Array {
			str = (str.split("\r\n")).join("\n");
			str = (str.split("\r")).join("\n");
			var data:Array = new Array();
			var tmp:Array = str.split("\n");
			var l:Number = tmp.length;
			for(var i:Number=0; i<l; i++){
				data.push(tmp[i].split(","));
			}
			if(data[data.length-1].length == 1 && data[data.length-1][0] == ""){data.pop();}
			return data;
		}
		
		private function createTriMesh(p0:Vertex3D, p1:Vertex3D, p2:Vertex3D):void {
			var col:Number = getColor( ((p0.y + p1.y + p2.y) / 3.0 - minZ) / rangeZ);
			var mat:ColorMaterial = new ColorMaterial(col, 1.0);
			var tri:TriangleMesh3D = new TriangleMesh3D( null, [ p0, p1, p2 ], [] );
			mesh.geometry.faces.push( new Triangle3D( tri, [ p0, p1, p2 ], mat, [new NumberUV( 0.5, 1 ), new NumberUV( 0, 0 ), new NumberUV( 1, 0 )] ));
			tri.geometry.ready = true;
		}
		
		private function getColor(v:Number):Number {
			var r:Number = Math.round( -238.0 * v * v + 493.0 * v);
			var g:Number = Math.round(480.0 * v * v - 480.0 * v + 255.0);
			var b:Number = Math.round(462*v*v-207*v);
			if (r > 255) r = 255;
			if (g > 255) g = 255;
			if (b > 255) b = 255;
			if (b < 0) b = 0;
			return (r<<16)+(g<<8)+b;
		}
		
		private function drawContour(val:Number):void {
			var lm:LineMaterial = new LineMaterial(0xff0000,0.9);
			var lines:Lines3D = new Lines3D(lm);
			var count:int = 0;
			for (var i:int = 0; i < elem.length; i++) {
				var d:Array = new Array(node[elem[i][0]], node[elem[i][1]], node[elem[i][2]]);
				var p:Array = sort(new Array(0, 1, 2), d);
				if (val >= p[0].y) {
					if (val > p[2].y) {
						continue;
					}else {
						var a:Vertex3D;
						var b:Vertex3D;
						var line:Line3D;
						if(val>=p[1].y){
							a = getPoint(p[0], p[2], val);
							b = getPoint(p[1], p[2], val);
							if (a == null || b == null) continue;
							line = new Line3D(lines, lm, 0.5, a, b);
							lines.addLine(line);
							count++;
						}else{
							a = getPoint(p[0], p[2], val);
							b = getPoint(p[0], p[1], val);
							if(a==null||b==null)continue;
							line = new Line3D(lines, lm, 0.5, a, b);
							lines.addLine(line);
							count++;
						}
					}
				}else{
					continue;
				}
			}
			if (count > 0) contour.addChild(lines);
		}
		
		private function sort(it:Array,d:Array):Array{
			for (var i:int = 1; i < it.length; i++) {
				if (d[it[i]].y < d[it[i - 1]].y) {
					var t:int=it[i-1];
					it[i-1]=it[i];
					it[i]=t;
					return sort(it,d);
				}
			}
			return new Array(d[it[0]],d[it[1]],d[it[2]]);
		}
		
		private function getPoint(small:Vertex3D,large:Vertex3D,val:Number):Vertex3D{
			if(small.y==large.y)return null;
			var rr:Number=(val-small.y)/(large.y-small.y);
			var x:Number=small.x;
			var z:Number=small.z;		
			var xx:Number=(large.x-x)*rr+x;
			var zz:Number=(large.z-z)*rr+z;
			var l10:Number=Math.sqrt(Math.pow(xx-x, 2)+Math.pow(zz-z, 2));
			var l11:Number=Math.sqrt(Math.pow(xx-large.x, 2)+Math.pow(zz-large.z, 2));
			var ret:Vertex3D = new Vertex3D();
			var i:int;
			if (l10 == 0) {
				ret.x = small.x;
				ret.y = small.y;
				ret.z = small.z;
			}else if (l10 == 1) {
				ret.x = large.x;
				ret.y = large.y;
				ret.z = large.z;
			}else{
				var r0:Number=1/l10;
				var r1:Number=1/l11;
				ret.x = xx;
				ret.z = zz;
				ret.y = val;
			}
			return ret;
		}
		
		private function createMap():void {
			elem = new Vector.<Array>();
			map = new Vector.<Array>();
			var id:int = 0;
			for (var i:int = 0; i < mx; i++) {
				for (var j:int = 0; j < my; j++) {
					if (i < mx - 1 && j < my - 1) {
						var i0:Array=new Array(i*my+j,(i+1)*my+j+1,(i+1)*my+j);
						var i1:Array=new Array(i*my+j,i*my+j+1,(i+1)*my+j+1);
						elem.push(i0);
						elem.push(i1);
					}else{
						continue;
					}
					if (i == mx - 1 || j == my - 1) continue;
					var j0:Array;
					var j1:Array;
					if(i==0){
						if(j==0){
							j0=new Array(id+1,id+my*2-1,-1);
							id++;
							map.push(j0);
							j1=new Array(-1,id+1,id-1);
							map.push(j1);
							id++;
						}else if(j==my-2){
							j0=new Array(id+1,id+my*2-1,id-1);
							id++;
							map.push(j0);
							j1=new Array(-1,-1,id-1);
							map.push(j1);
							id++;
						}else{
							j0=new Array(id+1,id+my*2-1,id-1);
							id++;
							map.push(j0);
							j1=new Array(-1,id+1,id-1);
							map.push(j1);
							id++;
						}
					}else if(i==mx-2){
						if(j==0){
							j0 = new Array(id + 1, -1, -1);
							id++;
							map.push(j0);
							j1=new Array(id-(my*2-1),id+1,id-1);
							map.push(j1);
							id++;
						}else if(j==my-2){
							j0=new Array(id+1,-1,id-1);
							id++;
							map.push(j0);
							j1=new Array(id-(my*2-1),-1,id-1);
							map.push(j1);
							id++;
						}else{
							j0=new Array(id+1,-1,id-1);
							id++;
							map.push(j0);
							j1=new Array(id-(my*2-1),id+1,id-1);
							map.push(j1);
							id++;
						}
					}else{
						if(j==0){
							j0=new Array(id+1,id+my*2-1,-1);
							id++;
							map.push(j0);
							j1=new Array(id-(my*2-1),id+1,id-1);
							map.push(j1);
							id++;
						}else if(j==my-2){
							j0=new Array(id+1,id+my*2-1,id-1);
							id++;
							map.push(j0);
							j1=new Array(id-(my*2-1),-1,id-1);
							map.push(j1);
							id++;
						}else{
							j0=new Array(id+1,id+my*2-1,id-1);
							id++;
							map.push(j0);
							j1=new Array(id-(my*2-1),id+1,id-1);
							map.push(j1);
							id++;
						}
					}
				}
			}
		}
	}
}