如何计算椭圆的周长

时间:2017-02-18 04:12:01

标签: python math ellipse

我想用给定的次轴和长轴值计算椭圆的周长。我目前正在使用 Python

我计算了椭圆的短轴和长轴长度,即 a b

计算面积很容易,但我想计算椭圆的周长来计算圆角长度。你有什么主意吗 ?

5 个答案:

答案 0 :(得分:4)

定义问题:主轴,短轴与半主轴,半轴不同 OP应该是明确的,那些抓住,与在线解决方案相比应该是

enter image description here

您可以(以数字方式)解决问题,我使用完整的轴定义

from sympy import *
a, b, w = symbols('a b w')

x = a/2 * cos(w)
y = b/2 * sin(w)

dx = diff(x, w)
dy = diff(y, w)

ds = sqrt(dx**2 + dy**2)

def perimeter(majr, minr):
    return Integral(ds.subs([(a,majr),(b,minr)]), (w, 0, 2*pi)).evalf().doit()

print('test1: a, b = 1 gives dia = 1 circle,  perimeter/pi = ',
      perimeter(1, 1)/pi.evalf())

print('test2: a, b = 4,6 ellipse perimeter = ', perimeter(4,6))

test1: a, b = 1 gives dia = 1 circle,  perimeter/pi =  1.00000000000000
test2: a, b = 4,6 ellipse perimeter =  15.8654395892906

它也可以导出符号ds方程作为函数来尝试其他Python lib集成函数

func_dw = lambdify((w, a, b), ds)

from scipy import integrate

print(integrate.quad(func_dw, 0, 2*np.pi, args=(4, 6)))

(15.865439589290586, 2.23277254813499e-12)  
  

scipy.integrate.quad(func,a,b,args =()...
  返回:
  y:float,从a到b的func的积分。
  abserr:float,估计的   结果中的绝对错误

答案 1 :(得分:2)

根据Ramanujan的寻找椭圆周长的近似公式 - >

>>> import math
>>>
>>> def calculate_perimeter(a,b):
...     perimeter = math.pi * ( 3*(a+b) - math.sqrt( (3*a + b) * (a + 3*b) ) )
...     return perimeter
...
>>> calculate_perimeter(2,3)
15.865437575563961

您可以将结果与google calculator进行比较

答案 2 :(得分:2)

如Mark所说的in a comment,您可以简单地使用scipy.special.ellipe。此实现使用complete elliptic integral of the second kind中近似的original C function ellpe.c。如scipy的文档所述:

计算使用近似值

E(m)〜P(1-m)-(1-m)log(1-m)Q(1-m)

其中 P Q 是十阶多项式

from scipy.special import ellipe

a = 3.5
b = 2.1
# eccentricity squared
e_sq = 1.0 - b**2/a**2
# circumference formula
C = 4 * a * ellipe(e_sq)
17.868899204378693

答案 3 :(得分:1)

这是一种比较上述答案的元答案。

实际上,Ramanujan 的二次近似比 Rezwan4029 的答案中的公式(使用 Ramanujan 的第一近似)更准确,也更复杂一些。第二个近似值是:

π * ((a+b) + (3(a-b)²) / (10*(a+b) + sqrt(a² + 14ab + b²)))

但我查看了上述所有答案并比较了他们的结果。出于稍后会变得显而易见的充分理由,我选择了 Gabriel 的版本作为真相来源,即与其他版本进行比较的价值。

对于 Rezwan4029 给出的答案,我在 2**(-10) .. 2**9 的网格上绘制了误差百分比。这是结果(两个轴都是幂,所以点 (3|5) 显示了半径为 2**3, 2**5 的椭圆的误差):

Error of Rezwan4029's answer

很明显,只有功率的差异与误差有关,所以我也画了这个:

Error of Rezwan4029's answer over power difference

无论如何,误差范围从圆的 0 到极偏心椭圆的 0.45%。根据您的应用,这可能是完全可以接受的,或者使解决方案无法使用。

对于拉马努金第二近似公式,情况非常相似,误差约为前者的 1/10:

Error of Ramanujan's formula

Error of Ramanujan's formula over power difference

Mark Dickinson 的 sympy 解决方案和 Gabriel 的 scipy 解决方案仍然有一些差异,但它们最多在 1e-6 的范围内,所以是一个不同的球场。但是sympy的解决方案非常慢,所以在大多数情况下可能应该使用scipy版本。

为了完整起见,这里是误差的分布(这次误差的对数在z轴上,否则它不会告诉我们太多,所以高度大致对应于有效位数):

Log of difference between scipy and sympy Log of difference between scipy and sympy over difference of power

结论:使用scipy方法。它很快,而且很可能非常准确,甚至可能是三种建议方法中最准确的。

答案 4 :(得分:0)

有一些很好的答案,但我想在精确/近似计算以及计算速度方面澄清一些事情。

h = pow(a-b, 2.0) / pow(a+b, 2.0)
C = (math.pi * (a+b) * (256.0 - 48.0 * h - 21.0 * h*h)
       /(256.0 - 112.0 * h + 3.0 * h*h))

还有许多其他方法,但这些方法对于普通应用程序最有用。