OpenLayers 和 turf.js 的靈異事件:什么?我畫的圓居然不是圓!
事情的起因:
使用ol.geom.Circle這個幾何可以在OpenLayers中畫一個圓形的要素,雖然我們知道它并不是OGC標(biāo)準(zhǔn)的要素類型。
昨天群友找我解決一個有意思的問題:使用投影EPSG:3857的時候,在用ol.geom.Circle畫了一個圓形的要素之后,又用turf.circle在同樣的位置,用同樣的半徑畫了一個圓形的要素。
var fCircleBeta = new Feature({
geometry: new Circle([4500000, 4500000], 1000000
)
})
vCircleSource.addFeature(fCircleBeta);
var circle = turf.circle(toLonLat([4500000, 4500000]), 1000000, { steps: 100, units: 'meters' });
var turfCircleFeatureNorth = (new GeoJSON()).readFeature(circle, {
dataProjection: "EPSG:4326",
featureProjection: "EPSG:3857"
});
vCircleSource.addFeature(turfCircleFeatureNorth);
結(jié)果卻變成了這樣:
?。?!這是什么情況?
事情的處理:
我仔細(xì)觀察了一下,叫他以0,0為圓心,再分別畫兩個圓。
然后就是這個樣子(為了方便區(qū)分,特意將turf的正多邊形逼近的圓減少了邊數(shù)):
基本重合了。
所以至此基本可以得到結(jié)論:turf是按照球面畫圓的,ol是按照平面畫圓的,當(dāng)按照3857投影坐標(biāo)系進(jìn)行投影后,越靠近北極,形變越大,所以turf畫的圓就投影為一個上寬下窄的、胖了一圈的“圓”。
為了證明此事,我還需要做一個實驗。
真相大白:
實驗的思路就是,以第一組的兩個圓為例,監(jiān)聽鼠標(biāo)移動事件,顯示鼠標(biāo)位置到[4500000,4500000]的距離。當(dāng)我把鼠標(biāo)分別放到兩個“圓”的邊上面時,大略就能計算得到“半徑”。借了兩個控件,簡單寫了一個鼠標(biāo)位置的popup:
var pointerMoveHandler = function (evt) {
if (evt.dragging) {
return;
}
let radiusFlat = Math.sqrt(Math.pow((evt.coordinate[0] - 4500000), 2) + Math.pow((evt.coordinate[1] - 4500000), 2));
let radiusSphere = olSphere.getDistance(toLonLat([4500000, 4500000]), toLonLat(evt.coordinate));
tooltipElement.innerHTML = "鼠標(biāo)坐標(biāo):" + evt.coordinate + "</br>" + "平面距離:" + radiusFlat + "</br>" + "球面距離:" + radiusSphere + "</br>";
helpTooltip.setPosition(evt.coordinate);
tooltipElement.classList.remove('hidden');
};
map.on('pointermove', pointerMoveHandler);
function createHelpTooltip() {
if (tooltipElement) {
tooltipElement.parentNode.removeChild(tooltipElement);
}
tooltipElement = document.createElement('div');
tooltipElement.className = 'tooltip hidden';
helpTooltip = new Overlay({
element: tooltipElement,
offset: [15, 0],
positioning: 'center-left'
});
map.addOverlay(helpTooltip);
}
然后就得到了下面的結(jié)果:
可見我的猜想是正確的。
結(jié)論:
并非靈異事件 ,只是繪制方法不同罷了。如果做空間分析,還是turf靠譜一點,畢竟是接近實地距離的。如果使用OpenLayers的ol.geom.Circle類,也不見得錯,只不過受到了3857坐標(biāo)系投影造成的誤差影響罷了——盡管看上去它才是正“圓”,但是到實地去真實測量到圓心距離的話,一定是小于理想半徑的。