[Google-maps] خرائط جوجل V3 - كيفية حساب مستوى التكبير لحدود معينة


Answers

بفضل جايلز غاردام على إجابته، لكنه لا يتناول سوى خطوط الطول وليس خطوط العرض. يجب أن يحسب الحل الكامل مستوى التكبير / التصغير اللازم لخط العرض ومستوى التكبير / التصغير اللازم لخط الطول، ثم أخذ أصغر (خارج نطاق آخر) للاثنين.

هنا هي الدالة التي تستخدم كل من خطوط الطول والعرض:

function getBoundsZoomLevel(bounds, mapDim) {
    var WORLD_DIM = { height: 256, width: 256 };
    var ZOOM_MAX = 21;

    function latRad(lat) {
        var sin = Math.sin(lat * Math.PI / 180);
        var radX2 = Math.log((1 + sin) / (1 - sin)) / 2;
        return Math.max(Math.min(radX2, Math.PI), -Math.PI) / 2;
    }

    function zoom(mapPx, worldPx, fraction) {
        return Math.floor(Math.log(mapPx / worldPx / fraction) / Math.LN2);
    }

    var ne = bounds.getNorthEast();
    var sw = bounds.getSouthWest();

    var latFraction = (latRad(ne.lat()) - latRad(sw.lat())) / Math.PI;

    var lngDiff = ne.lng() - sw.lng();
    var lngFraction = ((lngDiff < 0) ? (lngDiff + 360) : lngDiff) / 360;

    var latZoom = zoom(mapDim.height, WORLD_DIM.height, latFraction);
    var lngZoom = zoom(mapDim.width, WORLD_DIM.width, lngFraction);

    return Math.min(latZoom, lngZoom, ZOOM_MAX);
}

تجريبي على جسفيدل

المعلمات:

يجب أن تكون قيمة المعلمة " google.maps.LatLngBounds كائن google.maps.LatLngBounds .

يجب أن تكون قيمة المعلمة "مابديم" كائن بخصائص "ارتفاع" و "عرض" تمثل ارتفاع وعرض عنصر دوم الذي يعرض الخريطة. قد تحتاج إلى تقليل هذه القيم إذا كنت ترغب في ضمان الحشو. وهذا يعني أنك قد لا تريد أن تكون علامات الخريطة ضمن الحدود قريبة جدا من حافة الخريطة.

إذا كنت تستخدم مكتبة مسج، يمكن الحصول على قيمة mapDim كما يلي:

var $mapDiv = $('#mapElementId');
var mapDim = { height: $mapDiv.height(), width: $mapDiv.width() };

إذا كنت تستخدم مكتبة النموذج الأولي، يمكن الحصول على قيمة مابديم كما يلي:

var mapDim = $('mapElementId').getDimensions();

قيمة الإرجاع:

قيمة الإرجاع هي الحد الأقصى لمستوى التكبير الذي سيظل يعرض الحدود بالكامل. وستكون هذه القيمة بين 0 ومستوى التكبير الأقصى، شامل.

الحد الأقصى لمستوى التكبير / التصغير هو 21. (أعتقد أنه كان 19 فقط لخادم غوغل مابس أبي v2.)

تفسير:

تستخدم خرائط غوغل إسقاط ميركاتور. في إسقاط ميركاتور خطوط الطول متباعدة على قدم المساواة، ولكن خطوط العرض ليست كذلك. المسافة بين خطوط زيادة خط العرض لأنها تذهب من خط الاستواء إلى القطبين. في الواقع المسافة يميل نحو ما لا نهاية كما أنه يصل إلى القطبين. ومع ذلك، لا تظهر خريطة خرائط غوغل خطوط عرض أعلى من 85 درجة تقريبا شمالا أو أقل من 85 درجة تقريبا جنوبا. ( المرجع ) (أنا حساب القطع الفعلي في +/- 85.05112877980658 درجة.)

وهذا يجعل حساب الكسور للحدود أكثر تعقيدا لخط العرض من خط الطول. لقد استخدمت صيغة من ويكيبيديا لحساب جزء خط العرض. أفترض أن هذا يطابق الإسقاط الذي تستخدمه خرائط غوغل. بعد كل شيء، تحتوي صفحة وثائق خرائط غوغل التي أربطها أعلاه على رابط إلى صفحة ويكيبيديا نفسها.

