Source code for domonic.geom.vec2

"""
    domonic.geom.vec2
    ====================================

"""
import math

# import operator


[docs] class vec2: """[vec2]""" def __init__(self, x: float = 0, y: float = 0): self.x: float = x self.y: float = y def __mul__(self, other): if isinstance(other, (int, float)): return vec2(self.x * other, self.y * other) if isinstance(other, vec2): return vec2(self.x * other.x, self.y * other.y) raise ValueError("Unsupported operand type for multiplication") def __div__(self, other): if isinstance(other, vec2): return self.__class__((self.x / other.x, self.y / other.y)) else: return self.__class__((self.x / other, self.y / other)) def __mod__(self, other): if isinstance(other, vec2): return self.__class__(self.x % other.x, self.y % other.y) else: return self.__class__(self.x % other, self.y % other) def __getitem__(self, item): if isinstance(item, int): if item == 0: return self.x elif item == 1: return self.y elif isinstance(item, str): if item == "x": return self.x elif item == "y": return self.y def __len__(self): return 2 def __add__(self, other): if isinstance(other, vec2): return vec2(self.x + other.x, self.y + other.y) if isinstance(other, (int, float)): return vec2(self.x + other, self.y + other) raise ValueError("Unsupported operand type for subtraction") def __sub__(self, other): if isinstance(other, vec2): return vec2(self.x - other.x, self.y - other.y) if isinstance(other, (int, float)): return vec2(self.x - other, self.y - other) raise ValueError("Unsupported operand type for subtraction") def __truediv__(self, other): if isinstance(other, (int, float)): return vec2(self.x / other, self.y / other) if isinstance(other, vec2): return vec2(self.x / other.x, self.y / other.y) raise ValueError("Unsupported operand type for division") def __floordiv__(self, other): if isinstance(other, vec2): return vec2(self.x // other.x, self.y // other.y) if isinstance(other, (int, float)): return vec2(self.x // other, self.y // other) raise ValueError("Unsupported operand type for division") def __neg__(self): return vec2(-self.x, -self.y) def __eq__(self, other): if isinstance(other, vec2): return self.x == other.x and self.y == other.y return False def __ne__(self, other): return self.x != other.x or self.y != other.y def __lt__(self, other): return self.x < other.x and self.y < other.y def __le__(self, other): return self.x <= other.x and self.y <= other.y def __gt__(self, other): return self.x > other.x and self.y > other.y def __ge__(self, other): return self.x >= other.x and self.y >= other.y def __hash__(self): return hash((self.x, self.y)) def __setitem__(self, key, value): if key == 0: self.x = value elif key == 1: self.y = value else: raise IndexError("Index out of range") def __iter__(self): yield self.x yield self.y def __call__(self, *args, **kwargs): return self.x, self.y def __getstate__(self): return self.x, self.y def __copy__(self): return vec2(self.x, self.y) def __deepcopy__(self, memo): return vec2(self.x, self.y) def __round__(self, n): return vec2(round(self.x, n), round(self.y, n)) def __str__(self): return str(self.x) + " " + str(self.y)
[docs] def add(self, pt): """Adds a point to this point. returns new one""" return vec2(self.x + pt.x, self.y + pt.y)
[docs] def subtract(self, pt): """Subtract from this point. returns new one""" return vec2(self.x - pt.x, self.y - pt.y)
[docs] def copy(self): """Creates a copy of this Point object.""" return vec2(self.x, self.y)
[docs] def dot(self, other): """Returns the dot product of these two vectors""" x1 = self.x y1 = self.y x2 = other.x y2 = other.y return x1 * x2 + y1 * y2
[docs] def cross(self, other): """Returns the cross product of this and other. The cross product is considered 0 perpendicular to each other point""" x1 = self.x y1 = self.y x2 = other.x y2 = other.y return x1 * y2 - y1 * x2
[docs] def negative(self): """return vector but negative version""" return vec2(-self.x, -self.y)
def distance(self, other): x_dot = self.x - other.x y_dot = self.y - other.y return math.sqrt(x_dot * x_dot + y_dot * y_dot) def squareDistance(self, other): return self.distance(self) * self.distance(other)
[docs] def equals(self, other): """Returns true if all vectors components are the same""" return self.x == other.x and self.y == other.y
[docs] def interpolate(self, pt1, pt2, t): """Calculates the point that would be reached by this Point if we moved by a given distance vector over time t. Only floats are handled here.""" return vec2(self.x * (1 - t) + pt1.x * t, self.y * (1 - t) + pt1.y * t)
[docs] def copyRotateAround(self, target, angle): """moves the vector then rotate""" self.rotateAround(target, angle) return vec2(self.x, self.y)
def mirrorHorizontally(self): return self.rotateAround(vec2(1, 0), 90) def mirrorVertically(self): return self.rotateAround(vec2(0, 1), 90)
[docs] def negate(self): """Negate a vector. This results in vector with the same direction but different length""" return vec2(-self.x, -self.y)
[docs] def length(self): """returns the length of this vector""" return self.x
[docs] def squaredlength(self): """returns the squared length of this vector""" return self.x * self.x + self.y * self.y
[docs] def normalize(self): """returns a normalized vector""" return self / self.length()
[docs] def obj(self): """returns a obj representation of this vector""" return {"x": self.x, "y": self.y}
# def __repr__(self): # return str(self.x) + " " + str(self.y)
[docs] def json(self): """returns a json representation of this vector""" return str({"x": self.x, "y": self.y})
[docs] def angle(self): """returns the angle of this vector in radians""" return math.atan2(self.y, self.x)
[docs] def angleBetween(self, other): """returns the angle between this and another vector in radians""" return math.acos(self.dot(other) / (self.length() * other.length()))
[docs] def rotate(self, angle): """rotates this vector by an angle in radians""" x = self.x y = self.y self.x = x * math.cos(angle) - y * math.sin(angle) self.y = y * math.cos(angle) + x * math.sin(angle)
[docs] def rotateAround(self, target, angle): """Rotates the vector around another point. In fact it returns the other point.""" dot = self.dot(target) s = math.sin(angle / 2) c = math.cos(angle / 2) x = s * (self.x - dot * c) + c y = s * (self.y - dot * c) - c return vec2(x, y)
[docs] @staticmethod def cmp(a, b): """Compare two vectors.""" return (a > b) - (a < b)
# @staticmethod # def random(): # """ returns a random vector """ # return vec2(random.random(), random.random())
[docs] @staticmethod def random(min_x, max_x, min_y, max_y): """returns a random vector""" import random return vec2(random.uniform(min_x, max_x), random.uniform(min_y, max_y))
[docs] @staticmethod def random_unit_vector(min_x, max_x, min_y, max_y): """returns a random unit vector""" vec = vec2.random(min_x, max_x, min_y, max_y) return vec.normalize()
[docs] @staticmethod def random_point_in_circle(center, radius): """returns a random point in a circle""" vec = vec2.random(0, radius) return vec.add(center)
[docs] @staticmethod def random_point_in_rectangle(min_x, max_x, min_y, max_y): """returns a random point in a rectangle""" vec = vec2.random(min_x, max_x, min_y, max_y) return vec.add(vec2.random(0, 1))
# def rotateAround(self, target, angle): # """ Rotates the vector around another point. In fact it returns the other point.""" # dot = self.dot(target) # s = math.sin(angle) # c = math.cos(angle) # x = s * (self.x - dot * c) + c # y = s * (self.y - dot * c) - c # return vec2(x, y) # def rotateAroundLocal(self, point, angle): # """ Rotates the vector around a point. In fact it returns itself.""" # dot = self.dot(point) # s = math.sin(angle) # c = math.cos(angle) # x = s * (self.x - dot * c) + c # y = s * (self.y - dot * c) - c # return vec2(x, y) # def rotateLocal(self, point, angle): # """ Rotates the vector around a point. In fact it returns itself.""" # dot = self.dot(point) # s = math.sin(angle) # c = math.cos(angle) # x = s * (self.x - dot * c) + c # y = s * (self.y - dot * c) - c # self.x = x # self.y = y # return self