2012-09-20 23 views
12

गूगल स्थिर मानचित्र की डिग्री है, जो लौटा दिया गया है उदाहरण के लिए, अनुरोधGoogle स्थिर मानचित्र की सीमा कैसे प्राप्त करें?

http://maps.googleapis.com/maps/api/staticmap?center=0.0,0.0&zoom=10&size=640x640&sensor=false 

निम्नलिखित मुझे पता है के रूप में के लिए में सीमा कैसे प्राप्त करने के लिए, पूर्ण पृथ्वी नक्शा 256x256 छवि है। इसका मतलब है कि एन लंबवत पिक्सल में x डिग्री होती है, लेकिन क्षैतिज पिक्सल में 2x डिग्री होती है। सही?

Google says केंद्र मानचित्र के केंद्र को परिभाषित करता है, जो नक्शे के सभी किनारों से समतुल्य है। जैसा कि मैं पिक्सल में समतुल्य समझा (या डिग्री में?)। और प्रत्येक सफल ज़ूम स्तर दोनों क्षैतिज और लंबवत आयामों में परिशुद्धता को दोगुना करता है।

dLongitude = (HorizontalMapSizeInPixels/256) * (360/pow(2, zoom)); 

अक्षांश के लिए एक ही गणना: तो, मैं के रूप में प्रत्येक जूम मूल्य के लिए नक्शे के देशांतर के डेल्टा मूल्य मिल सकता है

dLatitude = (VerticalMapSizeInPixels/256) * (180/pow(2, zoom)); 

VerticalMapSizeInPixels और HorizontalMapSizeInPixels URL में नक्शे का आकार के मापदंडों हैं।

देशांतर के डेल्टा मूल्य की गणना करना अच्छा है, लेकिन अक्षांश के लिए यह गलत है। मुझे अक्षांश के डेल्टा मान नहीं मिल रहे हैं, कुछ डेल्टा त्रुटि है।

+0

की संभावित डुप्लिकेट http://stackoverflow.com/questions/4730885/how-do-i-get-the-bounds-of-a-static-google-map?rq=1 – j0nes

उत्तर

30

जैसा कि मुझे पता है, पूर्ण पृथ्वी मानचित्र 256x256 छवि है।

हां।

इसका मतलब है कि एन लंबवत पिक्सल में x डिग्री होती है, लेकिन n क्षैतिज पिक्सल में 2x डिग्री होती है। सही?

नहीं। एक पिक्सेल अक्षांश के आधार पर अक्षांश की विभिन्न मात्रा का प्रतिनिधित्व करेगा। भूमध्य रेखा पर एक पिक्सेल ध्रुवों के पास एक पिक्सेल से कम अक्षांश का प्रतिनिधित्व करता है।

मानचित्र के कोनों केंद्र, ज़ूम स्तर और मानचित्र आकार पर निर्भर होंगे, और आपको गणना करने के लिए मर्केटर प्रक्षेपण का उपयोग करना होगा। आप पूर्ण एपीआई लोड करने के लिए नहीं करना चाहती हैं, तो यहां मर्केटर प्रक्षेप वस्तु है:

var MERCATOR_RANGE = 256; 

function bound(value, opt_min, opt_max) { 
    if (opt_min != null) value = Math.max(value, opt_min); 
    if (opt_max != null) value = Math.min(value, opt_max); 
    return value; 
} 

function degreesToRadians(deg) { 
    return deg * (Math.PI/180); 
} 

function radiansToDegrees(rad) { 
    return rad/(Math.PI/180); 
} 

function MercatorProjection() { 
    this.pixelOrigin_ = new google.maps.Point(MERCATOR_RANGE/2, MERCATOR_RANGE/2); 
    this.pixelsPerLonDegree_ = MERCATOR_RANGE/360; 
    this.pixelsPerLonRadian_ = MERCATOR_RANGE/(2 * Math.PI); 
}; 

MercatorProjection.prototype.fromLatLngToPoint = function(latLng, opt_point) { 
    var me = this; 

    var point = opt_point || new google.maps.Point(0, 0); 

    var origin = me.pixelOrigin_; 
    point.x = origin.x + latLng.lng() * me.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. 
    var siny = bound(Math.sin(degreesToRadians(latLng.lat())), -0.9999, 0.9999); 
    point.y = origin.y + 0.5 * Math.log((1 + siny)/(1 - siny)) * -me.pixelsPerLonRadian_; 
    return point; 
}; 

