cengal.math.geometry.ellipse.versions.v_0.ellipse

Module Docstring Docstrings: http://www.python.org/dev/peps/pep-0257/

  1#!/usr/bin/env python
  2# coding=utf-8
  3
  4# Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space>
  5# 
  6# Licensed under the Apache License, Version 2.0 (the "License");
  7# you may not use this file except in compliance with the License.
  8# You may obtain a copy of the License at
  9# 
 10#     http://www.apache.org/licenses/LICENSE-2.0
 11# 
 12# Unless required by applicable law or agreed to in writing, software
 13# distributed under the License is distributed on an "AS IS" BASIS,
 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15# See the License for the specific language governing permissions and
 16# limitations under the License.
 17
 18
 19"""
 20Module Docstring
 21Docstrings: http://www.python.org/dev/peps/pep-0257/
 22"""
 23
 24from cengal.math.numbers import RationalNumber
 25from cengal.time_management.repeat_for_a_time import Tracer
 26from math import sqrt, pi, factorial
 27
 28__author__ = "ButenkoMS <gtalk@butenkoms.space>"
 29__copyright__ = "Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space>"
 30__credits__ = ["ButenkoMS <gtalk@butenkoms.space>", ]
 31__license__ = "Apache License, Version 2.0"
 32__version__ = "4.4.1"
 33__maintainer__ = "ButenkoMS <gtalk@butenkoms.space>"
 34__email__ = "gtalk@butenkoms.space"
 35# __status__ = "Prototype"
 36__status__ = "Development"
 37# __status__ = "Production"
 38
 39class Ellipse:
 40    """
 41    https://www.youtube.com/watch?v=5nW3nJhBHL0
 42    http://www.ebyte.it/library/docs/math05a/EllipsePerimeterApprox05.html
 43    """
 44    def __init__(self, a: RationalNumber, b: RationalNumber):
 45        self.a = a
 46        self.b = b
 47    
 48    def y(self, x: RationalNumber) -> RationalNumber:
 49        return self.b * sqrt(1 - (x / self.a)**2)
 50    
 51    @property
 52    def area(self):
 53        return pi * self.a * self.b
 54    
 55    @property
 56    def h(self):
 57        return ((self.a - self.b)**2) / ((self.a + self.b)**2)
 58    
 59    @property
 60    def e(self):
 61        return sqrt(self.a**2 - self.b**2) / self.a
 62    
 63    @property
 64    def c(self):
 65        return self.a * self.e
 66    
 67    @property
 68    def perimeter__kepler(self):
 69        return 2 * pi * sqrt(self.a * self.b)
 70    
 71    @property
 72    def perimeter__naive(self):
 73        return 2 * pi * ((self.a + self.b) / 2)
 74    
 75    @property
 76    def perimeter__euler(self):
 77        return 2 * pi * sqrt((self.a**2 - self.b**2) / 2)
 78    
 79    @property
 80    def perimeter__matt_parker__lazy(self):
 81        """Computationly efficient. Not more that 6.1% deviation (less than 5% for `1 / 75` ellipses)
 82
 83        Returns:
 84            _type_: _description_
 85        """
 86        a = max(self.a, self.b)
 87        b = min(self.a, self.b)
 88        return pi * ((6 * a) / 5 + (3 * b) / 4)
 89    
 90    @property
 91    def perimeter__best_of__euler__and__matt_parker__lazy(self):
 92        a = max(self.a, self.b)
 93        b = min(self.a, self.b)
 94        if (a / b) >= 0.8:
 95            return self.perimeter__matt_parker__lazy
 96        else:
 97            return self.perimeter__euler
 98    
 99    @property
