Enhancement: Migrate width/height/depth to properties (#1024)

* Migrate width/height/depth to properties

* Fix examples

* Fix typos

* Import manim for doctests

* Expect Square for doctests

* Improve docs for width/height/depth properties
This commit is contained in:
friedkeenan 2021-02-14 05:33:12 -06:00 committed by GitHub
commit 3ad385a168
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 333 additions and 145 deletions

View file

@ -330,7 +330,7 @@ Plotting with Manim
y_max=6,
x_labeled_nums=[0,2,3],
**kwargs)
def construct(self):
self.setup_axes()
curve1 = self.get_graph(lambda x: 4 * x - x ** 2, x_min=0, x_max=4)
@ -435,7 +435,7 @@ Special Camera Settings
dot = Dot().shift(UL * 2)
image = ImageMobject(np.uint8([[0, 100, 30, 200],
[255, 0, 5, 33]]))
image.set_height(7)
image.height = 7
frame_text = Text("Frame", color=PURPLE).scale(1.4)
zoomed_camera_text = Text("Zoomed camera", color=RED).scale(1.4)

View file

@ -101,7 +101,7 @@ class WriteStuff(Scene):
)
group = VGroup(example_text, example_tex)
group.arrange(DOWN)
group.set_width(config["frame_width"] - 2 * LARGE_BUFF)
group.width = config["frame_width"] - 2 * LARGE_BUFF
self.play(Write(example_text))
self.play(Write(example_tex))

View file

@ -69,7 +69,7 @@ class MovingCamera(Camera):
float
The height of the frame.
"""
return self.frame.get_height()
return self.frame.height
@property
def frame_width(self):
@ -80,7 +80,7 @@ class MovingCamera(Camera):
float
The width of the frame.
"""
return self.frame.get_width()
return self.frame.width
@property
def frame_center(self):
@ -158,9 +158,9 @@ class MovingCamera(Camera):
# def realign_frame_shape(self):
# height, width = self.frame_shape
# if self.fixed_dimension == 0:
# self.frame_shape = (height, self.frame.get_width())
# self.frame_shape = (height, self.frame.width
# else:
# self.frame_shape = (self.frame.get_height(), width)
# self.frame_shape = (self.frame.height, width)
# self.resize_frame_shape(fixed_dimension=self.fixed_dimension)
def get_mobjects_indicating_movement(self):

View file

@ -54,12 +54,12 @@ class MultiCamera(MovingCamera):
for imfc in self.image_mobjects_from_cameras:
pixel_height, pixel_width = self.pixel_array.shape[:2]
imfc.camera.frame_shape = (
imfc.camera.frame.get_height(),
imfc.camera.frame.get_width(),
imfc.camera.frame.height,
imfc.camera.frame.width,
)
imfc.camera.reset_pixel_shape(
int(pixel_height * imfc.get_height() / self.frame_height),
int(pixel_width * imfc.get_width() / self.frame_width),
int(pixel_height * imfc.height / self.frame_height),
int(pixel_width * imfc.width / self.frame_width),
)
def reset(self):

View file

@ -404,8 +404,8 @@ def serialize_mobject(mobject):
logger.info(
f"Expected path {mobject.path} to be under the assets dir ({assets_dir_path})"
)
mob_proto.image_mobject_data.height = mobject.get_height()
mob_proto.image_mobject_data.width = mobject.get_width()
mob_proto.image_mobject_data.height = mobject.height
mob_proto.image_mobject_data.width = mobject.width
mob_center = mobject.get_center()
mob_proto.image_mobject_data.center.x = mob_center[0]
mob_proto.image_mobject_data.center.y = mob_center[1]

View file

