Home > Mobile >  How can I fix Vector() takes no arguments with python
How can I fix Vector() takes no arguments with python

Time:05-09

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
  • Related