3

おい。Google マップを使用するマップ アプリケーションがあります。マップから境界を取得し、その根拠でいくつかのクラスタリング マーカーを実行しますが、クラスタを同じ場所にとどめるために、通過する境界をスナップする方法を知りたいです。 Google が使用するタイルグリッド。彼らがマップに使用する四分木アルゴリズムは、本質的に私が求めているものです

ビューポートがあるタイルの境界を取得するにはどうすればよいですか。説明しようとしました:) Google タイル ビューポート クラスタ

ビューポートではなくタイル境界でクラスター計算を行う場合、グリッドに分割すると、クラスターは同じ場所に留まります。これは、グリッドが各ズーム レベルで絶対的であるためです。

また、これにより、境界がタイルに「スナップ」する必要がある場合にクエリが非常に類似するため、クエリのキャッシュが改善され、ユーザーは既に表示されている近くのマーカーでパンできるようになります。

アップデート

私は最初からやり直しています...

私はこれを持っています

    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));  
}

アップデート!!!!2011 年 12 月 3 日 - ほぼ完成 タイルはある程度正確ですが、完全ではないため、パンするとクラスターが少し「動き回る」ことがあります。$step = ($sbounds[3]-$sbounds[1])*1000000;タイルの幅と長さは、同じズーム レベルの他のタイルと緯度と経度で同じであると考えられるため、期待したように、各ズーム レベルで計算が常に同じであるとは限らないためです。.

4

1 に答える 1

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

編集:問題は解決されました。OPはプライベートメールで回答しました:

于 2011-03-11T15:43:23.657 に答える