@ -16,16 +16,27 @@ from ..utils.color import BLACK
class ScreenRectangle(Rectangle):
def __init__(self, aspect_ratio=16.0 / 9.0, height=4, **kwargs):
self.aspect_ratio = aspect_ratio
self.height = height
Rectangle.__init__(self, **kwargs)
self.set_width(self.aspect_ratio * self.get_height(), stretch=True)
Rectangle.__init__(self, width=aspect_ratio * height, height=height, **kwargs)
@property
def aspect_ratio(self):
"""The aspect ratio.
When set, the width is stretched to accommodate
the new aspect ratio.
"""
return self.width / self.height
@aspect_ratio.setter
def aspect_ratio(self, value):
self.stretch_to_fit_width(value * self.height)
class FullScreenRectangle(ScreenRectangle):
def __init__(self, **kwargs):
ScreenRectangle.__init__(self, **kwargs)
self.set_height(config["frame_height"])
self.height = config["frame_height"]
class FullScreenFadeRectangle(FullScreenRectangle):
@ -41,8 +52,18 @@ class FullScreenFadeRectangle(FullScreenRectangle):
class PictureInPictureFrame(Rectangle):
def __init__(self, height=3, aspect_ratio=16.0 / 9.0, **kwargs):
self.height = height
self.aspect_ratio = aspect_ratio
Rectangle.__init__(
self, width=self.aspect_ratio * self.height, height=self.height, **kwargs
)
Rectangle.__init__(self, width=aspect_ratio * height, height=height, **kwargs)
@property
def aspect_ratio(self):
"""The aspect ratio.
When set, the width is stretched to accommodate
the new aspect ratio.
"""
return self.width / self.height
@aspect_ratio.setter
def aspect_ratio(self, value):
self.stretch_to_fit_width(value * self.height)

View file

@ -413,7 +413,7 @@ class Circle(Arc):
# TODO: Figure out and fix
self.replace(mobject, dim_to_match, stretch)
self.set_width(np.sqrt(mobject.get_width() ** 2 + mobject.get_height() ** 2))
self.width = np.sqrt(mobject.width ** 2 + mobject.height ** 2)
return self.scale(buffer_factor)
def point_at_angle(self, angle):
@ -519,9 +519,7 @@ class LabeledDot(Dot):
rendered_label = label
if radius is None:
radius = (
0.1 + max(rendered_label.get_width(), rendered_label.get_height()) / 2
)
radius = 0.1 + max(rendered_label.width, rendered_label.height) / 2
Dot.__init__(self, radius=radius, **kwargs)
rendered_label.move_to(self.get_center())
self.add(rendered_label)
@ -530,10 +528,8 @@ class LabeledDot(Dot):
class Ellipse(Circle):
def __init__(self, width=2, height=1, **kwargs):
Circle.__init__(self, **kwargs)
self.width = width
self.height = height
self.set_width(self.width, stretch=True)
self.set_height(self.height, stretch=True)
self.stretch_to_fit_width(width)
self.stretch_to_fit_height(height)
class AnnularSector(Arc):
@ -788,11 +784,10 @@ class TangentLine(Line):
class Elbow(VMobject):
def __init__(self, width=0.2, angle=0, **kwargs):
self.width = width
self.angle = angle
VMobject.__init__(self, **kwargs)
self.set_points_as_corners([UP, UP + RIGHT, RIGHT])
self.set_width(self.width, about_point=ORIGIN)
self.scale_to_fit_width(width, about_point=ORIGIN)
self.rotate(self.angle, about_point=ORIGIN)
@ -1227,20 +1222,27 @@ class Rectangle(Polygon):
close_new_points=True,
**kwargs
):
self.height = height
self.width = width
self.mark_paths_closed = mark_paths_closed
self.close_new_points = close_new_points
Polygon.__init__(self, UL, UR, DR, DL, color=color, **kwargs)
self.set_width(self.width, stretch=True)
self.set_height(self.height, stretch=True)
self.stretch_to_fit_width(width)
self.stretch_to_fit_height(height)
class Square(Rectangle):
def __init__(self, side_length=2.0, **kwargs):
self.side_length = side_length
Rectangle.__init__(self, height=side_length, width=side_length, **kwargs)
@property
def side_length(self):
"""The square's side length."""
return self.width
@side_length.setter
def side_length(self, value):
self.width = value
class RoundedRectangle(Rectangle):
def __init__(self, corner_radius=0.5, **kwargs):
@ -1279,8 +1281,8 @@ class ArrowTip(VMobject):
... def __init__(self, **kwargs):
... RegularPolygon.__init__(self, n=5, **kwargs)
... length = 0.35
... self.set_width(length)
... self.set_height(length, stretch=True)
... self.width = length
... self.stretch_to_fit_height(length)
>>> arr = Arrow(np.array([-2, -2, 0]), np.array([2, 2, 0]),
... tip_shape=MyCustomArrowTip)
>>> isinstance(arr.tip, RegularPolygon)
@ -1419,8 +1421,8 @@ class ArrowTriangleTip(ArrowTip, Triangle):
start_angle=start_angle,
**kwargs
)
self.set_width(length)
self.set_height(length, stretch=True)
self.width = length
self.stretch_to_fit_height(length)
class ArrowTriangleFilledTip(ArrowTriangleTip):
@ -1450,8 +1452,8 @@ class ArrowCircleTip(ArrowTip, Circle):
Circle.__init__(
self, fill_opacity=fill_opacity, stroke_width=stroke_width, **kwargs
)
self.set_width(length)
self.set_height(length, stretch=True)
self.width = length
self.stretch_to_fit_height(length)
class ArrowCircleFilledTip(ArrowCircleTip):
@ -1482,8 +1484,8 @@ class ArrowSquareTip(ArrowTip, Square):
side_length=length,
**kwargs
)
self.set_width(length)
self.set_height(length, stretch=True)
self.width = length
self.stretch_to_fit_height(length)
class ArrowSquareFilledTip(ArrowSquareTip):

