3 Replies Latest reply on Nov 3, 2010 1:20 PM by brock.haywood

    Porting GoogleMapUtility to AS3

    HyderAlamgir

      I couldn't find anyone having ported the GoogleMapUtility to AS3 from PHP... so I tried my hand at it.

       

      I ended up with an internal build error. Love those, don't you!

       

       

      I've hosted the code here

      http://code.google.com/p/google-map-utility-as3/source/browse/trunk/GoogleMapUtility.as

       

       

      The original PHP can be found here:

      http://uwmike.com/maps/GoogleMapUtility.php.source

       

       

      Could someone do a quick review and see where I may be screwing up.

      For instance, I don't where some variables need to be declared. PHP's loose coding is a mess to port out.

      Keep in mind, that I'm no AS3 genius, and I absolutely suck at math.

        • 1. Re: Porting GoogleMapUtility to AS3
          HyderAlamgir Level 1

          Ok, no answers yet.

           

          In any case, I've fixed the internal build error.

           

          Now, the calculations are all messed up. I get different results from calling the PHP function and different ones from calling the ported function in AS3.

           

           

          Anyone?!

          • 2. Re: Porting GoogleMapUtility to AS3
            _Natasha_ Level 4

            It's will bw easier to help if you write call parameters for functions and results for AS and PHP

            • 3. Re: Porting GoogleMapUtility to AS3
              brock.haywood

              You have errors in your rad2deg and deg2rad methods.

               

              Here is the fixed class:

               

              package com.google.maps

              {

              import flash.geom.Point;

              import flash.geom.Rectangle;

               

              public class GoogleMapsUtility

              {

              public static const TILE_SIZE:int = 256;

              public static var normalised:Point = new Point(-1, -1);

              public static var pixelCoords:Point;

              public static var scale:Number = 1;

               

              public static function fromXYToLatLng( point:Point, zoom:int ):Point

              {

              scale = ( 1 << (zoom)) * GoogleMapsUtility.TILE_SIZE;

              // CORRECT: Where does normalised come from?! //

              return new Point( int( GoogleMapsUtility.normalised.x * scale), int( GoogleMapsUtility.normalised.y * scale) );

              return new Point( pixelCoords.x % GoogleMapsUtility.TILE_SIZE,

              pixelCoords.y % GoogleMapsUtility.TILE_SIZE );

              }

               

              public static function fromMercatorCoords( point:Point ):Point

              {

              point.x *= 360;

               

              point.y = GoogleMapsUtility.rad2deg( Math.atan( GoogleMapsUtility.sinh( point.y )) * Math.PI );

              return point;

              }

               

              public static function sinh( x:Number ):Number

              {

              return ((Math.exp(x) - Math.exp(-x)) / 2.0);

              }

               

              public static function rad2deg( rad:Number ):Number

              {

              return (rad * 180 / Math.PI);

              }

               

              public static function deg2rad( deg:Number ):Number

              {

              return (deg * Math.PI / 180);

              }

               

              public static function getPixelOffsetInTile( lat:Number, lng:Number, zoom:Number ):Point

              {

              pixelCoords = GoogleMapsUtility.toZoomedPixelCoords( lat, lng, zoom);

              return new Point( pixelCoords.x % GoogleMapsUtility.TILE_SIZE,

              pixelCoords.y % GoogleMapsUtility.TILE_SIZE );

              }

               

              public static function getTerminalPixelOffsetInTile( lat:Number, lng:Number, zoom:Number,

              rot:Number, len:Number ):Point

              {

              var endlng:Number = lng + ( len / ( 3 * 9500 )) * Math.cos( GoogleMapsUtility.deg2rad( rot ));

              var endlat:Number = lat + ( len / ( 3 * 9500 )) * Math.sin( GoogleMapsUtility.deg2rad( rot ));

              var newpt:Point = GoogleMapsUtility.getPixelOffsetInTile( endlng, endlat, zoom );

              return newpt;

              }

               

              public static function getTileRect( x:Number, y:Number, zoom:Number ):Rectangle

              {

              // CORRECT: What types to use here -- Number?

              var tilesAtThisZoom:Number = 1 << zoom;

              var lngWidth:Number = 360.0 / tilesAtThisZoom;

              var lng:Number = -180 + ( x *  lngWidth );

              var latHeight:Number = 2.0 / tilesAtThisZoom;

              var lat:Number = (( tilesAtThisZoom / 2 - y - 1 ) * latHeight );

               

              /** convert lat and latHeight to degrees in a transverse mercator projection

              * note that in fact the coordinates go from about -85 to +85 not -90 to 90! */

              latHeight += lat;

              latHeight = ( 2 * Math.atan( Math.exp( Math.PI * latHeight ))) - ( Math.PI / 2 );

              latHeight *= ( 180 / Math.PI );

              lat = ( 2 * Math.atan( Math.exp( Math.PI * lat ))) - ( Math.PI / 2 );

              lat *= ( 180 / Math.PI );

               

              latHeight -= lat;

               

              if ( lngWidth < 0 )

              {

              lng = lng + lngWidth;

              lngWidth = -lngWidth;

              }

               

              if ( latHeight < 0 )

              {

              lat = lat + latHeight;

              latHeight = -latHeight;

              }

               

              /**

              $latHeightMerc = 1.0 / $tilesAtThisZoom;

              $topLatMerc = $y * $latHeightMerc;

              $bottomLatMerc = $topLatMerc + $latHeightMerc;

               

              $bottomLat = (180 / M_PI) * ((2 * atan(exp(M_PI *

              (1 - (2 * $bottomLatMerc))))) - (M_PI / 2));

              $topLat = (180 / M_PI) * ((2 * atan(exp(M_PI *

              (1 - (2 * $topLatMerc))))) - (M_PI / 2));

               

              $latHeight = $topLat - $bottomLat;

              */

               

              return new Rectangle( lng, lat, lngWidth, latHeight );

              }

               

              public static function toMercatorCoords( lat:Number, lng:Number ):Point

              {

              if ( lng > 180 ) {

              lng -= 360;

              }

               

              lng /= 360;

              lat = GoogleMapsUtility.invhypsin( Math.tan( GoogleMapsUtility.deg2rad( lat ))) / Math.PI/2;

              /**$lat = 0.5 - ((log(tan((M_PI / 4) + ((0.5 * M_PI * $lat) / 180))) / M_PI) / 2.0);*/

              return new Point( lng, lat );

              }

               

              public static function toNormalisedMercatorCoords( point:Point, z:Number ):Point

              {

              point.x += 0.5;

              point.x *= z ^ 2;

              point.y = Math.abs( point.y - 0.5 );

              point.y *= z^2;

              return point;

              }

               

              public static function toZoomedPixelCoords( lat:Number, lng:Number, zoom:int ):Point

              {

              var pt:Point;

               

              pt = GoogleMapsUtility.toNormalisedMercatorCoords(

              GoogleMapsUtility.toMercatorCoords( lat,  lng ), zoom );

              GoogleMapsUtility.normalised.x = pt.x;

              GoogleMapsUtility.normalised.y = pt.y;

               

              GoogleMapsUtility.scale = ( 1 << ( zoom )) * GoogleMapsUtility.TILE_SIZE;

              return new Point( int( GoogleMapsUtility.normalised.x * GoogleMapsUtility.scale ), int( GoogleMapsUtility.normalised.y * scale ));

              }

               

              public static function invhypsin( z:Number ):Number {

              return Math.log( z + Math.sqrt( z^2 + 1 ));

              }

               

              }

              }