JustToThePoint English Website Version
JustToThePoint en español
JustToThePoint in Thai

Vectors in Python

Vectors using NumPy

A vector is an object that has both a magnitude or size and a direction. “Geometrically, we can picture a vector as a directed line segment, whose length is the magnitude of the vector and with an arrow indicating the direction,” An introduction to vectors, Math Insight.

Vectors in Python

user@pc:~$ python # Let's work with vectors in Python
Python 3.8.10 (default, Jun  2 2021, 10:49:15) 
>>> import numpy as np # NumPy is a library that supports vectors and matrices in an optimized way.
>>> v = np.array([3, 4, 5]) # Data manipulation in Python is almost synonymous with NumPy array manipulation.
>>> w = np.array([2, 7, 1])
>>> np.add(v, w) # numpy.add adds arguments element-wise: v+w.
array([ 5, 11,  6])
>>> np.subtract(v, w) # numpy.subtract subtracts arguments element-wise: v-w.
array([ 1, -3,  4])
>>> v*3
array([ 9, 12, 15])
>>> np.dot(v, w) # It calculates the dot product or scalar product of v and w.
39
>>> np.linalg.norm(v) # It computes the magnitude or Euclidean norm of v.
7.0710678118654755 # = sqrt(50)
>>> np.cross(v, w) # numpy.cross returns the cross product of two vectors. 
array([-31,   7,  13])
>>> x = np.array([4, 2, 4])
>>> x/np.linalg.norm(x) # It normalizes the vector. 
array([0.66666667, 0.33333333, 0.66666667]) # {2/3,1/3,2/3}

Our own 2d vector class

import math
from settings import * # It defines the constant THRESHOLD
import copy
class myVector(object):
    """ It defines a two-dimensional vector with Cartesian coordinates."""
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    ## It implements the addition of two vectors.
    # @params other is the vector from which self is to be added.
    # @return the new vector object that is the result of self + other.
    def __add__(self, other):
        if isinstance(other, int):
            other = myVector(other)

        return myVector(self.x + other.x, self.y + other.y)

    __radd__ = __add__

radd is called if the left object does not have an add method or that method does not know how to add the two objects, e.g., v1 = myVector(2, 3), print(2 + v1) prints 4i + 3j.

    ## It implements the subtraction of two vectors.
    # @params other is the vector from which self is to be subtracted.
    # @return the new vector object that is the result of self - other.
    def __sub__(self, other):
        if isinstance(other, int):
            other = myVector(other)
        
        return myVector(self.x - other.x, self.y - other.y)

    def __rsub__(self, other):
        return myVector(other) - self

    def __neg__(self):
        return myVector(-self.x, -self.y)

    ## It implements the multiplication of a scalar by a vector.
    def __mul__(self, scalar):
        if isinstance(scalar, int) or isinstance(scalar, float):
            return myVector(self.x * scalar, self.y * scalar)
        raise NotImplementedError('You can only multiply a vector by a scalar')

    def __rmul__(self, scalar):
        """__rmul__ needs to be implemented so scalar * vector also works."""
        return self._mul__(scalar)

    ## It implements the division of the vector by a scalar.
    def __div__(self, scalar):
        if scalar != 0:
            return myVector(self.x / float(scalar), self.y / float(scalar))
        return None

    def __truediv__(self, scalar):
        return self._div__(scalar)

__eq__ implements the comparison of two vectors: self and other. Typically, it would be something like return self.x == other.x and self.y == other.y.

However, rounding errors when using computers are to be expected and we want to be able to deal with them in a consistent manner. This will be useful when we code our Pacman clone.

    def __eq__(self, other):
        return (self.x - other.x).magnitude() < THRESHOLD and (self.y - other.y).magnitude < THRESHOLD

    def __ne__(self, other):
        return not self._eq__(other) 
    
    def magnitude(self):
        """ It returns the absolute value or magnitude of the vector."""
        return math.sqrt(self.x**2 + self.y**2)

    def distanceTo(self, other):
        """ It calculates the distance between two vectors or points: self and other."""
        return (self-other).magnitude()

    def to_polar(self):
        """It calculates the vector in polar coordinates."""
        return self.magnitude(), math.atan2(self.y, self.x)

    def __repr__(self):
        """It returns a string representation of the vector."""
        return repr((self.x, self.y))

    def __str__(self):
        """It returns a string representation of the vector."""
        return f"{self.x:.2f}i + {self.y:.2f}j"

    @staticmethod
    def distance(v1, v2):
    """ It calculates the distance between two vectors."""
        return (v1-v2).magnitude() 

    def __copy__(self):
    """ It creates a new instance or clone of the object without touching the object itself."""
        return myVector(self.x, self.y)

    def getVector(self):
        return self.x, self.y

    def getVectorAsInt(self):
        return int(self.x), int(self.y)

    def dot(self, other):
        """It implements the scalar product of vectors. It returns the scalar or dot product of self and other. Both self and other must be vectors."""

        if not isinstance(other, myVector):
            raise TypeError('Both arguments need to be vectors.')
        return self.x * other.x + self.y * other.y

    # We want to alias the __matmul__ method to dot so we can use a @ b as well as a.dot(b).
    __matmul__ = dot

    def normalize(self):
        """ It returns the normalized vector."""
        return self.__class__(self.x/self.magnitude(), self.y/self.magnitude())

if __name__ == '__main__':
    v1 = myVector(2, 3)
    v2 = copy.copy(v1)
    v2 = 2 + v1
    print(v1) # 2.00i + 3.00j. We modify the copy but the original object remains unchanged.
    print(v2) # 4.00i + 3.00j
    v2 = myVector(3, -1.5)
    print('repr(v2) = ', repr(v2)) # repr(v2) =  (3, -1.5)
    print('v1 + v2 = ', v1 + v2) # v1 + v2 =  5.00i + 1.50j
    print('v1 - v2 = ', v1 - v2) # v1 - v2 =  -1.00i + 4.50j
    pprint('abs(v1) = ', myVector.magnitude(v1)) # abs(v1) =  3.605551275463989
    print('-v2 = ', -v2) # -v2 = -3.00i + 1.50j
    print('v1 * 3 = ', v1 * 3) # v1 * 3 =  6.00i + 9.00j
    print(v1.normalize()) # 0.55i + 0.83j
    print('7 * v1 = ', 7 * v1) # 7 * v1 =  14.00i + 21.00j
    print('v2 / 2.5 = ', v2 / 2.5) # v2 / 2.5 =  1.20i + -0.60j
    print('v1.dot(v2) = v1 @ v2 = ', v1 @ v2) # v1.dot(v2) = v1 @ v2 =  1.5
    print("v1.distance_to(v2) = " + str(v1.distanceTo(v2))) # v1.distance_to(v2) = 4.6097722286464435
    print('v1 as a polar vector, (r, theta) =', v1.to_polar()) # v1 as a polar vector, (r, theta) = (3.605551275463989, 0.982793723247329)
Bitcoin donation

JustToThePoint Copyright © 2011 - 2022 PhD. Máximo Núñez Alarcón, Anawim. ALL RIGHTS RESERVED. Bilingual e-books, articles, and videos to help your child and your entire family succeed, develop a healthy lifestyle, and have a lot of fun.

This website uses cookies to improve your navigation experience.
By continuing, you are consenting to our use of cookies, in accordance with our Cookies Policy and Website Terms and Conditions of use.