Tính hộp giới hạn theo trung tâm và tỷ lệ nhất định trong Android?


8

Đưa ra các điều kiện sau:

  • một quy mô như 1:50000
  • trung tâm của khung nhìn là 100°E, 20°N
  • kích thước của khung nhìn là 400x600

Làm cách nào để tính hộp giới hạn của khung nhìn?


Hệ tọa độ địa lý của bản đồ là EPSG: 4490.

Chúng tôi muốn hiển thị chúng trong một phép chiếu khác nhau như Mercator hoặc latitude_longitude_projection (có thể đây là dự án chưa được nói).

Kích thước của khung nhìn được tính bằng pixel.


Bản đồ của bạn là gì? Web Mercator? Hay bạn hiển thị một bản đồ chưa được cung cấp trong lat / lon? Và kích thước của khung nhìn của bạn, đó có phải là pixel không? Là quy mô trong piels? Bạn có sử dụng bất kỳ khung / thư viện ánh xạ nào có thể có chức năng này không?
atlefren

Phần mềm và phiên bản GIS nào bạn đang sử dụng để thử và làm điều này?
PolyGeo

@atlefren: Tôi upadte bài viết.
Giser

@PolyGeo: Không, chúng tôi đã cố gắng hiển thị dữ liệu bản đồ trong Android. Và chúng tôi không tìm thấy bất kỳ thư viện.
Giser

1
Android, bạn đang sử dụng API Google Maps hay chỉ hiển thị hình ảnh đơn giản? Tôi cũng khuyên bạn không nên sử dụng hệ thống tọa độ chưa được cung cấp để hiển thị bản đồ của mình, vì nó sẽ bị biến dạng nặng nề.
atlefren

Câu trả lời:


9

Ok, với một số vấn đề ban đầu đã xóa nhiệm vụ tương đối đơn giản.

Tỷ lệ, được đặt trước là f.ex 1: 50000 có nghĩa là một đơn vị trên bản đồ tương ứng với 50.000 đơn vị trong thế giới thực.

Đối với bản đồ giấy được in tỷ lệ 1: 50000, điều này có nghĩa là 1 mét trên bản đồ tương ứng với 50.000 mét trong thế giới thực hoặc để dễ dàng hơn: 1 cm trên bản đồ tương ứng với 50 mét trong thế giới thực. Càng xa càng tốt.

Khi máy tính (hoặc màn hình điện thoại) vào chương trình, điều đó khó khăn hơn nhiều: đơn vị đo trên màn hình là một pixel, không ánh xạ trực tiếp đến centimet. OpenLayers đang (hoặc ít nhất là ở đâu) sử dụng "Dots per inch" và giả sử rằng một inch tương ứng với 72 pixel (điều này có ý nghĩa trên màn hình 72 dpi, nhưng sai trên màn hình Retina. Nhưng bây giờ, hãy kiên trì 72 dpi (vì đây là điều mà hầu hết các thư viện lập bản đồ thực hiện (tôi nghĩ, điều chỉnh đều được chào đón)).

OpenLayers có chức năng OpenLayers.Util.getResolutionFromScale (xem nguồn ):

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;
};
  • Với các đơn vị = "độ" (mà EPSG: 4490 là, từ những gì tôi thu thập được), chúng tôi nhận được inch_per unit = 4374754 (OpenLayers.INCHES_PER_UNIT ["độ"])

  • tỷ lệ 1: 50000 (tương ứng với 1/50000 = 0,00002) (đây là những gì penLayers.Util.n normalizeScale tính toán) cho NormScale = 0,00002

  • OpenLayers.DOTS_PER_INCH = 72

Sau đó chúng ta có thể tính toán độ phân giải như

1 / (0.00002 * 4374754 * 72) = 0.00015873908440210453

Biết điểm trung tâm (lon = 100, lat = 30), kích thước pixel của chế độ xem (w = 400, h = 600) và độ phân giải, sau đó chúng ta có thể sử dụng hàm tính toánBound từ OpenLayers.Map (xem nguồn ):

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

mà chúng ta có thể giảm xuống:

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

Gọi điều này với các giá trị của chúng tôi mang lại:

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

Sau đó, chúng ta có thể kết hợp tất cả điều này với một hàm hoạt động theo độ với mẫu số tỷ lệ đã cho:

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

Câu trả lời tuyệt vời. Trong thực tế, dường như điểm quan trọng ở đây là dpigiá trị. Phải không?
Giser

Oh, làm thế nào về chiếu? Có vẻ như các mã trên được sử dụng để tính toán mức độ trực tiếp.
Giser

Vâng, đó là chính xác. Miễn là người dùng của bạn không mong đợi sử dụng bản đồ theo cùng kiểu với bản đồ giấy (tức là đo trên nó), mọi giá trị đều có thể được sử dụng (và tôi nghĩ rằng hầu hết các thư viện bản đồ đều sử dụng 72 hoặc 96)
atlefren

điều duy nhất bạn cần biết về phép chiếu là các đơn vị của nó, OpenLayers sử dụng mảng OpenLayers.INCHES_PER_UNIT [units] trong Utils.js. web mercator sử dụng mét làm đơn vị, có nghĩa là 39,37 thay vì 4374754 để tính độ phân giải
atlefren

@atlerfren: Xin chào, có vẻ như bạn là một chuyên gia về openlayers, tôi gặp một số vấn đề liên quan đến nó. Bạn có thể dành chút thời gian để có một cheatk cho bài viết này? gis.stackexchange.com/q/61256/12681
giser
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.