View file

@ -84,9 +84,8 @@ class ManimBanner(VGroup):
tex.next_to(anim, buff=0.01)
tex.align_to(self.M, DOWN)
anim.add(tex)
anim.set_color(self.font_color).set_height(
m_height_over_anim_height * self.M.get_height()
)
anim.set_color(self.font_color)
anim.height = m_height_over_anim_height * self.M.height
# Note: "anim" is only shown in the expanded state
# and thus not yet added to the submobjects of self.

View file

@ -132,7 +132,7 @@ class Matrix(VMobject):
def add_brackets(self, left="\\big[", right="\\big]"):
bracket_pair = MathTex(left, right)
bracket_pair.scale(2)
bracket_pair.stretch_to_fit_height(self.get_height() + 2 * self.bracket_v_buff)
bracket_pair.stretch_to_fit_height(self.height + 2 * self.bracket_v_buff)
l_bracket, r_bracket = bracket_pair.split()
l_bracket.next_to(self, LEFT, self.bracket_h_buff)
r_bracket.next_to(self, RIGHT, self.bracket_h_buff)
@ -228,7 +228,7 @@ def get_det_text(
):
parens = MathTex("(", ")")
parens.scale(initial_scale_factor)
parens.stretch_to_fit_height(matrix.get_height())
parens.stretch_to_fit_height(matrix.height)
l_paren, r_paren = parens.split()
l_paren.next_to(matrix, LEFT, buff=0.1)
r_paren.next_to(matrix, RIGHT, buff=0.1)

View file