MercatorProjection.prototype.fromPointToLatLng = function(point) { 
    var me = this; 

    var origin = me.pixelOrigin_; 
    var lng = (point.x - origin.x)/me.pixelsPerLonDegree_; 
    var latRadians = (point.y - origin.y)/-me.pixelsPerLonRadian_; 
    var lat = radiansToDegrees(2 * Math.atan(Math.exp(latRadians)) - Math.PI/2); 
    return new google.maps.LatLng(lat, lng); 
}; 

//pixelCoordinate = worldCoordinate * Math.pow(2,zoomLevel) 

आप एक अलग फाइल करने के लिए कि बचा सकता है उदाहरण के लिए "MercatorProjection.js", और फिर अपने आवेदन में यह भी शामिल है।

<script src="MercatorProjection.js"></script> 
ऊपर लोड फ़ाइल के साथ

, निम्नलिखित समारोह दिए गए आकार के और किसी दिए गए ज़ूम पर एक नक्शे के दप और पूर्वोत्तर कोने गणना करता है।

function getCorners(center,zoom,mapWidth,mapHeight){ 
    var scale = Math.pow(2,zoom); 
    var centerPx = proj.fromLatLngToPoint(center); 
    var SWPoint = {x: (centerPx.x -(mapWidth/2)/ scale) , y: (centerPx.y + (mapHeight/2)/ scale)}; 
    var SWLatLon = proj.fromPointToLatLng(SWPoint); 
    alert('SW: ' + SWLatLon); 
    var NEPoint = {x: (centerPx.x +(mapWidth/2)/ scale) , y: (centerPx.y - (mapHeight/2)/ scale)}; 
    var NELatLon = proj.fromPointToLatLng(NEPoint); 
    alert(' NE: '+ NELatLon); 
} 

और आप इसे इस तरह से फोन चाहते हैं:

var proj = new MercatorProjection(); 
var G = google.maps; 
var centerPoint = new G.LatLng(49.141404, -121.960988); 
var zoom = 10; 
getCorners(centerPoint,zoom,640,640); 
+0

कितना सटीक है इस? मैंने इसे जावा में पोर्ट किया, मुझे कहना होगा कि मैं इसके साथ वास्तव में खुश हूं! मैं केवल कुछ मीटर हूँ। मुझे आश्चर्य है कि क्या यह एल्गोरिदम है या मैं गलती कर रहा हूं। कुछ कारणों से मुझे 2.0 के साथ कॉर्नर्स में कई पैमाने पर होना था, जहां सीमाएं बड़ी थीं। – clankill3r

+0

समझ गया कि मुझे आकार = 1024x1024 के साथ अनुरोध था। इसने मुझे 1080x1080 की एक छवि दी जो मुझे पता नहीं था! तो मैंने एक छोटे से क्षेत्र की जांच कर सीमा तय की। एक छोटे से क्षेत्र में परिणाम ... – clankill3r

+0

अरे @marcelo, मुझे आपके कोड के साथ सी # में अनुवाद करने में समस्या है। समस्या पर अधिक जानकारी [यहां] (http://stackoverflow.com/questions/37008037/get-sw-ne-corners-of-google-static-maps-api) – Leniaal

2

यहाँ PHP में मार्सेलो के कोड है, जो शायद थोड़ा साफ किया जा सकता की लाइन अनुवाद द्वारा एक पंक्ति है। बहुत अच्छा काम करता है! कठिन भाग करने के लिए मार्सेलो के लिए धन्यवाद।

define("MERCATOR_RANGE", 256); 

function degreesToRadians($deg) { 
    return $deg * (M_PI/180); 
} 

function radiansToDegrees($rad) { 
    return $rad/(M_PI/180); 
} 

function bound($value, $opt_min, $opt_max) { 
    if ($opt_min != null) $value = max($value, $opt_min); 
    if ($opt_max != null) $value = min($value, $opt_max); 
    return $value; 
} 

class G_Point { 
    public $x,$y; 
    function G_Point($x=0, $y=0){ 
     $this->x = $x; 
     $this->y = $y; 
    } 
} 

class G_LatLng { 
    public $lat,$lng; 
    function G_LatLng($lt, $ln){ 
     $this->lat = $lt; 
     $this->lng = $ln; 
    } 
} 

