開発環境 |
Apache Flex SDK 4.12.1 |
|
FlashDevelop 4.6.2.5 |
実行環境 |
Microsoft Windows 8.1 (64bit) |
プロジェクトの種類 |
ActionScript 3/AS3 Project |
プロジェクト名 |
AzimuthalEquidistant |
参考
Main.as
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.geom.Vector3D;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.ui.Keyboard;
import mx.utils.StringUtil;
public class Main extends Sprite
{
private const PI2:Number = Math.PI * 2;
private var textField:TextField = new TextField;
private var bitmapData:BitmapData = new BitmapData(600, 600, false);
private var bitmap:Bitmap = new Bitmap(bitmapData);
[Embed(source = "earthmap1k.jpg")]
private const TextureBitmap:Class;
private var bmEarth:Bitmap = new TextureBitmap;
private var bmdEarth:BitmapData = bmEarth.bitmapData;
private var lat:int = 35; // 緯度
private var lon:int = 135; // 経度
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
textField.defaultTextFormat = new TextFormat(null, 20, 0xffff00);
textField.autoSize = TextFieldAutoSize.LEFT;
stage.addChild(textField);
stage.addChildAt(bitmap, 0);
onRender();
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
private function onRender():void
{
textField.text = StringUtil.substitute("lat:{0} lon:{1}", lat, lon);
var centerLatRad:Number = lat * Math.PI / 180; // -PI/2 ~ PI/2
var centerLonRad:Number = lon * Math.PI / 180; // -PI ~ PI
var cosCenterLon:Number = Math.cos(centerLonRad);
var sinCenterLon:Number = Math.sin(centerLonRad);
// axis
var ay:Number = Math.sin(centerLatRad);
var ar:Number = Math.cos(centerLatRad);
var az:Number = cosCenterLon * ar;
var ax:Number = sinCenterLon * ar;
var axis:Vector3D = new Vector3D(ax, ay, az, 1);
axis.normalize();
bitmapData.lock();
for (var by:int = 0; by < bitmapData.height; by++)
{
var y:Number = (by / (bitmapData.height - 1)) * 2 - 1; // -1 ~ 1
for (var bx:int = 0; bx < bitmapData.width; bx++)
{
var x:Number = (bx / (bitmapData.width - 1)) * 2 - 1; // -1 ~ 1
var color:uint = 0x808080;
// 距離(=回転軸からの角度) 0 ~ 1
var dist:Number = Math.sqrt(x * x + y * y);
if (dist <= 1)
{
// 方位角(=回転する角度)
var angleRad:Number = Math.atan2(x, -y); // -PI ~ PI
// 回転する座標
var p:Vector3D = new Vector3D;
var rad:Number = centerLatRad + dist * Math.PI;
p.y = Math.sin(rad);
var r:Number = Math.cos(rad);
p.z = cosCenterLon * r;
p.x = sinCenterLon * r;
p.w = 0;
// 回転
var rot:Vector3D = new Vector3D;
angleRad *= 0.5;
var sinAngle:Number = Math.sin(angleRad);
rot.x = axis.x * sinAngle;
rot.y = axis.y * sinAngle;
rot.z = axis.z * sinAngle;
rot.w = axis.w * Math.cos(angleRad);
var conj:Vector3D = new Vector3D( -rot.x, -rot.y, -rot.z, rot.w);
var q:Vector3D = MulQ(MulQ(conj, p), rot);
// 緯度、経度
var latRad:Number = Math.asin(q.y); // -PI/2 ~ PI/2
var lonRad:Number = Math.atan2(q.x, q.z); // -PI ~ PI
// テクスチャサンプリング
var tx:int = (0.5 + lonRad / PI2) * 1000;
var ty:int = (0.5 - latRad / Math.PI) * 500;
color = bmdEarth.getPixel(tx, ty);
}
bitmapData.setPixel(bx, by, color);
}
}
bitmapData.unlock();
}
private function MulQ(q1:Vector3D, q2:Vector3D):Vector3D
{
var q:Vector3D = new Vector3D;
q.x = (q1.w * q2.x) + (q1.x * q2.w) + (q1.y * q2.z) - (q1.z * q2.y);
q.y = (q1.w * q2.y) + (q1.y * q2.w) + (q1.z * q2.x) - (q1.x * q2.z);
q.z = (q1.w * q2.z) + (q1.z * q2.w) + (q1.x * q2.y) - (q1.y * q2.x);
q.w = (q1.w * q2.w) - (q1.x * q2.x) - (q1.y * q2.y) - (q1.z * q2.z);
return q;
}
private function onKeyDown(e:KeyboardEvent):void
{
var delta:int = (e.ctrlKey) ? 15 : 1;
switch (e.keyCode)
{
case Keyboard.LEFT:
lon -= delta;
if (lon < -180) lon += 360;
break;
case Keyboard.UP:
lat += delta;
if (90 < lat) lat = 90;
break;
case Keyboard.RIGHT:
lon += delta;
if (180 <= lon) lon -= 360;
break;
case Keyboard.DOWN:
lat -= delta;
if (lat < -90) lat = -90;
break;
default:
return;
}
onRender();
}
}
}
最終更新:2014年07月03日 11:58