Skip to content

Commit 747982e

Browse files
Merge branch 'master' into ty-invalid-type-arguments-2
2 parents 8df8158 + 26f49ab commit 747982e

2 files changed

Lines changed: 161 additions & 0 deletions

File tree

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,7 @@
574574
* [Radar Target Calculation](geodesy/radar_target_calculation.py)
575575

576576
## [Geometry](geometry)
577+
* [Braik Mac Construction](geometry/braik_mac_construction.py)
577578
* [Geometry](geometry/geometry.py)
578579
* [Graham Scan](geometry/graham_scan.py)
579580
* [Jarvis March](geometry/jarvis_march.py)

geometry/braik_mac_construction.py

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
"""
2+
braikenridge_maclaurin_construction
3+
https://mathworld.wolfram.com/ConicSection.html
4+
5 Points define a conic section on a 2D normal orthogonal plane using this technique.
5+
"""
6+
7+
from __future__ import annotations
8+
9+
from dataclasses import dataclass, field
10+
11+
from numpy import array, linalg
12+
13+
14+
@dataclass
15+
class Point:
16+
"""
17+
A point defined by 2 floats representing a length on a normalized
18+
orthogonal coordinate system
19+
default coordinate is the origin
20+
21+
>>> Point(-1.0, 0.0)
22+
Point(x=-1.0, y=0.0)
23+
"""
24+
25+
x: float = 0.0
26+
y: float = 0.0
27+
28+
def __post_init__(self) -> None:
29+
if not isinstance(self.x, (int, float)):
30+
raise TypeError("x must be an int or float numeric value")
31+
if not isinstance(self.y, (int, float)):
32+
raise TypeError("y must be an int or float numeric value")
33+
34+
35+
@dataclass
36+
class BraikMac:
37+
"""
38+
Given a list of 5 points, determine the corresponding
39+
conic section equation and provide it to the user
40+
41+
| x**2 xy y**2 x y 1 |
42+
| x1**2 x1y1 y1**2 x1 y1 1 |
43+
| x2**2 x2y2 y2**2 x2 y2 1 | = 0
44+
| x3**2 x3y3 y3**2 x3 y3 1 |
45+
| x4**2 x4y4 y4**2 x4 y4 1 |
46+
| x5**2 x5y5 y5**2 x5 y5 1 |
47+
48+
>>> p1 = Point(0.0,0.0)
49+
>>> p2 = Point(5.0,0.0)
50+
>>> p3 = Point(2.0,3.0)
51+
>>> p4 = Point(1.0,10.0)
52+
>>> p5 = Point(6.0,7.0)
53+
>>> BraikMac([p1,p2,p3,p4,p5]) # doctest: +NORMALIZE_WHITESPACE
54+
BraikMac(p_list=[Point(x=0.0, y=0.0), Point(x=5.0, y=0.0),
55+
Point(x=2.0, y=3.0), Point(x=1.0, y=10.0), Point(x=6.0, y=7.0)])
56+
"""
57+
58+
p_list: list[Point] = field(default_factory=list)
59+
60+
def __post_init__(self) -> None:
61+
n = 0
62+
for p in self.p_list:
63+
if not isinstance(p, Point):
64+
raise TypeError("Array must be point objects.")
65+
n += 1
66+
if n != 5:
67+
raise TypeError("Array must be 5 point objects.")
68+
69+
@property
70+
def generate(self) -> str:
71+
x1 = self.p_list[0].x
72+
y1 = self.p_list[0].y
73+
x2 = self.p_list[1].x
74+
y2 = self.p_list[1].y
75+
x3 = self.p_list[2].x
76+
y3 = self.p_list[2].y
77+
x4 = self.p_list[3].x
78+
y4 = self.p_list[3].y
79+
x5 = self.p_list[4].x
80+
y5 = self.p_list[4].y
81+
82+
x2_matrix = array(
83+
[
84+
[x1 * y1, y1**2, x1, y1, 1],
85+
[x2 * y2, y2**2, x2, y2, 1],
86+
[x3 * y3, y3**2, x3, y3, 1],
87+
[x4 * y4, y4**2, x4, y4, 1],
88+
[x5 * y5, y5**2, x5, y5, 1],
89+
]
90+
)
91+
92+
a = linalg.det(x2_matrix)
93+
94+
xy_matrix = array(
95+
[
96+
[x1**2, y1**2, x1, y1, 1],
97+
[x2**2, y2**2, x2, y2, 1],
98+
[x3**2, y3**2, x3, y3, 1],
99+
[x4**2, y4**2, x4, y4, 1],
100+
[x5**2, y5**2, x5, y5, 1],
101+
]
102+
)
103+
104+
b = -linalg.det(xy_matrix)
105+
106+
y2_matrix = array(
107+
[
108+
[x1**2, x1 * y1, x1, y1, 1],
109+
[x2**2, x2 * y2, x2, y2, 1],
110+
[x3**2, x3 * y3, x3, y3, 1],
111+
[x4**2, x4 * y4, x4, y4, 1],
112+
[x5**2, x5 * y5, x5, y5, 1],
113+
]
114+
)
115+
116+
c = linalg.det(y2_matrix)
117+
118+
x_matrix = array(
119+
[
120+
[x1**2, x1 * y1, y1**2, y1, 1],
121+
[x2**2, x2 * y2, y2**2, y2, 1],
122+
[x3**2, x3 * y3, y3**2, y3, 1],
123+
[x4**2, x4 * y4, y4**2, y4, 1],
124+
[x5**2, x5 * y5, y5**2, y5, 1],
125+
]
126+
)
127+
128+
d = -linalg.det(x_matrix)
129+
130+
y_matrix = array(
131+
[
132+
[x1**2, x1 * y1, y1**2, x1, 1],
133+
[x2**2, x2 * y2, y2**2, x2, 1],
134+
[x3**2, x3 * y3, y3**2, x3, 1],
135+
[x4**2, x4 * y4, y4**2, x4, 1],
136+
[x5**2, x5 * y5, y5**2, x5, 1],
137+
]
138+
)
139+
140+
e = linalg.det(y_matrix)
141+
142+
const_matrix = array(
143+
[
144+
[x1**2, x1 * y1, y1**2, x1, y1],
145+
[x2**2, x2 * y2, y2**2, x2, y2],
146+
[x3**2, x3 * y3, y3**2, x3, y3],
147+
[x4**2, x4 * y4, y4**2, x4, y4],
148+
[x5**2, x5 * y5, y5**2, x5, y5],
149+
]
150+
)
151+
152+
f = -linalg.det(const_matrix)
153+
154+
return f"0 = {a:+.2} X**2 {b:+.2} XY {c:+.2} Y**2 {d:+.2} X {e:+.2} Y {f:+.2}"
155+
156+
157+
if __name__ == "__main__":
158+
from doctest import testmod
159+
160+
testmod()

0 commit comments

Comments
 (0)