100    def perimeter__ramanujan_1(self):
101        return pi * (3 * (self.a + self.b) - sqrt((3 * self.a + self.b) * (self.a + 3 * self.b)))
102    
103    @property
104    def perimeter__matt_parker__precise(self):
105        a = max(self.a, self.b)
106        b = min(self.a, self.b)
107        return pi * ((53 * a) / 3 + (717 * b) / 35 - sqrt(269 * a ** 2 + 667 * a * b + 371 * b ** 2))
108    
109    @property
110    def perimeter__best_of__ramanujan_1__and__matt_parker__precise(self):
111        a = max(self.a, self.b)
112        b = min(self.a, self.b)
113        if (a / b) >= 2.4:
114            return self.perimeter__matt_parker__precise
115        else:
116            return self.perimeter__ramanujan_1
117    
118    @property
119    def perimeter__ramanujan_2(self):
120        return pi * (self.a + self.b) * (1 + (3 * self.h) / (10 + sqrt(4 - 3 * self.h)))
121    
122    def perimeter__infinite_sum__time_lim(self, desired_approximation_time: float, return_iterations_num: bool = False):
123        e = self.e
124        first_multiplier = 2 * self.a * pi
125        second_multiplier = 1
126        tr = Tracer(desired_approximation_time)
127        while tr.iter():
128            i = tr.total_number_of_iterations_made
129            second_multiplier -= ((factorial(2 * i) ** 2) / ((2 ** i * factorial(i)) ** 4)) * ((e ** (2 * i)) / (2 * i - 1))
130
131        if return_iterations_num:
132            return first_multiplier * second_multiplier, tr.total_number_of_iterations_made
133        else:
134            return first_multiplier * second_multiplier
135    
136    def perimeter__infinite_sum__iter_lim(self, iterations_num: int):
137        e = self.e
138        first_multiplier = 2 * self.a * pi
139        second_multiplier = 1
140        for i in range(1, iterations_num + 1):
141            second_multiplier -= ((factorial(2 * i) ** 2) / ((2 ** i * factorial(i)) ** 4)) * ((e ** (2 * i)) / (2 * i - 1))
142
143        return first_multiplier * second_multiplier
144    
145    @staticmethod
146    def from_r1_r2(r1: RationalNumber, r2: RationalNumber):
147        return Ellipse((r1 + r2) / 2, 1)
class Ellipse:
 40class Ellipse:
 41    """
 42    https://www.youtube.com/watch?v=5nW3nJhBHL0
 43    http://www.ebyte.it/library/docs/math05a/EllipsePerimeterApprox05.html
 44    """
 45    def __init__(self, a: RationalNumber, b: RationalNumber):
 46        self.a = a
 47        self.b = b
 48    
 49    def y(self, x: RationalNumber) -> RationalNumber:
 50        return self.b * sqrt(1 - (x / self.a)**2)
 51    
 52    @property
 53    def area(self):
 54        return pi * self.a * self.b
 55    
 56    @property
 57    def h(self):
 58        return ((self.a - self.b)**2) / ((self.a + self.b)**2)
 59    
 60    @property
 61    def e(self):
 62        return sqrt(self.a**2 - self.b**2) / self.a
 63    
 64    @property
 65    def c(self):
 66        return self.a * self.e
 67    
 68    @property
 69    def perimeter__kepler(self):
 70        return 2 * pi * sqrt(self.a * self.b)
 71    
 72    @property
 73    def perimeter__naive(self):
 74        return 2 * pi * ((self.a + self.b) / 2)
 75    
 76    @property
 77    def perimeter__euler(self):
 78        return 2 * pi * sqrt((self.a**2 - self.b**2) / 2)
 79    
 80    @property
 81    def perimeter__matt_parker__lazy(self):
 82        """Computationly efficient. Not more that 6.1% deviation (less than 5% for `1 / 75` ellipses)
 83
 84        Returns:
 85            _type_: _description_
 86        """
 87        a = max(self.a, self.b)
 88        b = min(self.a, self.b)
 89        return pi * ((6 * a) / 5 + (3 * b) / 4)
 90    
 91    @property
 92    def perimeter__best_of__euler__and__matt_parker__lazy(self):
 93        a = max(self.a, self.b)
 94        b = min(self.a, self.b)
 95        if (a / b) >= 0.8:
 96            return self.perimeter__matt_parker__lazy
 97        else:
 98            return self.perimeter__euler
 99    
100    @property
101    def perimeter__ramanujan_1(self):
102        return pi * (3 * (self.a + self.b) - sqrt((3 * self.a + self.b) * (self.a + 3 * self.b)))
103    
104    @property
105    def perimeter__matt_parker__precise(self):
106        a = max(self.a, self.b)
107        b = min(self.a, self.b)
108        return pi * ((53 * a) / 3 + (717 * b) / 35 - sqrt(269 * a ** 2 + 667 * a * b + 371 * b ** 2))
109    
110    @property
111    def perimeter__best_of__ramanujan_1__and__matt_parker__precise(self):
112        a = max(self.a, self.b)
113        b = min(self.a, self.b)
114        if (a / b) >= 2.4:
115            return self.perimeter__matt_parker__precise
116        else:
117            return self.perimeter__ramanujan_1
118    
119    @property
120    def perimeter__ramanujan_2(self):
121        return pi * (self.a + self.b) * (1 + (3 * self.h) / (10 + sqrt(4 - 3 * self.h)))
122    
123    def perimeter__infinite_sum__time_lim(self, desired_approximation_time: float, return_iterations_num: bool = False):
124        e = self.e
125        first_multiplier = 2 * self.a * pi
126        second_multiplier = 1
127        tr = Tracer(desired_approximation_time)
128        while tr.iter():
129            i = tr.total_number_of_iterations_made
130            second_multiplier -= ((factorial(2 * i) ** 2) / ((2 ** i * factorial(i)) ** 4)) * ((e ** (2 * i)) / (2 * i - 1))
131
132        if return_iterations_num:
133            return first_multiplier * second_multiplier, tr.total_number_of_iterations_made
134        else:
135            return first_multiplier * second_multiplier
136    
137    def perimeter__infinite_sum__iter_lim(self, iterations_num: int):
138        e = self.e
139        first_multiplier = 2 * self.a * pi
140        second_multiplier = 1
141        for i in range(1, iterations_num + 1):
142            second_multiplier -= ((factorial(2 * i) ** 2) / ((2 ** i * factorial(i)) ** 4)) * ((e ** (2 * i)) / (2 * i - 1))
143
144        return first_multiplier * second_multiplier
145    
146    @staticmethod
147    def from_r1_r2(r1: RationalNumber, r2: RationalNumber):
148        return Ellipse((r1 + r2) / 2, 1)
Ellipse(a: Union[int, float], b: Union[int, float])
45    def __init__(self, a: RationalNumber, b: RationalNumber):
46        self.a = a
47        self.b = b
a
b
def y(self, x: Union[int, float]) -> Union[int, float]:
49    def y(self, x: RationalNumber) -> RationalNumber:
50        return self.b * sqrt(1 - (x / self.a)**2)
area
52    @property
53    def area(self):
54        return pi * self.a * self.b
h
56    @property
57    def h(self):
58        return ((self.a - self.b)**2) / ((self.a + self.b)**2)
e
60    @property
61    def e(self):
62        return sqrt(self.a**2 - self.b**2) / self.a
c
64    @property
65    def c(self):
66        return self.a * self.e
perimeter__kepler
68    @property
69    def perimeter__kepler(self):
70        return 2 * pi * sqrt(self.a * self.b)
perimeter__naive
72    @property
73    def perimeter__naive(self):
74        return 2 * pi * ((self.a + self.b) / 2)
perimeter__euler
76    @property
77    def perimeter__euler(self):
78        return 2 * pi * sqrt((self.a**2 - self.b**2) / 2)
perimeter__matt_parker__lazy
80    @property
81    def perimeter__matt_parker__lazy(self):
82        """Computationly efficient. Not more that 6.1% deviation (less than 5% for `1 / 75` ellipses)
83
84        Returns:
85            _type_: _description_
86        """
87        a = max(self.a, self.b)
88        b = min(self.a, self.b)
89        return pi * ((6 * a) / 5 + (3 * b) / 4)

