【问题标题】:splines arc on three js globe not working三个js地球上的样条弧不起作用
【发布时间】:2015-09-10 19:03:05
【问题描述】:

我一直在关注几个关于在 three.js 地球上绘制弧线的示例。尽管我无法正确计算数学并且结果投影不正确,但我几乎已经完成了这项工作。我很感激任何人看一下代码并告诉我我做错了什么。谢谢

import oHoverable from 'o-hoverable';
import d3 from 'd3';
import oHeader from 'o-header';
import THREE from 'three.js';


// var OrbitControls = require('three-orbit-controls')(THREE);
// console.log("orbitControls=",OrbitControls);



oHoverable.init(); // makes hover effects work on touch devices

document.addEventListener('DOMContentLoaded', function () {
  oHoverable.init(); // makes hover effects work on touch devices

  var dataset=spreadsheet.data
  console.log(dataset)
    // This let's you inspect the resulting image in the console.
    //console.log(canvas.node().toDataURL()); //F


  var startLon=45
  var startLat=75
  var endLon=0
  var endLat=0
  var posX = 200;
  var posY = 600;
  var posZ = 1800;
  var width = document.getElementById('main').getBoundingClientRect().width;
  var height = 600;

  var FOV = 45;
  var NEAR = 2;
  var FAR = 4000;
  var controls;

  // some global variables and initialization code 
  // simple basic renderer
  var renderer = new THREE.WebGLRenderer();
  renderer.setSize(width,height);
  renderer.setClearColor( 0x000000, 1);

  // add it to the target element
  var globeDiv = document.getElementById("globeDiv");
  globeDiv.appendChild(renderer.domElement);

  // setup a camera that points to the center
  var camera = new THREE.PerspectiveCamera(FOV,width/height,NEAR,FAR);
  camera.position.set(posX,posY, posZ);
  camera.lookAt(new THREE.Vector3(0,0,0));

  // create a basic scene and add the camera
  var scene = new THREE.Scene();
  scene.add(camera);

  //spotlight set up in the same location as the camera
  var light = new THREE.DirectionalLight(0xffffff, 1.0, 200 );
  light.position.set(posX,posY,posZ);
  scene.add(light);

  //Add Earth
  var radious=650
  var line
  // var earthGeo=new THREE.SphereGeometry(radious,100,100);
  // var earthMat=new THREE.MeshPhongMaterial();
  // earthMat.map=THREE.ImageUtils.loadTexture("images/world.jpg");
  // earthMat.bumpMap=THREE.ImageUtils.loadTexture("images/bumpmap.jpg");
  // earthMat.bumpScale=8;
  // earthMat.shininess=10;
  // var earthObject = new THREE.Mesh(earthGeo,earthMat);
  // scene.add(earthObject);

  // //Add clouds
  // var cloudGeo=new THREE.SphereGeometry(radious,60,60);
  // var cloudsMat=new THREE.MeshPhongMaterial({
  //     opacity: 0.5,
  //     transparent: true,
  //     color: 0xffffff
  // });
  // cloudsMat.map=THREE.ImageUtils.loadTexture("images/clouds.png");
  //  var meshClouds = new THREE.Mesh( cloudGeo, cloudsMat );
  // meshClouds.scale.set(1.015, 1.015, 1.015 );
  // scene.add(meshClouds);

  //Add lines
  var root = new THREE.Object3D();
  for (var i = 0; i < dataset.length; i++) {
    endLon=dataset[i].lng;
    endLat=dataset[i].lat;
    makeCurve(startLat,startLon,endLat,endLon);
    root.add(line);
  };
  scene.add(root)



  function makeCurve(startLon,startLat,endLon,endLat){
    console.log("makeCurve",startLon,startLat,endLon,endLat);
    var phiFrom = startLon * Math.PI / 180;
    var thetaFrom = (startLat+90) * Math.PI / 180;
    //calculates "from" point
    var xF = radious * Math.cos(phiFrom) * Math.sin(thetaFrom);
    var yF = radious * Math.sin(phiFrom);
    var zF = radious * Math.cos(phiFrom) * Math.cos(thetaFrom);

    phiFrom = endLon * Math.PI / 180;
    thetaFrom = (endLat+90) * Math.PI / 180;
    //calculates "from" point
    var xT = radious * Math.cos(phiFrom) * Math.sin(thetaFrom);
    var yT = radious * Math.sin(phiFrom);
    var zT = radious * Math.cos(phiFrom) * Math.cos(thetaFrom);
    //Sets up vectors
    var vF = new THREE.Vector3(xF, yF, zF);
    var vT = new THREE.Vector3(xT, yT, zT);

    var dist = vF.distanceTo(vT);
    // here we are creating the control points for the first ones.
    // the 'c' in front stands for control.
    var cvT = vT.clone();
    var cvF = vF.clone();

    // get the half point of the vectors points.
    var xC = ( 0.5 * (vF.x + vT.x) );
    var yC = ( 0.5 * (vF.y + vT.y) );
    var zC = ( 0.5 * (vF.z + vT.z) );

    // then we create a vector for the midpoints.

    var subdivisions = 100;
    var geometry = new THREE.Geometry();
    var curve = new THREE.QuadraticBezierCurve3();
    curve.v0 = new THREE.Vector3(xF, yF, zF);
    curve.v1 = new THREE.Vector3(xT, yT, zT);
    curve.v2 = new THREE.Vector3(xC, yC, zC);
    for (var i = 0; i < subdivisions; i++) {
      geometry.vertices.push( curve.getPoint(i / subdivisions) )
    }
    var material = new THREE.LineBasicMaterial( { color: 0xf2c0a4, linewidth: 2 } );
    line = new THREE.Line(geometry, material);
  }


  // controls = new THREE.OrbitControls( camera );
  render();

  function render() {
      var timer = Date.now() * 0.0001;
      // camera.position.x=(Math.cos(timer)*1800);
      // camera.position.z=(Math.sin(timer)*1800);
      camera.lookAt( scene.position );
      // light.position.x = (Math.cos(timer)*2000);
      // light.position.z = (Math.sin(timer)*2000);
      light.lookAt(scene.position);
      //earthObject.rotation.y += 0.0014;
      root.rotation.y += 0.0014;
      //meshClouds.rotation.y += 0.001;
      renderer.render(scene,camera);
      requestAnimationFrame(render );
  }

});