class MercatorProjection { 

    private $pixelOrigin_, $pixelsPerLonDegree_, $pixelsPerLonRadian_; 

    function MercatorProjection() { 
     $this->pixelOrigin_ = new G_Point(MERCATOR_RANGE/2, MERCATOR_RANGE/2); 
     $this->pixelsPerLonDegree_ = MERCATOR_RANGE/360; 
     $this->pixelsPerLonRadian_ = MERCATOR_RANGE/(2 * M_PI); 
    } 

    public function fromLatLngToPoint($latLng, $opt_point=null) { 
     $me = $this; 

     $point = $opt_point ? $opt_point : new G_Point(0,0); 

     $origin = $me->pixelOrigin_; 
     $point->x = $origin->x + $latLng->lng * $me->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 = $origin->y + 0.5 * log((1 + $siny)/(1 - $siny)) * -$me->pixelsPerLonRadian_; 
     return $point; 
    } 

    public function fromPointToLatLng($point) { 
     $me = $this; 

     $origin = $me->pixelOrigin_; 
     $lng = ($point->x - $origin->x)/$me->pixelsPerLonDegree_; 
     $latRadians = ($point->y - $origin->y)/-$me->pixelsPerLonRadian_; 
     $lat = radiansToDegrees(2 * atan(exp($latRadians)) - M_PI/2); 
     return new G_LatLng($lat, $lng); 
    } 

    //pixelCoordinate = worldCoordinate * pow(2,zoomLevel) 
} 

function getCorners($center, $zoom, $mapWidth, $mapHeight){ 
    $scale = pow(2, $zoom); 
    $proj = new MercatorProjection(); 
    $centerPx = $proj->fromLatLngToPoint($center); 
    $SWPoint = new G_Point($centerPx->x-($mapWidth/2)/$scale, $centerPx->y+($mapHeight/2)/$scale); 
    $SWLatLon = $proj->fromPointToLatLng($SWPoint); 
    $NEPoint = new G_Point($centerPx->x+($mapWidth/2)/$scale, $centerPx->y-($mapHeight/2)/$scale); 
    $NELatLon = $proj->fromPointToLatLng($NEPoint); 
    return array(
     'N' => $NELatLon->lat, 
     'E' => $NELatLon->lng, 
     'S' => $SWLatLon->lat, 
     'W' => $SWLatLon->lng, 
    ); 
} 

उपयोग:

$centerLat = 49.141404; 
$centerLon = -121.960988; 
$zoom = 10; 
$mapWidth = 640; 
$mapHeight = 640; 
$centerPoint = new G_LatLng($centerLat, $centerLon); 
$corners = getCorners($centerPoint, $zoom, $mapWidth, $mapHeight); 
$mapURL = "http://maps.googleapis.com/maps/api/staticmap?center={$centerLat},{$centerLon}&zoom={$zoom}&size={$mapWidth}x{$mapHeight}&scale=2&maptype=roadmap&sensor=false"; 
12

अपने जवाब के लिए धन्यवाद मार्सेलो। यह काफी मददगार रहा है।

from __future__ import division 
import math 
MERCATOR_RANGE = 256 

def bound(value, opt_min, opt_max): 
    if (opt_min != None): 
    value = max(value, opt_min) 
    if (opt_max != None): 
    value = min(value, opt_max) 
    return value 


def degreesToRadians(deg) : 
    return deg * (math.pi/180) 


def radiansToDegrees(rad) : 
    return rad/(math.pi/180) 


class G_Point : 
    def __init__(self,x=0, y=0): 
     self.x = x 
     self.y = y 



class G_LatLng : 
    def __init__(self,lt, ln): 
     self.lat = lt 
     self.lng = ln 


class MercatorProjection : 


    def __init__(self) : 
     self.pixelOrigin_ = G_Point(MERCATOR_RANGE/2, MERCATOR_RANGE/2) 
     self.pixelsPerLonDegree_ = MERCATOR_RANGE/360 
     self.pixelsPerLonRadian_ = MERCATOR_RANGE/(2 * math.pi) 


    def fromLatLngToPoint(self, latLng, opt_point=None) : 
     point = opt_point if opt_point is not None else G_Point(0,0) 
     origin = self.pixelOrigin_ 
     point.x = origin.x + latLng.lng * self.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(math.sin(degreesToRadians(latLng.lat)), -0.9999, 0.9999) 
     point.y = origin.y + 0.5 * math.log((1 + siny)/(1 - siny)) * -  self.pixelsPerLonRadian_ 
     return point 


