added exam exercise 16
This commit is contained in:
parent
a685f530f6
commit
4097f8e010
122
exam/ex16/geometry.py
Normal file
122
exam/ex16/geometry.py
Normal file
|
@ -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))
|
21
exam/ex16/main.py
Normal file
21
exam/ex16/main.py
Normal file
|
@ -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))
|
Loading…
Reference in New Issue
Block a user