我想从 Geometry / Wolfram Mathematica 人那里得到帮助。我想在 JavaScript (p5.js) 环境中可视化这个 3D Rose。
该图最初是Paul Nylander在 2004-2006 年使用 wolfram 语言生成的,下面是代码:
Rose[x_, theta_] := Module[{
phi = (Pi/2)Exp[-theta/(8 Pi)],
X = 1 - (1/2)((5/4)(1 - Mod[3.6 theta, 2 Pi]/Pi)^2 - 1/4)^2},
y = 1.95653 x^2 (1.27689 x - 1)^2 Sin[phi];
r = X(x Sin[phi] + y Cos[phi]);
{r Sin[theta], r Cos[theta], X(x Cos[phi] - y Sin[phi]), EdgeForm[]
}];
ParametricPlot3D[
Rose[x, theta], {x, 0, 1}, {theta, -2 Pi, 15 Pi},
PlotPoints -> {25, 576}, LightSources -> {{{0, 0, 1}, RGBColor[1, 0, 0]}},
Compiled -> False
]
我尝试在 JavaScript 中实现该代码,如下所示。
function rose(){
for(let theta = 0; theta < 2700; theta += 3){
beginShape(POINTS);
for(let x = 2.3; x < 3.3; x += 0.02){
let phi = (180/2) * Math.exp(- theta / (8*180));
let X = 1 - (1/2) * pow(((5/4) * pow((1 - (3.6 * theta % 360)/180), 2) - 1/4), 2);
let y = 1.95653 * pow(x, 2) * pow((1.27689*x - 1), 2) * sin(phi);
let r = X * (x*sin(phi) + y*cos(phi));
let pX = r * sin(theta);
let pY = r * cos(theta);
let pZ = (-X * (x * cos(phi) - y * sin(phi)))-200;
vertex(pX, pY, pZ);
}
endShape();
}
}
但我在下面得到了这个结果
与原来的不同,顶部的花瓣过于拉伸。
我怀疑
let y = 1.95653 * pow(x, 2) * pow((1.27689*x - 1), 2) * sin(phi);
可能应该像下面...
let y = pow(1.95653*x, 2*pow(1.27689*x - 1, 2*sin(theta)));
但这与原著相去甚远。
也许我在问一个愚蠢的问题,但我已经被困了好几天了。
如果您看到错误,请告诉我。提前谢谢你
更新:
我将 x 范围更改为原始定义的 0~1。还简化了如下所示的 JS 代码以查找错误。
function rose_debug(){
for(let theta = 0; theta < 15*PI; theta += PI/60){
beginShape(POINTS);
for(let x = 0.0; x < 1.0; x += 0.005){
let phi = (PI/2) * Math.exp(- theta / (8*PI));
let y = pow(x, 4) * sin(phi);
let r = (x * sin(phi) + y * cos(phi));
let pX = r * sin(theta);
let pY = r * cos(theta);
let pZ = x * cos(phi) - y * sin(phi);
vertex(pX, pY, pZ);
}
endShape();
}
}
此外,当我在“let y =...”行中删除术语“sin(phi)”时,如下所示
let y = pow(x, 4);
此时我开始怀疑原始方程的错误,但我发现了 Jorge García Tíscar(西班牙语)的另一篇文章,它成功地用 wolfram 语言实现了完全相同的 3D 玫瑰。
所以,现在我真的不知道原来的方程式是如何形成的
更新2:已解决
我按照 Trentium 的建议(下面的答案 2)坚持将 0 ~ 1 作为 x 的范围,然后将 r 和 X 乘以任意数字。
for(let x = 0; x < 1; x += 0.05){
r = r * 200;
X = X * 200;
简化的最终代码:
function rose_debug3(){
for(let x = 0; x <= 1; x += 0.05){
beginShape(POINTS);
for(let theta = -2*PI; theta <= 15*PI; theta += 17*PI/2000){
let phi = (PI / 2) * Math.exp(- theta / (8 * PI));
let X = 1 - (1/2) * ((5/4) * (1 - ((3.6 * theta) % (2*PI))/PI) ** 2 - 1/4) ** 2;
let y = 1.95653 * (x ** 2) * ((1.27689*x - 1) ** 2) * sin(phi);
let r = X * (x * sin(phi) + y * cos(phi));
if(0 < r){
const factor = 200;
let pX = r * sin(theta)*factor;
let pY = r * cos(theta)*factor;
let pZ = X * (x * cos(phi) - y * sin(phi))*factor;
vertex(pX, pY, pZ);
}
}
endShape();
}
}
我最初得到垂直拉伸图形的原因是 x 的范围。我认为改变 x 的范围只会影响图形的整个大小。但实际上,范围影响如下。
(1): 0 ~ x ~ 1, (2): 0 ~ x ~ 1.2
(3):0~x~1.5,(4):0~x~2.0
(5): 翻转 (4)
到目前为止,我看到了像上面(5)这样的结果,没有意识到正确的形状隐藏在那个图中。
非常感谢 Trentium 对我的帮助!