Plotly.js sphere with mesh3d

岁酱吖の 提交于 2021-02-10 16:19:03

问题


I'm trying to plot a simple sphere with plotly.js. However when using the mesh3d option the plot of the sphere comes out looking very rough and unrefined. Any advice on how to smooth it out would be appreciated.

a = [];
b = [];
c = [];

phiArr = [];
thetaArr = [];
function makeInterval(startValue, stopValue, numPoints) {
    var arr = [];
    var step = (stopValue - startValue) / (numPoints - 1);
    for (var i = 0; i < numPoints; i++) {
      arr.push(startValue + (step * i));
    }
    return arr;
  }
phiArr = makeInterval(0, Math.PI, 20);
thetaArr = makeInterval(0, 2*Math.PI, 20); 

for (i=0; i<thetaArr.length; i++){
    for (j=0; j<phiArr.length; j++){
        a.push(Math.cos(thetaArr[i]) * Math.sin(phiArr[j]));
        b.push(Math.sin(thetaArr[i]) * Math.sin(phiArr[j]));   
        c.push(Math.cos(phiArr[j]));
    }
}

var data = [{
    opacity: 0.2,
    color: 'rgb(211,211,211)',
    type: 'mesh3d',
    x: a,
    y: b,
    z: c,
}];


var layout = {
    title: 'My Sphere',
    autosize: false,
    width: 600,
    height: 600,
    margin: {
        l: 65,
        r: 50,
        b: 65,
        t: 90,
    }
};
Plotly.newPlot('myDiv', data, layout);
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id="myDiv"></div>


回答1:


The simplest solution draws two semispheres:

a = [];
b = [];
c = [];

phiArr = [];
thetaArr = [];
function makeInterval(startValue, stopValue, numPoints) {
    var arr = [];
    var step = (stopValue - startValue) / (numPoints - 1);
    for (var i = 0; i < numPoints; i++) {
      arr.push(startValue + (step * i));
    }
    return arr;
  }

////////////////
// EDIT 1: calculate only upper half of the sphere

phiArr = makeInterval(0, Math.PI/2, 20);  
///////////////
thetaArr = makeInterval(0, 2*Math.PI, 20); 

for (i=0; i<thetaArr.length; i++){
    for (j=0; j<phiArr.length; j++){
        a.push(Math.cos(thetaArr[i]) * Math.sin(phiArr[j]));
        b.push(Math.sin(thetaArr[i]) * Math.sin(phiArr[j]));   
        c.push(Math.cos(phiArr[j]));
    }
}

const dataitem = {
    opacity: 0.2,
    color: 'rgb(211,211,211)',
    type: 'mesh3d',
    x: a,
    y: b,
    z: c,
}

//////////////////////
// EDIT 2: obtain the second half of the sphere by duplicating 
// the upper semisphere ("..." operator before "dataitem") and 
// changing its "z" attribute into negative vales:

var data = [
    dataitem,
    {...dataitem, z: c.map(v => -v)}
];
//////////////////////

var layout = {
    title: 'My Sphere',
    autosize: false,
    width: 600,
    height: 600,
    margin: {
        l: 65,
        r: 50,
        b: 65,
        t: 90,
    }
};
Plotly.newPlot('myDiv', data, layout);
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id="myDiv"></div>




回答2:


From great source from @Josef Wittmann , here it is a function ready to be copied into your code:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta name="generator" content="PSPad editor, www.pspad.com">
  <title></title>
 
  </head>
  <body>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
  <script>

/////////////////////
function getSphereData(name, width, height, color, opacity) {

    var layout = {
        title: name,
        autosize: false,
        width: width,
        height: height,
        margin: {
            l: 65,
            r: 50,
            b: 65,
            t: 90,
        }
    };

    
    a = [];
    b = [];
    c = [];
    
    var phiArr = [];
    var thetaArr = [];
    var numPoints = 20;
    
    var startValue = 0;
    var stopValuePhi = Math.PI/2;
    var stopValueTheta = 2*Math.PI;
    var stepPhi = stopValuePhi / (numPoints - 1);
    var stepTheta = stopValueTheta / (numPoints - 1);
    for (var i = 0; i < numPoints; i++) {
      phiArr.push(stepPhi * i);
      thetaArr.push(stepTheta * i);
    }

    for (i=0; i<thetaArr.length; i++){
        for (j=0; j<phiArr.length; j++){
            a.push(Math.cos(thetaArr[i]) * Math.sin(phiArr[j]));
            b.push(Math.sin(thetaArr[i]) * Math.sin(phiArr[j]));   
            c.push(Math.cos(phiArr[j]));
        }
    }


    const dataitem = {
        opacity: opacity,
        color: 'rgb(211,211,211)',
        type: 'mesh3d',
        x: a,
        y: b,
        z: c,
    }   
        

    // Obtain the second half of the sphere by 
    // duplicating  the upper semisphere ("..." operator before "dataitem") and 
    // changing its "z" attribute into negative vales:
    
    var data = [
        dataitem,
        {...dataitem, z: c.map(v => -v)}
    ];
    
    return {data:data, layout:layout};
}
////////////////////    

// Example usage:
window.onload = function () {
    var sphere = getSphereData("Sphere", 600,600, 0.3, 'rgb(211,211,211)');
    Plotly.newPlot('myDiv',  sphere.data, sphere.layout);  
}
  </script>
  
  
    <div id="myDiv" name="myDiv"></div>
  </body>
</html>

JSFiddle: https://jsfiddle.net/spacexplorer2020/wceo7hmn/



来源:https://stackoverflow.com/questions/65622546/plotly-js-sphere-with-mesh3d

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!