Computationly efficient. Not more that 6.1% deviation (less than 5% for 1 / 75 ellipses)

Returns: _type_: _description_

perimeter__best_of__euler__and__matt_parker__lazy
91    @property
92    def perimeter__best_of__euler__and__matt_parker__lazy(self):
93        a = max(self.a, self.b)
94        b = min(self.a, self.b)
95        if (a / b) >= 0.8:
96            return self.perimeter__matt_parker__lazy
97        else:
98            return self.perimeter__euler
perimeter__ramanujan_1
100    @property
101    def perimeter__ramanujan_1(self):
102        return pi * (3 * (self.a + self.b) - sqrt((3 * self.a + self.b) * (self.a + 3 * self.b)))
perimeter__matt_parker__precise
104    @property
105    def perimeter__matt_parker__precise(self):
106        a = max(self.a, self.b)
107        b = min(self.a, self.b)
108        return pi * ((53 * a) / 3 + (717 * b) / 35 - sqrt(269 * a ** 2 + 667 * a * b + 371 * b ** 2))
perimeter__best_of__ramanujan_1__and__matt_parker__precise
110    @property
111    def perimeter__best_of__ramanujan_1__and__matt_parker__precise(self):
112        a = max(self.a, self.b)
113        b = min(self.a, self.b)
114        if (a / b) >= 2.4:
115            return self.perimeter__matt_parker__precise
116        else:
117            return self.perimeter__ramanujan_1
perimeter__ramanujan_2
119    @property
120    def perimeter__ramanujan_2(self):
121        return pi * (self.a + self.b) * (1 + (3 * self.h) / (10 + sqrt(4 - 3 * self.h)))
def perimeter__infinite_sum__time_lim( self, desired_approximation_time: float, return_iterations_num: bool = False):
123    def perimeter__infinite_sum__time_lim(self, desired_approximation_time: float, return_iterations_num: bool = False):
124        e = self.e
125        first_multiplier = 2 * self.a * pi
126        second_multiplier = 1
127        tr = Tracer(desired_approximation_time)
128        while tr.iter():
129            i = tr.total_number_of_iterations_made
130            second_multiplier -= ((factorial(2 * i) ** 2) / ((2 ** i * factorial(i)) ** 4)) * ((e ** (2 * i)) / (2 * i - 1))
131
132        if return_iterations_num:
133            return first_multiplier * second_multiplier, tr.total_number_of_iterations_made
134        else:
135            return first_multiplier * second_multiplier
def perimeter__infinite_sum__iter_lim(self, iterations_num: int):
137    def perimeter__infinite_sum__iter_lim(self, iterations_num: int):
138        e = self.e
139        first_multiplier = 2 * self.a * pi
140        second_multiplier = 1
141        for i in range(1, iterations_num + 1):
142            second_multiplier -= ((factorial(2 * i) ** 2) / ((2 ** i * factorial(i)) ** 4)) * ((e ** (2 * i)) / (2 * i - 1))
143
144        return first_multiplier * second_multiplier
@staticmethod
def from_r1_r2(r1: Union[int, float], r2: Union[int, float]):
146    @staticmethod
147    def from_r1_r2(r1: RationalNumber, r2: RationalNumber):
148        return Ellipse((r1 + r2) / 2, 1)