開発環境 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