Skip to content

Commit bc643e9

Browse files
committed
Port remainder of geometry.py
1 parent 4246483 commit bc643e9

File tree

7 files changed

+384
-209
lines changed

7 files changed

+384
-209
lines changed

manim/mobject/opengl_geometry.py

Lines changed: 172 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from ..utils.iterables import adjacent_pairs
1111
from ..utils.simple_functions import fdiv
1212

13-
# from ..utils.simple_functions import clip
13+
from ..utils.simple_functions import clip
1414
from ..utils.space_ops import angle_of_vector
1515
from ..utils.space_ops import angle_between_vectors
1616
from ..utils.space_ops import compass_directions
@@ -90,7 +90,7 @@ def get_unpositioned_tip(self, **kwargs):
9090
config = dict()
9191
config.update(self.tip_config)
9292
config.update(kwargs)
93-
return ArrowTip(**config)
93+
return OpenGLArrowTip(**config)
9494

9595
def position_tip(self, tip, at_start=False):
9696
# Last two control points, defining both
@@ -591,164 +591,176 @@ def get_last_handle(self):
591591
return self.submobjects[-1].get_points()[-2]
592592

593593

594-
# class TangentLine(Line):
595-
# CONFIG = {"length": 1, "d_alpha": 1e-6}
596-
#
597-
# def __init__(self, vmob, alpha, **kwargs):
598-
# digest_config(self, kwargs)
599-
# da = self.d_alpha
600-
# a1 = clip(alpha - da, 0, 1)
601-
# a2 = clip(alpha + da, 0, 1)
602-
# super().__init__(vmob.pfp(a1), vmob.pfp(a2), **kwargs)
603-
# self.scale(self.length / self.get_length())
604-
#
605-
#
606-
# class Elbow(VMobject):
607-
# CONFIG = {
608-
# "width": 0.2,
609-
# "angle": 0,
610-
# }
611-
#
612-
# def __init__(self, **kwargs):
613-
# super().__init__(self, **kwargs)
614-
# self.set_points_as_corners([UP, UP + RIGHT, RIGHT])
615-
# self.set_width(self.width, about_point=ORIGIN)
616-
# self.rotate(self.angle, about_point=ORIGIN)
617-
#
618-
#
619-
# class Arrow(Line):
620-
# CONFIG = {
621-
# "fill_color": GREY_A,
622-
# "fill_opacity": 1,
623-
# "stroke_width": 0,
624-
# "buff": MED_SMALL_BUFF,
625-
# "thickness": 0.05,
626-
# "tip_width_ratio": 5,
627-
# "tip_angle": PI / 3,
628-
# "max_tip_length_to_length_ratio": 0.5,
629-
# "max_width_to_length_ratio": 0.1,
630-
# }
631-
#
632-
# def set_points_by_ends(self, start, end, buff=0, path_arc=0):
633-
# # Find the right tip length and thickness
634-
# vect = end - start
635-
# length = max(get_norm(vect), 1e-8)
636-
# thickness = self.thickness
637-
# w_ratio = fdiv(self.max_width_to_length_ratio, fdiv(thickness, length))
638-
# if w_ratio < 1:
639-
# thickness *= w_ratio
640-
#
641-
# tip_width = self.tip_width_ratio * thickness
642-
# tip_length = tip_width / (2 * np.tan(self.tip_angle / 2))
643-
# t_ratio = fdiv(self.max_tip_length_to_length_ratio, fdiv(tip_length, length))
644-
# if t_ratio < 1:
645-
# tip_length *= t_ratio
646-
# tip_width *= t_ratio
647-
#
648-
# # Find points for the stem
649-
# if path_arc == 0:
650-
# points1 = (length - tip_length) * np.array([RIGHT, 0.5 * RIGHT, ORIGIN])
651-
# points1 += thickness * UP / 2
652-
# points2 = points1[::-1] + thickness * DOWN
653-
# else:
654-
# # Solve for radius so that the tip-to-tail length matches |end - start|
655-
# a = 2 * (1 - np.cos(path_arc))
656-
# b = -2 * tip_length * np.sin(path_arc)
657-
# c = tip_length ** 2 - length ** 2
658-
# R = (-b + np.sqrt(b ** 2 - 4 * a * c)) / (2 * a)
659-
#
660-
# # Find arc points
661-
# points1 = Arc.create_quadratic_bezier_points(path_arc)
662-
# points2 = np.array(points1[::-1])
663-
# points1 *= R + thickness / 2
664-
# points2 *= R - thickness / 2
665-
# if path_arc < 0:
666-
# tip_length *= -1
667-
# rot_T = rotation_matrix_transpose(PI / 2 - path_arc, OUT)
668-
# for points in points1, points2:
669-
# points[:] = np.dot(points, rot_T)
670-
# points += R * DOWN
671-
#
672-
# self.set_points(points1)
673-
# # Tip
674-
# self.add_line_to(tip_width * UP / 2)
675-
# self.add_line_to(tip_length * LEFT)
676-
# self.tip_index = len(self.get_points()) - 1
677-
# self.add_line_to(tip_width * DOWN / 2)
678-
# self.add_line_to(points2[0])
679-
# # Close it out
680-
# self.append_points(points2)
681-
# self.add_line_to(points1[0])
682-
#
683-
# if length > 0:
684-
# # Final correction
685-
# super().scale(length / self.get_length())
686-
#
687-
# self.rotate(angle_of_vector(vect) - self.get_angle())
688-
# self.rotate(
689-
# PI / 2 - np.arccos(normalize(vect)[2]),
690-
# axis=rotate_vector(self.get_unit_vector(), -PI / 2),
691-
# )
692-
# self.shift(start - self.get_start())
693-
# self.refresh_triangulation()
694-
#
695-
# def reset_points_around_ends(self):
696-
# self.set_points_by_ends(
697-
# self.get_start(), self.get_end(), path_arc=self.path_arc
698-
# )
699-
# return self
700-
#
701-
# def get_start(self):
702-
# nppc = self.n_points_per_curve
703-
# points = self.get_points()
704-
# return (points[0] + points[-nppc]) / 2
705-
#
706-
# def get_end(self):
707-
# return self.get_points()[self.tip_index]
708-
#
709-
# def put_start_and_end_on(self, start, end):
710-
# self.set_points_by_ends(start, end, buff=0, path_arc=self.path_arc)
711-
# return self
712-
#
713-
# def scale(self, *args, **kwargs):
714-
# super().scale(*args, **kwargs)
715-
# self.reset_points_around_ends()
716-
# return self
717-
#
718-
# def set_thickness(self, thickness):
719-
# self.thickness = thickness
720-
# self.reset_points_around_ends()
721-
# return self
722-
#
723-
# def set_path_arc(self, path_arc):
724-
# self.path_arc = path_arc
725-
# self.reset_points_around_ends()
726-
# return self
727-
#
728-
#
729-
# class Vector(Arrow):
730-
# CONFIG = {
731-
# "buff": 0,
732-
# }
733-
#
734-
# def __init__(self, direction=RIGHT, **kwargs):
735-
# if len(direction) == 2:
736-
# direction = np.hstack([direction, 0])
737-
# super().__init__(ORIGIN, direction, **kwargs)
738-
#
739-
#
740-
# class DoubleArrow(Arrow):
741-
# def __init__(self, *args, **kwargs):
742-
# Arrow.__init__(self, *args, **kwargs)
743-
# self.add_tip(at_start=True)
744-
#
745-
#
746-
# class CubicBezier(VMobject):
747-
# def __init__(self, a0, h0, h1, a1, **kwargs):
748-
# VMobject.__init__(self, **kwargs)
749-
# self.add_cubic_bezier_curve(a0, h0, h1, a1)
750-
#
751-
#
594+
class OpenGLTangentLine(OpenGLLine):
595+
def __init__(self, vmob, alpha, length=1, d_alpha=1e-6, **kwargs):
596+
self.length = length
597+
self.d_alpha = d_alpha
598+
da = self.d_alpha
599+
a1 = clip(alpha - da, 0, 1)
600+
a2 = clip(alpha + da, 0, 1)
601+
super().__init__(vmob.pfp(a1), vmob.pfp(a2), **kwargs)
602+
self.scale(self.length / self.get_length())
603+
604+
605+
class OpenGLElbow(OpenGLVMobject):
606+
def __init__(self, width=0.2, angle=0, **kwargs):
607+
self.angle = angle
608+
super().__init__(self, **kwargs)
609+
self.set_points_as_corners([UP, UP + RIGHT, RIGHT])
610+
self.set_width(width, about_point=ORIGIN)
611+
self.rotate(self.angle, about_point=ORIGIN)
612+
613+
614+
class OpenGLArrow(OpenGLLine):
615+
def __init__(
616+
self,
617+
start=LEFT,
618+
end=RIGHT,
619+
path_arc=0,
620+
fill_color=GREY_A,
621+
fill_opacity=1,
622+
stroke_width=0,
623+
buff=MED_SMALL_BUFF,
624+
thickness=0.05,
625+
tip_width_ratio=5,
626+
tip_angle=PI / 3,
627+
max_tip_length_to_length_ratio=0.5,
628+
max_width_to_length_ratio=0.1,
629+
**kwargs
630+
):
631+
self.thickness = thickness
632+
self.tip_width_ratio = tip_width_ratio
633+
self.tip_angle = tip_angle
634+
self.max_tip_length_to_length_ratio = max_tip_length_to_length_ratio
635+
self.max_width_to_length_ratio = max_width_to_length_ratio
636+
super().__init__(
637+
start=start,
638+
end=end,
639+
buff=buff,
640+
path_arc=path_arc,
641+
fill_color=fill_color,
642+
fill_opacity=fill_opacity,
643+
stroke_width=stroke_width,
644+
**kwargs
645+
)
646+
647+
def set_points_by_ends(self, start, end, buff=0, path_arc=0):
648+
# Find the right tip length and thickness
649+
vect = end - start
650+
length = max(get_norm(vect), 1e-8)
651+
thickness = self.thickness
652+
w_ratio = fdiv(self.max_width_to_length_ratio, fdiv(thickness, length))
653+
if w_ratio < 1:
654+
thickness *= w_ratio
655+
656+
tip_width = self.tip_width_ratio * thickness
657+
tip_length = tip_width / (2 * np.tan(self.tip_angle / 2))
658+
t_ratio = fdiv(self.max_tip_length_to_length_ratio, fdiv(tip_length, length))
659+
if t_ratio < 1:
660+
tip_length *= t_ratio
661+
tip_width *= t_ratio
662+
663+
# Find points for the stem
664+
if path_arc == 0:
665+
points1 = (length - tip_length) * np.array([RIGHT, 0.5 * RIGHT, ORIGIN])
666+
points1 += thickness * UP / 2
667+
points2 = points1[::-1] + thickness * DOWN
668+
else:
669+
# Solve for radius so that the tip-to-tail length matches |end - start|
670+
a = 2 * (1 - np.cos(path_arc))
671+
b = -2 * tip_length * np.sin(path_arc)
672+
c = tip_length ** 2 - length ** 2
673+
R = (-b + np.sqrt(b ** 2 - 4 * a * c)) / (2 * a)
674+
675+
# Find arc points
676+
points1 = OpenGLArc.create_quadratic_bezier_points(path_arc)
677+
points2 = np.array(points1[::-1])
678+
points1 *= R + thickness / 2
679+
points2 *= R - thickness / 2
680+
if path_arc < 0:
681+
tip_length *= -1
682+
rot_T = rotation_matrix_transpose(PI / 2 - path_arc, OUT)
683+
for points in points1, points2:
684+
points[:] = np.dot(points, rot_T)
685+
points += R * DOWN
686+
687+
self.set_points(points1)
688+
# Tip
689+
self.add_line_to(tip_width * UP / 2)
690+
self.add_line_to(tip_length * LEFT)
691+
self.tip_index = len(self.get_points()) - 1
692+
self.add_line_to(tip_width * DOWN / 2)
693+
self.add_line_to(points2[0])
694+
# Close it out
695+
self.append_points(points2)
696+
self.add_line_to(points1[0])
697+
698+
if length > 0:
699+
# Final correction
700+
super().scale(length / self.get_length())
701+
702+
self.rotate(angle_of_vector(vect) - self.get_angle())
703+
self.rotate(
704+
PI / 2 - np.arccos(normalize(vect)[2]),
705+
axis=rotate_vector(self.get_unit_vector(), -PI / 2),
706+
)
707+
self.shift(start - self.get_start())
708+
self.refresh_triangulation()
709+
710+
def reset_points_around_ends(self):
711+
self.set_points_by_ends(
712+
self.get_start(), self.get_end(), path_arc=self.path_arc
713+
)
714+
return self
715+
716+
def get_start(self):
717+
nppc = self.n_points_per_curve
718+
points = self.get_points()
719+
return (points[0] + points[-nppc]) / 2
720+
721+
def get_end(self):
722+
return self.get_points()[self.tip_index]
723+
724+
def put_start_and_end_on(self, start, end):
725+
self.set_points_by_ends(start, end, buff=0, path_arc=self.path_arc)
726+
return self
727+
728+
def scale(self, *args, **kwargs):
729+
super().scale(*args, **kwargs)
730+
self.reset_points_around_ends()
731+
return self
732+
733+
def set_thickness(self, thickness):
734+
self.thickness = thickness
735+
self.reset_points_around_ends()
736+
return self
737+
738+
def set_path_arc(self, path_arc):
739+
self.path_arc = path_arc
740+
self.reset_points_around_ends()
741+
return self
742+
743+
744+
class OpenGLVector(OpenGLArrow):
745+
def __init__(self, direction=RIGHT, buff=0, **kwargs):
746+
self.buff = buff
747+
if len(direction) == 2:
748+
direction = np.hstack([direction, 0])
749+
super().__init__(ORIGIN, direction, buff=buff, **kwargs)
750+
751+
752+
class OpenGLDoubleArrow(OpenGLArrow):
753+
def __init__(self, *args, **kwargs):
754+
OpenGLArrow.__init__(self, *args, **kwargs)
755+
self.add_tip(at_start=True)
756+
757+
758+
class OpenGLCubicBezier(OpenGLVMobject):
759+
def __init__(self, a0, h0, h1, a1, **kwargs):
760+
OpenGLVMobject.__init__(self, **kwargs)
761+
self.add_cubic_bezier_curve(a0, h0, h1, a1)
762+
763+
752764
class OpenGLPolygon(OpenGLVMobject):
753765
def __init__(self, *vertices, **kwargs):
754766
self.vertices = vertices

0 commit comments

Comments
 (0)