D3 + Three.js:经纬网投影 - 不能将投影应用于经纬网

时间:2017-07-09 20:03:19

标签: javascript d3.js svg three.js

我试图在three.js中创建3D刻度。目前的努力首先使用D3在SVG中建立一个mollweide投影刻度。然后它提取网格路径点,将它们转换为three.js向量。

然而,得到的three.js格线仅仅是一个球体刻度,并且不响应所需的投影(mollweide)点。有什么想法吗?

这显示在下面的文件中。违规函数是顶点(点)



 <!DOCTYPE HTML>

<html>

<head>
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="https://d3js.org/d3.geo.projection.v0.min.js"></script>
<script src="https://d3js.org/d3-array.v1.min.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/r86/build/three.min.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/r86/examples/js/controls/OrbitControls.js"></script>

  <title>3D Mollweide Projection</title>
  <style type="text/css">
  <!--
 .background {
  fill: #a4bac7;
}

.foreground {
  fill: none;
  stroke: #333;
  stroke-width: 1.5px;
}

.graticule {
  fill: none;
  stroke: #fff;
  stroke-width: .5px;
}


  -->
  </style>
</head>

<body style=font-family:arial>

<center>SVG Drawing (mollweide projection):</center>
<svg id=projectionSVG width=600 height=440 overflow=visible />
Three.js Drawing (rotate and mousewheel zoom):<br>
<div  id=container></div>

<script>
var projection
var gratPathPointArray=[]
var radius = 230


//----build svg graticule----
    projection = d3.geo.mollweide()
    .scale(120);

    var path = d3.geo.path()
    .projection(projection);

    var graticule = d3.geo.graticule();

    var svg= d3.select("#projectionSVG")
    svg.append("path")
    .datum(graticule.outline)
    .attr("class", "background")
    .attr("d", path);

    var graticuleG=svg.append("g")
    .attr("class", "graticule")
    .selectAll("path")
    .data(graticule.lines)
    .enter().append("path")
    .attr("d", path);


    var graticulePathG=projectionSVG.lastChild

    var graticulePaths=graticulePathG.childNodes
    for(p=0;p<graticulePaths.length;p++)
    {
        var holdArray=[]
        var graticulePath=graticulePaths[p]
        var d=graticulePath.getAttribute("d")
        var d=d.replace(/M/,"").replace(/L/g,",")
        var dSplit=d.split(",")
        for(var k=0;k<dSplit.length;k++)
        {
        var x=dSplit[k]
        var y=dSplit[k+1]
        holdArray.push([x,y])
        k++
        }
        gratPathPointArray.push(holdArray)
    }

    threeJSVectors()

function threeJSVectors()
{
    initThree()

    var geometry = new THREE.Geometry();
    var material= new THREE.LineBasicMaterial({color: 0xaaaaaa})


    var splineVectors=[]
    //=========graticule lines==============
    gratPathPointArray.forEach(function(line)
    {
        d3.pairs(line.map(vertex), function(a, b)
        {
            geometry.vertices.push(a, b);
        });
    });

    scene.add( new THREE.LineSegments(geometry, material))

    animate()
    render()
}

//----build three.js graticule---
var renderer,camera,controls,scene
function initThree()
{
    var width = 600,
    height = 600

    scene = new THREE.Scene;
    camera = new THREE.PerspectiveCamera(70, width / height, 1, 1000);
    renderer = new THREE.WebGLRenderer({alpha: true});

    camera.position.x = -7;
    camera.position.y = -245;
    camera.position.z = 315;
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(width, height);
    container.appendChild(renderer.domElement);
    controls = new THREE.OrbitControls( camera,renderer.domElement );
    controls.addEventListener( 'change', render );
}
//---does not apply projection????---
//--convert path point to vector---
function vertex(point)
{
    //---get lng/lat degrees of each projection point--
     var invertLL=projection.invert(point)
       //---to radians--
    var lambda = invertLL[0] * Math.PI / 180,
    phi = invertLL[1] * Math.PI / 180,
    cosPhi = Math.cos(phi);
    return new THREE.Vector3(
        radius * cosPhi * Math.cos(lambda),
        radius * cosPhi * Math.sin(lambda),
        radius * Math.sin(phi)
    );
}

