forked from 3b1b/videos
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathregion.py
107 lines (84 loc) · 3.19 KB
/
region.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
from copy import deepcopy
import itertools as it
from manimlib.constants import *
from manimlib.mobject.mobject import Mobject
from manimlib.utils.iterables import adjacent_pairs
# Warning: This is all now pretty deprecated, and should not be expected to work
class Region(Mobject):
CONFIG = {
"display_mode": "region"
}
def __init__(self, condition=(lambda x, y: True), **kwargs):
"""
Condition must be a function which takes in two real
arrays (representing x and y values of space respectively)
and return a boolean array. This can essentially look like
a function from R^2 to {True, False}, but & and | must be
used in place of "and" and "or"
"""
Mobject.__init__(self, **kwargs)
self.condition = condition
def _combine(self, region, op):
self.condition = lambda x, y: op(
self.condition(x, y),
region.condition(x, y)
)
def union(self, region):
self._combine(region, lambda bg1, bg2: bg1 | bg2)
return self
def intersect(self, region):
self._combine(region, lambda bg1, bg2: bg1 & bg2)
return self
def complement(self):
self.bool_grid = ~self.bool_grid
return self
class HalfPlane(Region):
def __init__(self, point_pair, upper_left=True, *args, **kwargs):
"""
point_pair of the form [(x_0, y_0,...), (x_1, y_1,...)]
Pf upper_left is True, the side of the region will be
everything on the upper left side of the line through
the point pair
"""
if not upper_left:
point_pair = list(point_pair)
point_pair.reverse()
(x0, y0), (x1, y1) = point_pair[0][:2], point_pair[1][:2]
def condition(x, y):
return (x1 - x0) * (y - y0) > (y1 - y0) * (x - x0)
Region.__init__(self, condition, *args, **kwargs)
def region_from_line_boundary(*lines, **kwargs):
reg = Region(**kwargs)
for line in lines:
reg.intersect(HalfPlane(line, **kwargs))
return reg
def region_from_polygon_vertices(*vertices, **kwargs):
return region_from_line_boundary(*adjacent_pairs(vertices), **kwargs)
def plane_partition(*lines, **kwargs):
"""
A 'line' is a pair of points [(x0, y0,...), (x1, y1,...)]
Returns the list of regions of the plane cut out by
these lines
"""
result = []
half_planes = [HalfPlane(line, **kwargs) for line in lines]
complements = [deepcopy(hp).complement() for hp in half_planes]
num_lines = len(lines)
for bool_list in it.product(*[[True, False]] * num_lines):
reg = Region(**kwargs)
for i in range(num_lines):
if bool_list[i]:
reg.intersect(half_planes[i])
else:
reg.intersect(complements[i])
if reg.bool_grid.any():
result.append(reg)
return result
def plane_partition_from_points(*points, **kwargs):
"""
Returns list of regions cut out by the complete graph
with points from the argument as vertices.
Each point comes in the form (x, y)
"""
lines = [[p1, p2] for (p1, p2) in it.combinations(points, 2)]
return plane_partition(*lines, **kwargs)