Kas*_*ers 13 numerical wolfram-mathematica zero contour
我有两个变量的函数f(x,y),其中我需要知道它与零交叉的曲线的位置.ContourPlot非常有效地做到了这一点(即:它使用巧妙的多网格方法,而不仅仅是一个强力细粒度扫描),但只是给了我一个情节.我想有一组值{x,y}(具有一些指定的分辨率)或者可能有一些插值函数,它允许我访问这些轮廓的位置.
想过从ContourPlot的FullForm中提取这个,但这似乎有点像黑客.有更好的方法吗?
Sza*_*lcs 12
如果您最终从中提取点数ContourPlot,这是一种简单的方法:
points = Cases[
Normal@ContourPlot[Sin[x] Sin[y] == 1/2, {x, -3, 3}, {y, -3, 3}],
Line[pts_] -> pts,
Infinity
]
Join @@ points (* if you don't want disjoint components to be separate *)
Run Code Online (Sandbox Code Playgroud)
编辑
它似乎ContourPlot不会产生非常精确的轮廓.它们当然是用于绘图而且足够好,但这些要点并不完全在于轮廓:
In[78]:= Take[Join @@ points /. {x_, y_} -> Sin[x] Sin[y] - 1/2, 10]
Out[78]= {0.000163608, 0.0000781187, 0.000522698, 0.000516078,
0.000282781, 0.000659909, 0.000626086, 0.0000917416, 0.000470424,
0.0000545409}
Run Code Online (Sandbox Code Playgroud)
我们可以尝试用自己的方法来追踪轮廓,但是以一般的方式做这件事会很麻烦.这是一个概念,适用于具有平滑轮廓的平滑变化的功能:
从某个点(pt0)开始,找到沿着渐变的轮廓的交点f.
现在我们在轮廓上有一个点.沿着轮廓的切线移动一个固定的步骤(resolution),然后从步骤1开始重复.
这是一个基本实现,只适用于可以符号区分的函数:
rot90[{x_, y_}] := {y, -x}
step[f_, pt : {x_, y_}, pt0 : {x0_, y0_}, resolution_] :=
Module[
{grad, grad0, t, contourPoint},
grad = D[f, {pt}];
grad0 = grad /. Thread[pt -> pt0];
contourPoint =
grad0 t + pt0 /. First@FindRoot[f /. Thread[pt -> grad0 t + pt0], {t, 0}];
Sow[contourPoint];
grad = grad /. Thread[pt -> contourPoint];
contourPoint + rot90[grad] resolution
]
result = Reap[
NestList[step[Sin[x] Sin[y] - 1/2, {x, y}, #, .5] &, {1, 1}, 20]
];
ListPlot[{result[[1]], result[[-1, 1]]}, PlotStyle -> {Red, Black},
Joined -> True, AspectRatio -> Automatic, PlotMarkers -> Automatic]
Run Code Online (Sandbox Code Playgroud)

红点是"起点",而黑点是轮廓的痕迹.
编辑2
也许这是一个更简单,更好的解决方案,使用类似的技术来使我们得到的点ContourPlot更精确.从初始点开始,然后沿着渐变移动,直到我们与轮廓相交.
请注意,此实现也适用于无法以符号方式区分的函数.只需定义函数,就f[x_?NumericQ, y_?NumericQ] := ...好像这样.
f[x_, y_] := Sin[x] Sin[y] - 1/2
refine[f_, pt0 : {x_, y_}] :=
Module[{grad, t},
grad = N[{Derivative[1, 0][f][x, y], Derivative[0, 1][f][x, y]}];
pt0 + grad*t /. FindRoot[f @@ (pt0 + grad*t), {t, 0}]
]
points = Join @@ Cases[
Normal@ContourPlot[f[x, y] == 0, {x, -3, 3}, {y, -3, 3}],
Line[pts_] -> pts,
Infinity
]
refine[f, #] & /@ points
Run Code Online (Sandbox Code Playgroud)
从ContourPlot(可能由于David Park)提取点数略有变化:
pts = Cases[
ContourPlot[Cos[x] + Cos[y] == 1/2, {x, 0, 4 Pi}, {y, 0, 4 Pi}],
x_GraphicsComplex :> First@x, Infinity];
Run Code Online (Sandbox Code Playgroud)
或(作为{x,y}点的列表)
ptsXY = Cases[
Cases[ContourPlot[
Cos[x] + Cos[y] == 1/2, {x, 0, 4 Pi}, {y, 0, 4 Pi}],
x_GraphicsComplex :> First@x, Infinity], {x_, y_}, Infinity];
Run Code Online (Sandbox Code Playgroud)
编辑
正如这里所讨论的,Paul Abbott在Mathematica期刊中发表的一篇文章(在间隔中查找根)给出了以下两种替代方法,用于从ContourPlot获取{x,y}值列表,包括(!)
ContourPlot[...][[1, 1]]
Run Code Online (Sandbox Code Playgroud)
对于上面的例子
ptsXY2 = ContourPlot[
Cos[x] + Cos[y] == 1/2, {x, 0, 4 Pi}, {y, 0, 4 Pi}][[1, 1]];
Run Code Online (Sandbox Code Playgroud)
和
ptsXY3 = Cases[
Normal@ContourPlot[
Cos[x] + Cos[y] == 1/2, {x, 0, 4 Pi}, {y, 0, 4 Pi}],
Line[{x__}] :> x, Infinity];
Run Code Online (Sandbox Code Playgroud)
哪里
ptsXY2 == ptsXY == ptsXY3
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7134 次 |
| 最近记录: |