@ -354,6 +354,86 @@ class Mobject(Container):
# Unhandled attribute, therefore error
raise AttributeError
@property
def width(self):
"""The width of the mobject.
Returns
-------
:class:`float`
Examples
--------
.. manim:: WidthExample
class WidthExample(Scene):
def construct(self):
decimal = DecimalNumber().to_edge(UP)
rect = Rectangle(color=BLUE)
rect_copy = rect.copy().set_stroke(GRAY, opacity=0.5)
decimal.add_updater(lambda d: d.set_value(rect.width))
self.add(rect_copy, rect, decimal)
self.play(rect.animate.set(width=7))
self.wait()
"""
# Get the length across the X dimension
return self.length_over_dim(0)
@width.setter
def width(self, value):
self.scale_to_fit_width(value)
@property
def height(self):
"""The height of the mobject.
Returns
-------
:class:`float`
Examples
--------
.. manim:: HeightExample
class HeightExample(Scene):
def construct(self):
decimal = DecimalNumber().to_edge(UP)
rect = Rectangle(color=BLUE)
rect_copy = rect.copy().set_stroke(GRAY, opacity=0.5)
decimal.add_updater(lambda d: d.set_value(rect.height))
self.add(rect_copy, rect, decimal)
self.play(rect.animate.set(height=5))
self.wait()
"""
# Get the length across the Y dimension
return self.length_over_dim(1)
@height.setter
def height(self, value):
self.scale_to_fit_height(value)
@property
def depth(self):
"""The depth of the mobject.
Returns
-------
:class:`float`
"""
# Get the length across the Z dimension
return self.length_over_dim(2)
@depth.setter
def depth(self, value):
self.scale_to_fit_depth(value)
def get_array_attrs(self):
return ["points"]
@ -754,24 +834,120 @@ class Mobject(Container):
self.scale(length / old_length, **kwargs)
return self
def scale_to_fit_width(self, width, **kwargs):
"""Scales the mobject to fit a width while keeping height/depth proportional.
Returns
-------
:class:`Mobject`
``self``
Examples
--------
::
>>> from manim import *
>>> sq = Square()
>>> sq.height
2.0
>>> sq.scale_to_fit_width(5)
Square
>>> sq.width
5.0
>>> sq.height
5.0
"""
return self.rescale_to_fit(width, 0, stretch=False, **kwargs)
def stretch_to_fit_width(self, width, **kwargs):
"""Stretches the mobject to fit a width, not keeping height/depth proportional.
Returns
-------
:class:`Mobject`
``self``
Examples
--------
::
>>> from manim import *
>>> sq = Square()
>>> sq.height
2.0
>>> sq.stretch_to_fit_width(5)
Square
>>> sq.width
5.0
>>> sq.height
2.0
"""
return self.rescale_to_fit(width, 0, stretch=True, **kwargs)
def scale_to_fit_height(self, height, **kwargs):
"""Scales the mobject to fit a height while keeping width/depth proportional.
Returns
-------
:class:`Mobject`
``self``
Examples
--------
::
>>> from manim import *
>>> sq = Square()
>>> sq.width
2.0
>>> sq.scale_to_fit_height(5)
Square
>>> sq.height
5.0
>>> sq.width
5.0
"""
return self.rescale_to_fit(height, 1, stretch=False, **kwargs)
def stretch_to_fit_height(self, height, **kwargs):
"""Stretches the mobject to fit a height, not keeping width/depth proportional.
Returns
-------
:class:`Mobject`
``self``
Examples
--------
::
>>> from manim import *
>>> sq = Square()
>>> sq.width
2.0
>>> sq.stretch_to_fit_height(5)
Square
>>> sq.height
5.0
>>> sq.width
2.0
"""
return self.rescale_to_fit(height, 1, stretch=True, **kwargs)
def scale_to_fit_depth(self, depth, **kwargs):
"""Scales the mobject to fit a depth while keeping width/height proportional."""
return self.rescale_to_fit(depth, 2, stretch=False, **kwargs)
def stretch_to_fit_depth(self, depth, **kwargs):
"""Stretches the mobject to fit a depth, not keeping width/height proportional."""
return self.rescale_to_fit(depth, 2, stretch=True, **kwargs)
def set_width(self, width, stretch=False, **kwargs):
return self.rescale_to_fit(width, 0, stretch=stretch, **kwargs)
def set_height(self, height, stretch=False, **kwargs):
return self.rescale_to_fit(height, 1, stretch=stretch, **kwargs)
def set_depth(self, depth, stretch=False, **kwargs):
return self.rescale_to_fit(depth, 2, stretch=stretch, **kwargs)
def set_coord(self, value, dim, direction=ORIGIN):
curr = self.get_coord(dim, direction)
shift_vect = np.zeros(self.dim)
@ -810,8 +986,8 @@ class Mobject(Container):
raise Warning("Attempting to replace mobject with no points")
return self
if stretch:
self.stretch_to_fit_width(mobject.get_width())
self.stretch_to_fit_height(mobject.get_height())
self.stretch_to_fit_width(mobject.width)
self.stretch_to_fit_height(mobject.height)
else:
self.rescale_to_fit(
mobject.length_over_dim(dim_to_match), dim_to_match, stretch=False
@ -1061,15 +1237,6 @@ class Mobject(Container):
np.max, np.max, dim
) - self.reduce_across_dimension(np.min, np.min, dim)
def get_width(self):
return self.length_over_dim(0)
def get_height(self):
return self.length_over_dim(1)
def get_depth(self):
return self.length_over_dim(2)
def get_coord(self, dim, direction=ORIGIN):
"""
Meant to generalize get_x, get_y, get_z

View file

@ -53,7 +53,6 @@ class NumberLine(Line):
self.unit_size = unit_size
self.include_ticks = include_ticks
self.tick_size = tick_size
self.width = width
self.tick_frequency = tick_frequency
self.leftmost_tick = leftmost_tick
self.numbers_with_elongated_ticks = numbers_with_elongated_ticks
@ -83,8 +82,8 @@ class NumberLine(Line):
color=color,
**kwargs,
)
if self.width is not None:
self.set_width(self.width)
if width is not None:
self.width = width
self.unit_size = self.get_unit_size()
self.shift(-self.number_to_point(self.number_at_center))

View file

@ -114,9 +114,9 @@ class DecimalNumber(VMobject):
for i, c in enumerate(num_string):
if c == "-" and len(num_string) > i + 1:
self[i].align_to(self[i + 1], UP)
self[i].shift(self[i + 1].get_height() * DOWN / 2)
self[i].shift(self[i + 1].height * DOWN / 2)
elif c == ",":
self[i].shift(self[i].get_height() * DOWN / 2)
self[i].shift(self[i].height * DOWN / 2)
if self.unit and self.unit.startswith("^"):
self.unit_sign.align_to(self, UP)
#
@ -187,7 +187,7 @@ class DecimalNumber(VMobject):
new_submobject.original_id = generated_id
# Make sure last digit has constant height
new_decimal.scale(self[-1].get_height() / new_decimal[-1].get_height())
new_decimal.scale(self[-1].height / new_decimal[-1].height)
new_decimal.move_to(self, self.edge_to_fix)
new_decimal.match_style(self)

View file

@ -51,8 +51,8 @@ class SampleSpace(Rectangle):
def add_title(self, title="Sample space", buff=MED_SMALL_BUFF):
# TODO, should this really exist in SampleSpaceScene
title_mob = Tex(title)
if title_mob.get_width() > self.get_width():
title_mob.set_width(self.get_width())
if title_mob.width > self.width:
title_mob.width = self.width
title_mob.next_to(self, UP, buff=buff)
self.title = title_mob
self.add(title_mob)
@ -175,8 +175,6 @@ class BarChart(VGroup):
**kwargs
):
VGroup.__init__(self, **kwargs)
self.height = height
self.width = width
self.n_ticks = n_ticks
self.tick_width = tick_width
self.label_y_axis = label_y_axis
@ -191,19 +189,19 @@ class BarChart(VGroup):
if self.max_value is None:
self.max_value = max(values)
self.add_axes()
self.add_bars(values)
self.add_axes(width, height)
self.add_bars(values, width, height)
self.center()
def add_axes(self):
x_axis = Line(self.tick_width * LEFT / 2, self.width * RIGHT)
y_axis = Line(MED_LARGE_BUFF * DOWN, self.height * UP)
def add_axes(self, width, height):
x_axis = Line(self.tick_width * LEFT / 2, width * RIGHT)
y_axis = Line(MED_LARGE_BUFF * DOWN, height * UP)
ticks = VGroup()
heights = np.linspace(0, self.height, self.n_ticks + 1)
heights = np.linspace(0, height, self.n_ticks + 1)
values = np.linspace(0, self.max_value, self.n_ticks + 1)
for y, value in zip(heights, values):
tick = Line(LEFT, RIGHT)
tick.set_width(self.tick_width)
tick.width = self.tick_width
tick.move_to(y * UP)
ticks.add(tick)
y_axis.add(ticks)
@ -215,18 +213,18 @@ class BarChart(VGroup):
labels = VGroup()
for tick, value in zip(ticks, values):
label = MathTex(str(np.round(value, 2)))
label.set_height(self.y_axis_label_height)
label.height = self.y_axis_label_height
label.next_to(tick, LEFT, SMALL_BUFF)
labels.add(label)
self.y_axis_labels = labels
self.add(labels)
def add_bars(self, values):
buff = float(self.width) / (2 * len(values) + 1)
def add_bars(self, values, width, height):
buff = float(width) / (2 * len(values) + 1)
bars = VGroup()
for i, value in enumerate(values):
bar = Rectangle(
height=(value / self.max_value) * self.height,
height=(value / self.max_value) * height,
width=buff,
stroke_width=self.bar_stroke_width,
fill_opacity=self.bar_fill_opacity,

View file

@ -15,9 +15,13 @@ class SurroundingRectangle(Rectangle):
def __init__(self, mobject, color=YELLOW, buff=SMALL_BUFF, **kwargs):
self.color = color
self.buff = buff
kwargs["width"] = mobject.get_width() + 2 * self.buff
kwargs["height"] = mobject.get_height() + 2 * self.buff
Rectangle.__init__(self, color=color, **kwargs)
Rectangle.__init__(
self,
color=color,
width=mobject.width + 2 * self.buff,
height=mobject.height + 2 * self.buff,
**kwargs
)
self.move_to(mobject)

View file

@ -90,7 +90,7 @@ class Brace(MathTex):
else:
mob.move_to(self.get_tip())
buff = kwargs.get("buff", DEFAULT_MOBJECT_TO_MOBJECT_BUFFER)
shift_distance = mob.get_width() / 2.0 + buff
shift_distance = mob.width / 2.0 + buff
mob.shift(self.get_direction() * shift_distance)
return self

View file

@ -238,8 +238,8 @@ class Code(VGroup):
foreground = VGroup(self.code, self.line_numbers)
else:
foreground = self.code
height = foreground.get_height() + 0.1 * 3 + 2 * self.margin
width = foreground.get_width() + 0.1 * 3 + 2 * self.margin
height = foreground.height + 0.1 * 3 + 2 * self.margin
width = foreground.width + 0.1 * 3 + 2 * self.margin
rect = RoundedRectangle(
corner_radius=self.corner_radius,
@ -262,7 +262,7 @@ class Code(VGroup):
)
self.background_mobject = VGroup(rect, buttons)
x = (height - foreground.get_height()) / 2 - 0.1 * 3
x = (height - foreground.height) / 2 - 0.1 * 3
self.background_mobject.shift(foreground.get_center())
self.background_mobject.shift(UP * x)
if self.insert_line_no:

View file

@ -84,13 +84,11 @@ class SVGMobject(VMobject):
self.file_name = file_name or self.file_name
self.ensure_valid_file()
self.should_center = should_center
self.height = height
self.width = width
self.unpack_groups = unpack_groups
VMobject.__init__(
self, fill_opacity=fill_opacity, stroke_width=stroke_width, **kwargs
)
self.move_into_position()
self.move_into_position(width, height)
def ensure_valid_file(self):
"""Reads self.file_name and determines whether the given input file_name
@ -504,17 +502,17 @@ class SVGMobject(VMobject):
)
self.ref_to_element.update(new_refs)
def move_into_position(self):
def move_into_position(self, width, height):
"""Uses the SVGMobject's config dictionary to set the Mobject's
width, height, and/or center it. Use ``width``, ``height``, and
``should_center`` respectively to modify this.
"""
if self.should_center:
self.center()
if self.height is not None:
self.set_height(self.height)
if self.width is not None:
self.set_width(self.width)
if height is not None:
self.height = height
if width is not None:
self.width = width
class VMobjectFromSVGPathstring(VMobject):

