2017-11-29 12 views
3

私のオンラインマップ、特にスマートフォンのパフォーマンスを向上させるために、アップロード前にできるだけジオデータを準備するMike Bostockの助言に従いますそれはサーバーに(彼のcommand-line cartographyによると)。たとえば、マップをロードするときに、ブラウザの表示を非表示にするのではなく、コマンドラインでTopoJSONデータを通常d3.geoConicEqualArea()経由で投影しています。事前に投影されたジオメトリvブラウザにそれを実行させる(効率性と柔軟性)

しかし、私はまた、私は、「焼く」スケールまたは事前TopoJSONファイルに値を変換することはできませんを意味し、動的に.scale.fitSize.fitExtent.translateのようなメソッドを使用します。

Bostock recommendsd3.geoTransform()を投影のプロキシとして使用すると、すでに投影されたデータを扱っていても、拡大/縮小したい場合はd3.geoConicEqualArea()のようになります。例えば、y軸上の投影を反転するために、彼は示唆:

var reflectY = d3.geoTransform({ 
     point: function(x, y) { 
     this.stream.point(x, -y); 
     } 
    }), 

    path = d3.geoPath() 
     .projection(reflectY); 

私の質問:私はこのD3の機能を使用する場合は、私はまだ、データの多くを行うために視聴者のブラウザを強制されていません処理が悪くなります。データの前処理のポイントは、これを避けることです。あるいは、私は上記のd3.geoTransform()関数に含まれる処理作業を過大評価していますか?私はこのD3の機能を使用する場合は

答えて

6

、私はまだパフォーマンスを悪化させるであろう、データ処理の多くを行うために視聴者のブラウザ を強制されていませんか? データを前処理することは、これを避けることです。または、私は 上記のd3.geoTransform() 関数に含まれる処理作業を過大評価していますか?

短答:投影データを変換するために必要な作業量を過大評価しています。 D3のgeoProjections


球状自然D3のgeoProjectionは比較的ユニークです。多くのプラットフォーム、ツール、またはライブラリは、緯度と経度のペアで構成されたポイントを取得し、それらがデカルト平面上にあるかのように扱います。これは数学を非常に単純化しますが、コストはかかります:パスはデカルト経路に従います。

D3は、経度緯度ポイントを以下のように扱います.3次元楕円体上のポイント。これは計算コストがかかりますが、大きなサークルルートに沿って経路セグメントをルーティングするなど、他の利点もあります。

d3は3D地球上の点として座標を治療する際に負担する余分な計算コストは​​以下のとおりです。

  1. 球面数学

は、芯出し、スケーリングの前に簡単な地理投影を見てみましょうなど:

function mercator(x, y) { 
    return [x, Math.log(Math.tan(Math.PI/4 + y/2))]; 
} 

これはあなたのプロ変換よりも時間がかかる可能性があります上記のポーズ。

  1. デカルト平面上

をとしてパス、二点間の線が容易であり、球に、これは困難です。 179度の東から179度の西に伸びる線を取る - これらを、デカルト平面上にあるかのように扱い、地球全体に線を引く。球状の地球上で、線は抗経絡を横切る。

したがって、経路を平坦化するには、経路に沿ってサンプリングが必要であり、ポイント間の大きな円の距離には曲がりが必要なため、追加ポイントが必要です。これについてはd3ではわかりませんが、確かに発生します。

デカルト平面上の点は、追加のサンプリングを必要としません。それらは既にフラットであり、ポイント間の線は直線です。地球が別の方法で折り返すかどうかを検出する必要はありません。

操作後の投影したら、.fitSizeのようなもの)を使用すると、d3.geoTransform(と提案しているもの、実質的な追加作業を強制的に投影

:機能はに基づいて変換し、スケーリングする必要がある彼らの投影された場所とサイズ

これは、オートセンタリング機能を使用すると、d3v3(fitSize()より前)で非常によく見えます。計算には、投影されたフィーチャのsvg範囲が含まれます。


基本準科学的性能比較

、私は3つのにGeoJSONファイル作成米国の米国国勢調査局のシェープファイルを使用した:((ロング/緯度)WGS84を使用して

  • ワンファイルサイズ:389 kb)
  • プレーンd3のノードにgeoprojectを使用するもの。

速度のゴールドスタンダードは、オプション3であるべきであるが、データがスケーリングさに基づいて中心d3.geoAlbers().fitSize([500,500],d)(ファイルサイズ385キロバイト)とノードにおける

  • つgeoproject:geoAlbersは(386キロバイトのファイルサイズ)を形質転換します予想される表示範囲、変換なし私が使用して500×500 SVGにこれらのプロジェクトを進め、ここで必要とされると、私は

    それをテストするために、ヌル投影を使用します。

    // For the unprojected data 
    var projection = d3.geoAlbers() 
    .fitSize([500,500],wgs84); 
    
    var geoPath = d3.geoPath().projection(projection) 
    
    
    // for the projected but unscaled and uncentered data 
    var transform = d3.geoIdentity() 
        .fitSize([500,500],albers); 
    
        var projectedPath = d3.geoPath() 
        .projection(transform); 
    
    // for the projected, centered, and scaled data 
    var nullProjection = d3.geoPath() 
    
    • 71ミリ秒:WGS84
    • 33は、MS:写し出されたが、スケーリングされていないと非中心
    • 21ミリ秒:写し出され、スケール百本を数回実行すると、私は(データがプリロードされた)の平均レンダリング時間を得ました中央に配置されています

    実際にセンタリングされ、スケーリングされているかどうかにかかわらず、データを事前投影する際にかなりのパフォーマンスバンプがあると言っても安全です。 d3.geoTransform()とは対照的に、それはfitSize()の使用を可能にし、かつy上で必要な場合は、反映することができますように私はd3.geoIdentity()を使用

    注:.reflectY(true);

  • +0

    は、この詳細な回答のためにあなたをとても感謝。私は多くのことを学びました。そしてこれらの3つのパフォーマンステストを二重に実行するために!私の最大のTopoJSONファイルはわずか550KBですが、あなたのアドバイスは助けてくれますが、スマートフォンではまだかなりのパフォーマンス上の問題があります:) – Markus

    +0

    いつものように華麗です!あなたがd3-geoでサンプリングを認識してはならないと信じられませんか? [Adaptive Resampling](https://bl.ocks.org/mbostock/3795544)のMike Bostockのブロックを知っていますか?それはあなたが話していることですよね?それはv3ですが、まだ... – altocumulus

    +0

    @ Markus、可能であれば、私はあなたのtopojsonを単純化します、550kbはtopojsonのためのかなりのビットです、もしそれがオプションでないなら、キャンバスを使うことは、すでに。 –

    関連する問題