/* 電位を計算して3次元表示する教材。 画面下部の赤丸(正電荷)・青丸(負電荷)をドラッグして緑の四角の中に入れると、 上の画面が変更されます。 上の画面はマウスドラッグで視点変更、↑↓キーでカメラ距離変更できます。 追記:定数を少しいじりました(3/10,14:10) */ package { import flash.display.Sprite; import flash.display.Graphics; import flash.events.Event; import org.papervision3d.core.geom.renderables.Vertex3D; [SWF(width="465",height="465",backgroundColor="#CCCCCC")] public class Main extends Sprite { private var canvas:canvas3D; private var charges:Array; public function Main() { //3Dキャンバス canvas = new canvas3D(465, 300); addChild(canvas); //2Dフィールド var field2D:Sprite = new Sprite(); var fg:Graphics = field2D.graphics; fg.beginFill(0xFFFFFF); fg.lineStyle(2, 0x00CC99); fg.drawRect(-75, -75, 150, 150); fg.endFill(); fg.moveTo(0, -75); fg.lineTo(0, 75); fg.moveTo(-75, 0); fg.lineTo(75, 0); field2D.x = 225; field2D.y = 380; addChild(field2D); //電荷 charges = [ new PCharge(), new PCharge(), new PCharge(), new NCharge(), new NCharge(), new NCharge() ]; for (var i:int = 0; i < charges.length; i++) { var c:Charge = charges[i] as Charge; c.x = -90; c.y = 20 * i - 65; field2D.addChild(c); c.addEventListener(Event.CHANGE, changeHandler); } } private function changeHandler(e:Event):void { var vertices:Array = canvas.v; for (var i:int = 0; i < vertices.length; i++) { var v:Vertex3D = vertices[i]; var tempV:Number = 0; for (var j:int = 0; j < charges.length; j++) { var c:Charge = charges[j]; //2Dフィールドの座標を3Dキャンバスの座標に対応させる var cx:Number = c.x / 150 * 500; var cy:Number = c.y / 150 * 500; //電位を計算 if(c.x > -75 && c.y > -75 && c.x < 75 && c.y < 75) tempV += 500 * c.q / Math.sqrt((v.x - cx)*(v.x - cx) + (v.y - cy)*(v.y - cy)) } v.z = tempV; } } } } import flash.display.Graphics; import flash.events.Event; import flash.events.KeyboardEvent; import org.papervision3d.view.BasicView; import org.papervision3d.materials.WireframeMaterial; import org.papervision3d.objects.primitives.Plane; class canvas3D extends BasicView { public var v:Array; private var r:Number = 800; private var theta:Number = 60; private var phi:Number = -90; private var mouseDownX:Number; private var mouseDownY:Number; public function canvas3D(w:uint, h:uint) { super(w, h, false); var g:Graphics = this.graphics; g.beginFill(0x000000); g.drawRect(0, 0, w, h); g.endFill(); var m:WireframeMaterial = new WireframeMaterial(0xFF0000); m.doubleSided = true; var field:Plane = new Plane(m, 500, 500, 30, 30); field.rotationX = -90; scene.addChild(field); setCameraPosition(r, theta, phi); camera.zoom = 80; startRendering(); v = field.geometry.vertices; addEventListener(Event.ADDED_TO_STAGE, function(e:Event):void { addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void { //マウスダウン位置を記録 mouseDownX = mouseX; mouseDownY = mouseY; addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler); }); stage.addEventListener(MouseEvent.MOUSE_UP, function(e:MouseEvent):void { removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler); }); stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler); }); } /** * カメラの位置を極座標から直交座標に変換する。 * @param $r * @param $theta * @param $phi */ private function setCameraPosition($r:Number, $theta:Number, $phi:Number):void { var thetaRad:Number = $theta / 180 * Math.PI; var phiRad:Number = $phi / 180 * Math.PI; camera.x = -$r * Math.sin(thetaRad) * Math.cos(phiRad); camera.y = $r * Math.cos(thetaRad); camera.z = $r * Math.sin(thetaRad) * Math.sin(phiRad); } /** * ドラッグ量を角度に変換し、カメラの位置を設定する。 * @param e */ private function mouseMoveHandler(e:MouseEvent):void { if (e.buttonDown) { phi += e.stageX - mouseDownX; theta -= e.stageY - mouseDownY; if (theta > 179) theta = 179; if (theta < 1) theta = 1; if (phi < -180) phi = -179; if (phi > 0) phi = -1; setCameraPosition(r, theta, phi);//直交座標に変換 mouseDownX = e.stageX; mouseDownY = e.stageY; } } /** * カメラの中心からの距離を設定する。↑:近づく、↓:遠ざかる。 * @param e */ private function keyDownHandler(e:KeyboardEvent):void { switch(e.keyCode) { case 38: r -= 50; setCameraPosition(r, theta, phi); break; case 40: r += 50; setCameraPosition(r, theta, phi); break; } } } import flash.display.Sprite; import flash.events.MouseEvent; import flash.events.Event; class Charge extends Sprite { public var q:Number = 0; private var ev:Event = new Event(Event.CHANGE); public function Charge() { init(); } private function init():void { buttonMode = true; addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void { startDrag(); } ); addEventListener(MouseEvent.MOUSE_UP, function(e:MouseEvent):void { stopDrag(); if(y < -75) y = -75; dispatchEvent(ev); } ); } } import flash.display.Sprite; class PCharge extends Charge { public function PCharge() { q = 10; var g:Graphics = this.graphics; g.beginFill(0xFF0000); g.drawCircle(0, 0, 5); g.endFill(); } } import flash.display.Sprite; class NCharge extends Charge { public function NCharge() { q = -10; var g:Graphics = this.graphics; g.beginFill(0x0000FF); g.drawCircle(0, 0, 5); g.endFill(); } } Electric potential