A point class and a rectangle class without using inheritance - python

I am trying to create a point class that has the data attribute of floating point values 'x' and 'y' to therefore define a location of a point in 2D space. Additionally I want to have methods of init such as it being an initialization of default values x = 0 and y = 0. And then a move function which accepts the 'x' and 'y' as a new location of the point. And finally a function which tells the distance to a point. I want this to return the Euclidian distance from this point to another point at x, y. How would this be done?
Here is the code I have so far for the above description:
import math
class Point:
def __init__(self):
self.x = 0 # initialize to 0
self.y = 0 # initialize to 0
def move(self, x, y):
self.x = x
self.y = y
Could use help on this and the Eucliean distance from this point to another point at x,y. Not sure if I have the right idea so far. New to python so don't know how to test the functionality of this code. Would appreciate the help!
After that part I'd to be able to define two points at two opposite corners of a rectangle and use the Points defined above without using inheritance. Any ideas on how to create this class?

You could do something like this (comments in the code):
example:
class Point:
def __init__(self, x: float=0.0, y: float=0.0)-> None: # assign default values
self.x = x
self.y = y
def move_by(self, dx: float, dy: float)-> None: # move Point by dx, dy
self.x += dx
self.y += dy
def move_to(self, new_x: float, new_y: float)-> None: # relocate Point to new x, y position
self.x = new_x
self.y = new_y
def distance(self, other: 'Point')-> float: # calculates and returns the Euclidian distance between self and other
if isinstance(other, Point):
x0, y0 = self.x, self.y
x1, y1 = other.x, other.y
return ((x1 - x0)**2 + (y1 - y0)**2) ** 0.5
return NotImplemented
def __str__(self)-> str: # add a nice string representation
return f'Point({self.x}, {self.y})'
tests:
p = Point(1, 2)
q = Point()
print(p, q, p.distance(q) == 5**0.5)
p.move_by(.1, -.1)
print(p)
output:
Point(1, 2) Point(0.0, 0.0) True
Point(1.1, 1.9)
And the Rectangle class could be like this: [edited to add default Point values]
In Rectangle.__init__, the min and max values of the x and y values of the Points provided as parameters are sorted in order to determine the top left and bottom right points defining the rectangle
class Rectangle:
def __init__(self, p0: Point=Point(), p1: Point=Point(1.0, 1.0))-> None: # <--- [edit]: now with default values
x0, y0 = p0.x, p0.y
x1, y1 = p1.x, p1.y
self.topleft = Point(min(x0, x1), max(y0, y1)) # calculate the topleft and bottomright
self.bottomright = Point(max(x0, x1), min(y0, y1)) # of the bounding box
def __str__(self)-> str:
return f'Rectangle defined by bbox at: {self.topleft}, {self.bottomright})'
tests:
p = Point(1, 2)
q = Point()
print(p, q, p.distance(q) == 5**0.5)
p.move_by(.1, -.1)
print(p)
r = Rectangle(p, q)
print(r)
output:
Point(1, 2) Point(0.0, 0.0) True
Point(1.1, 1.9)
Rectangle defined by bbox at: Point(0.0, 1.9), Point(1.1, 0.0))
[Edit:] with default values for Points in Rectangle:
s = Rectangle()
print(s)
output:
Rectangle defined by bbox at: Point(0.0, 1.0), Point(1.0, 0.0))

Related

Find the intersection and union of two rectangles

