2016-11-24 13 views
2

Я установил карту листовки с пользовательским CRS (EPSG: 32633). Карта, как правило, работает хорошо, за исключением того, что она зависает всякий раз, когда я пытаюсь масштабировать карту с помощью пинча, чтобы увеличить количество мобильных устройств.Почему ущипнуть зубы не работает в пользовательских crs в листовке?

Ошибка, возникающая при масштабировании для увеличения, - «Непринятая ошибка: недопустимый объект LatLng: (NaN, NaN)».

Вот jsfiddle, который может быть использован для воспроизведения проблемы:

http://jsfiddle.net/thL5bbnv/2/

Вот код (который также используется в jsfiddle):

// Defining the projection system 
L.Projection.UTM33 = { 
    ZONE: 33, 
    R_MINOR: 6356752.3142, 
    R_MAJOR: 6378137, 
    DEG_TO_RAD: Math.PI/180, 
    RAD_TO_DEG: 180/Math.PI, 

    bounds: L.bounds([-2500000, 3500000], [3045984, 9045984]), 

    project: function(latlng) { 
    var latRad = latlng.lat * this.DEG_TO_RAD, 
     longRad = latlng.lng * this.DEG_TO_RAD, 
     longOriginRad = (-183 + (6 * this.ZONE)) * this.DEG_TO_RAD, 
     eccs = 1 - ((this.R_MINOR/this.R_MAJOR) * (this.R_MINOR/this.R_MAJOR)), 
     k0 = 0.9996, 
     eccps = eccs/(1 - eccs), 
     n = this.R_MAJOR/Math.sqrt(1 - eccs * Math.sin(latRad) * Math.sin(latRad)), 
     t = Math.tan(latRad) * Math.tan(latRad), 
     c = eccps * Math.cos(latRad) * Math.cos(latRad), 
     a = Math.cos(latRad) * (longRad - longOriginRad), 
     m = this.R_MAJOR * ((1 - eccs/4 - 3 * eccs * eccs/64 - 5 * eccs * eccs * eccs/256) * latRad - (3 * eccs/8 + 3 * eccs * eccs/32 + 45 * eccs * eccs * eccs/1024) * Math.sin(2 * latRad) + (15 * eccs * eccs/256 + 45 * eccs * eccs * eccs/1024) * Math.sin(4 * latRad) - (35 * eccs * eccs * eccs/3072) * Math.sin(6 * latRad)), 
     x = k0 * n * (a + (1 - t + c) * a * a * a/6 + (5 - 18 * t + t * t + 72 * c - 58 * eccps) * a * a * a * a * a/120) + 500000.0, 
     y = k0 * (m + n * Math.tan(latRad) * (a * a/2 + (5 - t + 9 * c + 4 * c * c) * a * a * a * a/24.0 + (61.0 - 58 * t + t * t + 600.0 * c - 330.0 * eccps) * a * a * a * a * a * a/720)); 

    return new L.Point(x, y); 
    }, 

    unproject: function(point) { 
    var eccs = 1 - ((this.R_MINOR/this.R_MAJOR) * (this.R_MINOR/this.R_MAJOR)), 
     e1 = (1 - Math.sqrt(1 - eccs))/(1 + Math.sqrt(1 - eccs)), 
     k0 = 0.9996, 
     x = point.x - 500000, 
     y = point.y, 
     longOrigin = (this.ZONE - 1) * 6 - 180 + 3, 
     eccps = (eccs)/(1 - eccs), 
     m = y/k0, 
     mu = m/(this.R_MAJOR * (1 - eccs/4 - 3 * eccs * eccs/64 - 5 * eccs * eccs * eccs/256)), 
     phi1Rad = (mu + (3 * e1/2 - 27 * e1 * e1 * e1/32) * Math.sin(2 * mu) + (21 * e1 * e1/16 - 55 * e1 * e1 * e1 * e1/32) * Math.sin(4 * mu) + (151 * e1 * e1 * e1/96) * Math.sin(6 * mu)), 
     n1 = this.R_MAJOR/Math.sqrt(1 - eccs * Math.sin(phi1Rad) * Math.sin(phi1Rad)), 
     t1 = Math.tan(phi1Rad) * Math.tan(phi1Rad), 
     c1 = eccps * Math.cos(phi1Rad) * Math.cos(phi1Rad), 
     r1 = this.R_MAJOR * (1 - eccs)/Math.pow(1 - eccs * Math.sin(phi1Rad) * Math.sin(phi1Rad), 1.5), 
     d = x/(n1 * k0), 
     lng = ((longOrigin * this.DEG_TO_RAD + ((d - (1 + 2 * t1 + c1) * d * d * d/6 + (5 - 2 * c1 + 28 * t1 - 3 * c1 * c1 + 8 * eccps + 24 * t1 * t1) * d * d * d * d * d/120)/Math.cos(phi1Rad))) * this.RAD_TO_DEG), 
     lat = ((phi1Rad - (n1 * Math.tan(phi1Rad)/r1) * (d * d/2 - (5 + 3 * t1 + 10 * c1 - 4 * c1 * c1 - 9 * eccps) * d * d * d * d/24 + (61 + 90 * t1 + 298 * c1 + 45 * t1 * t1 - 252 * eccps - 3 * c1 * c1) * d * d * d * d * d * d/720)) * this.RAD_TO_DEG); 

    return new L.LatLng(lat, lng); 
    } 
}; 

