Cách tính mức thu phóng tối ưu để hiển thị hai hoặc nhiều điểm trên bản đồ


11

Chúng tôi muốn hiển thị một số điểm đánh dấu trên bản đồ tĩnh và muốn tính toán mức thu phóng tối ưu như Google Maps. Chúng tôi đã tính toán hình chữ nhật giới hạn và tâm điểm của bản đồ nhưng bây giờ chúng tôi có một thời gian khó khăn để tính toán zoomlevel chính xác để hiển thị toàn bộ hình chữ nhật giới hạn. Ai đó có thể xin vui lòng chỉ cho chúng tôi đi đúng hướng?


Nó không phức tạp lắm, nhưng tại sao không chỉ nhân MBR lên 120% và phóng to đến đó? Bất cứ điều gì khác phụ thuộc vào định nghĩa của bạn về "tối ưu", phải không?
ThomM

+1 theo ý tưởng của ThomM. Đây chính xác là những gì ArcGIS làm.
Ragi Yaser Burhum

1
Xin lỗi, nhưng MBR này là gì?
Rodrigo

Câu trả lời:


4

Để có được mức thu phóng, bạn sẽ cần biết kích thước pixel của bản đồ. Bạn cũng sẽ cần phải làm toán của mình trong tọa độ thủy ngân hình cầu.

  1. Chuyển đổi vĩ độ, kinh độ sang thủy ngân hình cầu x, y.
  2. Nhận khoảng cách giữa hai điểm của bạn trong Mercator hình cầu.
  3. Đường xích đạo dài khoảng 40m được chiếu và các ô có chiều rộng 256 pixel, do đó, chiều dài pixel của bản đồ đó ở mức thu phóng nhất định là khoảng 256 * khoảng cách / 40000000 * 2 ^ zoom . Hãy thử thu phóng = 0, thu phóng = 1, thu phóng = 2 cho đến khi khoảng cách quá dài so với kích thước pixel của bản đồ.

1
Hy vọng tôi đã hiểu từ xa những gì bạn thực sự hỏi. = \
Michal Migurski

Tìm thấy câu hỏi này trong khi tìm kiếm câu trả lời này, cảm ơn.
BenjaminGolder

@MichalMigurski bạn có thể giải thích làm thế nào để tính khoảng cách giữa 2 điểm trong bộ tạo hình cầu? đặc biệt là tọa độ x ... tôi đang bị mắc kẹt cảm ơn.
otmezger

4

Đây là mã C # tôi sử dụng trong 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: hộp giới hạn trong các hợp âm dài / lat (x = long, y = lat)
  • paddingFactor: điều này có thể được sử dụng để có được hiệu ứng "120%" mà ThomM đề cập đến. Giá trị 1,2 sẽ giúp bạn có được 120%.

Lưu ý rằng trong trường hợp của tôi zoomcó thể là một số thực. Trong trường hợp bản đồ Web, bạn cần một giá trị thu phóng nguyên, vì vậy bạn nên sử dụng một cái gì đó như (int)Math.Floor(zoom)để có được nó.

Tất nhiên, mã này chỉ áp dụng cho phép chiếu Web Mercator.


1
Cảm ơn vì điều đó. Mã cho CenterMapOnPoint có sẵn không?
mcintyre321

Hoàn hảo! Tôi đã sử dụng công cụ này để tính toán thu phóng BoundingBox trong OsmDroid SDK và nó hoạt động :)
Billda

Tôi tìm những thư viện này ở đâu? Tôi không thể tìm thấy một phép thử GeometryUtils hoặc Bound2. Tôi có cần phải tải xuống một cái gì đó từ maperitive? Tôi chỉ thấy một ứng dụng ở đó.
Hạ sĩ

@Dowlers GeometryUtilschỉ được sử dụng ở đây để chuyển đổi độ sang radian và ngược lại, đó là một công thức toán học đơn giản. Bounds2về cơ bản chỉ là một cấu trúc hình chữ nhật. Mã này được cung cấp nhiều hơn dưới dạng mã giả hơn là thứ có thể sao chép trực tiếp.
Igor Brejc

Ahh có bạn Tôi phải thừa nhận rằng sau khi tôi đặt câu hỏi, tôi đã thực hiện một số câu hỏi xung quanh ứng dụng tạo mẫu và tìm thấy các dll tôi cần. Nhưng tôi nhận thấy những hạn chế cấp phép nên tôi đã đi một con đường khác. Tôi đã sử dụng mã từ bài viết này để thay thế: rbrundritt.wordpress.com/2009/07/21/ Kẻ
Hạ sĩ

1

Nếu bạn đang sử dụng OpenLayers thì Map.getZoomForExtentsẽ tính toán mức thu phóng cao nhất có thể phù hợp với toàn bộ phạm vi trên bản đồ. Sự extentcần thiết phải được chiếu trong bản đồ. Bạn cũng có thể sử dụng a fill_factorđể tránh hiển thị các điểm trên rìa bản đồ và max_zoomđể hạn chế thu phóng có thể:

extent = extent.scale(1/fill_ratio);
var zoom = Math.min(map.getZoomForExtent(map_extent), max_zoom);
map.setCenter(extent.getCenterLonLat(), zoom);

điều này không khắc phục được vấn đề của tôi, nhưng nó khiến tôi tìm ra phương pháp fitBound của Leaflet, nó đã cứu tôi.
SamuelDev
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.