Javascript 样条曲线在三个圆弧上不工作
我一直在关注几个关于在three.js地球仪上映射圆弧的示例。虽然我很难得到正确的数学结果,并且得到的投影是不正确的,但我几乎已经成功了。如果有人看一下代码并告诉我我做错了什么,我将不胜感激。谢谢Javascript 样条曲线在三个圆弧上不工作,javascript,three.js,Javascript,Three.js,我一直在关注几个关于在three.js地球仪上映射圆弧的示例。虽然我很难得到正确的数学结果,并且得到的投影是不正确的,但我几乎已经成功了。如果有人看一下代码并告诉我我做错了什么,我将不胜感激。谢谢 import oHoverable from 'o-hoverable'; import d3 from 'd3'; import oHeader from 'o-header'; import THREE from 'three.js'; // var OrbitControls = requi
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 );
}
});
从“o-hoverable”导入oHoverable;
从“d3”中导入d3;
从“o-header”导入oHeader;
从'THREE.js'导入三个;
//var轨道控制=需要(“三轨道控制”)(三);
//console.log(“orbitControls=”,orbitControls);
oHoverable.init();//使悬停效果在触摸设备上工作
document.addEventListener('DOMContentLoaded',函数(){
oHoverable.init();//使悬停效果在触摸设备上工作
var数据集=电子表格.data
console.log(数据集)
//让我们在控制台中检查生成的图像。
//console.log(canvas.node().toDataURL());//F
var=45
var=75
var endLon=0
var endLat=0
var-posX=200;
var-posY=600;
var posZ=1800;
var width=document.getElementById('main').getBoundingClientRect().width;
var高度=600;
var-FOV=45;
var近=2;
var-FAR=4000;
风险值控制;
//一些全局变量和初始化代码
//简单基本渲染器
var renderer=new THREE.WebGLRenderer();
设置大小(宽度、高度);
setClearColor(0x000000,1);
//将其添加到目标元素
var globeDiv=document.getElementById(“globeDiv”);
globeDiv.appendChild(renderer.domeElement);
//设置一个指向中心的相机
var摄像机=新的三视角摄像机(视野、宽度/高度、近距离、远距离);
摄像机位置设置(posX、posY、posZ);
摄像机。注视(新三个。矢量3(0,0,0));
//创建基本场景并添加摄影机
var scene=new THREE.scene();
场景。添加(摄影机);
//聚光灯设置在与摄影机相同的位置
var灯光=新的三方向灯光(0xffffff,1.0200);
light.position.set(posX、posY、posZ);
场景。添加(灯光);
//加土
放射值=650
var线
//var earthGeo=新的三倍比球法(radious,100100);
//var earthMat=新的三个.MeshPhongMaterial();
//earthMat.map=THREE.ImageUtils.loadTexture(“images/world.jpg”);
//earthMat.bumpMap=THREE.ImageUtils.loadTexture(“images/bumpMap.jpg”);
//接地网,比例=8;
//接地网的光泽度=10;
//var earthObject=新的三个网格(earthGeo、earthMat);
//场景。添加(earthObject);
////添加云
//var cloudGeo=新的三种球度法(radious,60,60);
//var cloudsMat=新的3.0网格材质({
//不透明度:0.5,
//透明:是的,
//颜色:0xffffff
// });
//cloudsMat.map=THREE.ImageUtils.loadTexture(“images/clouds.png”);
//var meshClouds=new THREE.Mesh(cloudGeo,cloudsMat);
//网格云。比例。设置(1.015,1.015,1.015);
//场景。添加(网格云);
//添加行
var root=new THREE.Object3D();
对于(var i=0;i
数据样本如下所示,并加载到其他位置
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,-25135
奥地利,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.2
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 );
}
});