Menghitung kotak pembatas dengan diberikan pusat dan skala di Android?

8

Mengingat kondisi ini:

  • skala seperti 1:50000
  • pusat viewport adalah 100°E, 20°N
  • ukuran viewport adalah 400x600

Bagaimana saya bisa menghitung kotak pembatas viewport?


Sistem koordinat geografis peta adalah EPSG: 4490.

Kami ingin menampilkannya dalam proyeksi berbeda seperti Mercator atau latitude_longitude_projection (mungkin ini yang dikatakan tidak diproyeksikan).

Ukuran viewport dalam piksel.

Giser
sumber
Proyeksi apa yang ada di peta Anda? Mercator Web? Atau apakah Anda menampilkan peta yang tidak diproyeksikan di lat / lon? Dan ukuran viewport Anda, apakah itu dalam piksel? Apakah skalanya dalam piels? Apakah Anda menggunakan kerangka pemetaan / pustaka yang mungkin memiliki fungsi untuk ini?
atlefren
Perangkat lunak dan versi GIS apa yang Anda gunakan untuk mencoba dan melakukan ini?
PolyGeo
@ atlefren: Saya meningkatkan posting.
Giser
@PolyGeo: Tidak ada, kami mencoba menampilkan data peta di android. Dan kami belum menemukan perpustakaan.
Giser
1
Android, apakah Anda menggunakan Google Maps API atau sekadar menampilkan gambar? Saya juga merekomendasikan untuk tidak menggunakan sistem koordinat yang tidak diproyeksikan untuk menampilkan peta Anda, karena akan terlihat sangat terdistorsi.
atlefren

Jawaban:

9

Ok, dengan beberapa masalah awal diselesaikan tugasnya relatif sederhana.

Skala, disajikan sebagai f.ex 1: 50000 berarti bahwa satu unit pada peta sesuai dengan 50.000 unit di dunia nyata.

Untuk peta kertas yang dicetak skala 1: 50000 ini berarti bahwa 1 meter pada peta setara dengan 50.000 meter di dunia nyata, atau untuk membuatnya lebih mudah: 1 cm pada peta setara dengan 50 meter di dunia nyata. Sejauh ini bagus.

Ketika komputer (atau layar ponsel) memasuki acara itu jauh lebih sulit: satuan ukuran pada layar adalah pixel, yang tidak memetakan langsung ke sentimeter. OpenLayers adalah (atau setidaknya di mana) menggunakan "Dots per inch", dan diasumsikan bahwa satu inci sesuai dengan 72 piksel (ini masuk akal pada layar 72 dpi, tetapi salah pada yaitu Retina Menampilkan. Tapi untuk sekarang, mari kita tetap berpegang pada 72 dpi (karena inilah yang dilakukan sebagian besar perpustakaan pemetaan (saya pikir, koreksi disambut)).

OpenLayers memiliki fungsi OpenLayers.Util.getResolutionFromScale (lihat sumber ):

OpenLayers.Util.getResolutionFromScale = function (scale, units) {
    var resolution;
    if (scale) {
        if (units == null) {
            units = "degrees";
        }
        var normScale = OpenLayers.Util.normalizeScale(scale);
        resolution = 1 / (normScale * OpenLayers.INCHES_PER_UNIT[units]
                                        * OpenLayers.DOTS_PER_INCH);
    }
    return resolution;
};
  • Dengan unit = "derajat" (yang EPSG: 4490 adalah, dari apa yang saya kumpulkan) kita mendapatkan inci_per unit = 4374754 (OpenLayers.INCHES_PER_UNIT ["derajat"])

  • skala 1: 50000 (yang sesuai dengan 1/50000 = 0,00002) (inilah yang menghitung penLayers.Util.normalizeScale) memberikan normScale = 0,00002

  • OpenLayers.DOTS_PER_INCH = 72

Kami kemudian dapat menghitung resolusi sebagai

1 / (0.00002 * 4374754 * 72) = 0.00015873908440210453

Mengetahui titik pusat (lon = 100, lat = 30), ukuran piksel viewport (w = 400, h = 600) dan resolusi kita kemudian dapat menggunakan fungsi calculBounds dari OpenLayers.Map (lihat sumber ):

calculateBounds: function(center, resolution) {

        var extent = null;

        if (center == null) {
            center = this.getCachedCenter();
        }
        if (resolution == null) {
            resolution = this.getResolution();
        }

        if ((center != null) && (resolution != null)) {
            var halfWDeg = (this.size.w * resolution) / 2;
            var halfHDeg = (this.size.h * resolution) / 2;

            extent = new OpenLayers.Bounds(center.lon - halfWDeg,
                                           center.lat - halfHDeg,
                                           center.lon + halfWDeg,
                                           center.lat + halfHDeg);
        }

        return extent;
    },

yang dapat kita kurangi menjadi:

function calculateBounds(center, resolution, size) {       
    var halfWDeg = (size.w * resolution) / 2;
    var halfHDeg = (size.h * resolution) / 2;
    return {
        "left": center.lon - halfWDeg,
        "bottom": center.lat - halfHDeg,
        "right": center.lon + halfWDeg,
        "top": center.lat + halfHDeg
    };
}

Menyebut ini dengan nilai-nilai kami memberi:

calculateBounds({"lon": 100, "lat": 30}, 0.00015873908440210453, {"w": 400, "h":600});
{ 
    left: 99.96825218311957, 
    bottom: 29.95237827467937,
    right: 100.03174781688043,
    top: 30.04762172532063
}

Kami kemudian dapat menggabungkan semua ini ke fungsi yang bekerja untuk derajat dengan penyebut skala yang diberikan:

function calculateBounds(center, scaleDenominator, size) {       
    var resolution = 1 / ((1 / scaleDenominator) * 4374754 * 72)
    var halfWDeg = (size.w * resolution) / 2;
    var halfHDeg = (size.h * resolution) / 2;
    return {
        "left": center.lon - halfWDeg,
        "bottom": center.lat - halfHDeg,
        "right": center.lon + halfWDeg,
        "top": center.lat + halfHDeg
    };
}
atlefren
sumber
Jawaban yang bagus Bahkan, tampaknya titik kunci di sini adalah dpinilainya. Bukan?
Giser
Oh, bagaimana dengan proyeksi? Tampaknya kode di atas digunakan untuk menghitung derajat secara langsung.
Giser
Ya itu benar. Selama pengguna Anda tidak berharap untuk menggunakan peta dengan cara yang sama seperti peta kertas (yaitu mengukurnya) nilai apa pun dapat digunakan (dan saya pikir sebagian besar perpustakaan pemetaan menggunakan 72 atau 96)
atlefren
satu-satunya hal yang perlu Anda ketahui tentang proyeksi adalah unitnya, OpenLayers menggunakan OpenLayers.INCHES_PER_UNIT [units] array di Utils.js. web mercator menggunakan meter sebagai unit, yang berarti 39,37 bukannya 4374754 untuk menghitung resolusi
atlefren
@atlerfren: Hai, sepertinya Anda adalah ahli openlayers, saya menemui beberapa masalah yang berkaitan dengannya. Bisakah Anda meluangkan waktu untuk melakukan checek pada posting ini? gis.stackexchange.com/q/61256/12681
giser