How to make a dashed rectangle with consistent spacing in manim?

1.5k Views Asked by At

How to create a dashed rectangle with equally spaced dashes on both edges in manim? I've tried inheriting from Rectangle and adding dashes the same way as it is implemented for DashedLine but it produces very different densities on the longer and shorter edges. Here is my attempt (code derived from MIT licensed manim repository):

%%manim HighLevelIntuition -l -q
from manimlib_imports import *

class DashedRectangle(Rectangle):
    CONFIG = {
        "dash_length": DEFAULT_DASH_LENGTH,
        "dash_spacing": None,
        "positive_space_ratio": 0.5,
    }

    def __init__(self, *args, **kwargs):
        Rectangle.__init__(self, *args, **kwargs)
        ps_ratio = self.positive_space_ratio
        num_dashes = self.calculate_num_dashes(ps_ratio)
        dashes = DashedVMobject(
            self,
            num_dashes=num_dashes,
            positive_space_ratio=ps_ratio
        )
        self.clear_points()
        self.add(*dashes)

    def calculate_num_dashes(self, positive_space_ratio):
        try:
            full_length = self.dash_length / positive_space_ratio
            return int(np.ceil(
                self.get_arc_length() / full_length
            ))
        except ZeroDivisionError:
            return 1

class HighLevelIntuition(Scene):

    def construct(self):
        self.play(ShowCreation(DashedRectangle(width=10, height=2)))

And that's how it looks like currently:

enter image description here

1

There are 1 best solutions below

4
TheoremOfBeethoven On BEST ANSWER

Check this:

class DashedRectangle(VGroup):
    CONFIG={
        "num_dashes": 30,
        "positive_space_ratio": 0.5,
        "width":5,
        "height":4
    }
    def __init__(self, *args, **kwargs):
        VGroup.__init__(self, *args,**kwargs)
        h1=[ORIGIN,UP*self.height]
        w1=[UP*self.height,UP*self.height+RIGHT*self.width]
        h2=[UP*self.height+RIGHT*self.width,RIGHT*self.width]
        w2=[RIGHT*self.width,ORIGIN]
        alpha=self.width/self.height
        divs=self.num_dashes

        n_h=int(divs/(2*(alpha+1)))
        n_w=int(alpha*n_h)
        dashedrectangle=VGroup()
        for n,l in zip([n_w,n_h],[[w1,w2],[h1,h2]]):
            for side in l:
                line=VMobject()
                line.set_points_as_corners(side)
                dashedrectangle.add(DashedVMobject(line,num_dashes=n,positive_space_ratio=self.positive_space_ratio))
        self.add(dashedrectangle[0],dashedrectangle[3],dashedrectangle[1],dashedrectangle[2])



class DashedRectangleScene(Scene):
    def construct(self):
        rec=DashedRectangle()
        rec.move_to(ORIGIN)
        self.play(ShowCreation(rec))
        self.wait()

DashedSquare