抱歉之前没看清题目,弦长相等的话就只能FindRoot了。
优化主要体现在两方面,一是利用椭圆的轴对称性分奇偶处理只计算上半圆,二是利用FindRoot的向量模式整体求解。除此之外就是一些比较细节的地方,比如去掉Sqrt之类。
代码如下,400用时1秒多一点。进一步优化的话可以加上编译,不过感觉这个效率已经可以接受了(编译过的代码贴在下面了,400用时0.05s)
eqnEvenQ[\[Theta]list_List] := Module[{lenList},
lenList =
2 (a0^2 + b0^2 + (-a0^2 + b0^2) Cos[#1 + #2]) Sin[(#1 - #2)/
2]^2 & @@@ Partition[N@Flatten@{0, \[Theta]list, \[Pi]}, 2, 1];
lenList[[2 ;; -1]] - lenList[[1 ;; -2]]
];
eqnOddQ[\[Theta]list_List] := Module[{lenList},
lenList =
2 (a0^2 + b0^2 + (-a0^2 + b0^2) Cos[#1 + #2]) Sin[(#1 - #2)/
2]^2 & @@@ Partition[N@Flatten@{0, \[Theta]list}, 2, 1];
AppendTo[lenList, (2 b0 Sin[\[Theta]list[[-1]]])^2];
lenList[[2 ;; -1]] - lenList[[1 ;; -2]]
];
plot[n_?EvenQ] := Module[{\[Theta]list},
\[Theta]list =
Flatten[{0, \[Theta] /.
FindRoot[
eqnEvenQ[\[Theta]], {\[Theta],
Range[n/2 - 1]/(n/2)*\[Pi]}], \[Pi]}];
ParametricPlot[{a0 Cos[t], b0 Sin[t]}, {t, 0, 2 Pi},
Epilog -> {Red,
Line[{a0 Cos[#], b0 Sin[#]} & /@
Join[\[Theta]list, -Reverse@\[Theta]list[[1 ;; -2]]]]},
AspectRatio -> Automatic]
];
plot[n_?OddQ] := Module[{\[Theta]list},
\[Theta]list =
Flatten[{0, \[Theta] /.
FindRoot[
eqnOddQ[\[Theta]], {\[Theta],
Range[(n - 1)/2]/((n - 1)/2)*\[Pi]}]}];
ParametricPlot[{a0 Cos[t], b0 Sin[t]}, {t, 0, 2 Pi},
Epilog -> {Red,
Line[{a0 Cos[#], b0 Sin[#]} & /@
Join[\[Theta]list, -Reverse@\[Theta]list]]},
AspectRatio -> Automatic]
];
plot[400] // AbsoluteTiming
把编译过的也贴上来吧,400用时0.05s
eqnEvenQ[\[Theta]list_List] := cEven[\[Theta]list];
cEven = With[{a0 = a0, b0 = b0},
Compile[{{\[Theta], _Real, 1}},
Module[{lenList, \[Theta]list},
\[Theta]list = Append[Prepend[\[Theta], 0], \[Pi]];
lenList =
Table[2 (a0^2 +
b0^2 + (-a0^2 +
b0^2) Cos[\[Theta]list[[i]] + \[Theta]list[[
i + 1]]]) Sin[(\[Theta]list[[i]] - \[Theta]list[[
i + 1]])/2]^2, {i, Length[\[Theta]list] - 1}];
lenList[[2 ;; -1]] - lenList[[1 ;; -2]]
], CompilationTarget -> "C"]
];
eqnOddQ[\[Theta]list_List] := cOdd[\[Theta]list];
cOdd = With[{a0 = a0, b0 = b0},
Compile[{{\[Theta], _Real, 1}},
Module[{lenList, \[Theta]list},
\[Theta]list = Prepend[\[Theta], 0];
lenList =
Table[2 (a0^2 +
b0^2 + (-a0^2 +
b0^2) Cos[\[Theta]list[[i]] + \[Theta]list[[
i + 1]]]) Sin[(\[Theta]list[[i]] - \[Theta]list[[
i + 1]])/2]^2, {i, Length[\[Theta]list] - 1}];
AppendTo[lenList, (2 b0 Sin[\[Theta]list[[-1]]])^2];
lenList[[2 ;; -1]] - lenList[[1 ;; -2]]
], CompilationTarget -> "C"]
];
plot[n_?EvenQ] := Module[{\[Theta]list},
\[Theta]list =
Flatten[{0, \[Theta] /.
FindRoot[
eqnEvenQ[\[Theta]], {\[Theta],
Range[n/2 - 1]/(n/2)*\[Pi]}], \[Pi]}];
ParametricPlot[{a0 Cos[t], b0 Sin[t]}, {t, 0, 2 Pi},
Epilog -> {Red,
Line[{a0 Cos[#], b0 Sin[#]} & /@
Join[\[Theta]list, -Reverse@\[Theta]list[[1 ;; -2]]]]},
AspectRatio -> Automatic]
];
plot[n_?OddQ] := Module[{\[Theta]list},
\[Theta]list =
Flatten[{0, \[Theta] /.
FindRoot[
eqnOddQ[\[Theta]], {\[Theta],
Range[(n - 1)/2]/((n - 1)/2)*\[Pi]}]}];
ParametricPlot[{a0 Cos[t], b0 Sin[t]}, {t, 0, 2 Pi},
Epilog -> {Red,
Line[{a0 Cos[#], b0 Sin[#]} & /@
Join[\[Theta]list, -Reverse@\[Theta]list]]},
AspectRatio -> Automatic]
];
plot[400] // AbsoluteTiming
==============================以下原答案=============================
可以用椭圆积分EllipticE,然后利用InverseFunction代替FindRoot。函数的具体说明参考帮助文档,我这里就只发代码了
a0 = 4;
b0 = 3;
plot[n_] := Module[{\[Theta]list},
\[Theta]list =
InverseFunction[
EllipticE[#, 1 - a0^2/b0^2] &] /@ (N@
EllipticE[2 \[Pi], 1 - a0^2/b0^2]*Range[n]/n);
ParametricPlot[{a0 Cos[t], b0 Sin[t]}, {t, 0, 2 Pi},
Epilog -> {Red, Line[{a0 Cos[#], b0 Sin[#]} & /@ \[Theta]list]},
AspectRatio -> Automatic]
];
plot[400] // AbsoluteTiming
400份在我这里用时0.3秒左右