// Defining the utm crs 
L.CRS.EPSG32633 = L.extend({}, L.CRS.Earth, { 
    code: "EPSG:32633", 
    projection: L.Projection.UTM33, 
    transformation: new L.Transformation(1, 2500000, -1, 9045984), 
    scale: function(zoom) { 
    return 1/(21664/Math.pow(2, zoom)); 
    } 
}); 

// Creating map with the utm crs 
var map = new L.map('map', { 
    crs: L.CRS.EPSG32633, 
    minZoom: 0, 
    maxZoom: 15, 
    zoomControl: true 
}).on("load", function(e) { 
    // Adding utm basemap 
var layer = new L.TileLayer.WMS('https://opencache.statkart.no/gatekeeper/gk/gk.open', { 
    layers: "topo2", 
    format: "image/png", 
    transparent: false, 
    attribution: "© Kartverket" 
}); 

layer.addTo(e.target); 

}).setView([65.276178, 16.683775], 3); 

UPDATE: Вот стек след для ошибки, которую я получаю:

Uncaught Error: Invalid LatLng object: (NaN, NaN) 
    at o.LatLng (https://unpkg.com/[email protected]/dist/leaflet.js:5:14154) 
    at Object.unproject (http://fiddle.jshell.net/thL5bbnv/2/show/:105:12) 
    at Object.pointToLatLng (https://unpkg.com/[email protected]/dist/leaflet.js:5:18431) 
    at e.unproject (https://unpkg.com/[email protected]/dist/leaflet.js:5:30126) 
    at e.layerPointToLatLng (https://unpkg.com/[email protected]/dist/leaflet.js:5:30242) 
    at e._fireDOMEvent (https://unpkg.com/[email protected]/dist/leaflet.js:6:3634) 
    at e._handleDOMEvent (https://unpkg.com/[email protected]/dist/leaflet.js:6:3071) 
    at HTMLDivElement.h (https://unpkg.com/[email protected]/dist/leaflet.js:6:11270) 
    at e._simulateEvent (https://unpkg.com/[email protected]/dist/leaflet.js:8:31479) 
    at e._onMove (https://unpkg.com/[email protected]/dist/leaflet.js:8:31242)o.LatLng @ leaflet.js:5unproject @ (index):105pointToLatLng @ leaflet.js:5unproject @ leaflet.js:5layerPointToLatLng @ leaflet.js:5_fireDOMEvent @ leaflet.js:6_handleDOMEvent @ leaflet.js:6h @ leaflet.js:6_simulateEvent @ leaflet.js:8_onMove @ leaflet.js:8h @ leaflet.js:6 
leaflet.js:5 Uncaught Error: Invalid LatLng object: (NaN, NaN)(…)o.LatLng @ leaflet.js:5unproject @ (index):105pointToLatLng @ leaflet.js:5unproject @ leaflet.js:5layerPointToLatLng @ leaflet.js:5_fireDOMEvent @ leaflet.js:6_handleDOMEvent @ leaflet.js:6h @ leaflet.js:6_simulateEvent @ leaflet.js:8_onMove @ leaflet.js:8h @ leaflet.js:6 

Я пытаюсь понять, почему щепотка для масштабирования не работает, и что я могу сделать, чтобы исправить эту проблему. Кто-нибудь знает, почему ущипнуть для масштабирования приведет к недопустимому объекту LatLng: (NaN, NaN), когда используется пользовательская проекция?

+1

У вас есть полная ошибка стека ошибки? – IvanSanchez

ответ

2

ОК, так что я проследил проблему вплоть до вызова map.getScaleZoom():

debug screenshot

Этой функция напрямую зависит от scale метода CRS карт содержат, который вы определили как

scale: function(zoom) { 
    return 1/(21664/Math.pow(2, zoom)); 
} 

Теперь метод CRS scale должен реализовать обратный метода zoom CRS. Это сказано в Leaflet API documentation for L.CRS.

Вы не определяет метод zoom в L.CRS.EPSG32633, но ...

L.CRS.EPSG32633 = L.extend({}, L.CRS.Earth, { 

... вы используете L.CRS.Earth.zoom() вместо этого. Поэтому, если scale(zoom(x)) не 1 для любого значения x, все не получится. Во-первых, уровень масштабирования переходит с 1,01 до -19,4. Затем LatLng получает значение 1e+233. Затем код проецирования принимает это и начинает извергать Infinity и NaN, и все заканчивается огнем.

Исправить scale и zoom методов L.CRS.EPSG32633, чтобы они были идемпотентными.


Независимо от ошибки, я рекомендую вам использовать Proj4Leaflet вместо реализации проекционного кода самостоятельно. Он протестирован, поддерживается и поддерживается всеми известными проекциями EPSG и CRS.

+0

Большое спасибо за великолепное объяснение того, как это работает. Я выполнил ваше предложение и добавил метод масштабирования, который является обратным методу масштабирования, и теперь он работает. – stanleycas