I have a problem with a task. I need to write an python code which calculates a quadratic distance between two points.
The formula is:
D^2 = (x1 - x2)^2 + (y1 - y2)^2
and my code:
def quadratic_distance(p1: Point, p2: Point) -> float:
# YOUR CODE HERE
class p1:
def __init__(self, x1, y1):
self.x = x1
self.y = y1
class p2:
def __init__(self, x2, y2):
self.x = x2
self.y = y2
result1 = p1.x - p2.x
result2 = result1**2
result3 = p1.y - p2.y
result4 = result3**2
result5 = result2 + result4
return result5
but my problem is that i get an attribute error
AttributeError: type object 'p1' has no attribute 'x'
I am fairly new in the object oriented programming and have been stuck at this task. I hope someone can help me
assert quadratic_distance(Point(0, 0),Point(1, 1)) == 1.75
should be the solution
According to your formula, quadratic distance between Point(0,0) and Point(1,1) is 2. Not 1.75
This is my code. Try this
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
P1 = Point(0,0)
P2 = Point(1,1)
def quadratic_distance(p1: Point, p2: Point) -> float:
result1 = p1.x - p2.x
result2 = result1**2
result3 = p1.y - p2.y
result4 = result3**2
result5 = result2 + result4
return result5
print(quadratic_distance(P1, P2))
You are getting an error because you have not created an object of the class. In python, x is not an attribute of a class but x is the attribute of its object.
So you can do it as:
class p1:
def __init__(self, x1, y1):
self.x = x1
self.y = y1
class p2:
def __init__(self, x2, y2):
self.x = x2
self.y = y2
p1_obj = p1(5,5)
p2_obj = p2(10,10)
result1 = p1_obj.x - p2_obj.x
result2 = result1**2
result3 = p1_obj.y - p2_obj.y
result4 = result3**2
result5 = result2 + result4
return results
You can further improve it as p1 and p2 have the same properties (data member and member function) so we can just use one class named p (or any other name) and create two object p1 and p2 of the class
Although you have declared the class p1 and p2 but you haven't created any object. So, you are getting this error.
x and y are the instances of class p1 and p2 you can't access by their class name.
Either define x and y as class variables inside the class or define a object each of class p1 and p2 like given below.
p1ob=p1(4,5)
p2ob=p2(5,6)
Related
I wrote classes for Ray, Line, Point, and some other shapes, but I was stopped by the need for a function that takes a Line class object and a Ray class object as a parameter, and returns the point at which the line and the ray intersect.
Point class:
class Point:
def __init__(self, x: float, y: float):
self.x = x
self.y = y
def __getitem__(self, index):
if index == 0:
return self.x
elif index == 1:
return self.y
def __iter__(self):
yield self.x
yield self.y
def __str__(self):
return f"x = {self.x}; y = {self.y}"
Ray class:
class Ray:
def __init__(self, start: Point, end: Point):
self.start = start
self.end = end
def get_direction(self):
x_diff = self.end[0] - self.start[0]
y_diff = self.end[1] - self.start[1]
return (x_diff, y_diff)
Line class:
class Line:
def __init__(self, point1: Point, point2: Point):
self.point1 = point1
self.point2 = point2
def get_direction(self) -> tuple:
x_diff = abs(self.point2[0] - self.point1[0])
y_diff = abs(self.point2[1] - self.point1[1])
return (x_diff, y_diff)
def get_params(self) -> tuple:
x1, y1 = self.point1
x2, y2 = self.point2
a = y2 - y1
b = x1 - x2
c = x2 * y1 - x1 * y2
return a, b, c
def get_normal(self):
a, b, c = self.get_params()
return -b, a, c
And perhaps the following functions can help:
Is the point on the line?
def point_on_line(point: Point, line: Line):
x1, y1 = line.point1
x2, y2 = line.point2
x, y = point
return (y - y1) * (x2 - x1) == (y2 - y1) * (x - x1)
Is the point on the ray?
def point_on_ray(point: Point, ray: Ray) -> bool:
start = ray.start
end = ray.end
direction = ray.get_direction()
x_diff = point[0] - start[0]
y_diff = point[1] - start[1]
if x_diff * direction[1] == y_diff * direction[0]:
if x_diff >= 0 and y_diff >= 0:
return True
return False
I am bad in Math so i asked ChatGPT to help me, but he wrote some functions which will return wrong result
I tried giving ChatGPT several completely different prompts, and I got several completely different functions in response, but anyway, they all didn't work. Some of them returned the wrong points, some of them thought the ray and the line were parallel, although they have not worked correctly
You have to solve equation system
ray.start.x + t * ray.diff.x = line.point1.x + u * line.diff.x
ray.start.y + t * ray.diff.y = line.point1.y + u * line.diff.y
for unknowns t and u, then check that t >= 0
Then substitute t value into the left parts to get intersection point coordinates.
Standalone Python function
def ray_line_intersection(rx0, ry0, rdiffx, rdiffy, lx0, ly0, ldiffx, ldiffy):
denom = ldiffy * rdiffx - ldiffx * rdiffy
if denom == 0: #ray and line are parallel or coincident
return (1) if (lx0 - rx0) * rdiffy == (ly0 - ry0) * rdiffx else None
t = (ldiffx * (ry0 - ly0) + ldiffy * (lx0 - rx0)) / denom
return (rx0 + rdiffx * t, ry0 + rdiffy * t) if t >=0 else None
print(ray_line_intersection(0, 0, 1, 1, 3, 0, -1, 1))
print(ray_line_intersection(0, 0, 1, 1, 3, 0, 1, 1))
print(ray_line_intersection(0, 0, 1, 1, -1, -1, 4, 4))
print(ray_line_intersection(0, 0, 1, 1, -1, 0, 1, -1))
>>> (1.5, 1.5) normal intersection
>>> None parallel
>>> 1 ray lies in the line
>>> None intersection beyond ray range
I'm trying to coding a Point class to determine if a 3 given point can make a trainagle.
this is the Class I did:
import math
class Point(object):
def __init__(self, x1, y1):
self.x = x1
self.y = y1
def getX(self):
return int(self.x)
def getY(self):
return int(self.y)
def Distance(self):
return math.sqrt((self.x ** 2) + (self.y ** 2))
def PointToStr(self):
return '({}, {})'.format(self.x, self.y)
def DistanceFromPoint(self, pX):
dx = int(self.getX - pX.getX)
dy = int(self.getY - pX.getY)
return math.sqrt((dx * dx) + (dy * dy))
#classmethod
def FromString(cls, Point_str):
x, y = Point_str
return cls(x, y)
and this is my Pyhton file:
from Point import Point
def isTriangle(x1, y1, x2, y2, x3, y3):
return (y2 - y1) * (x3 - x2) != (y3 - y2) * (x2 - x1)
def isTriangle2(p1, p2, p3):
d1 = p1.DistanceFromPoint(p2)
d2 = p1.DistanceFromPoint(p3)
d3 = p2.DistanceFromPoint(p3)
if d1 + d2 > d3 and d1 + d3 > d2 and d2 + d3 > d1:
return True
else:
return False
def main():
p1 = Point(5, 10)
p2 = Point(7, 10)
p3 = Point(15, 10)
print(p1.PointToStr())
print(p2.PointToStr())
print(isTriangle(p1.getX(), p1.getY(), p2.getX(), p2.getY(), p3.getX(), p3.getY()))
print(isTriangle2(p1, p2, p3))
if __name__ == "__main__":
main()
when I'm trying to run isTriangle2 I get the following error:
TypeError: unsupported operand type(s) for -: 'method' and 'method'
this is the traceback:
Traceback (most recent call last):
File "C:\Users\barva\PycharmProjects\Giraffe\Ariel-notebook\lec_7+8.py", line 28, in <module>
main()
File "C:\Users\barva\PycharmProjects\Giraffe\Ariel-notebook\lec_7+8.py", line 25, in main
print(isTriangle2(p1, p2, p3))
File "C:\Users\barva\PycharmProjects\Giraffe\Ariel-notebook\lec_7+8.py", line 9, in isTriangle2
d1 = p1.DistanceFromPoint(p2)
File "C:\Users\barva\PycharmProjects\Giraffe\Ariel-notebook\Point.py", line 23, in DistanceFromPoint
dx = int(self.getX - pX.getX)
At first I tought isTriangle2 didnt transfer the given point to int when I used the getX() and getY() function so I did try to cast them but that didnt help as well.
than I tried to change the class a bit, I think the error is coming from DistanceFromPoint function in the Point class but I dont know how to fix that
in
dx = int(self.getX - pX.getX)
dy = int(self.getY - pX.getY)
The getters are functions and need to be called like functions (i.e add () when the getters are called)
One solution would be to use the #property decorator in the methods getX and getY:
#property
def getX(self):
return int(self.x)
#property
def getY(self):
return int(self.y)
This way the functions getX and getY will become properties of the class, so you will need to remove the "()" when using them:
print(isTriangle(p1.getX, p1.getY, p2.getX, p2.getY, p3.getX, p3.getY))
i need to find out whether two circles which are c1 and c2 touch each other externally and at only one point by using Circle class.
I created method which is touches. The method should return a boolean value and it needs to be called like this c1.touches(c2)
this formula to check circles touch or intersect with each other formula
this is my code
import math
class Circle:
def __init__(self, x, y, r):
self.x = x
self.y = y
self.r = r
def touches(self):
dist_between_centers = math.sqrt((self.c1.x - self.c2.x)^(2 + (self.c1.y - self.c2.y)^2))
if dist_between_centers == (self.c1.r + self.c2.r):
print("True")
elif dist_between_centers > (self.c1.r + self.c2.r):
print("False")
else:
print("False")
c1 = Circle(2,3,12)
c2 = Circle(15, 28, 10)
c1.touches(c2)
However i am getting error like this, TypeError: touches() takes 1 positional argument but 2 were given
Seems like you mix up with usage self, c1 and c2 in def touches
You should pass c2 as parameter to def touches(circle). Inside method you should refer the first circle as self rather self.c1 and the second as circle rather than self.c2
Final code like this
import math
class Circle:
def __init__(self, x, y, r):
self.x = x
self.y = y
self.r = r
def touches(self, circle):
dist_between_centers = math.sqrt((self.x - circle.x)^2 + (self.y - circle.y)^2)
if dist_between_centers == (self.r + circle.r):
print("True")
elif dist_between_centers > (self.r + circle.r):
print("False")
else:
print("False")
c1 = Circle(2, 3, 12)
c2 = Circle(15, 28, 10)
c1.touches(c2)
I have been working on an assignment for one of my introductory classes. I am almost done with my code and but I keep getting "AttributeError: 'tuple' object has no attribute 'dist'." I understand that the problem starts from midpt function and that I need to return an instance of the class instead of the tuple; however, I have not been able to do that. Could you please take a look at my code? It would be much appreciated.
'''
import math
class Point(object):
# The contructor for Point class
def __init__(self, x = 0, y = 0):
self.x = float(x)
self.y = float(y)
# The getter for x
#property
def x(self):
return self._x
# The setter for x
#x.setter
def x(self, value):
self._x = value
# The getter for y
#property
def y(self):
return self._y
# The setter for y
#y.setter
def y(self, value):
self._y = value
# Function for getting the distance between two points
def dist(self, other):
xVar = (other.x - self.x) ** 2
yVar = (other.y - self.x) ** 2
equation = xVar + yVar
distance = math.sqrt(equation)
return distance
# Function for getting the midpoint
def midpt(self, other):
xVar = (other.x - self.x) / 2
yVar = (other.y - self.y) / 2
midpoint = (xVar,yVar)
return midpoint
# Magic function for printing
def __str__(self):
return "({},{})".format(self.x, self.y)
##########################################################
# ***DO NOT MODIFY OR REMOVE ANYTHING BELOW THIS POINT!***
# Create some points
p1 = Point()
p2 = Point(3, 0)
p3 = Point(3, 4)
# Display them
print("p1:", p1)
print("p2:", p2)
print("p3:", p3)
# Calculate and display some distances
print("distance from p1 to p2:", p1.dist(p2))
print("distance from p2 to p3:", p2.dist(p3))
print("distance from p1 to p3:", p1.dist(p3))
# Calculate and display some midpoints
print("midpt of p1 and p2:", p1.midpt(p2))
print("midpt of p2 and p3:", p2.midpt(p3))
print("midpt of p1 and p3:", p1.midpt(p3))
# Just a few more things...
p4 = p1.midpt(p3)
print("p4:", p4)
print("distance from p4 to p1:", p4.dist(p1))
You might want to change midpoint = (xVar,yVar) to midpoint = Point(xVar, yVar).
In this way, p4 is a Point (and not a tuple!) instance, and you can call the dist method on it.
I am currently expanding by python skills by programming a procedurally generated dungeon level in text format. I am confused as to why my "intersects" define is not working. Here is the class containing the def:
class Room:
global x1
global x2
global y1
global y2
global w
global h
global centre
def __init__(self,x,y,w,h):
x1 = x
x2 = x + w
y1 = y
y2 = y + h
self.x = x
self.y = y
self.w = w
self.h = h
centre = math.floor((x1 + x2) / 2),math.floor((y1 + y2) / 2)
#function that checks if the rooms intersect by comparing corner pins relative to the x,y tile map
def intersects(self,room):
if x1 <= room.x2 and x2 >= room.x1 and y1 <= room.y2 and room.y2 >= room.y1:
return True
return False
Here is where it's called:
def placeRooms(r):
rooms = []
#Where the room data is stored
for r in range(0,r):
w = minRoomSize + randint(minRoomSize,maxRoomSize)
h = minRoomSize + randint(minRoomSize,maxRoomSize)
x = randint(1,map_width - w - 1) + 1
y = randint(1,map_height - h - 1) + 1
newRoom = Room(x,y,w,h)
failed = False
#for every room generated, this function checks if new room intersects with the last one
for otherRoom in rooms:
if newRoom.intersects(otherRoom):
failed = True
break
if failed == False:
createRoom(newRoom)
rooms.append(newRoom)
Full traceback:
Traceback (most recent call last):
File "C:\Users\Max\Desktop\LiClipse Workspace\testing\RandomDungeon.py", line 78, in <module>
placeRooms(2)
File "C:\Users\Max\Desktop\LiClipse Workspace\testing\RandomDungeon.py", line 65, in placeRooms
if newRoom.intersects(otherRoom):
File "C:\Users\Max\Desktop\LiClipse Workspace\testing\RandomDungeon.py", line 41, in intersects
if x1 <= room.x2 and x2 >= room.x1 and y1 <= room.y2 and room.y2 >= room.y1:
NameError: name 'x1' is not defined
I hope someone can help me understand why this code won't work, thank you.
I have managed to fix the problem. I'm sorry if my question was not defined very well. I have only been learning Python for around 4 weeks and i am used to Java which has a very different syntax. Here is my solution:
def __init__(self,x,y,w,h):
self.x1 = x
self.x2 = x + w
self.y1 = y
self.y2 = y + h
self.x = x
self.y = y
self.w = w
self.h = h
As most previous comments have said, you use global variables that shouldn't be global at all.
The way I understand your code, you meant for x1, x2, y1 and y2 to be attributes of your Room instance, meaning that each room has its own values for x1, x2, y1 and y2. In Python you don't have to declare attributes at the beginning of the class (where you declare all the global variables), you simply need to initialize the attributes in the __init__ method.
This means that you can safely delete all the global lines, and change your __init__ to
def __init__(self,x,y,w,h):
self.x1 = x
self.x2 = x + w
self.y1 = y
self.y2 = y + h
self.w = w
self.h = h
centre = (self.x1 + self.x2) // 2,(self.y1 + self.y2) // 2
(note that you don't need math.floor since you're already dealing with integers, simply use the integer division operator //)
That way you define x1, y1, x2, y2, w, h and center as attributes of your class meaning that each instance has its own values for these variables. In Python, you need to add self. before all calls to attributes of the object itself, so you should also modify intersects to add self. before each access to an attribute of your current object (all the x1, x2, etc. that are not already prefixed by room. in your code).
Also, while we're at it I don't think your intersect function works as intended, but that's another problem :)