公告:本站正式转型为非交互式静态网站!
转型:本站将通过笔记和博客的形式继续为大家服务,关于 Mathematica 问答服务请移步至QQ群:365716997
联系:如有问题请联系QQ群管理员,或发送邮件至:lixuan.xyz@qq.com。
感谢:最后非常感谢大家多年来的支持与帮助!
参考《互联网跟帖评论服务管理规定》《中华人民共和国网络安全法》《网络信息内容生态治理规定》《互联网用户账号信息管理规定》

—— 2022-11-27

欢迎来到 Mathematica 问答社区

提问时请贴上文本代码

语法高亮:在编辑器中点击

被禁止的话题:广告破解

请阅读:《提问的智慧》

备用域名:mma.ooo

支持LaTex数学公式
行内公式标识符:\$ 或“$\backslash ($”+“$\backslash )$”,
行间公式标识符:\$\$ 或 “$\backslash [$”+“$\backslash ]$”

社区建议QQ群:365716997

分类

+2 投票
2.9k 浏览
Block[{p = Pi/2  Exp[-(t/(8 Pi))], 
  u = 1 - 1/2 (1 - Mod[3.6 t, 2 Pi]/Pi)^4, y, r}, 
 y = 2 (x^2 - x)^2 Sin[p]; r = u (x Sin[p] + y Cos[p]); 
 ParametricPlot3D[{r Cos[t], r Sin[t], 
   u (x Cos[p] - y Sin[p])}, {t, -2 Pi, 15 Pi}, {x, 0, 1}, 
  Mesh -> None]]

这段代码用ParametricPlot3D有点慢,而Matlab和Python则是先生成离散的数据再画,MMA里如果用Table先生成数据,再用ListPointPlot3D或者Graphics3D + Polygon好像比较难得到同样的效果啊

用户: 孺子剑牛不群 (216 分)
parametricplot3d里的表达式,是一些简单计算,可考虑compile,但是可能会出一些新问题。评论by mobile.
图像很漂亮。像是月季花。
函数中用到了求模函数,估计这是慢的关键。
画散点图倒是可以,不过要想连成花瓣就难了。

1个回答

+3 投票

1. 今天深究了一下这个问题,发现源代码中ParametircPlot3D这句话如果完全不改得到的图,其实是个美丽的错误,也就是说这个图与函数并不相符。

首先是一些常规定义,将最终的函数表达式命名为expr。

p = Pi/2 Exp[-(t/(8 Pi))]; 
u = 1 - 1/2 (1 - Mod[3.6 t, 2 Pi]/Pi)^4; 
y = 2 (x^2 - x)^2 Sin[p]; 
r = u (x Sin[p] + y Cos[p]);
expr = {r Cos[t], r Sin[t], u (x Cos[p] - y Sin[p])};

2. 其次可以发现expr就是一堆简单计算,可以使用compile加速。

cf = With[{expr = N@expr}, Compile[{{t, _Real}, {x, _Real}}, expr]];

3. 然后验证一下cf和expr之间的误差,处于机器精度级别,可以忽略。

Table[Evaluate@expr - cf[t, x], {t, -2 Pi, 15 Pi, 0.2}, {x, 0, 1, 
     0.005}] // Abs // Flatten // Total
(*1.9026*10^-11*)

4. 然后就可以画图了。下面用表列出了画图的时间、图的点数。

SetOptions[ParametricPlot3D, Mesh -> None];
p1 = AbsoluteTiming[ParametricPlot3D[expr, {t, -2 Pi, 15 Pi}, {x, 0, 1}]];
p2 = AbsoluteTiming[
   ParametricPlot3D[cf[t, x], {t, -2 Pi, 15 Pi}, {x, 0, 1}, 
    PlotPoints -> 45]];
Grid[{{"point number", "timing", "picture"}, {Length@p1[[2, 1, 1]], 
   First@p1, p1[[2]]}, {Length@p2[[2, 1, 1]], First@p2, p2[[2]]}}, 
 Frame -> All, Alignment -> Center]

5. 可以发现,在点数相同的情况下,好像cf出来的图很丑,远没有expr的漂亮,expr的花瓣都是分开的,而且有点像多边形。实际上呢?来个细节图。

SetOptions[
  ParametricPlot3D, {Mesh -> None, ViewPoint -> {0, 0, Infinity}, 
   ImageSize -> 200}];
p1 = ParametricPlot3D[expr, {t, -2 Pi, 0}, {x, 0, 0.1}, PlotPoints -> 60];
p2 = ParametricPlot3D[cf[t, x], {t, -2 Pi, 0}, {x, 0, 1}, PlotPoints -> 55];
Grid[{{"p1 point:", "p2 point:"}, {Length@p1[[1, 1]], 
    Length@p2[[1, 1]]}, {p1, p2}}]

6. 可以看到,如果看细节图,就知道其实每个花瓣是圆弧形的,而且相互之间是完全连在一起的!所以最初的那个ParametircPlot3D得到的图,是完全错误的!

7. 那么完全正确的图是什么样的呢?是下面这样的(其实PlotPoint设置为200仍然不够,花瓣之间还是有些问题)。

SetOptions[
  ParametricPlot3D, {Mesh -> None, ViewPoint -> {1.3, -2.4, 2}}];
ParametricPlot3D[cf[t, x], {t, -2 Pi, 11 Pi}, {x, 0, 1}, 
 PlotPoints -> 200]

用户: 苹果 (2.2k 分)
修改于 用户:苹果
(原评论已删)本条评论最初说的内容大致是,用编译函数画出来的那幅图好像不对,因为从解析式来看,花瓣和花瓣应该是分开的。<-但是这个评论是错误的,仔细检查后会发现这个解析式只是在部分地方连续不可导,所以,才有了下面的评论。

苹果把能说的基本都说了,这里只稍微补充下。这个图形在全体Mod[3.6 t, 2 Pi]的位置连续不可导,直接画图效果不是很好,先分开画再Show在一起会好看些(执行速度也较在单幅图上加PlotPoints优):

cf = Compile[{t, x}, #, RuntimeOptions -> {"EvaluateSymbolically" -> False}] &@expr
Show[ParametricPlot3D[cf[t, x], {t, #1, #2}, {x, 0, 1}] & @@@ 
  Partition[Prepend[(Range[-3, 27] 2 π)/3.6, -2 π], 2, 1], PlotRange -> All]

 

“所以最初的那个ParametircPlot3D得到的图,是完全错误的!”。我并没有明确说编译和原表达式的计算数值结果(或剪切结果)是否错误。我是说,原表达式画出的图,是严重错误,也就是圆弧形被画成了折线形,而错误的折线形的花却比真实的圆弧形的花好看。在PlotPoint足够大时(例如最后的代码设置为200),应该剪切掉的区域已经小到基本可以忽略了。
嗯?你关注的是折线的问题啊?我是觉得花瓣没分开这点比较影响视觉效果。
折线对最终眼睛看到的图形的影响,远远大于剪切区域,也就是原始图≠我的图≈你的图。增加PlotPoints确实无法消除剪切区域,但是可以减小剪切区域,“应该剪切掉的区域已经小到基本可以忽略了”。
你的回答呢?我觉得很有意义啊。至少当时我是想去找剪切区域的解析表达式,就是没找到,然后就放弃了。还有删评论造成的最终的对话,感觉很诡异啊。
那个回答被我转换成上面的带了代码的那条评论了。最开始那条评论我修改之后又给补上了。(这边只能隐藏评论,不能删除……)
...