2011-03-10 2 views
3

안녕하세요. Google지도를 사용하는지도 애플리케이션이 있습니다. 나는 그 경계선을지도에서 벗어나서 그 근거로 일부 클러스터링 마커를하지만 같은 장소에 클러스터를 유지할 수 있도록하기 위해 통과하는 경계를 만드는 방법을 알고 싶습니다. 구글이 사용하는 타일 그리드. 내가 요구하고있어 그들이 본질적으로 자신의지도에 사용하는 쿼드 트리 알고리즘은 내가 뷰포트에있는 타일의 경계를 취득 할 방법줌 레벨 n에서 Google지도의 타일 크기를 계산합니다.

이다. 나는 그것을 설명하기 위해 노력했습니다 :) google tiles viewport cluster

뷰포트가 아닌 타일 경계에서 클러스터 계산을 수행 할 경우 그리드를 분할 할 때 그리드가 각 줌 레벨에서 절대적 일 때 클러스터가 같은 위치에 유지됩니다.

또한 바운드가 타일에 "스냅인"되어야 할 때 쿼리가 훨씬 비슷해지며 사용자가 근접 식으로 마커를 이미 표시 할 수있게되므로 더 나은 쿼리 캐싱을 허용합니다.

UPDATE 나는 그것을 다음과 같습니다 사용이

