2011-09-06 238 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; 
}