three.jsとの3次元マップの開発の例

火災インテリジェンスの可視化の床を行うための企業、使用する必要があるが、3次元の地球のセシウムを研究するために、オープンソースのエンジンをのWeb3D、セシウムが、床の感触をんがやり過ぎですが、経験は良くありません、最終的な選択は、小規模なシーンに適して強力です3。

その3次元地図アプリケーションを開発するために3つの簡単な要件を取ることは問題ありません、3は、グラフィックスエンジンであり、Webベースの2Dおよび3Dマップは、グラフィックスエンジンです。

座標変換1

      実際の地理座標の経度、緯度、高度、及び右利きを用いthree.jsシステムのX、Y、Z、考慮された座標はメルカトルに緯度と経度の座標を変換し、再び3つに対応する座標系です。座標系を3つに対応する実際のプロジェクト、経度及び緯度ターンメルカトル、メルカトル値が大きすぎるは、座標距離の原点は、遠くのユーザ相互作用である、そこて第1の中間点を画定する、精度の損失であり、そしてうメルカトルは、中間点の値を減算した結果。(I z軸に対応する経度、緯度にx軸対応し、対応するy軸の高さ)

関数lonlatToMercator(経度、緯度、高さ){
     VARの Z =高?高さ:0 ;
    VAR X =(LON / 180.0)* 20037508.3427892 VaRの Y =(にMath.PI / 180.0)* 緯度。
    VAR TMP =にMath.PI / 4.0 + Y / 2.0 
    Y = 20037508.3427892 * Math.log(Math.tan(TMP))/ にMath.PI。
    リターン{X:X、Y:Y、Z:Z}。
} 
VARの中心= lonlatToMercator(lonVal、latVal、heightVal)。
関数lonlatToThree(経度、緯度、高さ){
     VARの Z =高?高さ:0 ;
    VAR X =(LON / 180.0)* 20037508.3427892 VaRの Y =(にMath.PI / 180.0)* 緯度。
    VAR TMP =にMath.PI / 4.0 + Y / 2.0 
    Y = 20037508.3427892 * Math.log(Math.tan(TMP))/ にMath.PI。
    VaRの結果= { 
        X:X - center.x、
        Y:Y - center.y、
        Z:Z -  center.z
    }。
    戻り値の結果; 
}

2.負荷モデル

 

    サポートthree.jsモデルの様々な、私はその後、COLLADAモデルに直接転送し、その後3つのCOLLADAモデルローダ搭載モデルを使用して、ビルドモデルスケッチマスターに使用し、ロードされました。three.jsと対応するように、及び位置XZ軸デフォルトモデルので、モデル反転動作からです。

ラベルを作成します3。

    3は、常にSpriteクラスを使用することができますカメラのPOIが直面しているラベルを作成し、あなたはまた、スプライトのテクスチャとしてグラフィックのアイコン+テキストタイプを作成するためにキャンバスを使用することができます。デフォルトスプライト3dは、カメラから近いスプライト、大画面上のスプライトの固定長であり、大きすぎるか小さすぎる小さな逆に、溶液をスクリーンピクセルの点で計算され、スプライトファジーキャンバス歪みの原因となります3D座標の長さの比は、スプライトは、次いで、適切な長さ3dにスケーリングされます。

VaRの位置= sprite.position。
VARキャンバス= sprite.material.map.image。
もし(キャンバス){
     VAR poiRect = {W:canvas.width、H:canvas.height}。
    VaRのスケール= getPoiScale(位置、poiRect)。
    sprite.scale。セット(スケール[ 0 ]、スケール[ 1 ]、1.0 )。
} 
 
