How to get bounds of a google static map?

后端 未结 5 1838
自闭症患者
自闭症患者 2020-12-05 01:07

How to get bounds in degrees of google static map which has been returned, for example, for following request

http://maps.googleapis.com/maps/api/staticmap?c         


        
5条回答
  •  一生所求
    2020-12-05 01:55

    Here is translation to Delphi/Pascal with some optimizations to correspond more strict Pascal language and memory management.

    unit Mercator.Google.Maps;
    
    interface
    
    uses System.Math;
    
    type TG_Point = class(TObject)
        private
            Fx: integer;
            Fy: integer;
        public
            property x: integer read Fx write Fx;
            property y: integer read Fy write Fy;
    
            constructor Create(Ax: integer = 0; Ay: integer = 0);
    end;
    
    type TG_LatLng = class(TObject)
        private
            FLat: double;
            FLng: double;
        public
            property Lat: double read FLat write FLat;
            property Lng: double read FLng write FLng;
    
            constructor Create(ALat: double; ALng: double);
    end;
    
    type TMercatorProjection = class(TObject)
        private
            pixelOrigin_: TG_Point;
            pixelsPerLonDegree_, pixelsPerLonRadian_: double;
    
            function degreesToRadians(deg: double): double;
            function radiansToDegrees(rad: double): double;
            function bound(value: double; opt_min: double; opt_max: double): double;
        public
            constructor Create;
            procedure fromLatLngToPoint(latLng: TG_LatLng; var point: TG_Point);
            procedure fromPointToLatLng(point: TG_point; var latLng: TG_LatLng);
            procedure getCorners(center: TG_LatLng; zoom: integer; mapWidth: integer; mapHeight: integer;
                                 var NELatLon: TG_LatLng; var SWLatLon: TG_LatLng);
    end;
    
    implementation
    
    const MERCATOR_RANGE = 256;
    
    constructor TG_Point.Create(Ax: Integer = 0; Ay: Integer = 0);
    begin
         inherited Create;
         Fx := Ax;
         Fy := Ay
    end;
    
    // **************
    
    constructor TG_LatLng.Create(ALat: double; ALng: double);
    begin
         inherited Create;
         FLat := ALat;
         FLng := ALng
    end;
    
    // **************
    
    constructor TMercatorProjection.Create;
    begin
        inherited Create;
    
        pixelOrigin_ := TG_Point.Create( Round(MERCATOR_RANGE / 2), Round(MERCATOR_RANGE / 2));
        pixelsPerLonDegree_ := MERCATOR_RANGE / 360;
        pixelsPerLonRadian_ := MERCATOR_RANGE / (2 * PI);
    end;
    
    // Translate degrees to radians
    function TMercatorProjection.degreesToRadians(deg: double): double;
    begin
      Result := deg * (PI / 180);
    end;
    
    // Translate radians to degrees
    function TMercatorProjection.radiansToDegrees(rad: double): double;
    begin
      Result := rad / (PI / 180);
    end;
    
    // keep value insid defined bounds
    function TMercatorProjection.bound(value: double; opt_min: double; opt_max: double): double;
    begin
      if Value < opt_min then Result := opt_min
      else if Value > opt_max then Result := opt_max
      else Result := Value;
    end;
    
    procedure TMercatorProjection.fromLatLngToPoint(latLng: TG_LatLng; var point: TG_Point);
    var
        siny: double;
    begin
       if Assigned(point) then
       begin
          point.x := Round(pixelOrigin_.x + latLng.lng * pixelsPerLonDegree_);
          // NOTE(appleton): Truncating to 0.9999 effectively limits latitude to
          // 89.189.  This is about a third of a tile past the edge of the world tile.
          siny := bound(sin(degreesToRadians(latLng.lat)), -0.9999, 0.9999);
          point.y := Round(pixelOrigin_.y + 0.5 * ln((1 + siny) / (1 - siny)) * -pixelsPerLonRadian_);
       end;
    end;
    
    procedure TMercatorProjection.fromPointToLatLng(point: TG_point; var latLng: TG_LatLng);
    var
        latRadians: double;
    begin
        if Assigned(latLng) then
        begin
          latLng.lng := (point.x - pixelOrigin_.x) / pixelsPerLonDegree_;
          latRadians := (point.y - pixelOrigin_.y) / -pixelsPerLonRadian_;
          latLng.lat := radiansToDegrees(2 * arctan(exp(latRadians)) - PI / 2);
        end;
    end;
    
    //pixelCoordinate = worldCoordinate * pow(2,zoomLevel)
    
    procedure TMercatorProjection.getCorners(center: TG_LatLng; zoom: integer; mapWidth: integer; mapHeight: integer;
                         var NELatLon: TG_LatLng; var SWLatLon: TG_LatLng);
    var
        scale: double;
        centerPx, SWPoint, NEPoint: TG_Point;
    begin
        scale := power(2, zoom);
    
        centerPx := TG_Point.Create(0, 0);
        try
            fromLatLngToPoint(center, centerPx);
            SWPoint := TG_Point.Create(Round(centerPx.x-(mapWidth/2)/scale), Round(centerPx.y+(mapHeight/2)/scale));
            NEPoint := TG_Point.Create(Round(centerPx.x+(mapWidth/2)/scale), Round(centerPx.y-(mapHeight/2)/scale));
            try
                fromPointToLatLng(SWPoint, SWLatLon);
                fromPointToLatLng(NEPoint, NELatLon);
            finally
                SWPoint.Free;
                NEPoint.Free;
            end;
        finally
            centerPx.Free;
        end;
    end;
    
    end.
    

    Usage example:

                with TMercatorProjection.Create do
                try
                    CLatLon := TG_LatLng.Create(Latitude, Longitude);
                    SWLatLon := TG_LatLng.Create(0,0);
                    NELatLon := TG_LatLng.Create(0,0);
                    try
                        getCorners(CLatLon, Zoom,
                                    MapWidth, MapHeight,
                                    SWLatLon, NELatLon);
                    finally
                        ShowMessage('SWLat='+FloatToStr(SWLatLon.Lat)+' | SWLon='+FloatToStr(SWLatLon.Lng));
                        ShowMessage('NELat='+FloatToStr(NELatLon.Lat)+' | NELon='+FloatToStr(NELatLon.Lng));
    
                        SWLatLon.Free;
                        NELatLon.Free;
                        CLatLon.Free;
                    end;
                finally
                    Free;
                end;
    

提交回复
热议问题