I need to find the area of ​​intersection and union of two rectangles, as well as the ratio of the intersection area to the union area. What is the best way to do this?
Picture
def intersection_over_union(a, b):
ax1 = a['left']
ay1 = a['top']
aw = a['width']
ah = a['height']
ax2 = ax1 + aw
ay2 = ay1 + ah
bx1 = b['left']
by1 = b['top']
bw = b['width']
bh = b['height']
bx2 = bx1 + bw
by2 = by1 + bh
delta_x = max(ax1, bx1) - min(ax2, bx2)
delta_y = max(ay1, by1) - min(ay2, by2)
overlap = delta_x * delta_y
union = aw * ah + bw * bh - overlap
print(overlap, union)
return overlap / union
Assuming you are dealing with AABB (axis aligned bounding box) this little class defines everything you need:
class Rect:
def __init__(self, x, y, w, h):
self.x = x
self.y = y
self.w = w
self.h = h
def bottom(self):
return self.y + self.h
def right(self):
return self.x + self.w
def area(self):
return self.w * self.h
def union(self, b):
posX = min(self.x, b.x)
posY = min(self.y, b.y)
return Rect(posX, posY, max(self.right(), b.right()) - posX, max(self.bottom(), b.bottom()) - posY)
def intersection(self, b):
posX = max(self.x, b.x)
posY = max(self.y, b.y)
candidate = Rect(posX, posY, min(self.right(), b.right()) - posX, min(self.bottom(), b.bottom()) - posY)
if candidate.w > 0 and candidate.h > 0:
return candidate
return Rect(0, 0, 0, 0)
def ratio(self, b):
return self.intersection(b).area() / self.union(b).area()
if __name__ == "__main__":
assert Rect(1, 1, 1, 1).ratio(Rect(1, 1, 1, 1)) == 1
assert round(Rect(1, 1, 2, 2).ratio(Rect(2, 2, 2, 2)), 4) == 0.1111
One way I believe you could do this (although I am not sure it is the best solution as you've asked for), is to develop a function that creates a rectangle in a plane, and stores all of its corners' coordinates in a list.
Every time you create a rectangle (let's say you create it from the bottom left, increasing its x and y coordinates as you go), check for each coordinate if the x coordinate is within the other rectangle's x-range i.e. x_min < x < x_max. If so, check the y-coordinate. If the coordinate is within the x and y ranges of another rectangle, it's part of the intersection.
Repeat for all coordinates as you create them and save the intersection coordinates, and find the intersection's corners. With that, you can calculate the area of intersection and union between the two triangles, and their ratio to one another.

Polygon Class: Finding area and length of Rectangle and Triangle

I have been given the following code.
class Polygon:
'''Class to represent polygon objects.'''
def __init__(self, points):
'''Initialize a Polygon object with a list of points.'''
self.points = points
def length(self):
'''Return the length of the perimeter of the polygon.'''
P = self.points
return sum(sqrt((x1 - x0) ** 2 + (y1 - y0) ** 2)
for (x0, y0), (x1, y1) in zip(P, P[1:] + P[:1]))
def area(self):
'''Return the area of the polygon.'''
P = self.points
A = 0
for (x0, y0), (x1, y1) in zip(P, P[1:] + P[:1]):
A += x0 * y1 - y0 * x1
return abs(A / 2)
I have to implement __init__ methods (and no other method) of two subclasses; Rectangle and Triangle such that a rectangle can be created by:
rectangle = Rectangle(width, height)
and a triangle by:
triangle = Triangle(a, b, c)
I have coded the Rectangle one with the following:
class Rectangle(Polygon):
def __init__(self, width, height):
self.width = width
self.height = height
self.points = [(0,0), (0, height), (width, height), (width, 0)]
And the above code passes all the tests when input is only for Rectangle.
However, I have trouble doing the same for Triangle. The input should be a, b and c where those are the side lengths of the triangle. I cannot figure out which points to use to generate the length and area of the Triangle:
class Triangle(Polygon):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
self.points = ??
I have tried all combinations of points using the side lengths, however, none are passing the test.
Have a look at:
https://www.omnicalculator.com/math/triangle-height#how-to-find-the-height-of-a-triangle-formulas
h = 0.5 * ((a + b + c) * (-a + b + c) * (a - b + c) * (a + b - c))**0.5 / b
ac = (c**2 - h**2)**0.5
self.points = [
(0, 0),
(a, 0),
(ac, h),
]
By getting h and then applying Pythagoras' Theorem you are obtain the co-ordinates of the "third" point. The first two are trivial: the origin, and another point along one of the axes.
A minor point: instead of setting points directly it might be cleaner to call super().__init__(points).

Python fast way to check N points are in the same "area"

I have a clicking applicaiton on a phone.
I want to sample last N points so it won't click the same "place" over and over again.
I guess it should be kind of this:
This I want to avoid.
I guess the circlue center should be the center of all points ?
How to determind the radius ?
I think calculation of the last N dots can be used to calculte the "new" N dots once a new click is done, to reduce performance.
Any suggestions ?
Thanks
def clicking_loop_protection(self, x, y, methods):
'''
:param x:
:param y:
:param method: 'xpath'/'point' it can be both
:return:
'''
def centroid(points):
_len = len(points)
x_coords = [p[0] for p in points]
y_coords = [p[1] for p in points]
centroid_x = sum(x_coords) / _len
centroid_y = sum(y_coords) / _len
return centroid_x, centroid_y
def calculate_points_distance(x1, y1, x2, y2):
dist = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
return dist
point_res = True
if 'point' in methods:
# add current point
_point = (x, y)
try:
self.points_history[self.points_history_index] = _point
except IndexError:
self.points_history.append(_point)
if len(self.points_history) == self.points_history_length:
centroid_point_x, centroid_point_y = centroid(self.points_history)
radius = self.displayWidth/10
for point in self.points_history:
# distance from centroid should be less than radius (to fail the test)
distance = calculate_points_distance(centroid_point_x, centroid_point_y, point[0], point[1])
if distance > radius:
point_res = True # pass test !
break
else:
point_res = False
self.points_history_index += 1
self.points_history_index %= self.points_history_length
return xpath_res and point_res

I have set of points like P1,P2,P3,....,Pn and each point has x and y as numbers. How can I do math to these points in python?

I have these points:
P1 = (1,2) = (1**2+2**2)**1/2 = 5**1/2 //this is how we can compute the point and so on for the rest. the ** means the power of.
P2 = (3,2) //P2.x = 3 , P2.y = 2 and so on for the rest points
P3 = (1,1) // P3.x= 1 , P3.y = 1
..
..
..
Pn = (m,k)
P= <P1(1,2),P2(3,2),P3(1,1),......,Pn(2,2)>
P
|P|= ((P1**2)+(P2**2)+.....+(Pn**2))**1/2 //the square root of the sum of square points
What is the best way to write python function for a distance from P1 to Pn? for those equations Sx and Sy
Sx = (P1.x)/|P| + (P2.x)/|P| + (P3.x)/|P| + ...... +(Pn.x)/|P|
Sy = (P1.y)/|P| + (P2.y)/|P| + (P3.y)/|P| + ...... +(Pn.y)/|P|
form the above equations we will get point of S(Sx,Sy).
I tried my way I put x values in a list and y values in another list to slice it based on n value. so suppose you already have x, y values of P:
x = [1,3,1,.......,m]
y = [2,2,1, ......,k]
In pure Python, you can create a Point class, and overload relevant operators:
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def sqnorm(self):
p = self * self
return p.x + p.y
def __add__(self, other):
return Point(self.x + other.x, self.y + other.y)
def __radd__(self, other):
return self.sqnorm() + other
def __mul__(self, other):
return Point(self.x * other.x, self.y * other.y)
And a norm function:
def norm(points):
return math.sqrt(sum(points))
Usage:
points = [Point(1,2), Point(3,2), Point(1,1)]
print(norm(points))
In NumPy,
import numpy as np
x = np.array(x)
y = np.array(y)
points = np.concatenate((x, y), axis=1)
norm = np.sum(points**2)
Sx = x / norm
Sy = y / norm

python (pygame and pyopenGL) Convert 3D models (. obj file) into a sequence of gray image [duplicate]

This question already has an answer here:
How to save pygame scene as jpeg?
(1 answer)
Closed 11 months ago.
Currently I'm working on object recognition systems, which need a whole lot of training data.
I am trying to convert a 3D model into a sequence of gray images, rotating the model and sampling the 2D image with a certain time interval.
Because I am mainly working on python, so I try to solve this problem based on pygame and pyopenGL, I found this example for loading an .obj file, but it won't work at the very beginning, which took me quite long time to figure out where is the problem.
And now the core problem somehow reduce to as follow:
class Point3D:
def __init__(self, x = 0, y = 0, z = 0):
self.x, self.y, self.z = float(x), float(y), float(z)
def rotateX(self, angle):
""" Rotates the point around the X axis by the given angle in degrees. """
rad = angle * math.pi / 180
cosa = math.cos(rad)
sina = math.sin(rad)
y = self.y * cosa - self.z * sina
z = self.y * sina + self.z * cosa
return Point3D(self.x, y, z)
def rotateY(self, angle):
""" Rotates the point around the Y axis by the given angle in degrees. """
rad = angle * math.pi / 180
cosa = math.cos(rad)
sina = math.sin(rad)
z = self.z * cosa - self.x * sina
x = self.z * sina + self.x * cosa
return Point3D(x, self.y, z)
def rotateZ(self, angle):
""" Rotates the point around the Z axis by the given angle in degrees. """
rad = angle * math.pi / 180
cosa = math.cos(rad)
sina = math.sin(rad)
x = self.x * cosa - self.y * sina
y = self.x * sina + self.y * cosa
return Point3D(x, y, self.z)
def project(self, win_width, win_height, fov, viewer_distance):
""" Transforms this 3D point to 2D using a perspective projection. """
factor = fov / (viewer_distance + self.z)
x = self.x * factor + win_width / 2
y = -self.y * factor + win_height / 2
return Point3D(x, y, self.z)
class Simulation:
def __init__(self, win_width = 640, win_height = 480):
pygame.init()
self.screen = pygame.display.set_mode((win_width, win_height))
pygame.display.set_caption("Simulation of a rotating 3D Cube (http://codeNtronix.com)")
self.clock = pygame.time.Clock()
self.vertices = [
Point3D(-1,1,-1),
Point3D(1,1,-1),
Point3D(1,-1,-1),
Point3D(-1,-1,-1),
Point3D(-1,1,1),
Point3D(1,1,1),
Point3D(1,-1,1),
Point3D(-1,-1,1)
]
# Define the vertices that compose each of the 6 faces. These numbers are
# indices to the vertices list defined above.
self.faces = [(0,1,2,3),(1,5,6,2),(5,4,7,6),(4,0,3,7),(0,4,5,1),(3,2,6,7)]
# Define colors for each face
self.colors = [(255,0,255),(255,0,0),(0,255,0),(0,0,255),(0,255,255),(255,255,0)]
self.angle = 0
def run(self):
""" Main Loop """
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
self.clock.tick(50)
self.screen.fill((0,32,0))
# It will hold transformed vertices.
t = []
for v in self.vertices:
# Rotate the point around X axis, then around Y axis, and finally around Z axis.
r = v.rotateX(self.angle).rotateY(self.angle).rotateZ(self.angle)
# Transform the point from 3D to 2D
p = r.project(self.screen.get_width(), self.screen.get_height(), 256, 4)
# Put the point in the list of transformed vertices
t.append(p)
# Calculate the average Z values of each face.
avg_z = []
i = 0
for f in self.faces:
z = (t[f[0]].z + t[f[1]].z + t[f[2]].z + t[f[3]].z) / 4.0
avg_z.append([i,z])
i = i + 1
# Draw the faces using the Painter's algorithm:
# Distant faces are drawn before the closer ones.
for tmp in sorted(avg_z,key=itemgetter(1),reverse=True):
face_index = tmp[0]
f = self.faces[face_index]
pointlist = [(t[f[0]].x, t[f[0]].y), (t[f[1]].x, t[f[1]].y),
(t[f[1]].x, t[f[1]].y), (t[f[2]].x, t[f[2]].y),
(t[f[2]].x, t[f[2]].y), (t[f[3]].x, t[f[3]].y),
(t[f[3]].x, t[f[3]].y), (t[f[0]].x, t[f[0]].y)]
pygame.draw.polygon(self.screen,self.colors[face_index],pointlist)
self.angle += 1
pygame.display.flip()
if name == "main":
Simulation().run()
The example above draws a cube and keep rotating it, then how can I get the pixel data directly?
What library or package can provide me the ability of getting the pixel data of the 2D project directly. (IPL ? or pyopenGL ?)
THX
You could take a 'screenshot' using glreadpixels. You can then pass it to the python image library which saves it as a file to disk: https://stackoverflow.com/a/4122290/2422450

Categories