関数getPoiScale(位置、poiRect){ 
    場合(!位置)に復帰VaRの距離= camera.position.distanceTo(位置)。
    VaRのトップ= Math.tan(camera.fov / 2Math.PI * / 180 [)*距離;     // カメラcamera.fovのの撮影角度
    のvar meterPerPixel = 2 *トップ/ container.clientHeight;
     VAR scaleXプロパティ= poiRect.w * meterPerPixel;
     VARとscaleY = poiRect.h * meterPerPixel;
     リターン [ scaleXプロパティ、scaleYの、1.0 ]; 
}

 

 4.マーク衝突

      ズーム時に必然的にそこにカバーされる各ケースを標識、ラベルを作成したら、そうではないだけでは、外観は、地図情報をカバーする影響すること、そこディスプレイは、カバーラベルの間で検出する必要がある、といくつかのマークは表示されません。

        ここでの要点は、回転のスクリーン座標に3D座標を示され、その後、スプライトキャンバス長さと高さに応じて、画面のスプライト矩形を知ることができます。次いで、スプライト矩形を交差各標識点の計算があります。

 VARスプライト1 = {X:X1、Y:Y1、W:W1、H:のH1};     // 左下スプライト1のX、Y、幅、高さ
    VAR sprite2 = {X:X2、Y:Y2、W:H、のW2 :H2};     //は左隅のX、Y、幅、高さが低くsprite2
   // 二つのスプライト衝突マークかどうかを検出する
    機能isPOIRect(スプライト1、sprite2){
         VAR X1 = sprite1.x、sprite1.y = Y1、W1 =スプライト1を。 W = H1のsprite1.h;
         VARのX2 = sprite2.x、Y2 = sprite2.y、W1 = sprite2.w、= H1 sprite2.h;
         IF(X1> X2 = X1 &&> = X2 + W2の){
             リターン falseに; 
        } そう IF(X1 <X2 = X1 + W1 && <= X2){
             リターン falseに
        } そう であれば(Y1> Y2 = && Y1> = Y2 + H2){
             戻り 
        } そう であれば(Y1 <Y2 = && Y1 + H1 <= Y2){
             戻り 
        } {
             戻り 
        } 
    }

 

装填装置

      デバイスを作成し、私も似たでラベルを作成し、Spriteクラスを使用し、スケーリング後、画面サイズのスプライトは変わりません。

デバイスをクリックします6.

    マウスのための3D raycasterクラスは同一のスプライトオブジェクトは、この方法のシミュレーション装置をクリックすると、選択されてもよいオブジェクトを選択します。どのdeviceGroupは、すべてのデバイスがスプライトobject3d対象をファイルに保存です。

関数(E){onDocumentMouseDown 
        e.preventDefault(); 
        mouse.x =(e.clientX / window.innerWidth)* 2 - 1。; 
        mouse.y = - (e.clientY / window.innerHeight)* 2 + 1 ;
         / / 0.5想定されるz方向における三次元の単位ベクトルを作成する
         // 系の座標点には、このベクトルを変換するために、カメラ
        のvarベクトル= 新しい新しい THREE.Vector3(mouse.x、mouse.y、0.5 ).unproject(カメラ);
         // ベクター線の開始点を形成し、視点の光線がカメラ座標系、クリックされたポイントへカメラ線方向ベクトルで、このベクトルは、標準規格化されなければなりません。
        VAR Raycasterは= 新しい新THREE.Raycaster(camera.position、vector.sub(camera.position).normalize());
         // 線と交差モデル、直線の選択された一連の
        VAR交差raycaster.intersectObjects =([devicegroup]、真の);          
         IF( intersects.length> 0 ){
             varが交差する交差= [ 0 ]。オブジェクト;
             IFは(THREE.Spriteのinstanceof交差){
                 // デバイスアイコンをクリック
            }   
        } 
    }

 

7.ポップアップボックス

       クリックデバイス後、必要がスタイルポップアップボックス、次いで三次元座標を定義するポップアップスタイル、通常特定の情報提示装置は、ポイントデバイス座標ポップアップ画面に変換特定オフセット、次に置くポップアップを設定しますスクリーンの位置は後方にシフトしました。そして、あなたがカメラを変更するたびに、ポップアップ位置を再計算します。

// スクリーン座標への三つの世界座標は
機能しthreeToScreen(位置、カメラ){
     VARの worldVector = 新新THREE.Vector3(
            position.x、
            position.y、
            position.z 
    ); 
    VAR standardVector = worldVector.project(カメラ); // 標準デバイス座標に世界座標
    VAR A = window.innerWidth / 2 ;
     VARの B = window.innerHeight / 2 ;
     VAR X =恐らくMath.round(standardVector.x * A + A); // 画面の標準デバイス座標は、回転座標
    VAR Yを恐らくMath.round =(-standardVector.y + B * B); // 画面の標準デバイス座標は、回転座標
    リターン{ 
        X:X、
        Y:Y 
    }。
}

 

8.機器アニメーション

        このようなアニメーションのような単純なデバイスは、デバイスの材料、サイズ、位置の材料を変更することにより、デバイスを変更するタイミングを介して点滅アイコンデバイスを実現するために実装することができます。

        頂点はシミュレート火災に突出するため、オンライン参照していくつかの時間を費やしたとTHREE.Vector3を使用することにより、ドット炎のすべてを作成するための最初のループは、オブジェクト炎パーティクルシステムのアニメーションを、作られた、THREE.Geometry内のオブジェクトを置きます;その後、オブジェクトはTHREE.PointsMaterial(透明材料と配置された透明:真混合と加算THREE.AddictiveBlending)を通過し、火炎キャンバスグレインパターンを作成するために使用し、最終的に上記THREE.Geometry THREE.Points THREE.PointsMaterialオブジェクトを作成し、完全火炎粒子システムの初期化。

        各粒子は、最後の動きがアニメーションの効果を達成するために特定のルールを有する粒子を駆動し、座標単を有しています。

 

9.マウス描画します

        3Dでは、三次元座標にマウス位置の対応が光線であり、プロット点として、図面の平面を追加描画し、マウスクリックの平面との交点を求める必要があります。モニタ、マウスが上に描画するためのイベントをクリックして移動します。

        線を描画すると、頂点のジオメトリを変更するには、直接的なラインを、マウスをクリックして移動し、表面を描画するときに、頂点を変更するだけでなく、の形状として、(私はEarcut.jsを使用)の三角形の組み合わせのすべての頂点を計算する必要が最後に面しており、このジオメトリをポリゴンメッシュを作成することは幾何学です。

//positions 三维坐标数组[[x,y,z],[x,y,z],...]
function createPolygon(positions){
    var shapePositons = [];
     for(var i=0;i<positions.length;i++){
        var position = positions[i];
        shapePositons.push(new THREE.Vector3(position[0],position[1],position[2]));
    }
    var data = [];
    for(var i=0;i<positions.length;i++){
        var position = positions[i];
        data.push(position[0],position[1]);
    }
    var faces = [];
    var triangles = Earcut.triangulate(data);
    if(triangles && triangles.length != 0){
        for(var i=0;i<triangles.length;i++){
            var length = triangles.length;
            if(i%3==0 && i < length-2){
                faces.push(new THREE.Face3(triangles[i],triangles[i+1],triangles[i+2]));
            }
        }
    }
    var geometry = new THREE.BufferGeometry();
    geometry.vertices = shapePositons;
    geometry.faces = faces;
    
    var mesh = new THREE.Mesh(geometry,material);
    return mesh;
}

 

おすすめ

転載: www.cnblogs.com/smedas/p/12440987.html