问题
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