function TileMyBounds($sx, $sy, $nx, $ny, $zoom) 
{ 

     function TileMyBounds($sx, $sy, $nx, $ny, $zoom) 
{ 
    list($nmx,$nmy) = $this->LatLonToMeters($ny/1000000, $nx/1000000); 
    list($ntx, $nty) = $this->MetersToTile($nmx, $nmy, $zoom); 
    $nbounds = $this->TileLatLonBounds($ntx, $nty, $zoom); 
    list($smx,$smy) = $this->LatLonToMeters($sy/1000000, $sx/1000000); 
    list($stx, $sty) = $this->MetersToTile($smx, $smy, $zoom); 
    $sbounds = $this->TileLatLonBounds($stx, $sty, $zoom); 

    $step = ($sbounds[3]-$sbounds[1])*1000000; 

    return array($sbounds[0]*1000000, $sbounds[1]*1000000, $nbounds[2]*1000000, $nbounds[3]*1000000, $step); 
} 

과 기능이있어

내가 이상 시작하고

... :

function clusterGrid($zoom,$nelt,$nelg,$swlt,$swlg) 
    { 
    $singlemarkers = array(); 
    $clusters = array(); 

list($swlg, $swlt, $nelg, $nelt, $step) = $this->TileMyBounds($swlg, $swlt, $nelg, $nelt, $zoom); 
$calcbounds = $this->TileMyBounds($swlg, $swlt, $nelg, $nelt, $zoom); 
$queryconcat = ""; 
$length_lng = ceil(($nelg-$swlg)/$step); 
$length_lat = ceil(($nelt-$swlt)/$step); 
$orgnelg = $nelg; 
$orgswlt = $swlt; 

for($i=0;$i < $length_lng + 1; $i++) { 
    $nelg -= $step; 
    $temp_swlt = $swlt; 

    for($j=0; $j < $length_lat + 1; $j++) { 

     $temp_swlt += $step; 

     if($nelg > $orgnelg) continue; 
     if($temp_swlt > $nelt) continue; 
     if($nelg < $swlg) continue; 
     if($temp_swlt < $orgswlt) continue; 

     $q = $this->db->select(' 
      COUNT(*) AS CO, 
      (MAX(lat)+MIN(lat))/2 AS lat, 
      (MAX(lng)+MIN(lng))/2 AS lng') 
     ->where('`lat` BETWEEN '.$temp_swlt.' AND '.($temp_swlt+$step).' AND 
      `lng` BETWEEN '.($nelg-$step).' AND '.$nelg) 
     ->get('markers'); 
     $queryconcat += $this->db->last_query(); 
     $result = $q->row_array(); 

     if($result['CO'] == 0) { 
      continue; 
     } 
      $clusters[] = array('lat' => ($result['lat']), 'lng' => ($result['lng']), 'size' => $result['CO']); 
     } 
    } 
return array('singlemarkers' => '', 'clustermarkers' => $clusters, 'bounds' => $calcbounds, 'lengths' => array($length_lng, $length_lat)); 
} 

업데이트 !!!! 12/03/2011 - 거의 다 타일은 다소 정확하지만 전체적으로는 그렇지 않습니다. 따라서 주변을 패닝하면 클러스터가 조금 움직일 수 있습니다. 사실 $step = ($sbounds[3]-$sbounds[1])*1000000; 계산은 각 확대/축소 수준에서 항상 동일하지 않기 때문에 타일이 동일한 너비와 길이의 lat와 lon을 다른 모든 타일과 같은 크기로 확대한다고 생각하기 때문에 기대했던 것처럼 수평.

+0

안녕하세요 @ 야콥, Java로 구현하는 방법을 알고 있습니까? 정적 이미지 맵을 사용하여 사용자의 현재 위치를 표시하는 Android 애플리케이션을 개발 중입니다. 현재 뷰포트의 픽셀 좌표를 가져 오려면 지정된 줌 레벨에서 Google지도의 전체 크기를 알아야합니다. – eros

답변

1

하지만 뭔가 이상하지 않습니다. 아무도 내가 swlg, swlat, nelg, nelat와 줌 레벨에서 통과 할 때 나는 뷰포트 좌표를받지 못했습니다 이유를 말해 줄 수

당신은 4 개 경계 좌표로 먼저 공간 채움 곡선 방정식을 해결하려면 .

list($lng, $lat) = array ($row['lng'], $row['lat']); 
list($mx, $my) = $mercator->LatLonToMeters($lat, $lng); 
list($tx, $ty) = $mercator->MetersToTile($mx, $my, MAXZOOM); 
list($tx, $ty) = array ($tx, ((1 << MAXZOOM) - 1) - $ty); 
list($minx, $miny) = $this->PixelsToMeters($tx*$this->tileSize, $ty*$this->tileSize, $zoom); 
list($maxx, $maxy) = $this->PixelsToMeters(($tx+1)*$this->tileSize, ($ty+1)*$this->tileSize, $zoom); 
return array($minx, $miny, $maxx, $maxy); 

또는

list($lng, $lat) = array ($row['lng'], $row['lat']); 
list($mx, $my) = $mercator->LatLonToMeters($lat, $lng); 
list($tx, $ty) = $mercator->MetersToTile($mx, $my, MAXZOOM); 
list($tx, $ty) = array ($tx, ((1 << MAXZOOM) - 1) - $ty); 
$bounds = $this->TileBounds($tx, $ty, $zoom); 
list($minLat, $minLon) = $this->MetersToLatLon($bounds[0], $bounds[1]); 
list($maxLat, $maxLon) = $this->MetersToLatLon($bounds[2], $bounds[3]); 
return array($minLat, $minLon, $maxLat, $maxLon); 

EDIT : 문제는 해결된다. OP가 개인 메일로 대답했습니다 :

+0

@epitah - 왜 tilesize가 하나의 확대/축소 수준에서 다른 것처럼 보일지에 대한 단서가 있습니다. 타일에 논리가 없으면이 줄이 없어야합니다 : $ sbounds [2] - $ sbounds [0], 항상 줄 수 있습니다. 내가 계산 한 타일에 관계없이 동일한 줌 레벨에서 동일한 결과가 나타 납니까? – Jakob

+0

@epitah 원래 게시물에 대한 내 편집을 살펴 보시기 바랍니다. 조금만 수정하면됩니다. – Jakob

+0

@Jakob : 전자 메일로 보내 왔지만 오류로 보입니다.당신은 예를 살펴나요 : foreach는 (범위 ($ tminy $ 타이로, $의 tmaxy)) \t \t \t foreach는 (범위 ($ tminx, $ tmaxx)를 $로 TX)를 \t \t \t { \t \t \t \t $ quadtree = $ this-> QuadTree ($ tx, $ ty, $ zoom); \t \t \t \t \t \t \t \t $의 도착 [$ 쿼드 트리] = $ this-> TileLatLonBounds ($의 TX, $ 타이, $ 크게); \t \t \t} 그는 쿼드 트리를 사용하고 있습니다. – Bytemain

관련 문제