diff --git a/active_projects/holomorphic.py b/active_projects/holomorphic.py index e4b17922..c68113c4 100644 --- a/active_projects/holomorphic.py +++ b/active_projects/holomorphic.py @@ -80,7 +80,6 @@ class AnalyzeZSquared(ComplexTransformationScene, ZoomedScene): else: arrow = Arrow( point, out_point, - use_rectangular_stem=False, path_arc=path_arc, buff=SMALL_BUFF, ) diff --git a/manimlib/mobject/geometry.py b/manimlib/mobject/geometry.py index a223c834..d2e72d2c 100644 --- a/manimlib/mobject/geometry.py +++ b/manimlib/mobject/geometry.py @@ -21,7 +21,76 @@ DEFAULT_DOT_RADIUS = 0.08 DEFAULT_DASH_LENGTH = 0.05 -class Arc(VMobject): +class TipableVMobject(VMobject): + CONFIG = { + "tip_length": 0.3, + # TODO + "normal_vector": OUT, + } + """ + Meant simply for shard functionality between + Arc and Line + """ + + def add_tip(self, tip_length=None, at_start=False): + tip = self.get_unpositioned_tip(tip_length) + # Last two control points, defining both + # the end, and the tangency direction + if at_start: + anchor = self.get_start() + handle = self.get_first_handle() + self.start_tip = tip + else: + handle = self.get_last_handle() + anchor = self.get_end() + self.tip = tip + tip.rotate(angle_of_vector(handle - anchor)) + tip.shift(anchor - tip.get_start()) + + self.reset_endpoints_based_on_tip(tip, at_start) + self.add(tip) + return self + + def get_unpositioned_tip(self, tip_length=None): + if tip_length is None: + tip_length = self.tip_length + tip = Triangle(start_angle=PI) + tip.match_style(self) + tip.set_fill(self.get_stroke_color(), opacity=1) + tip.set_height(tip_length) + tip.set_width(tip_length, stretch=True) + return tip + + def reset_endpoints_based_on_tip(self, tip, at_start): + tip_base = tip.point_from_proportion(0.5) + if at_start: + self.put_start_and_end_on( + tip_base, self.get_end() + ) + else: + self.put_start_and_end_on( + self.get_start(), tip_base, + ) + return self + + def get_first_handle(self): + return self.points[1] + + def get_last_handle(self): + return self.points[-2] + + # def get_end(self): + # if hasattr(self, "tip"): + # return self.tip[0].get_anchors()[0] + # else: + # return Line.get_end(self) + + # def get_start(self): + # if hasattr(self, "tip"): + # pass + + +class Arc(TipableVMobject): CONFIG = { "radius": 1.0, "num_components": 9, @@ -64,27 +133,6 @@ class Arc(VMobject): anchors[1:], ) - def add_tip(self, tip_length=0.25, at_start=False): - tip = self.tip = Triangle(start_angle=PI) - tip.match_style(self) - tip.set_fill(self.get_stroke_color(), opacity=1) - tip.set_height(tip_length) - tip.set_width(tip_length, stretch=True) - tip.move_to(ORIGIN, LEFT) - # Last two control points, defining both - # the end, and the tangency direction - if at_start: - end, handle = self.points[:2] - else: - handle, end = self.points[-2:] - tip.rotate( - angle_of_vector(handle - end), - about_point=ORIGIN - ) - tip.shift(end) - self.add(tip) - return self - def get_arc_center(self): """ Looks at the normals to the first two @@ -254,7 +302,7 @@ class Annulus(Circle): self.shift(self.arc_center) -class Line(VMobject): +class Line(TipableVMobject): CONFIG = { "buff": 0, "path_arc": None, # angle of arc specified here @@ -346,6 +394,15 @@ class Line(VMobject): about_point=self.get_start(), ) + def set_opacity(self, opacity, family=True): + # Overwrite default, which would set + # the fill opacity + self.set_stroke(opacity=opacity) + if family: + for sm in self.submobjects: + sm.set_opacity(opacity, family) + return self + class DashedLine(Line): CONFIG = { @@ -393,6 +450,12 @@ class DashedLine(Line): else: return Line.get_end(self) + def get_first_handle(self): + return self.submobjects[0].points[1] + + def get_last_handle(self): + return self.submobjects[-1].points[-2] + class Elbow(VMobject): CONFIG = { @@ -409,83 +472,41 @@ class Elbow(VMobject): class Arrow(Line): CONFIG = { - "tip_length": 0.25, + "stroke_width": 6, + "buff": MED_SMALL_BUFF, + # "tip_length": 0.25, "tip_width_to_length_ratio": 1, "max_tip_length_to_length_ratio": 0.35, "max_stem_width_to_tip_width_ratio": 0.3, - "buff": MED_SMALL_BUFF, "preserve_tip_size_when_scaling": True, - "normal_vector": OUT, - "use_rectangular_stem": True, "rectangular_stem_width": 0.05, } def __init__(self, *args, **kwargs): - points = list(map(self.pointify, args)) - if len(args) == 1: - args = (points[0] + UP + LEFT, points[0]) Line.__init__(self, *args, **kwargs) - self.init_tip() - if self.use_rectangular_stem and not hasattr(self, "rect"): - self.add_rectangular_stem() - self.init_colors() + self.add_tip(tip_length=self.tip_length) + # self.init_colors() def init_tip(self): self.add_tip() - def add_tip(self, add_at_end=True): - tip = VMobject( - close_new_points=True, - mark_paths_closed=True, - fill_color=self.color, - fill_opacity=1, - stroke_color=self.color, - stroke_width=0, - ) - tip.add_at_end = add_at_end - self.set_tip_points(tip, add_at_end, preserve_normal=False) - self.add(tip) - if not hasattr(self, 'tip'): - self.tip = VGroup() - self.tip.match_style(tip) - self.tip.add(tip) - return tip - - def add_rectangular_stem(self): - self.rect = Rectangle( - stroke_width=0, - fill_color=self.tip.get_fill_color(), - fill_opacity=self.tip.get_fill_opacity() - ) - self.add_to_back(self.rect) - self.set_stroke(width=0) - self.set_rectangular_stem_points() - - def set_rectangular_stem_points(self): - start, end = self.get_start_and_end() - tip_base_points = self.tip[0].get_anchors()[1:3] - tip_base = center_of_mass(tip_base_points) - tbp1, tbp2 = tip_base_points - perp_vect = tbp2 - tbp1 - tip_base_width = get_norm(perp_vect) - if tip_base_width > 0: - perp_vect /= tip_base_width - width = min( - self.rectangular_stem_width, - self.max_stem_width_to_tip_width_ratio * tip_base_width, - ) - if hasattr(self, "second_tip"): - start = center_of_mass( - self.second_tip.get_anchors()[1:] - ) - self.rect.set_points_as_corners([ - tip_base - perp_vect * width / 2, - start - perp_vect * width / 2, - start + perp_vect * width / 2, - tip_base + perp_vect * width / 2, - ]) - self.stem = self.rect # Alternate name - return self + # def add_tip(self, add_at_end=True): + # tip = VMobject( + # close_new_points=True, + # mark_paths_closed=True, + # fill_color=self.color, + # fill_opacity=1, + # stroke_color=self.color, + # stroke_width=0, + # ) + # tip.add_at_end = add_at_end + # self.set_tip_points(tip, add_at_end, preserve_normal=False) + # self.add(tip) + # if not hasattr(self, 'tip'): + # self.tip = VGroup() + # self.tip.match_style(tip) + # self.tip.add(tip) + # return tip def set_tip_points( self, tip, @@ -537,32 +558,23 @@ class Arrow(Line): self.normal_vector = self.get_normal_vector() return self - def get_end(self): - if hasattr(self, "tip"): - return self.tip[0].get_anchors()[0] - else: - return Line.get_end(self) - def get_tip(self): return self.tip - def put_start_and_end_on(self, *args, **kwargs): - Line.put_start_and_end_on(self, *args, **kwargs) - self.set_tip_points(self.tip[0], preserve_normal=False) - self.set_rectangular_stem_points() - return self + # def put_start_and_end_on(self, *args, **kwargs): + # Line.put_start_and_end_on(self, *args, **kwargs) + # self.set_tip_points(self.tip[0], preserve_normal=False) + # return self - def scale(self, scale_factor, **kwargs): - Line.scale(self, scale_factor, **kwargs) - if self.preserve_tip_size_when_scaling: - for t in self.tip: - self.set_tip_points(t, add_at_end=t.add_at_end) - if self.use_rectangular_stem: - self.set_rectangular_stem_points() - return self + # def scale(self, scale_factor, **kwargs): + # Line.scale(self, scale_factor, **kwargs) + # if self.preserve_tip_size_when_scaling: + # for t in self.tip: + # self.set_tip_points(t, add_at_end=t.add_at_end) + # return self - def copy(self): - return self.deepcopy() + # def copy(self): + # return self.deepcopy() class Vector(Arrow): diff --git a/old_projects/WindingNumber_G.py b/old_projects/WindingNumber_G.py index cea4524d..13327713 100644 --- a/old_projects/WindingNumber_G.py +++ b/old_projects/WindingNumber_G.py @@ -872,7 +872,6 @@ class IntroduceInputOutputScene(InputOutputScene): in_dot, out_dot, buff = SMALL_BUFF, path_arc = path_arc, - use_rectangular_stem = False, color = WHITE, ) curved_arrow.pointwise_become_partial(curved_arrow, 0, 0.95) @@ -1080,7 +1079,6 @@ class TwoDScreenInOurThreeDWorld(AltTeacherStudentsScene, ThreeDScene): arrow = Arrow( LEFT, RIGHT, path_arc = -TAU/4, - use_rectangular_stem = False, color = WHITE ) arrow.pointwise_become_partial(arrow, 0.0, 0.97) @@ -2473,7 +2471,6 @@ class MonomialTerm(PathContainingZero): label.add_background_rectangle(opacity = 1, buff = SMALL_BUFF) arrow = Arrow( 2*LEFT, 2*RIGHT, path_arc = -TAU/3, - use_rectangular_stem = False ) arrow.pointwise_become_partial(arrow, 0, 0.95) label.next_to(arrow, UP) @@ -2738,7 +2735,6 @@ class ShowComplexFunction(Scene): fx_dot = Dot(fx_point, color = YELLOW) arrow = Arrow( x_point, fx_point, - use_rectangular_stem = False, path_arc = TAU/3, color = YELLOW ) diff --git a/old_projects/alt_calc.py b/old_projects/alt_calc.py index b470d435..f581c2f9 100644 --- a/old_projects/alt_calc.py +++ b/old_projects/alt_calc.py @@ -1564,7 +1564,6 @@ class TalkThroughXSquaredExample(IntroduceTransformationView): if factor < 0: kwargs = { "path_arc": np.pi, - "use_rectangular_stem": False, } la = Arrow(UP, DOWN, **kwargs) ra = Arrow(DOWN, UP, **kwargs) @@ -2995,7 +2994,6 @@ class AnalyzeFunctionWithTransformations(NumberlineTransformationScene): VGroup(*[ Arrow( point, func(point), buff=SMALL_BUFF, - use_rectangular_stem=False, tip_length=0.15 ) for point in sample_points diff --git a/old_projects/basel/basel2.py b/old_projects/basel/basel2.py index eae0ab16..9d58dac2 100644 --- a/old_projects/basel/basel2.py +++ b/old_projects/basel/basel2.py @@ -1444,13 +1444,11 @@ class EarthScene(IntroduceScreen): equator_arrow = Vector( DOWN+2*RIGHT, color = WHITE, - use_rectangular_stem = False, ) equator_arrow.next_to(screen.get_center(), UP+LEFT, SMALL_BUFF) pole_arrow = Vector( UP+3*RIGHT, color = WHITE, - use_rectangular_stem = False, path_arc = -60*DEGREES, ) pole_arrow.shift( diff --git a/old_projects/bell.py b/old_projects/bell.py index 0a54ff0b..3197d684 100644 --- a/old_projects/bell.py +++ b/old_projects/bell.py @@ -1112,7 +1112,6 @@ class IntroduceLabeledFilters(ShowVariousFilterPairs): arrow = Arrow( ORIGIN, 3.5*RIGHT, path_arc = -0.9*np.pi, - use_rectangular_stem = False, color = BLUE, stroke_width = 5, ) @@ -1179,7 +1178,6 @@ class IntroduceLabeledFilters(ShowVariousFilterPairs): arrow0 = Arrow( 2*LEFT, 0.5*(UP+RIGHT), path_arc = 0.8*np.pi, - use_rectangular_stem = False, color = WHITE, stroke_width = 5, buff = 0 @@ -1187,7 +1185,6 @@ class IntroduceLabeledFilters(ShowVariousFilterPairs): arrow1 = Arrow( 2*LEFT, ORIGIN, path_arc = 0.8*np.pi, - use_rectangular_stem = False, color = GREEN, stroke_width = 5, buff = 0 diff --git a/old_projects/clacks/solution2/position_phase_space.py b/old_projects/clacks/solution2/position_phase_space.py index b2cc122b..650b6e89 100644 --- a/old_projects/clacks/solution2/position_phase_space.py +++ b/old_projects/clacks/solution2/position_phase_space.py @@ -1118,7 +1118,6 @@ class FailedAngleRelation(PositionPhaseSpaceScene): arc2.arrow = Arrow( equation[2].get_corner(DL), arc2.get_left(), - use_rectangular_stem=False, path_arc=-120 * DEGREES, buff=SMALL_BUFF, ) diff --git a/old_projects/dandelin.py b/old_projects/dandelin.py index e81810c6..4a2acf74 100644 --- a/old_projects/dandelin.py +++ b/old_projects/dandelin.py @@ -576,7 +576,6 @@ class EccentricityInThumbtackCase(ShowArrayOfEccentricities): eccentricity_label.get_right(), fraction.get_top() + MED_SMALL_BUFF * UP, path_arc=-60 * DEGREES, - use_rectangular_stem=False, ) fraction_arrow.pointwise_become_partial(fraction_arrow, 0, 0.95) diff --git a/old_projects/div_curl.py b/old_projects/div_curl.py index afff0dfb..15481911 100644 --- a/old_projects/div_curl.py +++ b/old_projects/div_curl.py @@ -2436,7 +2436,6 @@ class IntroduceCurl(IntroduceVectorField): result = VGroup(*[ Arrow( *points, - use_rectangular_stem=False, buff=2 * SMALL_BUFF, path_arc=90 * DEGREES ).set_stroke(width=5) @@ -2646,7 +2645,6 @@ class IllustrationUseVennDiagram(Scene): illustrated_by.get_bottom(), ff_circle.get_left(), path_arc=90 * DEGREES, - use_rectangular_stem=False, color=YELLOW, ) illustrated_by_arrow.pointwise_become_partial( @@ -4577,7 +4575,6 @@ class ThoughtsOnAds(Scene): viewer.next_to(vcb[1:], UP, LARGE_BUFF) arrow_config = { "path_arc": 60 * DEGREES, - "use_rectangular_stem": False, "tip_length": 0.15, } vcb_arrows = VGroup(*[ diff --git a/old_projects/lost_lecture.py b/old_projects/lost_lecture.py index e216d613..681f914c 100644 --- a/old_projects/lost_lecture.py +++ b/old_projects/lost_lecture.py @@ -505,7 +505,7 @@ class FeynmanFame(Scene): def get_feynman_diagram(self): x_min = -1.5 x_max = 1.5 - arrow = Arrow(LEFT, RIGHT, buff=0, use_rectangular_stem=False) + arrow = Arrow(LEFT, RIGHT, buff=0) arrow.tip.move_to(arrow.get_center()) arrows = VGroup(*[ arrow.copy().rotate(angle).next_to(point, vect, buff=0) diff --git a/old_projects/nn/part2.py b/old_projects/nn/part2.py index 0e5ed7c0..2b3e35a5 100644 --- a/old_projects/nn/part2.py +++ b/old_projects/nn/part2.py @@ -3109,7 +3109,6 @@ class InputRandomData(TestPerformance): rect.get_top(), self.network_mob.layers[0].neurons.get_top(), path_arc = -2*np.pi/3, - use_rectangular_stem = False, ) arrow.tip.set_stroke(width = 3) diff --git a/old_projects/nn/part3.py b/old_projects/nn/part3.py index 534b4653..fff9bb77 100644 --- a/old_projects/nn/part3.py +++ b/old_projects/nn/part3.py @@ -2699,7 +2699,6 @@ class SimplestNetworkExample(PreviewLearning): tip_length = 0.2 mob.arrow = Arrow( mob_spot, dot_spot, - use_rectangular_stem = False, path_arc = path_arc, tip_length = tip_length, buff = SMALL_BUFF, @@ -3407,7 +3406,6 @@ class SimplestNetworkExample(PreviewLearning): arrow = Arrow( dz_db.get_bottom(), one.get_bottom(), - use_rectangular_stem = False, path_arc = np.pi/2, color = WHITE, ) @@ -3485,7 +3483,6 @@ class SimplestNetworkExample(PreviewLearning): arrow = Arrow( dz_daLm1.get_bottom(), wL.get_bottom(), path_arc = np.pi/2, - use_rectangular_stem = False, color = WHITE, ) diff --git a/old_projects/putnam.py b/old_projects/putnam.py index 37fecd5a..8a6d1312 100644 --- a/old_projects/putnam.py +++ b/old_projects/putnam.py @@ -1342,7 +1342,6 @@ class BrilliantPuzzle(PiCreatureScene): for s1, s2 in adjacent_pairs(self.students): arrow = Arrow( s1.get_center(), s2.get_center(), - use_rectangular_stem = False, path_arc = np.pi/2, buff = 0.8 ) diff --git a/old_projects/quat3d.py b/old_projects/quat3d.py index 55e41ca0..af0a8c37 100644 --- a/old_projects/quat3d.py +++ b/old_projects/quat3d.py @@ -1148,7 +1148,7 @@ class RuleForQuaternionRotations(EulerAnglesAndGimbal): self.change_q([1, 0, 0, 0], run_time=2) # Unit vector - vect_mob = Vector(2 * vect, use_rectangular_stem=False) + vect_mob = Vector(2 * vect) vect_mob.pointwise_become_partial(vect_mob, 0, 0.95) pieces = VGroup(*vect_mob.get_pieces(25)) pieces.set_stroke(vect_mob.get_color(), 2) @@ -1272,7 +1272,6 @@ class RuleForQuaternionRotations(EulerAnglesAndGimbal): curved_arrow = Arrow( r * RIGHT, rotate_vector(r * RIGHT, 30 * DEGREES, OUT), buff=0, - use_rectangular_stem=False, path_arc=60 * DEGREES, color=LIGHT_GREY, ) diff --git a/old_projects/quaternions.py b/old_projects/quaternions.py index d51ea676..df60e340 100644 --- a/old_projects/quaternions.py +++ b/old_projects/quaternions.py @@ -1055,7 +1055,6 @@ class QuantumSpin(Scene): electron.set_sheen(0.3, UL) electron.set_fill(opacity=0.8) kwargs = { - "use_rectangular_stem": False, "path_arc": PI, } curved_arrows = VGroup( @@ -1608,7 +1607,6 @@ class DefineComplexNumbersPurelyAlgebraically(Scene): arrow = Arrow( brace.get_bottom(), target.get_top(), - use_rectangular_stem=False, ) final_arrows.add(arrow) final_arrows.set_stroke(BLACK, width=6, background=True) @@ -2756,7 +2754,6 @@ class IntroduceStereographicProjectionLinusView(IntroduceStereographicProjection neg_i_dot = dots[-2] kwargs1 = { - "use_rectangular_stem": False, "path_arc": -90 * DEGREES, "buff": SMALL_BUFF, } @@ -2911,7 +2908,6 @@ class ShowRotationUnderStereographicProjection(IntroduceStereographicProjection) for p1, p2 in adjacent_pairs(points): arrow = Arrow( p1, p2, path_arc=180 * DEGREES, - use_rectangular_stem=False, ) arrow.set_stroke(LIGHT_GREY, width=3) arrow.tip.set_fill(LIGHT_GREY) @@ -4033,7 +4029,6 @@ class ShowRotationsJustWithReferenceCircles(TwoDStereographicProjection): 2 * RIGHT, 2 * UP, buff=SMALL_BUFF, path_arc=PI, - use_rectangular_stem=False, ) arrow.set_stroke(LIGHT_GREY, 3) arrow.tip.set_fill(LIGHT_GREY) @@ -5391,19 +5386,16 @@ class RuleOfQuaternionMultiplication(HypersphereStereographicProjection): c2p = self.axes.coords_to_point i_arrow = Arrow( ORIGIN, 2 * RIGHT, path_arc=-120 * DEGREES, - use_rectangular_stem=False, buff=SMALL_BUFF, ) neg_one_arrow = Arrow( ORIGIN, 5.5 * RIGHT + UP, path_arc=-30 * DEGREES, - use_rectangular_stem=False, buff=SMALL_BUFF, ) neg_i_arrow = Arrow( 4.5 * LEFT + 1.5 * UP, ORIGIN, path_arc=-30 * DEGREES, - use_rectangular_stem=False, buff=SMALL_BUFF, ) one_arrow = i_arrow.copy() @@ -6036,7 +6028,6 @@ class MultiplicationFromTheRight(Scene): i.get_top(), j.get_top(), path_arc=-PI, - use_rectangular_stem=False, ) arrow.set_stroke(width=2) @@ -6122,7 +6113,6 @@ class HowQuaternionsRotate3dPoints(Scene): expression[0].get_top(), expression[2].get_top(), path_arc=-PI, - use_rectangular_stem=False, color=WHITE, ) right_arrow.set_stroke(width=4) diff --git a/old_projects/turbulence.py b/old_projects/turbulence.py index 3cf10e08..253eee23 100644 --- a/old_projects/turbulence.py +++ b/old_projects/turbulence.py @@ -496,7 +496,6 @@ class JokeRingEquation(Scene): point = 3.8 * LEFT + 0.2 * UP arrow1 = Arrow( items[0].get_left(), point + 0.8 * UP + 0.3 * RIGHT, - use_rectangular_stem=False, path_arc=90 * DEGREES, ) arrow1.pointwise_become_partial(arrow1, 0, 0.99) @@ -1064,7 +1063,6 @@ class ShowNavierStokesEquations(Scene): question.get_bottom(), graph.point_from_proportion(0.8), buff=SMALL_BUFF, - use_rectangular_stem=False, path_arc=-60 * DEGREES ) q_arrow.set_stroke(WHITE, 3) @@ -1394,7 +1392,6 @@ class SwirlDiameterD(Scene): kwargs = { "path_arc": PI, "buff": SMALL_BUFF, - "use_rectangular_stem": False, "color": WHITE } swirl = VGroup( diff --git a/old_projects/uncertainty.py b/old_projects/uncertainty.py index 99bfbeb3..62e273cc 100644 --- a/old_projects/uncertainty.py +++ b/old_projects/uncertainty.py @@ -4429,7 +4429,6 @@ class Promotion(PiCreatureScene): aops_logo.get_top(), morty.get_top(), path_arc = -0.4*TAU, - use_rectangular_stem = False, stroke_width = 5, tip_length = 0.5, ) diff --git a/old_projects/waves.py b/old_projects/waves.py index 46486c0f..f977acda 100644 --- a/old_projects/waves.py +++ b/old_projects/waves.py @@ -3336,7 +3336,6 @@ class ThreeFilters(ShootPhotonThroughFilter): arrow = Arrow( ORIGIN, 7*RIGHT, - use_rectangular_stem = False, path_arc = 0.5*np.pi, ) labels = VGroup(*list(map(TexMobject, ["0\\%", "25\\%"]))) @@ -3779,7 +3778,6 @@ class PhotonAtSlightAngle(ThreeFilters): arrow = Arrow( 2*LEFT, 2*RIGHT, path_arc = 0.8*np.pi, - use_rectangular_stem = False, ) label = TexMobject("15\\% \\text{ absorbed}") label.next_to(arrow, DOWN) @@ -4028,7 +4026,6 @@ class CircularPhotons(ShootPhotonThroughFilter): arrows = VGroup(*[ Arrow( v1, v2, - use_rectangular_stem = False, color = WHITE, path_arc = np.pi, )