الملاحظات الأخرى:

  1. تتراوح مستويات التكبير / التصغير من 0 إلى الحد الأقصى لمستوى التكبير / التصغير. مستوى التكبير / التصغير 0 هو تكبير الخريطة بشكل كامل. مستويات أعلى تكبير الخريطة في أبعد من ذلك. ( المرجع )
  2. على مستوى التكبير 0 العالم بأكمله يمكن عرضها في مساحة 256 × 256 بكسل. ( المرجع )
  3. لكل مستوى زوم أعلى عدد وحدات البكسل اللازمة لعرض نفس المنطقة الزوجي في كل من العرض والارتفاع. ( المرجع )
  4. التفاف الخرائط في الاتجاه الطولي، ولكن ليس في الاتجاه خط العرض.
Question

أبحث عن طريقة لحساب مستوى التكبير / التصغير لحدود معينة باستخدام واجهة برمجة تطبيقات خرائط غوغل V3، على غرار جيتبوندزومليفيل () في واجهة برمجة تطبيقات V2.

وهنا ما أريد القيام به:

// These are exact bounds previously captured from the map object
var sw = new google.maps.LatLng(42.763479, -84.338918);
var ne = new google.maps.LatLng(42.679488, -84.524313);
var bounds = new google.maps.LatLngBounds(sw, ne);
var zoom = // do some magic to calculate the zoom level

// Set the map to these exact bounds
map.setCenter(bounds.getCenter());
map.setZoom(zoom);

// NOTE: fitBounds() will not work

لسوء الحظ، لا أستطيع استخدام الأسلوب فيتبوندز () لحالة الاستخدام الخاصة بي. أنه يعمل بشكل جيد لتركيب علامات على الخريطة، لكنه لا يعمل بشكل جيد لتحديد حدود محددة. هنا مثال لماذا لا أستطيع استخدام الأسلوب فيتبوندز ().

map.fitBounds(map.getBounds()); // not what you expect



فاليريو على حق تقريبا مع حله، ولكن هناك بعض الخطأ المنطقي.

يجب عليك أولا التحقق من زاوية الطقس 2 أكبر من زاوية، قبل إضافة 360 في السلبية.

وإلا لديك دائما قيمة أكبر من زاوية

لذا فإن الحل الصحيح هو:

var west = calculateMin(data.longitudes);
var east = calculateMax(data.longitudes);
var angle = east - west;
var north = calculateMax(data.latitudes);
var south = calculateMin(data.latitudes);
var angle2 = north - south;
var zoomfactor;
var delta = 0;
var horizontal = false;

if(angle2 > angle) {
    angle = angle2;
    delta = 3;
}

if (angle < 0) {
    angle += 360;
}

zoomfactor = Math.floor(Math.log(960 * 360 / angle / GLOBE_WIDTH) / Math.LN2) - 2 - delta;

دلتا هناك، لأن لدي عرض أكبر من الارتفاع.




شكرا، وهذا ساعدني كثيرا في العثور على عامل التكبير الأكثر ملاءمة لعرض بشكل صحيح خط البولي. أجد الحد الأقصى والحد الأدنى من الإحداثيات بين النقاط التي يجب أن تتبع، وفي حال كان المسار "عمودي" جدا، أنا فقط إضافة بضعة أسطر من التعليمات البرمجية:

var GLOBE_WIDTH = 256; // a constant in Google's map projection
var west = <?php echo $minLng; ?>;
var east = <?php echo $maxLng; ?>;
*var north = <?php echo $maxLat; ?>;*
*var south = <?php echo $minLat; ?>;*
var angle = east - west;
if (angle < 0) {
    angle += 360;
}
*var angle2 = north - south;*
*if (angle2 > angle) angle = angle2;*
var zoomfactor = Math.round(Math.log(960 * 360 / angle / GLOBE_WIDTH) / Math.LN2);

في الواقع، عامل التكبير المثالي هو زومفاكتور-1.