3b1b-manim/once_useful_constructs/region.py

110 lines
3.2 KiB
Python
Raw Normal View History

import numpy as np
import itertools as it
from PIL import Image
from copy import deepcopy
from mobject.mobject import Mobject
from utils.iterables import adjacent_pairs
from constants import *
2018-03-31 15:37:23 -07:00
# Warning: This is all now pretty depricated, and should not be expected to work
class Region(Mobject):
2016-02-27 16:32:53 -08:00
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):
"""
2015-04-03 16:41:25 -07:00
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()
2015-04-03 16:41:25 -07:00
(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)
2015-06-19 08:31:02 -07:00
def region_from_line_boundary(*lines, **kwargs):
reg = Region(**kwargs)
for line in lines:
2015-06-19 08:31:02 -07:00
reg.intersect(HalfPlane(line, **kwargs))
return reg
def region_from_polygon_vertices(*vertices, **kwargs):
2017-05-31 16:07:37 -07:00
return region_from_line_boundary(*adjacent_pairs(vertices), **kwargs)
2015-06-19 08:31:02 -07:00
def plane_partition(*lines, **kwargs):
"""
2015-04-03 16:41:25 -07:00
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 = []
2015-06-19 08:31:02 -07:00
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):
2015-06-19 08:31:02 -07:00
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
2015-06-19 08:31:02 -07:00
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)]
2015-06-19 08:31:02 -07:00
return plane_partition(*lines, **kwargs)