summaryrefslogtreecommitdiff
path: root/circrect.py
diff options
context:
space:
mode:
authorlonkaars <loek@pipeframe.xyz>2024-01-09 19:52:25 +0100
committerlonkaars <loek@pipeframe.xyz>2024-01-09 19:52:25 +0100
commit8424afbd3636407a4e619b01f7c47a4fa0987947 (patch)
tree6f15d20f816ee102d47a5e180b0ede40b3cbea1c /circrect.py
parent251f03c22057f93daea2f38c6d8f693970cfc19f (diff)
alles afgemaakt
Diffstat (limited to 'circrect.py')
-rw-r--r--circrect.py53
1 files changed, 28 insertions, 25 deletions
diff --git a/circrect.py b/circrect.py
index e85ed77..a1dd27c 100644
--- a/circrect.py
+++ b/circrect.py
@@ -1,40 +1,43 @@
from numbers import Number
+from math import sqrt, asin
def clamp(low: Number, high: Number, num: Number) -> Number:
"""Limit range of ``num`` between ``low`` and ``high``"""
return max(low, min(high, num))
-def circrect(a: Number, b: tuple[Number, Number], c: tuple[Number, Number]) -> Number:
+def circrect(a: tuple[Number, Number], b: tuple[Number, Number], c: Number = 1) -> Number:
"""
- Calculate the area of the overlap between a circle with radius ``a`` and a
- rectangle defined by opposing corner points ``b`` and ``c``.
+ Calculate the area of the overlap between a rectangle defined by opposing
+ corner points ``a`` and ``b`` and a circle with radius ``c``.
Args:
- a: circle radius
- b: first corner coordinate of rectangle
- c: second corner coordinate of rectangle (opposite of b)
+ a: first corner coordinate of rectangle
+ b: second corner coordinate of rectangle (opposite of b)
+ c: circle radius (optional, with default of 1)
Returns:
Overlap area (square units)
"""
-
- # normalize input variables
- a = abs(a)
- b, c = (
- (min(b[0], c[0]), min(b[1], c[1])),
- (max(b[0], c[0]), max(b[1], c[1])),
- )
- b = (clamp(-a, a, b[0]), clamp(-a, a, b[1]))
- c = (clamp(-a, a, c[0]), clamp(-a, a, c[1]))
-
- return 0
-
-if __name__ == "__main__":
- print(
- circrect(1, (-1, -1), (1, 1)), # pi
- circrect(1, (1, 1), (-1, -1)), # pi
- circrect(-1, (-1, -1), (1, 1)), # pi
- circrect(2, (10, 10), (11, 11)), # 0
- circrect(10, (0, 0), (1, 1)), # 1
+ # input variable normalization
+ a, b = (
+ (min(a[0], b[0]), min(a[1], b[1])),
+ (max(a[0], b[0]), max(a[1], b[1])),
)
+ c = abs(c)
+ a = (clamp(-1, 1, a[0] / c), clamp(-1, 1, a[1] / c))
+ b = (clamp(-1, 1, b[0] / c), clamp(-1, 1, b[1] / c))
+
+ # can not have shared area if ab already has no area
+ if a == b: return 0.0
+
+ f = lambda x: sqrt(1 - x**2)
+ F = lambda x, n: 0.5 * (2*n*x + sqrt(1 - x**2)*x + asin(x))
+ g = lambda a, b: F(clamp(a[0], b[0], f(a[1])), -a[1]) \
+ - F(clamp(a[0], b[0], -f(a[1])), -a[1]) \
+ - F(clamp(a[0], b[0], f(b[1])), -b[1]) \
+ + F(clamp(a[0], b[0], -f(b[1])), -b[1])
+ h = lambda a, b: g((a[0], max(0, a[1])), (b[0], max(0, b[1]))) \
+ + g((a[0], max(0, -b[1])), (b[0], max(0, -a[1])))
+ o = h(a, b) * (c ** 2)
+ return o