2011-09-06 136 views
12

我在v3 api上繪製了一個Google Maps Circle。當用戶在那裏繪製圓圈(或者如果他們選擇了多邊形),他們可以將數據保存到服務器。如果用戶選擇了徑向搜索,則將中心座標和以英尺爲單位的半徑存儲到數據庫中。這意味着當用戶重新加載搜索時,它可以再次通過圓圈(如下圖)。繪製圓圈Google靜態地圖

Example of load

我有1點的問題,但是,當用戶選擇搜索什麼,他們想用它。如果多邊形繪製了多邊形,它會加載多邊形,如果它是一個圓形,則會穿過中心的標記。然而,我需要的是靜態地圖中的一個函數來繪製一個圓。

+0

的[是否可以畫一個圓谷歌的靜態地圖上?]可能重複(http://stackoverflow.com/questions/3766710/is-它,可能對拉一個圓上-A-谷歌靜態地圖) –

回答

22

有點在遊戲後期,但沒有我發現解決了我的問題(服務器端PHP只,沒有的JavaScript)。 我最終到了那裏,並在這裏詳細說明了我的方法:http://jomacinc.com/map-radius/,簡短版本如下。

這個PHP函數將在繞指定點了一圈返回的緯度/經度點編碼折線串,並在指定的半徑。該功能需要Gabriel Svennerberg的PHP折線編碼類(http://www.svennerberg.com/examples/polylines/PolylineEncoder.php.txt)。

function GMapCircle($Lat,$Lng,$Rad,$Detail=8){ 
$R = 6371; 

$pi = pi(); 

$Lat = ($Lat * $pi)/180; 
$Lng = ($Lng * $pi)/180; 
$d = $Rad/$R; 

$points = array(); 
$i = 0; 

for($i = 0; $i <= 360; $i+=$Detail): 
    $brng = $i * $pi/180; 

    $pLat = asin(sin($Lat)*cos($d) + cos($Lat)*sin($d)*cos($brng)); 
    $pLng = (($Lng + atan2(sin($brng)*sin($d)*cos($Lat), cos($d)-sin($Lat)*sin($pLat))) * 180)/$pi; 
    $pLat = ($pLat * 180) /$pi; 

    $points[] = array($pLat,$pLng); 
endfor; 

require_once('PolylineEncoder.php'); 
$PolyEnc = new PolylineEncoder($points); 
$EncString = $PolyEnc->dpEncode(); 

return $EncString['Points']; 
} 

現在,您可以使用上面的函數來創建靜態地圖。

/* set some options */ 
$MapLat    = '-42.88188'; // latitude for map and circle center 
$MapLng    = '147.32427'; // longitude as above 
$MapRadius = 100;         // the radius of our circle (in Kilometres) 
$MapFill   = 'E85F0E';    // fill colour of our circle 
$MapBorder = '91A93A';    // border colour of our circle 
$MapWidth  = 640;         // map image width (max 640px) 
$MapHeight = 480;         // map image height (max 640px) 

/* create our encoded polyline string */ 
$EncString = GMapCircle($MapLat,$MapLng, $MapRadius); 

/* put together the static map URL */ 
$MapAPI = 'http://maps.google.com.au/maps/api/staticmap?'; 
$MapURL = $MapAPI.'center='.$MapLat.','.$MapLng.'&size='.$MapWidth.'x'.$MapHeight.'&maptype=roadmap&path=fillcolor:0x'.$MapFill.'33%7Ccolor:0x'.$MapBorder.'00%7Cenc:'.$EncString.'&sensor=false'; 

/* output an image tag with our map as the source */ 
echo '<img src="'.$MapURL.'" />' 
+1

歡迎來到Stack Overflow!雖然這可能在理論上回答這個問題,[這將是更可取的](http://meta.stackexchange.com/q/8259)在這裏包括答案的重要部分,並提供供參考的鏈接。 –

+0

@jomac必須承認,一個很好的選擇,請遵循Shawn Chin的建議,並將PHP代碼和解釋發佈在您的答案上以供將來參考! – rickyduck

+1

謝謝你們,我已經擴大了我的答案。 – Jomac

2

我認爲這是不可能得出一個靜態的谷歌地圖上的圓圈。您需要通過折線來近似圓形(最好在encoded format)。這已經在Stackoverflow中提到過,並且它已經被證明是例如通過Free Map Tools

+0

感謝您的鏈接,我正要下去拉與多邊形圓的路線,但想着,也許這太過分了。第二個鏈接不幸的是API2。再次感謝 – rickyduck

+1

「谷歌靜態地圖API V2」是不是「谷歌地圖API V2/V3」的一部分,它是一個獨立的 API。因此它也可用於Google Maps API v3。在免費地圖工具中,您可以使用近似圓圈生成靜態地圖。您可以從Google Maps API v3生成相同的格式。 – Jiri

+0

對不起,我會看看我能做些什麼,並在完成後發佈代碼。 – rickyduck

8
function GMapCircle(lat,lng,rad,detail=8){ 

var uri = 'https://maps.googleapis.com/maps/api/staticmap?'; 
var staticMapSrc = 'center=' + lat + ',' + lng; 
staticMapSrc += '&size=100x100'; 
staticMapSrc += '&path=color:0xff0000ff:weight:1'; 

var r = 6371; 

var pi = Math.PI; 

var _lat = (lat * pi)/180; 
var _lng = (lng * pi)/180; 
var d = (rad/1000)/r; 

var i = 0; 

for(i = 0; i <= 360; i+=detail) { 
    var brng = i * pi/180; 

    var pLat = Math.asin(Math.sin(_lat) * Math.cos(d) + Math.cos(_lat) * Math.sin(d) * Math.cos(brng)); 
    var pLng = ((_lng + Math.atan2(Math.sin(brng) * Math.sin(d) * Math.cos(_lat), Math.cos(d) - Math.sin(_lat) * Math.sin(pLat))) * 180)/pi; 
    pLat = (pLat * 180)/pi; 

    staticMapSrc += "|" + pLat + "," + pLng; 
} 

return uri + encodeURI(staticMapSrc);} 

的Javascript

+0

難以置信的有用的! – iulial

+0

在這個版本中,'rad'以米爲單位。 – Azmisov

+0

有可能填補這個圈子? – MadeInMoon

2

版本基礎上answer from Jomac,下面是相同的代碼的一個Java/Android版本。

它使用PolyUtil類從Google Maps Android API Utility Library編碼的路徑。

import android.location.Location; 

import com.google.android.gms.maps.model.LatLng; 
import com.google.maps.android.PolyUtil; 

import java.util.ArrayList; 

public class GoogleStaticMapsAPIServices 
{ 
    private static final double EARTH_RADIUS_KM = 6371; 

    private static String GOOGLE_STATIC_MAPS_API_KEY = "XXXXXXXXXXXXX"; 

    public static String getStaticMapURL(Location location, int radiusMeters) 
    { 
     String pathString = ""; 
     if (radiusMeters > 0) 
     { 
      // Add radius path 
      ArrayList<LatLng> circlePoints = getCircleAsPolyline(location, radiusMeters); 

      if (circlePoints.size() > 0) 
      { 
       String encodedPathLocations = PolyUtil.encode(circlePoints); 
       pathString = "&path=color:0x0000ffff%7Cweight:1%7Cfillcolor:0x0000ff80%7Cenc:" + encodedPathLocations; 
      } 
     } 

     String staticMapURL = "https://maps.googleapis.com/maps/api/staticmap?size=640x320&markers=color:red%7C" + 
       location.getLatitude() + "," + location.getLongitude() + 
       pathString + 
       "&key=" + GOOGLE_STATIC_MAPS_API_KEY; 

     return staticMapURL; 
    } 

    private static ArrayList<LatLng> getCircleAsPolyline(Location center, int radiusMeters) 
    { 
     ArrayList<LatLng> path = new ArrayList<>(); 

     double latitudeRadians = center.getLatitude() * Math.PI/180.0; 
     double longitudeRadians = center.getLongitude() * Math.PI/180.0; 
     double radiusRadians = radiusMeters/1000.0/EARTH_RADIUS_KM; 

     double calcLatPrefix = Math.sin(latitudeRadians) * Math.cos(radiusRadians); 
     double calcLatSuffix = Math.cos(latitudeRadians) * Math.sin(radiusRadians); 

     for (int angle = 0; angle < 361; angle += 10) 
     { 
      double angleRadians = angle * Math.PI/180.0; 

      double latitude = Math.asin(calcLatPrefix + calcLatSuffix * Math.cos(angleRadians)); 
      double longitude = ((longitudeRadians + Math.atan2(Math.sin(angleRadians) * Math.sin(radiusRadians) * Math.cos(latitudeRadians), Math.cos(radiusRadians) - Math.sin(latitudeRadians) * Math.sin(latitude))) * 180)/Math.PI; 
      latitude = latitude * 180.0/Math.PI; 

      path.add(new LatLng(latitude, longitude)); 
     } 

     return path; 
    } 
} 
+0

這個答案值得更多的選票,因爲它爲所有變量使用明確的名稱,它有助於很多在理解那些初始的'r','d'和'brng'變量實際代表什麼。 –

0

分享我的C#版本

private string GMapCircle(double lat, double lng, double rad, int detail = 8) 
{ 
    const string uri = "https://maps.googleapis.com/maps/api/staticmap?"; 
    var staticMapSrc = "center=" + lat + "," + lng; 
    staticMapSrc += "&zoom=16"; 
    staticMapSrc += "&maptype=satellite"; 
    staticMapSrc += "&key=[YOURKEYHERE]"; 
    staticMapSrc += "&size=640x426"; 
    staticMapSrc += "&path=color:0xff0000ff:weight:1"; 

    const int r = 6371; 
    const double pi = Math.PI; 

    var latAux = (lat * pi)/180; 
    var longAux = (lng * pi)/180; 
    var d = (rad/1000)/r; 

    var i = 0; 

    if (rad > 0) 
    { 
     for (i = 0; i <= 360; i += detail) 
     { 
      var brng = i * pi/180; 

      var pLat = Math.Asin(Math.Sin(latAux) * Math.Cos(d) + Math.Cos(latAux) * Math.Sin(d) * Math.Cos(brng)); 
      var pLng = ((longAux + Math.Atan2(Math.Sin(brng) * Math.Sin(d) * Math.Cos(latAux), Math.Cos(d) - Math.Sin(latAux) * Math.Sin(pLat))) * 180)/pi; 
      pLat = (pLat * 180)/pi; 

      staticMapSrc += "|" + pLat + "," + pLng; 
     } 
    } 
    else 
    { 
     //TODO - Add marker 
    } 

    return uri + staticMapSrc; 
}