4
votes

I want to calculate perimeter of the ellipse with given values of minor and major axis value. I'm currently using Python.

I have calculated minor axis and major axis length for ellipse i.e. a and b.

It's easy to calculate area but I want to calculate perimeter of ellipse for calculating rounded length. Do you have any idea ?

6
I've already visited there and get confusedSagar Gautam
a lots of approximation there which one is best to use any idea ??Sagar Gautam
@SagarGautam none of them is the best as you have to select approximation suited for your ellipse. Which one choose depends on the eccentricity of ellipse. You can also do the curve integral numericaly by transforming your ellipse to set of lines and sum their length ...Spektre
I've thought there is a simple equation for perimeter like area but it's complex process. I was wrongSagar Gautam

6 Answers

6
votes

According to Ramanujan's first approximation formula of finding perimeter of Ellipse ->

>>> 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

You can compare the result with google calculator also

5
votes

a definition problem: major, minor axes differ from semi-major, semi-minor
the OP should be clear, those grabbing, comparing to online solutions should be too

enter image description here

you can get sympy to (numerically) solve the problem, I'm using the full axes definition

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

its also possible to export the symbolic ds equation as a function to try with other Python lib integration functions

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=()...
Returns:
y : float, The integral of func from a to b.
abserr : float, An estimate of the absolute error in the result

4
votes

As Mark stated in a comment, you can simply use scipy.special.ellipe. This implementation uses the complete elliptic integral of the second kind as approximated in the original C function ellpe.c. As described in scipy's docs:

the computation uses the approximation,

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

where P and Q are tenth-order polynomials

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
2
votes

This is kind of a meta answer comparing the ones above.

Actually, Ramanujan's second approximation is more accurate and a bit more complex than the formula in Rezwan4029's answer (which uses Ramanujan's first approximation). The second approximation is:

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

But I looked at all the answers above and compared their results. For good reasons which will become apparent later I chose Gabriel's version as the truth source, i.e. the value to compare the others against.

For the answer Rezwan4029 gave, I plotted the error in percent over a grid of 2**(-10) .. 2**9. This is the result (both axes are the power, so the point (3|5) shows the error for an ellipse of radii 2**3, 2**5):

Error of Rezwan4029's answer

It is obvious that only the difference in the power is relevant for the error, so I also plotted this:

Error of Rezwan4029's answer over power difference

What emerges in any case is that the error ranges from 0 for circles to 0.45% for extremely eccentric ellipses. Depending on your application this might be completely acceptable or render the solution unusable.

For Ramanujan's 2nd approximation formula the situation is very similar, the error is about 1/10 of the former:

Error of Ramanujan's formula

Error of Ramanujan's formula over power difference

The sympy solution of Mark Dickinson and the scipy solution of Gabriel still have still some differences, but they are at most in the range of 1e-6, so a different ball park. But the sympy solution is extremely slow, so the scipy version probably should be used in most cases.

For the sake of completeness, here's a distribution of the error (this time the logarithm of the error is on the z-axis, otherwise it wouldn't tell us very much, so the height corresponds roughly with the negative of the number of valid digits):

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

Conclusion: Use the scipy method. It's fast and very likely very accurate, maybe even the most accurate of the three proposed methods.

1
votes

There are some good answers but I wanted to clarify things in terms of exact/approximate calculations, as well as computational speed.

  • For the exact circumference, use scipy.special.ellipe as described by @Gabriel. Since this is implemented in C, it is also the fastest approach.

  • For the exact circumference using pure python, check out my pyellipse code https://gist.github.com/TimSC/4be20baeac7890e15773d31efb752d23 This code is about 5 times slower than using scipy.special.ellipe. The approach used is Gauss Kummer for low eccentricity, and Cayley 1876 for high eccentricity as suggested by http://www.numericana.com/answer/ellipse.htm#convergence

  • For good approximation that is fast to compute and has no scipy dependency, see Ramanujan's 2nd approximation as described by @Alfe

  • For another good approximation that is fast to compute (that avoids using square root), use the Padé approximation by Jacobsen and Waadeland 1985 http://www.numericana.com/answer/ellipse.htm#hudson

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))

There are many other approaches but these are the most useful for normal applications.

1
votes

For good approximation use the improvement made by a russian mathematician few years ago (not infinite series calculation but convergence calculation using AGM and MAGM) http://www.ams.org/notices/201208/rtx120801094p.pdf or
https://indico-hlit.jinr.ru/event/187/contributions/1769/attachments/543/931/SAdlaj.pdf An use is there: surface plots in matplotlib using a function z = f(x,y) where f cannot be written in standard functions. HowTo? (script for drawing a surface including isoperimeter curves: it means all X-Y from a curve are all half-parameter of all ellipses having the same perimeter). Or contact direct the mathematician, or buy at springernature.com the article "An Arithmetic-Geometric Mean of a Third Kind!",Semjon Adlaj, Federal Research Center “Informatics and Control” of the Russian Academy of Sciences, Vavilov St. 44, Moscow 119333, Russia [email protected]