View file

@ -241,7 +241,7 @@ class SingleStringMathTex(SVGMobject):
background_stroke_color=background_stroke_color,
**kwargs,
)
if self.height is None:
if height is None:
self.scale(TEX_MOB_SCALE_FACTOR)
if self.organize_left_to_right:
self.organize_submobjects_left_to_right()
@ -560,16 +560,16 @@ class Title(Tex):
self.match_underline_width_to_text = match_underline_width_to_text
self.underline_buff = underline_buff
Tex.__init__(self, *text_parts, **kwargs)
self.underline_width = config["frame_width"] - 2
self.scale(self.scale_factor)
self.to_edge(UP)
if self.include_underline:
underline_width = config["frame_width"] - 2
underline = Line(LEFT, RIGHT)
underline.next_to(self, DOWN, buff=self.underline_buff)
if self.match_underline_width_to_text:
underline.match_width(self)
else:
underline.set_width(self.underline_width)
underline.width = underline_width
self.add(underline)
self.underline = underline

View file

@ -228,7 +228,7 @@ class CairoText(SVGMobject):
if self.t2g:
self.set_color_by_t2g()
# anti-aliasing
if self.height is None and self.width is None:
if height is None and width is None:
self.scale(TEXT_MOB_SCALE_FACTOR)
def __repr__(self):
@ -568,7 +568,7 @@ class Paragraph(VGroup):
self[line_no].move_to(
np.array(
[
self.get_right()[0] - self[line_no].get_width() / 2,
self.get_right()[0] - self[line_no].width / 2,
self[line_no].get_center()[1],
0,
]
@ -578,7 +578,7 @@ class Paragraph(VGroup):
self[line_no].move_to(
np.array(
[
self.get_left()[0] + self[line_no].get_width() / 2,
self.get_left()[0] + self[line_no].width / 2,
self[line_no].get_center()[1],
0,
]
@ -799,7 +799,7 @@ class Text(SVGMobject):
if self.t2g:
self.set_color_by_t2g()
# anti-aliasing
if self.height is None and self.width is None:
if height is None and width is None:
self.scale(TEXT_MOB_SCALE_FACTOR)
def __repr__(self):
@ -1252,7 +1252,7 @@ class MarkupText(SVGMobject):
*(self._parse_color(grad["from"]), self._parse_color(grad["to"]))
)
# anti-aliasing
if self.height is None and self.width is None:
if height is None and width is None:
self.scale(TEXT_MOB_SCALE_FACTOR)
def text2hash(self):

View file

@ -54,11 +54,11 @@ class AbstractImageMobject(Mobject):
self.center()
h, w = self.get_pixel_array().shape[:2]
if self.scale_to_resolution:
self.height = h / self.scale_to_resolution * config["frame_height"]
height = h / self.scale_to_resolution * config["frame_height"]
else:
self.height = 3 ## this is the case for ImageMobjectFromCamera
self.stretch_to_fit_height(self.height)
self.stretch_to_fit_width(self.height * w / h)
height = 3 ## this is the case for ImageMobjectFromCamera
self.stretch_to_fit_height(height)
self.stretch_to_fit_width(height * w / h)
class ImageMobject(AbstractImageMobject):
@ -80,7 +80,7 @@ class ImageMobject(AbstractImageMobject):
def construct(self):
image = ImageMobject(np.uint8([[0, 100, 30, 200],
[255, 0, 5, 33]]))
image.set_height(7)
image.height = 7
self.add(image)
"""

View file

@ -1740,10 +1740,12 @@ class VectorizedPoint(VMobject):
)
self.set_points(np.array([location]))
def get_width(self):
@VMobject.width.getter
def width(self):
return self.artificial_width
def get_height(self):
@VMobject.height.getter
def height(self):
return self.artificial_height
def get_location(self):

View file

@ -926,22 +926,22 @@ class GraphScene(Scene):
group.add(group.df_label)
if len(labels) > 0:
max_width = 0.8 * group.dx_line.get_width()
max_height = 0.8 * group.df_line.get_height()
if labels.get_width() > max_width:
labels.set_width(max_width)
if labels.get_height() > max_height:
labels.set_height(max_height)
max_width = 0.8 * group.dx_line.width
max_height = 0.8 * group.df_line.height
if labels.width > max_width:
labels.width = max_width
if labels.height > max_height:
labels.height = max_height
if dx_label is not None:
group.dx_label.next_to(
group.dx_line, np.sign(dx) * DOWN, buff=group.dx_label.get_height() / 2
group.dx_line, np.sign(dx) * DOWN, buff=group.dx_label.height / 2
)
group.dx_label.set_color(group.dx_line.get_color())
if df_label is not None:
group.df_label.next_to(
group.df_line, np.sign(dx) * RIGHT, buff=group.df_label.get_height() / 2
group.df_line, np.sign(dx) * RIGHT, buff=group.df_label.height / 2
)
group.df_label.set_color(group.df_line.get_color())
@ -992,7 +992,7 @@ class GraphScene(Scene):
Any valid keyword argument of a self.play call.
"""
triangle = RegularPolygon(n=3, start_angle=np.pi / 2)
triangle.set_height(MED_SMALL_BUFF)
triangle.height = MED_SMALL_BUFF
triangle.move_to(self.coords_to_point(x_val, 0), UP)
triangle.set_fill(color, 1)
triangle.set_stroke(width=0)

View file

@ -15,7 +15,7 @@ Examples
text = Text("Hello World").set_color(BLUE)
self.add(text)
self.camera_frame.save_state()
self.play(self.camera_frame.animate.set_width(text.get_width() * 1.2))
self.play(self.camera_frame.animate.set(width=text.width * 1.2))
self.wait(0.3)
self.play(Restore(self.camera_frame))
@ -40,11 +40,11 @@ Examples
s = Square(color=BLUE, fill_opacity=0.5).move_to(2 * LEFT)
t = Triangle(color=YELLOW, fill_opacity=0.5).move_to(2 * RIGHT)
self.add(s, t)
self.play(self.camera_frame.animate.move_to(s).set_width(s.get_width()*2))
self.play(self.camera_frame.animate.move_to(s).set(width=s.width*2))
self.wait(0.3)
self.play(self.camera_frame.animate.move_to(t).set_width(t.get_width()*2))
self.play(self.camera_frame.animate.move_to(t).set(width=t.width*2))
self.play(self.camera_frame.animate.move_to(ORIGIN).set_width(14))
self.play(self.camera_frame.animate.move_to(ORIGIN).set(width=14))
.. manim:: MovingCameraOnGraph

View file

@ -99,14 +99,14 @@ class SampleSpaceScene(Scene):
def get_posterior_rectangles(self, buff=MED_LARGE_BUFF):
prior_rects = self.get_prior_rectangles()
areas = [rect.get_width() * rect.get_height() for rect in prior_rects]
areas = [rect.width * rect.height for rect in prior_rects]
total_area = sum(areas)
total_height = prior_rects.get_height()
total_height = prior_rects.height
post_rects = prior_rects.copy()
for rect, area in zip(post_rects, areas):
rect.stretch_to_fit_height(total_height * area / total_area)
rect.stretch_to_fit_width(area / rect.get_height())
rect.stretch_to_fit_width(area / rect.height)
post_rects.arrange(DOWN, buff=0)
post_rects.next_to(self.sample_space, RIGHT, buff)
return post_rects
@ -122,7 +122,7 @@ class SampleSpaceScene(Scene):
braces = post_rects.braces
labels = post_rects.labels
for rect, brace, label in zip(post_rects, braces, labels):
brace.stretch_to_fit_height(rect.get_height())
brace.stretch_to_fit_height(rect.height)
brace.next_to(rect, RIGHT, SMALL_BUFF)
label.next_to(brace, RIGHT, SMALL_BUFF)

View file

@ -204,6 +204,4 @@ class ZoomedScene(MovingCameraScene):
float
The zoom factor.
"""
return fdiv(
self.zoomed_camera.frame.get_height(), self.zoomed_display.get_height()
)
return fdiv(self.zoomed_camera.frame.height, self.zoomed_display.height)

View file

@ -21,7 +21,7 @@ def index_labels(mobject, label_height=0.15):
labels = VGroup()
for n, submob in enumerate(mobject):
label = Integer(n)
label.set_height(label_height)
label.height = label_height
label.move_to(submob)
label.set_stroke(BLACK, 5, background=True)
labels.add(label)

View file

@ -11,7 +11,7 @@ def test_simple_animate():
s = Square()
scale_factor = 2
anim = s.animate.scale(scale_factor).build()
assert anim.mobject.target.get_width() == scale_factor * s.get_width()
assert anim.mobject.target.width == scale_factor * s.width
def test_chained_animate():
@ -20,7 +20,7 @@ def test_chained_animate():
direction = np.array((1, 1, 0))
anim = s.animate.scale(scale_factor).shift(direction).build()
assert (
anim.mobject.target.get_width() == scale_factor * s.get_width()
anim.mobject.target.width == scale_factor * s.width
and (anim.mobject.target.get_center() == direction).all()
)

View file

@ -11,6 +11,6 @@ class WriteStuff(Scene):
)
group = VGroup(example_text, example_tex)
group.arrange(DOWN)
group.set_width(config["frame_width"] - 2 * LARGE_BUFF)
group.width = config["frame_width"] - 2 * LARGE_BUFF
self.play(Write(example_text))