Cara menghitung tingkat zoom optimal untuk menampilkan dua atau lebih titik pada peta

11

Kami ingin menampilkan beberapa penanda pada peta statis dan ingin menghitung tingkat zoom optimal seperti yang dilakukan Google Maps. Kami sudah menghitung persegi panjang pembatas dan titik tengah peta tapi sekarang kami kesulitan menghitung tingkat zoom yang benar untuk menampilkan seluruh persegi panjang pembatas. Bisakah seseorang tolong tunjukkan kami ke arah yang benar?

Tobias Schwarz
sumber
Ini tidak terlalu canggih, tetapi mengapa tidak melipatgandakan MBR sebesar 120% dan memperbesarnya? Ada lagi yang tergantung pada definisi Anda tentang "optimal", bukan?
ThomM
Memberi +1 pada gagasan ThomM. Inilah yang dilakukan ArcGIS.
Ragi Yaser Burhum
1
Maaf, apa MBR ini?
Rodrigo

Jawaban:

4

Untuk mendapatkan tingkat pembesaran, Anda harus mengetahui dimensi piksel peta Anda. Anda juga perlu melakukan matematika Anda dalam koordinat mercator bola.

  1. Konversi lintang, bujur ke mercator bola x, y.
  2. Dapatkan jarak antara dua titik Anda dalam mercator bola.
  3. Ekuator sekitar 40m meter panjangnya diproyeksikan dan ubin berukuran 256 piksel, sehingga panjang piksel peta itu pada tingkat zoom yang diberikan sekitar 256 * jarak / 40000000 * 2 ^ zoom . Coba zoom = 0, zoom = 1, zoom = 2 hingga jarak terlalu panjang untuk dimensi piksel peta Anda.
Michal Migurski
sumber
1
Berharap saya sudah jauh memahami apa yang sebenarnya Anda tanyakan. = \
Michal Migurski
Menemukan pertanyaan ini sambil mencari jawaban ini, terima kasih.
BenjaminGolder
@MichalMigurski dapatkah Anda menjelaskan bagaimana cara menghitung jarak antara 2 titik dalam mercator bola khususnya koordinat x ... saya terhenti terima kasih.
otmezger
4

Ini adalah kode C # yang saya gunakan di Maperitive :

    public void ZoomToArea (Bounds2 mapArea, float paddingFactor)
    {
        double ry1 = Math.Log((Math.Sin(GeometryUtils.Deg2Rad(mapArea.MinY)) + 1) 
            / Math.Cos(GeometryUtils.Deg2Rad(mapArea.MinY)));
        double ry2 = Math.Log((Math.Sin(GeometryUtils.Deg2Rad(mapArea.MaxY)) + 1) 
            / Math.Cos(GeometryUtils.Deg2Rad(mapArea.MaxY)));
        double ryc = (ry1 + ry2) / 2;
        double centerY = GeometryUtils.Rad2Deg(Math.Atan(Math.Sinh(ryc)));

        double resolutionHorizontal = mapArea.DeltaX / Viewport.Width;

        double vy0 = Math.Log(Math.Tan(Math.PI*(0.25 + centerY/360)));
        double vy1 = Math.Log(Math.Tan(Math.PI*(0.25 + mapArea.MaxY/360)));
        double viewHeightHalf = Viewport.Height/2.0f;
        double zoomFactorPowered = viewHeightHalf
            / (40.7436654315252*(vy1 - vy0));
        double resolutionVertical = 360.0 / (zoomFactorPowered * 256);

        double resolution = Math.Max(resolutionHorizontal, resolutionVertical) 
            * paddingFactor;
        double zoom = Math.Log(360 / (resolution * 256), 2);
        double lon = mapArea.Center.X;
        double lat = centerY;

        CenterMapOnPoint(new PointD2(lon, lat), zoom);
    }
  • mapArea: kotak pembatas dalam koordinat panjang / lat (x = panjang, y = lat)
  • paddingFactor: ini dapat digunakan untuk mendapatkan efek "120%" yang dirujuk oleh ThomM. Nilai 1,2 akan memberi Anda 120%.

Perhatikan bahwa dalam kasus saya zoomdapat berupa bilangan real. Dalam kasus peta Web, Anda memerlukan nilai zoom integer, jadi Anda harus menggunakan sesuatu seperti (int)Math.Floor(zoom)untuk mendapatkannya.

Tentu saja, kode ini hanya berlaku untuk proyeksi Web Mercator.

Igor Brejc
sumber
1
Terima kasih untuk ini. Apakah kode untuk CenterMapOnPoint tersedia?
mcintyre321
Sempurna! Saya telah menggunakan ini untuk menghitung zoom BoundingBox di OsmDroid SDK dan berfungsi :)
Billda
Di mana saya menemukan perpustakaan ini? Saya tidak dapat menemukan kumpulan GeometryUtils atau Bounds2. Apakah saya perlu mengunduh sesuatu dari maperitive? Saya hanya melihat aplikasi di sana.
Dowlers
@Dowlers GeometryUtilshanya digunakan di sini untuk mengubah derajat ke radian dan kembali, itu adalah rumus matematika sederhana. Bounds2pada dasarnya hanya struktur persegi panjang. Kode ini diberikan lebih sebagai pseudocode daripada sesuatu yang langsung dapat disalin.
Igor Brejc
Ahh menangkapmu. Saya harus mengakui bahwa setelah saya mengajukan pertanyaan, saya mencari-cari aplikasi maperitive dan menemukan .dlls yang saya butuhkan. Tapi saya perhatikan batasan lisensi jadi saya pergi ke rute lain. Saya menggunakan kode dari artikel ini sebagai gantinya: rbrundritt.wordpress.com/2009/07/21/…
Dowlers
1

Jika Anda menggunakan OpenLayers maka Map.getZoomForExtentakan menghitung level zoom tertinggi yang dapat memenuhi seluruh tingkat di peta. The extentkebutuhan untuk berada di proyeksi peta ini. Anda juga dapat menggunakan a fill_factoruntuk menghindari menampilkan titik di tepi peta, dan max_zoomuntuk membatasi kemungkinan zoom:

extent = extent.scale(1/fill_ratio);
var zoom = Math.min(map.getZoomForExtent(map_extent), max_zoom);
map.setCenter(extent.getCenterLonLat(), zoom);
Alex Morega
sumber
ini tidak memperbaiki masalah saya, tetapi itu menuntun saya untuk menemukan metode fitBounds Leaflet, yang menyelamatkan hari saya.
SamuelDev