mirror of
https://github.com/TheAlgorithms/Python.git
synced 2026-09-29 17:08:49 +08:00
Braikenridge-Maclaurin Construction of a Conic (#11205)
* Added conic construction file * Conic section code finalized for preliminary review * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixing ISC001 issue * Fixing variable declaration * Modify generate method to return a formatted string Changed the return type of the generate method to str and updated its implementation to return a formatted string instead of printing it. * updating DIRECTORY.md * updating DIRECTORY.md * Clean up comments and improve docstring formatting Removed commented-out documentation and updated docstring formatting. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Add imports for dataclass and numpy --------- Co-authored-by: AlexB <acbucha@clemson.edu> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss <cclauss@me.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: cclauss <cclauss@users.noreply.github.com>
This commit is contained in:
co-authored by
AlexB
pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Christian Clauss
github-actions
cclauss
parent
4dcbd94e50
commit
26f49ab010
@@ -0,0 +1,160 @@
|
||||
"""
|
||||
braikenridge_maclaurin_construction
|
||||
https://mathworld.wolfram.com/ConicSection.html
|
||||
5 Points define a conic section on a 2D normal orthogonal plane using this technique.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
from numpy import array, linalg
|
||||
|
||||
|
||||
@dataclass
|
||||
class Point:
|
||||
"""
|
||||
A point defined by 2 floats representing a length on a normalized
|
||||
orthogonal coordinate system
|
||||
default coordinate is the origin
|
||||
|
||||
>>> Point(-1.0, 0.0)
|
||||
Point(x=-1.0, y=0.0)
|
||||
"""
|
||||
|
||||
x: float = 0.0
|
||||
y: float = 0.0
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
if not isinstance(self.x, (int, float)):
|
||||
raise TypeError("x must be an int or float numeric value")
|
||||
if not isinstance(self.y, (int, float)):
|
||||
raise TypeError("y must be an int or float numeric value")
|
||||
|
||||
|
||||
@dataclass
|
||||
class BraikMac:
|
||||
"""
|
||||
Given a list of 5 points, determine the corresponding
|
||||
conic section equation and provide it to the user
|
||||
|
||||
| x**2 xy y**2 x y 1 |
|
||||
| x1**2 x1y1 y1**2 x1 y1 1 |
|
||||
| x2**2 x2y2 y2**2 x2 y2 1 | = 0
|
||||
| x3**2 x3y3 y3**2 x3 y3 1 |
|
||||
| x4**2 x4y4 y4**2 x4 y4 1 |
|
||||
| x5**2 x5y5 y5**2 x5 y5 1 |
|
||||
|
||||
>>> p1 = Point(0.0,0.0)
|
||||
>>> p2 = Point(5.0,0.0)
|
||||
>>> p3 = Point(2.0,3.0)
|
||||
>>> p4 = Point(1.0,10.0)
|
||||
>>> p5 = Point(6.0,7.0)
|
||||
>>> BraikMac([p1,p2,p3,p4,p5]) # doctest: +NORMALIZE_WHITESPACE
|
||||
BraikMac(p_list=[Point(x=0.0, y=0.0), Point(x=5.0, y=0.0),
|
||||
Point(x=2.0, y=3.0), Point(x=1.0, y=10.0), Point(x=6.0, y=7.0)])
|
||||
"""
|
||||
|
||||
p_list: list[Point] = field(default_factory=list)
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
n = 0
|
||||
for p in self.p_list:
|
||||
if not isinstance(p, Point):
|
||||
raise TypeError("Array must be point objects.")
|
||||
n += 1
|
||||
if n != 5:
|
||||
raise TypeError("Array must be 5 point objects.")
|
||||
|
||||
@property
|
||||
def generate(self) -> str:
|
||||
x1 = self.p_list[0].x
|
||||
y1 = self.p_list[0].y
|
||||
x2 = self.p_list[1].x
|
||||
y2 = self.p_list[1].y
|
||||
x3 = self.p_list[2].x
|
||||
y3 = self.p_list[2].y
|
||||
x4 = self.p_list[3].x
|
||||
y4 = self.p_list[3].y
|
||||
x5 = self.p_list[4].x
|
||||
y5 = self.p_list[4].y
|
||||
|
||||
x2_matrix = array(
|
||||
[
|
||||
[x1 * y1, y1**2, x1, y1, 1],
|
||||
[x2 * y2, y2**2, x2, y2, 1],
|
||||
[x3 * y3, y3**2, x3, y3, 1],
|
||||
[x4 * y4, y4**2, x4, y4, 1],
|
||||
[x5 * y5, y5**2, x5, y5, 1],
|
||||
]
|
||||
)
|
||||
|
||||
a = linalg.det(x2_matrix)
|
||||
|
||||
xy_matrix = array(
|
||||
[
|
||||
[x1**2, y1**2, x1, y1, 1],
|
||||
[x2**2, y2**2, x2, y2, 1],
|
||||
[x3**2, y3**2, x3, y3, 1],
|
||||
[x4**2, y4**2, x4, y4, 1],
|
||||
[x5**2, y5**2, x5, y5, 1],
|
||||
]
|
||||
)
|
||||
|
||||
b = -linalg.det(xy_matrix)
|
||||
|
||||
y2_matrix = array(
|
||||
[
|
||||
[x1**2, x1 * y1, x1, y1, 1],
|
||||
[x2**2, x2 * y2, x2, y2, 1],
|
||||
[x3**2, x3 * y3, x3, y3, 1],
|
||||
[x4**2, x4 * y4, x4, y4, 1],
|
||||
[x5**2, x5 * y5, x5, y5, 1],
|
||||
]
|
||||
)
|
||||
|
||||
c = linalg.det(y2_matrix)
|
||||
|
||||
x_matrix = array(
|
||||
[
|
||||
[x1**2, x1 * y1, y1**2, y1, 1],
|
||||
[x2**2, x2 * y2, y2**2, y2, 1],
|
||||
[x3**2, x3 * y3, y3**2, y3, 1],
|
||||
[x4**2, x4 * y4, y4**2, y4, 1],
|
||||
[x5**2, x5 * y5, y5**2, y5, 1],
|
||||
]
|
||||
)
|
||||
|
||||
d = -linalg.det(x_matrix)
|
||||
|
||||
y_matrix = array(
|
||||
[
|
||||
[x1**2, x1 * y1, y1**2, x1, 1],
|
||||
[x2**2, x2 * y2, y2**2, x2, 1],
|
||||
[x3**2, x3 * y3, y3**2, x3, 1],
|
||||
[x4**2, x4 * y4, y4**2, x4, 1],
|
||||
[x5**2, x5 * y5, y5**2, x5, 1],
|
||||
]
|
||||
)
|
||||
|
||||
e = linalg.det(y_matrix)
|
||||
|
||||
const_matrix = array(
|
||||
[
|
||||
[x1**2, x1 * y1, y1**2, x1, y1],
|
||||
[x2**2, x2 * y2, y2**2, x2, y2],
|
||||
[x3**2, x3 * y3, y3**2, x3, y3],
|
||||
[x4**2, x4 * y4, y4**2, x4, y4],
|
||||
[x5**2, x5 * y5, y5**2, x5, y5],
|
||||
]
|
||||
)
|
||||
|
||||
f = -linalg.det(const_matrix)
|
||||
|
||||
return f"0 = {a:+.2} X**2 {b:+.2} XY {c:+.2} Y**2 {d:+.2} X {e:+.2} Y {f:+.2}"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from doctest import testmod
|
||||
|
||||
testmod()
|
||||
Reference in New Issue
Block a user