function animate()
{
	requestAnimationFrame(animate);
	controls.update();
}

function render()
{
	camera.lookAt( scene.position );
    renderer.render(scene, camera);

}
</script>

</body>
</html>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

我不知道你在那里做什么:)你的顶点(点)函数正确地确定了2D点的3D位置,从而重建了地球。但是,如果您只想要扁平形状,请检查:

 <!DOCTYPE HTML>

<html>

<head>
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="https://d3js.org/d3.geo.projection.v0.min.js"></script>
<script src="https://d3js.org/d3-array.v1.min.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/r86/build/three.min.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/r86/examples/js/controls/OrbitControls.js"></script>

  <title>3D Mollweide Projection</title>
  <style type="text/css">
  <!--
 .background {
  fill: #a4bac7;
}

.foreground {
  fill: none;
  stroke: #333;
  stroke-width: 1.5px;
}

.graticule {
  fill: none;
  stroke: #fff;
  stroke-width: .5px;
}


  -->
  </style>
</head>

<body style=font-family:arial>

<center>SVG Drawing (mollweide projection):</center>
<svg id=projectionSVG width=600 height=440 overflow=visible />
Three.js Drawing (rotate and mousewheel zoom):<br>
<div  id=container></div>

<script>
var projection
var gratPathPointArray=[]
var radius = 230


//----build svg graticule----
    projection = d3.geo.mollweide()
    .scale(120);

    var path = d3.geo.path()
    .projection(projection);

    var graticule = d3.geo.graticule();

    var svg= d3.select("#projectionSVG")
    svg.append("path")
    .datum(graticule.outline)
    .attr("class", "background")
    .attr("d", path);

    var graticuleG=svg.append("g")
    .attr("class", "graticule")
    .selectAll("path")
    .data(graticule.lines)
    .enter().append("path")
    .attr("d", path);


    var graticulePathG=projectionSVG.lastChild

    var graticulePaths=graticulePathG.childNodes
    for(p=0;p<graticulePaths.length;p++)
    {
        var holdArray=[]
        var graticulePath=graticulePaths[p]
        var d=graticulePath.getAttribute("d")
        var d=d.replace(/M/,"").replace(/L/g,",")
        var dSplit=d.split(",")
        for(var k=0;k<dSplit.length;k++)
        {
        var x=dSplit[k]
        var y=dSplit[k+1]
        holdArray.push([x,y])
        k++
        }
        gratPathPointArray.push(holdArray)
    }

    threeJSVectors()

function threeJSVectors()
{
    initThree()

    var geometry = new THREE.Geometry();
    var material= new THREE.LineBasicMaterial({color: 0xaaaaaa})


    var splineVectors=[]
    //=========graticule lines==============
    gratPathPointArray.forEach(function(line)
    {
        d3.pairs(line.map(vertex), function(a, b)
        {
            geometry.vertices.push(a, b);
        });
    });

    scene.add( new THREE.LineSegments(geometry, material))

    animate()
    render()
}

//----build three.js graticule---
var renderer,camera,controls,scene
function initThree()
{
    var width = 600,
    height = 600

    scene = new THREE.Scene;
    camera = new THREE.PerspectiveCamera(70, width / height, 1, 1000);
    renderer = new THREE.WebGLRenderer({alpha: true});

    camera.position.x = -7;
    camera.position.y = -245;
    camera.position.z = 315;
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(width, height);
    container.appendChild(renderer.domElement);
    controls = new THREE.OrbitControls( camera,renderer.domElement );
    controls.addEventListener( 'change', render );
}
//---does not apply projection????---
//--convert path point to vector---
function vertex(point)
{
    return new THREE.Vector3(
        point[0] - 500,
        point[1] - 150,
        0
    );
}

function animate()
{
	requestAnimationFrame(animate);
	controls.update();
}

function render()
{
	camera.lookAt( scene.position );
    renderer.render(scene, camera);

}
</script>

</body>
</html>