This repository has been archived on 2023-03-25. You can view files and clone it, but cannot push or open issues or pull requests.

#### 105 lines 2.8 KiB Python Raw Permalink Blame History

 ```from math import * ``` ``` ``` ```def inner_product(a, b): ``` ``` return a.x * b.x + a.y * b.y ``` ``` ``` ```class Coordinate(object): ``` ``` """ ``` ``` Basic (x, y) coordinate class (or should it be called vector?) which allows some simple operations. ``` ``` """ ``` ``` def __init__(self, x, y): ``` ``` self.x = float(x) ``` ``` self.y = float(y) ``` ``` ``` ``` #polar coordinates ``` ``` @property ``` ``` def t(self): ``` ``` angle = atan2(self.y, self.x) ``` ``` if angle < 0: ``` ``` angle += pi * 2 ``` ``` return angle ``` ``` ``` ``` @t.setter ``` ``` def t(self, value): ``` ``` length = self.r ``` ``` self.x = cos(value) * length ``` ``` self.y = sin(value) * length ``` ``` ``` ``` ``` ``` @property ``` ``` def r(self): ``` ``` return hypot(self.x, self.y) ``` ``` ``` ``` @r.setter ``` ``` def r(self, value): ``` ``` angle = self.t ``` ``` self.x = cos(angle) * value ``` ``` self.y = sin(angle) * value ``` ``` ``` ``` def __repr__(self): ``` ``` return self.__str__() ``` ``` ``` ``` def __str__(self): ``` ``` return "(%f, %f)" % (self.x, self.y) ``` ``` ``` ``` def __eq__(self, other): ``` ``` return self.x == other.x and self.y == other.y ``` ``` ``` ``` def __add__(self, other): ``` ``` return Coordinate(self.x + other.x, self.y + other.y) ``` ``` ``` ``` def __sub__(self, other): ``` ``` return Coordinate(self.x - other.x, self.y - other.y) ``` ``` ``` ``` def __mul__(self, factor): ``` ``` return Coordinate(self.x * factor, self.y * factor) ``` ``` ``` ``` def __neg__(self): ``` ``` return Coordinate(-self.x, -self.y) ``` ``` ``` ``` def __rmul__(self, other): ``` ``` return self * other ``` ``` ``` ``` def __div__(self, quotient): ``` ``` return Coordinate(self.x / quotient, self.y / quotient) ``` ``` ``` ``` def __truediv__(self, quotient): ``` ``` return self.__div__(quotient) ``` ``` ``` ``` def dot(self, other): ``` ``` """dot product""" ``` ``` return self.x * other.x + self.y * other.y ``` ``` ``` ``` def cross_norm(self, other): ``` ``` """"the norm of the cross product""" ``` ``` self.x * other.y - self.y * other.x ``` ``` ``` ``` def close_enough_to(self, other, limit=1E-9): ``` ``` return (self - other).r < limit ``` ``` ``` ``` ``` ```class IntersectionError(ValueError): ``` ``` """Raised when two lines do not intersect.""" ``` ``` ``` ```def on_segment(pt, start, end): ``` ``` """Check if pt is between start and end. The three points are presumed to be collinear.""" ``` ``` pt -= start ``` ``` end -= start ``` ``` ex, ey = end.x, end.y ``` ``` px, py = pt.x, pt.y ``` ``` px *= cmp(ex, 0) ``` ``` py *= cmp(ey, 0) ``` ``` return px >= 0 and px <= abs(ex) and py >= 0 and py <= abs(ey) ``` ``` ``` ```def intersection (s1, e1, s2, e2, on_segments = True): ``` ``` D = (s1.x - e1.x) * (s2.y - e2.y) - (s1.y - e1.y) * (s2.x - e2.x) ``` ``` if D == 0: ``` ``` raise IntersectionError("Lines from {s1} to {e1} and {s2} to {e2} are parallel") ``` ``` N1 = s1.x * e1.y - s1.y * e1.x ``` ``` N2 = s2.x * e2.y - s2.y * e2.x ``` ``` I = ((s2 - e2) * N1 - (s1 - e1) * N2) / D ``` ``` ``` ``` if on_segments and not (on_segment(I, s1, e1) and on_segment(I, s2, e2)): ``` ``` raise IntersectionError("Intersection {0} is not on line segments [{1} -> {2}] [{3} -> {4}]".format(I, s1, e1, s2, e2)) ``` ``` return I ```