diff --git a/exam/ex16/geometry.py b/exam/ex16/geometry.py new file mode 100644 index 0000000..7de7e0a --- /dev/null +++ b/exam/ex16/geometry.py @@ -0,0 +1,122 @@ +from abc import abstractmethod, ABCMeta +from itertools import permutations +import numpy as np + +class Point(object): + __slots__ = ["x", "y"] + def __init__(self, x, y): + self.x = x + self.y = y + + def __abs__(self): + return (self.x**2 + self.y**2)**0.5 + def __add__(self, other): + if(isinstance(self, Point)): + return Point(self.x + other.x, self.y + other.y) + raise TypeError("cannot add {} and {}".format(type(other), type(self))) + def __sub__(self, other): + if(isinstance(self, Point)): + return Point(self.x - other.x, self.y - other.y) + raise TypeError("cannot subtract {} and {}".format(type(other), type(self))) + + def rotate(self, angle): + return Point(self.x * np.cos(angle) - self.y * np.sin(angle) + , self.x * np.sin(angle) + self.y * np.cos(angle)) + def __repr__(self): + return "{}({}, {})".format(type(self).__name__, self.x, self.y) + + +class TwoDimensionalObject(metaclass=ABCMeta): + @abstractmethod + def contains_point(self, point: Point): + pass + + def __contains__(self, other): + if(isinstance(other, Point)): + return self.contains_point(other) + raise TypeError("unable to check if {} is in {}".format(type(other), type(self))) + + +class Circle(TwoDimensionalObject): + def __init__(self, origin: Point, radius): + self.origin = origin + self.radius = radius + + def contains_point(self, point: Point): + return abs(self.origin - point) < self.radius + + def __repr__(self): + return "{}({}, {})".format(type(self).__name__, self.origin, self.radius) + +class Rectangle(TwoDimensionalObject): + """ + A Rectangle is constructed as follows: + The Points p1, p2 are connected using orthogonal lines:: + + p1 +-------+ + | | + | | + | | + +-------+ p2 + + and then the Rectangle is rotated ``angle`` degrees around ``p1``. + + """ + def __init__(self, p1: Point, p2: Point, angle=0): + self.p1 = p1 + self.p2 = p2 + + self.local_p1 = Point(0, 0) + self.local_p2 = (p2 - p1).rotate(angle) + + self.angle = angle + + def contains_point(self, point: Point): + point_in_eigen_frame = (point - self.p1).rotate(self.angle) + + if(self.local_p1.x < self.local_p2.x): + if(point_in_eigen_frame.x < self.local_p1.x or point_in_eigen_frame.x > self.local_p1.x): + return False + else: + if(point_in_eigen_frame.x > self.local_p1.x or point_in_eigen_frame.x < self.local_p1.x): + return False + + if(self.local_p1.y < self.local_p2.y): + if(point_in_eigen_frame.y < self.local_p1.y or point_in_eigen_frame.y > self.local_p1.y): + return False + else: + if(point_in_eigen_frame.y > self.local_p1.y or point_in_eigen_frame.y < self.local_p1.y): + return False + + return True + def __repr__(self): + return "{}({}, {}, angle={})".format(type(self).__name__, self.p1, self.p2, self.angle) + + +class Triangle(TwoDimensionalObject): + def __init__(self, p1: Point, p2: Point, p3: Point): + self.p1 = p1 + self.p2 = p2 + self.p3 = p3 + def contains_point(self, point: Point): + points = [self.p1, self.p2, self.p3] + triangle_surface = abs(sum([points[i].x * (points[(i + 1) % 3].y - points[(i + 2) % 3].y) for i in range(3)])) + + points = [point, self.p1, self.p2, self.p3] + surfaces = [abs(sum([p[i].x * (p[(i + 1) % 4].y - p[(i + 2) % 4].y) for i in range(4)])) for p in permutations(points)] + + return max(surfaces) < triangle_surface + def __repr__(self): + return "{}({}, {}, {})".format(type(self).__name__, self.p1, self.p2, self.p3) + + + +class CollectionOfFigures(object): + def __init__(self, figures): + self.figures = figures + + def containing(self, point: Point): + return [f for f in self.figures if point in f] + + def __repr__(self): + return "{}({})".format(type(self).__name__, repr(self.figures)) diff --git a/exam/ex16/main.py b/exam/ex16/main.py new file mode 100644 index 0000000..4142c10 --- /dev/null +++ b/exam/ex16/main.py @@ -0,0 +1,21 @@ + +from geometry import Point, Rectangle, Triangle, Circle, CollectionOfFigures + + +c1 = Circle(Point(0, 0), 1) +c2 = Circle(Point(4, 4), 2) +r1 = Rectangle(Point(0, 0), Point(4, 4)) +r2 = Rectangle(Point(-3, -3), Point(-1, -1)) +t1 = Triangle(Point(-1, -1), Point(-1, 1), Point(0, 1)) +t2 = Triangle(Point(0, 0), Point(6, 0), Point(0, 6)) +t3 = Triangle(Point(-5, -5), Point(0, 6), Point(5, -5)) + +collection = CollectionOfFigures([c1, c2, r1, r2, t1, t2, t3]) + +p1 = Point(4, 4) +p2 = Point(-1, 0) +p3 = Point(0, 0) + +print(p1, "is in", collection.containing(p1)) +print(p2, "is in", collection.containing(p2)) +print(p3, "is in", collection.containing(p3))