This python code is made to show the animation of 3D solar system with 2d projection.I make two file named solar_system_3d.py and simple_solar_system.py to write the code.But it cannot show properly due to the error:
raceback (most recent call last):
File ~/simple_solar_system.py:14 in sun = Sun(solar_system)
File ~/solar_system_3d.py:143 in init super(Sun, self).init(solar_system, mass, position, velocity)
File ~/solar_system_3d.py:89 in init self.velocity = Vector(*velocity)
TypeError: Vector() takes no arguments
Here is the code from "solar_system_3d.py": updated version:
# solar_system_3d.py
import itertools
import math
import matplotlib.pyplot as plt
from vectors import Vector
class SolarSystem:
def __init__(self, size, projection_2d=False):
self.size = size
self.projection_2d = projection_2d
self.bodies = []
self.fig, self.ax = plt.subplots(
1,
1,
subplot_kw={"projection": "3d"},
figsize=(self.size / 50, self.size / 50),
)
self.fig.tight_layout()
if self.projection_2d:
self.ax.view_init(10, 0)
else:
self.ax.view_init(0, 0)
def add_body(self, body):
self.bodies.append(body)
def update_all(self):
self.bodies.sort(key=lambda item: item.position[0])
for body in self.bodies:
body.move()
body.draw()
def draw_all(self):
self.ax.set_xlim((-self.size / 2, self.size / 2))
self.ax.set_ylim((-self.size / 2, self.size / 2))
self.ax.set_zlim((-self.size / 2, self.size / 2))
if self.projection_2d:
self.ax.xaxis.set_ticklabels([])
self.ax.yaxis.set_ticklabels([])
self.ax.zaxis.set_ticklabels([])
else:
self.ax.axis(False)
plt.pause(0.001)
self.ax.clear()
def calculate_all_body_interactions(self):
bodies_copy = self.bodies.copy()
for idx, first in enumerate(bodies_copy):
for second in bodies_copy[idx 1:]:
first.accelerate_due_to_gravity(second)
class SolarSystemBody:
min_display_size = 10
display_log_base = 1.3
def __init__(
self,
solar_system,
mass,
position=(0, 0, 0),
velocity=(0, 0, 0),
):
self.solar_system = solar_system
self.mass = mass
self.position = position
self.velocity = Vector(*velocity)
self.display_size = max(
math.log(self.mass, self.display_log_base),
self.min_display_size,
)
self.colour = "black"
self.solar_system.add_body(self)
def move(self):
self.position = (
self.position[0] self.velocity[0],
self.position[1] self.velocity[1],
self.position[2] self.velocity[2],
)
def draw(self):
self.solar_system.ax.plot(
*self.position,
marker="o",
markersize=self.display_size self.position[0] / 30,
color=self.colour
)
if self.solar_system.projection_2d:
self.solar_system.ax.plot(
self.position[0],
self.position[1],
-self.solar_system.size / 2,
marker="o",
markersize=self.display_size / 2,
color=(.5, .5, .5),
)
def accelerate_due_to_gravity(self, other):
distance = Vector(*other.position) - Vector(*self.position)
distance_mag = distance.get_magnitude()
force_mag = self.mass * other.mass / (distance_mag ** 2)
force = distance.normalize() * force_mag
reverse = 1
for body in self, other:
acceleration = force / body.mass
body.velocity = acceleration * reverse
reverse = -1
class Vector:
def __sub__(self, vec):
return Vector(self.x - vec.x)
class Sun(SolarSystemBody):
def __init__(
self,
solar_system,
mass=10_000,
position=(0, 0, 0),
velocity=(0, 0, 0),
):
super(Sun, self).__init__(solar_system, mass, position, velocity)
self.colour = "yellow"
class Planet(SolarSystemBody):
colours = itertools.cycle([(1, 0, 0), (0, 1, 0), (0, 0, 1)])
def __init__(
self,
solar_system,
mass=10,
position=(0, 0, 0),
velocity=(0, 0, 0),
):
super(Planet, self).__init__(solar_system, mass, position, velocity)
self.colour = next(Planet.colours)
here is the code from simple_solar_system.py:
# simple_solar_system.py
from solar_system_3d import SolarSystem, Sun, Planet
solar_system = SolarSystem(400, projection_2d=True)
sun = Sun(solar_system)
planets = (
Planet(
solar_system,
position=(150, 50, 0),
velocity=(0, 5, 5),
),
Planet(
solar_system,
mass=20,
position=(100, -50, 150),
velocity=(5, 0, 0)
)
)
while True:
solar_system.calculate_all_body_interactions()
solar_system.update_all()
solar_system.draw_all()
Plz help me, thx a lot!
CodePudding user response:
Python objects have what's called dunder methods, or double underscore. aka magic methods.
Heres what some look like
__lt__(), __le__(), __gt__(), or __ge__()
class Vector:
def __add__(self, vec):
return Vector(self.x vec.x)
I could say something like and then my Vector classes could be added with the
operator
Heres a better example docs.python - datamodel
CodePudding user response:
I assume you are using this vectors library.
Say you have two vectors:
from vectors import Vector
a = Vector(1, 1, 1)
b = Vector(2, 2, 2)
The Vector class from the vectors library has a function substract(other)
. You can then use this function to substract vectors in the following way:
a_minus_b = b.substract(a) # a - b
b_minus_a = a.substract(b) # b - a
You could replace all vector minuses in your code with the above code. However, you can also define the __sub__()
function on the Vector class like this:
class Vector(Vector):
def __sub__(self, other):
return other.substract(self)
That way a - b
will implicitly call the __sub()__
function.
Now you can substract vectors simply as:
a_minus_b = a - b
b_minus_a = b - a