標籤:

立體地圖的圖形細分

立體地圖的圖形細分

來自專欄 360企業安全可視化實驗室

今天,我來講地球的故事,先從為什麼要細分圖形開始。

我們希望實現這樣的效果:

我們想實現這樣的效果

我們希望做一種可交互的地球,當滑鼠懸浮到國家時,展示當前國家的信息。這樣比貼圖更有立體感、也能方便地獲取當前國家的屬性做些交互。

實現過程簡單地描述一下:我們把geojson勾邊描成平面形狀,將形狀拉抻為下圖中所示平面地圖幾何體,將幾何體轉為地球的坐標即可。

geojson勾邊描成平面形狀,將形狀拉抻後的效果

當我們完成平面轉立體的坐標後,發現俄羅斯和南極洲有些地方發生了塌陷(圖一中 俄羅斯白色的區域)

俄羅斯發生塌陷,出現白色

什麼原因呢?當我們用GeoJson勾出的幾何圖形時,實際上圖形由很多的三角形組成。圖二中看到三角形的描線的中間空出的白色,是由於邊長較大三角形蓋在地球表面,但圖形在地球上經度跨度很大,導致三角形的厚度沒能蓋住地球表面弧度產生的,如圖三。

圖二

圖三

解決的辦法,就是讓這些形狀細分成更多的三角形,將圖形細分,就不會出現這個問題了。如下圖:


調研兩種細分圖形方法

一、Subdivision

在線例子 代碼地址

它的細分採用「使用循環細分」的原理,傳入循環的次數(subdivisions)進行循環。但不擅長處理銳利的邊緣(sharp edges)

庫的使用方法:

var tess = new THREE.SubdivisionModifier(1);tess.modify(geometry);var mesh = new THREE.Mesh(geometry, material);

耗時實驗:

在本文的時間實驗中,我們使用同一組圖形數據進行實驗。

運行如上代碼進行一次細分,時間為 26.787109375ms ,把循環次數增加一次,則時間會加倍,57.43603515625ms。速度有點慢,但是這個庫得到的細分效果如下圖,能滿足我們需求。

使用後對比

Subdivision庫的細分三角形

Subdivision方法細分三角形填充半透明的材質,看細分的效果

Subdivision方法細分三角形填充實色的材質,效果較好

二、TessellateModifier

代碼地址

這種細分採用 「把長度超過「限定邊長值」(maxEdgeLength)的邊進行細分」的方法,處理後,會細分為很多的小三角形

庫的使用方法

所以使用時,需要一個maxEdgeLength,在調用modify方法:

var tessellateModifier = new THREE.TessellateModifier( 8 );for ( var i = 0; i < 6; i ++ ) { tessellateModifier.modify( geometry );}

時間實驗:

在數據相同的情況下,用如上函數調用一次TessellateModifier方法,用時為 2.52294921875ms,如果將 for循環的次數增加 2次 , 則 2.96484375ms ,時間增長幅度很小,但是得到的圖形填充色後有縫隙,有一些不足。

使用前後對比:

看,地圖裡麵線條(三角形)分得很細

TessellateModifier方法細分的形狀

細分的形狀填充上半透明的材質

細分形狀填充實色(有許多的白色小點)

三、兩種庫的對比

從上面的實驗我們得到了兩組庫的對比結果:

TessellateModifier 比 Subdivision 速度更快,如果側重速度,選擇TessellateModifier。

但是TessellateModifier實現的效果中填充後有縫隙,效果不如Subdivision。

本例中我們選擇Subdivision庫,本例在線地址


推薦閱讀:

QQX計劃推廣H5——這可能是地球上最美的H5,是怎麼做出來的?

TAG:WebGL | threejs |