def fromPointToLatLng(self,point) : 
     origin = self.pixelOrigin_ 
     lng = (point.x - origin.x)/self.pixelsPerLonDegree_ 
     latRadians = (point.y - origin.y)/-self.pixelsPerLonRadian_ 
     lat = radiansToDegrees(2 * math.atan(math.exp(latRadians)) - math.pi/2) 
     return G_LatLng(lat, lng) 

#pixelCoordinate = worldCoordinate * pow(2,zoomLevel) 

def getCorners(center, zoom, mapWidth, mapHeight): 
    scale = 2**zoom 
    proj = MercatorProjection() 
    centerPx = proj.fromLatLngToPoint(center) 
    SWPoint = G_Point(centerPx.x-(mapWidth/2)/scale, centerPx.y+(mapHeight/2)/scale) 
    SWLatLon = proj.fromPointToLatLng(SWPoint) 
    NEPoint = G_Point(centerPx.x+(mapWidth/2)/scale, centerPx.y-(mapHeight/2)/scale) 
    NELatLon = proj.fromPointToLatLng(NEPoint) 
    return { 
     'N' : NELatLon.lat, 
     'E' : NELatLon.lng, 
     'S' : SWLatLon.lat, 
     'W' : SWLatLon.lng, 
    } 

उपयोग::

>>> import MercatorProjection 
>>> centerLat = 49.141404 
>>> centerLon = -121.960988 
>>> zoom = 10 
>>> mapWidth = 640 
>>> mapHeight = 640 
>>> centerPoint = MercatorProjection.G_LatLng(centerLat, centerLon) 
>>> corners = MercatorProjection.getCorners(centerPoint, zoom, mapWidth, mapHeight) 
>>> corners 
{'E': -65.710988, 
'N': 74.11120692972199, 
'S': 0.333879313530149, 
'W': -178.210988} 
>>> mapURL = "http://maps.googleapis.com/maps/api/staticmap?center=%f,%f&zoom=%d&size=%dx%d&scale=2&maptype=roadmap&sensor=false"%(centerLat,centerLon,zoom,mapWidth,mapHeight) 
>>> mapURL 
http://maps.googleapis.com/maps/api/staticmap?center=49.141404,-121.960988&zoom=10&size=640x640&scale=2&maptype=roadmap&sensor=false' 
+2

छोटी गाड़ी: ज़ूम को 2 ** स्केल के रूप में परिभाषित किया जाना चाहिए, 2^स्केल नहीं जो कि 2 और स्केल के बीच थोड़ा सा एक्सओआर है – jmague

0

यहाँ मामले में किसी को भी रुचि रखते हैं, यहां अजगर कोड का संस्करण (PHP कोड का एक मोटा अनुवाद, शायद नहीं के रूप में pythonic यह हो सकता है के रूप में) होगा कुछ अनुकूलन के साथ डेल्फी/पास्कल में अनुवाद अधिक कठोर पास्कल भाषा और स्मृति प्रबंधन से मेल खाता है।

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. 

प्रयोग उदाहरण:

  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; 
0

बड़ा जूम कारकों के लिए (> = 8), जहां नक्शा पैमाने y अक्ष पर की गैर एकरूपता उपेक्षित किया जा सकता है, वहाँ बहुत आसान तरीका है, जहां हम सिर्फ पिक्सेल/(अक्षांश की डिग्री) संकल्प के लिए accout 1/cos (अक्षांश) सुधार में लेता है। ज़ूम = 0 के लिए प्रारंभिक संकल्प x और y के लिए 0 अक्षांश पर 360 डिग्री प्रति 360 डिग्री पिक्सेल है।

def get_static_map_bounds(lat, lng, zoom, sx, sy): 
    # lat, lng - center 
    # sx, sy - map size in pixels 

    # 256 pixels - initial map size for zoom factor 0 
    sz = 256 * 2 ** zoom 

    #resolution in degrees per pixel 
    res_lat = cos(lat * pi/180.) * 360./sz 
    res_lng = 360./sz 

    d_lat = res_lat * sy/2 
    d_lng = res_lng * sx/2 

    return ((lat-d_lat, lng-d_lng), (lat+d_lat, lng+d_lng))