5
5
import numpy as np
6
6
7
7
from typing import Union , Callable
8
+ from manimlib .mobject .mobject import Mobject
8
9
9
10
from manimlib .physics .body import Body
10
11
from manimlib .mobject .geometry import Line
@@ -20,26 +21,35 @@ class Force(metaclass=ABCMeta):
20
21
def __init__ (
21
22
self ,
22
23
bodies : tuple [Body , ...],
23
- line : Union [ Line , Line3D ] = None
24
+ mobjects : tuple [ Mobject , ...] = ()
24
25
) -> None :
25
26
"""
26
27
Initialize a new Force object
27
28
28
29
Keyword arguments
29
30
-----------------
30
- bodies (list[Body]): the bodies to which the force applies
31
- line: (Line | Line3D): line representing the force and follows
32
- the bodies, must already be set to have the bodies at its
33
- extremes (default None)
31
+ bodies (tuple[Body, ...]): the bodies to which the force applies
32
+ mobjects: tuple[Mobject, ...]: mobject(s) representing the force, should
33
+ be already set to a desired position (subclasses know
34
+ how to update them). Regular shapes should be used for 2D
35
+ simulations and 3D shapes for 3D simulations! Otherwise
36
+ things MAY BREAK! (default: empty tuple)
34
37
"""
35
- self .bodies : tuple [Body ] = bodies
38
+ self .bodies : tuple [Body , ... ] = bodies
36
39
if not self .bodies :
37
40
raise Exception ("No bodies have been provided!" )
38
- self .line = line
41
+ self .mobjects : tuple [ Mobject , ...] = mobjects
39
42
40
43
def __str__ (self ) -> str :
41
44
body_info : str = ',' .join ([f"body{ i } _index={ body .index } " for i , body in enumerate (self .bodies , start = 1 )])
42
- return (f"{ body_info } ,line={ self .line } " )
45
+ return (f"{ body_info } ,mobjects={ self .mobjects } " )
46
+
47
+ def update_mobjects (self ) -> None :
48
+ """
49
+ Update the foce mobject(s)
50
+ (to be implemented by each subclass)
51
+ """
52
+ pass
43
53
44
54
@abstractmethod
45
55
def apply (self , forces : np .ndarray ) -> None :
@@ -63,30 +73,55 @@ class NewtonGravitationalForce(Force):
63
73
64
74
def __init__ (
65
75
self ,
66
- bodies : tuple [Body ],
67
- line : Union [Line , Line3D ]= None ,
76
+ bodies : tuple [Body , Body ],
77
+ mobjects : tuple [ Union [Line , Line3D ]] = () ,
68
78
G : float = 1.0
69
79
) -> None :
70
80
"""
71
81
Initialize a new NewtonGravitationalForce instance
72
82
73
83
Keyword arguments
74
84
-----------------
75
- bodies (list[ Body]): the bodies to which the force applies
76
- line ( Line | Line3D): line representing the force and follows
85
+ bodies (tuple[Body, Body]): the bodies to which the force applies
86
+ mobjects (tuple[ Line | Line3D] ): line representing the force and follows
77
87
the bodies, must already be set to have the bodies at its
78
- extremes (default None )
88
+ extremes (start=bodies[0], end=bodies[1]) ( default: empty tuple )
79
89
G (float): gravitational constant (default: 1.0)
80
90
"""
81
91
if len (bodies ) != 2 :
82
92
raise Exception ("You must provide 2 bodies!" )
83
- super ().__init__ (bodies )
93
+ super ().__init__ (bodies , mobjects )
84
94
self .G : float = G
85
95
86
96
def __str__ (self ) -> str :
87
97
return (f"{ self .__class__ .__name__ } <{ super ().__str__ ()} ,"
88
98
f"G={ self .G } >" )
89
99
100
+ def update_mobjects (self ) -> None :
101
+ """
102
+ Update the line mobject to follow the bodies
103
+ """
104
+ if not self .mobjects or self .mobjects [0 ] is None :
105
+ return
106
+ line : Union [Line , Line3D ] = self .mobjects [0 ]
107
+ body1 , body2 = self .bodies [0 ], self .bodies [1 ]
108
+ delta_pos : np .ndarray = body2 .position - body1 .position
109
+ distance : float = np .linalg .norm (delta_pos )
110
+ if isinstance (line , Line ): # for 2D simulations
111
+ line .set_length (distance )
112
+ line .set_angle (np .arctan2 (delta_pos [1 ], delta_pos [0 ]))
113
+ line .move_to ((body1 .position + body2 .position )/ 2 )
114
+ elif isinstance (line , Line3D ): # TODO: implement this
115
+ print (
116
+ f"({ self .__class__ .__name__ } ) WARNING: updating "
117
+ "is not implemented yet."
118
+ )
119
+ else :
120
+ print (
121
+ f"({ self .__class__ .__name__ } ) WARNING: the mobject "
122
+ "is not a line. Cannot update it."
123
+ )
124
+
90
125
def apply (self , forces : np .ndarray ) -> None :
91
126
body1 , body2 = self .bodies [0 ], self .bodies [1 ]
92
127
delta_pos : np .ndarray = body2 .position - body1 .position
0 commit comments