数据样本如下并在别处加载 ftlabel,imfcode,lat,lng 阿富汗,512,33,66 阿尔巴尼亚,914,41,20 阿尔及利亚,612,28,3 安哥拉,614,-12.5,18.5 阿根廷,213,-34,-64 亚美尼亚,911,40,45 阿鲁巴岛,314,12.5,-69.97 澳大利亚,193,-25,135 奥地利,122,47.33,13.33 阿塞拜疆,912,40.5,47.5 巴哈马,313,24,-76 巴林,419,26,50.5 孟加拉国,513,24,90 巴巴多斯,316,13.17,-59.53 白俄罗斯,913,53,28 比利时,124,50.83,4 伯利兹,339,17.25,-88.75 贝宁,638,9.5,2.25 百慕大,319,32.33,-64.75 玻利维亚,218,-17,-65 波斯尼亚和黑塞哥维那,963,44.25,17.83 巴西,223,-10,-55 文莱,516,4.5,114.67 保加利亚,918,43,25 布基纳法索,748,13,-2 布隆迪,618,-3.5,30 柬埔寨,522,13,105 喀麦隆,622,6,12 加拿大,156,60,-96 佛得角,624,16,-24 中非共和国,626,7,21 乍得,628,15,19 智利,228,-30,-71 中国,924,35,105 哥伦比亚,233,4,-72 科摩罗,632,-12.17,44.25 哥斯达黎加,238,10,-84 科特迪瓦,662,8,-5 克罗地亚,960,45.17,15.5 古巴,928,22,-79.5

