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)系投影造成的誤差影響罷了——盡管看上去它才是正“圓”,但是到實地去真實測量到圓心距離的話,一定是小于理想半徑的。