88 lines
2.8 KiB
Python
88 lines
2.8 KiB
Python
import json
|
|
from math import hypot
|
|
import math
|
|
from helix.functions import fequal
|
|
|
|
|
|
class Coordinate(object):
|
|
def __init__(self, x, y, rotation=0., calculate_rounding=True):
|
|
self.x = x
|
|
self.y = y
|
|
self.rotation = rotation
|
|
|
|
if calculate_rounding:
|
|
self.__rounded_x = round(x, 3)
|
|
self.__rounded_y = round(y, 3)
|
|
else:
|
|
self.__rounded_x = x
|
|
self.__rounded_y = y
|
|
|
|
def __eq__(self, other):
|
|
if self is other:
|
|
return True
|
|
if not isinstance(other, self.__class__):
|
|
return False
|
|
if fequal(self.rotation, other.rotation, delta=1e-3):
|
|
return fequal(self.x, other.x, delta=1e-3) and fequal(self.y, other.y, delta=1e-3)
|
|
return False
|
|
|
|
@property
|
|
def dictionary(self):
|
|
return {"x": self.x, "y": self.y, "rotation": self.rotation}
|
|
|
|
def __repr__(self):
|
|
return json.dumps(self.dictionary, sort_keys=True)
|
|
|
|
def __sub__(self, other):
|
|
if fequal(self.rotation, other.rotation, delta=1e-1):
|
|
return Coordinate(self.x - other.x, self.y - other.y, self.rotation)
|
|
else:
|
|
raise ValueError
|
|
|
|
def __add__(self, other):
|
|
if abs(self.rotation - other.rotation) < 1e-3:
|
|
return Coordinate(self.x + other.x, self.y + other.y, self.rotation, calculate_rounding=False)
|
|
else:
|
|
raise ValueError
|
|
|
|
def __abs__(self):
|
|
return self.length()
|
|
|
|
def __lt__(self, other):
|
|
if self == other:
|
|
return False
|
|
if self.y < other.y:
|
|
return True
|
|
elif other.y < self.y:
|
|
return False
|
|
return self.x < other.x
|
|
|
|
def __round__(self, n=0):
|
|
return Coordinate(round(self.x, n), round(self.y, n), self.rotation)
|
|
|
|
def __hash__(self):
|
|
return hash(self.__rounded_x) ^ hash(self.__rounded_y) ^ hash(self.rotation)
|
|
|
|
# Returns a Coordinate based on self, rotated by self's rotation
|
|
def rotate(self):
|
|
rotation = math.radians(self.rotation)
|
|
x = self.x * math.cos(rotation) - self.y * math.sin(rotation)
|
|
y = self.x * math.sin(rotation) + self.y * math.cos(rotation)
|
|
return Coordinate(x, y)
|
|
|
|
# Returns a Coordinate based on self, rotated by self's negative rotation
|
|
def unrotate(self):
|
|
rotation = math.radians(-self.rotation)
|
|
x = self.x * math.cos(rotation) - self.y * math.sin(rotation)
|
|
y = self.x * math.sin(rotation) + self.y * math.cos(rotation)
|
|
return Coordinate(x, y)
|
|
|
|
def scale(self, x, y):
|
|
return Coordinate(self.x * x, self.y * y, self.rotation)
|
|
|
|
def neg_translate(self, other):
|
|
return Coordinate(self.x - other.x, self.y - other.y, self.rotation)
|
|
|
|
def length(self):
|
|
return hypot(self.x, self.y)
|