【问题讨论】:

    标签: javascript three.js


    【解决方案1】:

    稍微清理了数学,但基本上我将 lon 和 lat 传递给了以错误方式接收它们的函数。代码现在可以运行,看起来像这样

    import oHoverable from 'o-hoverable';
    import d3 from 'd3';
    import oHeader from 'o-header';
    import THREE from 'three.js';
    
    
    
    oHoverable.init(); // makes hover effects work on touch devices
    
    document.addEventListener('DOMContentLoaded', function () {
      oHoverable.init(); // makes hover effects work on touch devices
    
      var dataset=spreadsheet.data
      //console.log(dataset)
    
      var startLat=38
      var startLon=-100
      var endLon=0
      var endLat=0
      var posX = 200;
      var posY = 600;
      var posZ = 1800;
      var width = document.getElementById('main').getBoundingClientRect().width;
      var height = 600;
    
      var FOV = 45;
      var NEAR = 2;
      var FAR = 4000;
      var controls;
    
      // some global variables and initialization code 
      // simple basic renderer
      var renderer = new THREE.WebGLRenderer();
      renderer.setSize(width,height);
      renderer.setClearColor( 0x000000, 1);
    
      // add it to the target element
      var globeDiv = document.getElementById("globeDiv");
      globeDiv.appendChild(renderer.domElement);
    
      // setup a camera that points to the center
      var camera = new THREE.PerspectiveCamera(FOV,width/height,NEAR,FAR);
      camera.position.set(posX,posY, posZ);
      camera.lookAt(new THREE.Vector3(0,0,0));
    
      // create a basic scene and add the camera
      var scene = new THREE.Scene();
      scene.add(camera);
    
      //spotlight set up in the same location as the camera
      var light = new THREE.DirectionalLight(0xffffff, 1.0, 200 );
      light.position.set(posX,posY,posZ);
      scene.add(light);
    
      //Add Earth
      var radius=600
      var curveObject
      var earthGeo=new THREE.SphereGeometry(radius,100,100);
      var earthMat=new THREE.MeshPhongMaterial();
      earthMat.map=THREE.ImageUtils.loadTexture("images/world.jpg");
      earthMat.bumpMap=THREE.ImageUtils.loadTexture("images/bumpmap.jpg");
      earthMat.bumpScale=8;
      earthMat.shininess=10;
      var earthObject = new THREE.Mesh(earthGeo,earthMat);
      scene.add(earthObject);
    
      //Add clouds
      var cloudGeo=new THREE.SphereGeometry(radius,60,60);
      var cloudsMat=new THREE.MeshPhongMaterial({
          opacity: 0.5,
          transparent: true,
          color: 0xffffff
      });
      cloudsMat.map=THREE.ImageUtils.loadTexture("images/clouds.png");
       var meshClouds = new THREE.Mesh( cloudGeo, cloudsMat );
      meshClouds.scale.set(1.015, 1.015, 1.015 );
      scene.add(meshClouds);
    
      //Add lines
      var lineObject = new THREE.Object3D();
      for (var i = 0; i < dataset.length; i++) {
        endLon=dataset[i].lng;
        endLat=dataset[i].lat;
        makeCurve(startLon,startLat,endLon,endLat,i);
        lineObject.add(curveObject);
      };
      scene.add(lineObject)
    
    
      // takes lon lat and a radius and turns that into vector
      function to3DVector(lon, lat, radius) {
        var phi = lat * Math.PI / 180;
        var theta = (lon + 90) * Math.PI / 180;
        var xF = radius * Math.cos(phi) * Math.sin(theta);
        var yF = radius * Math.sin(phi);
        var zF = radius * Math.cos(phi) * Math.cos(theta);
        return new THREE.Vector3(xF, yF, zF);
      }
    
      function makeCurve(startLon,startLat,endLon,endLat,i){
        var widthScale = d3.scale.linear()
                    .domain([0, d3.max(dataset, function(d) { return d.imfcode; })])
                    .range([1, 12]);
    
        var vF = to3DVector(startLon, startLat, radius);
        var vT = to3DVector(endLon, endLat, radius);
    
        // then you get the half point of the vectors points.
        var xC = ( 0.5 * (vF.x + vT.x) );
        var yC = ( 0.5 * (vF.y + vT.y) );
        var zC = ( 0.5 * (vF.z + vT.z) );
    
        // then we create a vector for the midpoints.
        var mid = new THREE.Vector3(xC, yC, zC);
    
        var dist = vF.distanceTo(vT);
        // here we are creating the control points for the first ones.
        // the 'c' in front stands for control.
        var cvT = vT.clone();
        var cvF = vF.clone();
        var smoothDist = map(dist, 0, 10, 0, 15/dist );
        console.log(smoothDist);
        mid.setLength( radius * smoothDist );
    
        cvT.add(mid);
        cvF.add(mid);
    
        cvT.setLength( radius * smoothDist );
        cvF.setLength( radius * smoothDist );
    
        var curve = new THREE.CubicBezierCurve3( vF, cvF, cvT, vT );
    
        var geometry2 = new THREE.Geometry();
        geometry2.vertices = curve.getPoints( 50 );
    
        var material2 = new THREE.LineBasicMaterial( { transparent: true,opacity :0.6, color : 0xff0000,linewidth:widthScale(dataset[i].imfcode)} );
    
    
        // Create the final Object3d to add to the scene
        curveObject = new THREE.Line( geometry2, material2 );
    
        function map(value, low1, high1, low2, high2) {
          return low2 + (high2 - low2) * (value - low1) / (high1 - low1);
        }
      }
    
      render();
    
      function render() {
        var timer = Date.now() * 0.0001;
        // camera.position.x=(Math.cos(timer)*1800);
        // camera.position.z=(Math.sin(timer)*1800);
        camera.lookAt( scene.position );
        // light.position.x = (Math.cos(timer)*2000);
        // light.position.z = (Math.sin(timer)*2000);
        light.lookAt(scene.position);
        earthObject.rotation.y += 0.0005;
        lineObject.rotation.y += 0.0005;
        meshClouds.rotation.y += 0.0012;
        renderer.render(scene,camera);
        requestAnimationFrame(render );
      }
    
    
    });
    

    【讨论】:

      猜你喜欢
      • 2021-11-21
      • 2021-06-06
      • 2019-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多