|
30 | 30 | from ...utils.simple_functions import clip_in_place |
31 | 31 | from ...utils.space_ops import rotate_vector |
32 | 32 | from ...utils.space_ops import get_norm |
| 33 | +from ...utils.space_ops import shoelace_direction |
33 | 34 |
|
34 | 35 | # TODO |
35 | 36 | # - Change cubic curve groups to have 4 points instead of 3 |
@@ -879,6 +880,68 @@ def get_subcurve(self, a, b): |
879 | 880 | vmob.pointwise_become_partial(self, a, b) |
880 | 881 | return vmob |
881 | 882 |
|
| 883 | + def get_direction(self): |
| 884 | + """Uses :func:`~.space_ops.shoelace_direction` to calculate the direction. |
| 885 | + The direction of points determines in which direction the |
| 886 | + object is drawn, clockwise or counterclockwise. |
| 887 | +
|
| 888 | + Examples |
| 889 | + -------- |
| 890 | + The default direction of a :class:`~.Circle` is counterclockwise:: |
| 891 | +
|
| 892 | + >>> from manim import Circle |
| 893 | + >>> Circle().get_direction() |
| 894 | + 'CCW' |
| 895 | +
|
| 896 | + Returns |
| 897 | + ------- |
| 898 | + :class:`str` |
| 899 | + Either `"CW"` or `"CCW"`. |
| 900 | + """ |
| 901 | + return shoelace_direction(self.get_start_anchors()) |
| 902 | + |
| 903 | + def reverse_direction(self): |
| 904 | + """Reverts the point direction by inverting the point order. |
| 905 | +
|
| 906 | + Returns |
| 907 | + ------- |
| 908 | + :class:`VMobject` |
| 909 | + Returns self. |
| 910 | +
|
| 911 | + Examples |
| 912 | + -------- |
| 913 | + .. manim:: ChangeOfDirection |
| 914 | +
|
| 915 | + class ChangeOfDirection(Scene): |
| 916 | + def construct(self): |
| 917 | + ccw = RegularPolygon(5) |
| 918 | + ccw.shift(LEFT).rotate |
| 919 | + cw = RegularPolygon(5) |
| 920 | + cw.shift(RIGHT).reverse_direction() |
| 921 | +
|
| 922 | + self.play(ShowCreation(ccw), ShowCreation(cw), |
| 923 | + run_time=4) |
| 924 | + """ |
| 925 | + self.points = self.points[::-1] |
| 926 | + return self |
| 927 | + |
| 928 | + def force_direction(self, target_direction): |
| 929 | + """Makes sure that points are either directed clockwise or |
| 930 | + counterclockwise. |
| 931 | +
|
| 932 | + Parameters |
| 933 | + ---------- |
| 934 | + target_direction : :class:`str` |
| 935 | + Either ``"CW"`` or ``"CCW"``. |
| 936 | + """ |
| 937 | + if target_direction not in ("CW", "CCW"): |
| 938 | + raise ValueError('Invalid input for force_direction. Use "CW" or "CCW"') |
| 939 | + if self.get_direction() != target_direction: |
| 940 | + # Since we already assured the input is CW or CCW, |
| 941 | + # and the directions don't match, we just reverse |
| 942 | + self.reverse_direction() |
| 943 | + return self |
| 944 | + |
882 | 945 |
|
883 | 946 | class VGroup(VMobject): |
884 | 947 | def __init__(self, *vmobjects, **kwargs): |
|
0 commit comments