I have
class Point:
def __init__(self, initX, initY):
self.x = initX
self.y = initY
def getX(self):
return self.x
def getY(self):
return self.y
def __str__(self):
return "x=" + str(self.x) + ", y=" + str(self.y)
class Rectangle:
def __init__(self, initP, initW, initH):
self.__location = initP
self.__width = initW
self.__height = initH
def getWidth(self):
return self.__width
def getHeight(self):
return self.__height
def getLocation(self):
return self.__location
#---------------------------------------------------------------
#string
def __str__(self):
return "x=" + str(self.__location.x) + ", y=" + str(self.__location.y) +", Width=" + str(self.getWidth()) + ", Height=" +str(self.getHeight())
def area(self):
return self.getWidth() * self.getHeight()
def calculatePerimeter(self):
return self.getWidth()*2 +self.getHeight()*2
def transpose(self):
temp = self.__width
self.__width = self.__height
self.__height = temp
def encloses(self, otherP):
return ((self.getWidth() + self.getLocation().getX()) > otherP.getX()\
and (self.getLocation().getX()) <otherP.getX() \
and (self.getHeight() + self.getLocation().getY()) >otherP.getY()\
and self.getLocation().getY() < otherP.getY())
def computeDiagonal(self):
d = (self.getWidth()**2 + self.getHeight()**2) ** 0.5
return d
def detectCollision(firstRectangle, secondRectangle):
print(firstRectangle.getWidth())
print(secondRectangle)
first = Rectangle(Point(1,0), 4, 3)
second = Rectangle(Point(4,0), 4, 3)
Rectangle.detectCollision(first, second)
I am trying to detect a collision. I'm a bit stuck. (detectCollision)
I am having trouble getting the value from the point class to the rectangle class.
Does anybody have any idea?
The function detectCollision is wrong. I was testing and I could get the width, and the height with getHeight() but I could not get the values inside Point.
I am having trouble getting the value from the point class to the rectangle class.
I think you need to read through a good tutorial on classes. Maybe the chapter in the official tutorial, or maybe a third-party tutorial. StackOverflow is not a good place to learn basic concepts.
You don't actually want to get a value from the point class, you want to get the value from a particular point instance. After all, there are lots of points in the world, and each one has different x and y values, and you're trying to check if some particular point has collided with the rectangle.
How do you know which instance? You take one as a parameter. And then you can access that object's members, methods, etc., just like you do with a string or any other object.
class Rectangle(object):
# existing stuff
def collision_check(self, point):
return (self.left <= point.getX() <= self.right and
self.top <= point.getY() <= self.bottom)
That's it.
Except that you probably don't want getX and getY methods in the first place; better to just do point.x and point.y.
Also, I've obviously had to make some assumptions about how you defined Rectangle (left/top/bottom/right? left/right/width/top? topleftpoint/bottomrightpoint?) and about what you mean by "collision" (hitting the edge of the rectangle, or the interior of the rectangle?), etc., since you didn't explain any of that. But hopefully you can adapt this to whatever your actual design is.
So, how do you use this? You just pass a point as an argument to the method, same as you do with, say, len:
>>> rect = Rectangle(10, 10, 20, 20)
>>> point1 = Point(5, 5)
>>> rect.collision_check(point1)
False
>>> point2 = Point(15, 15)
>>> rect.collision_check(point2)
True
Now that you've shown us more of your code, it looks like you're trying to collision-check two rectangles—and, more importantly, your problem is that your rectangle uses a Point as its top-left origin, and you don't know how to access the coordinations of that.
From your description, "I was testing and I could get the width, and the height with getHeight() but I could not get the values inside Point", you seem to still be missing the key issue here. You don't want to get the values inside Point. Point is a class—a factory for creating actual point objects. You want to get the values inside one of those actual point objects, the one you've stored in a rectangle object's __location and made available through a getLocation method. (As I already explained, you should get rid of those getter methods and just have a location attribute, but let's forget that for now.)
So, the way you get the particular point object you're interested in is to call getLocation() on the rectangle, and then the way you get the x and y values for that particular point object is to call its getX and getY methods. So, here's an example of using all those methods:
firstLocation = firstRectangle.getLocation()
firstLeft = firstLocation.getX()
Or you can combine those calls into one expression:
firstLeft = firstRectangle.getLocation().getX()
So, you can do something like this:
def detectCollision(firstRectangle, secondRectangle):
firstLeft = firstRectangle.getLocation().getX()
firstRight = firstLeft + firstRectangle.getWidth()
# similar code for top and bottom, and for second rectangle
return ((firstLeft <= secondLeft <= firstRight or
firstLeft <= secondRight <= firstRight) and
(firstTop <= secondTop <= firstBottom or
firstTop <= secondBottom <= firstBottom))
Related
I need to overload the addition function so that it takes in the first point and the end point as the left and right side of the equation and outputs the equation. This is what my code looks right now. I'm not sure how to involve the line class?
import math
class Point:
'''Class that creates points. Attributes: Eastings and Northings'''
def __init__(self,x,y):
self.eastings = x
self.northings = y
def getCoords(self):
self.coords = (self.eastings,self.northings)
return self.coords
def setCoords(self,other_x,other_y):
self.eastings = float(other_x)
self.northings = float(other_y)
def __str__(self):
return f"{self.eastings},{self.northings}"
def __add__(self,new_point):
pass
#creates a line (new class)
class Line(Point):
'''Class that creates line object based on two points'''
def __init__(self,start,end):
self.start = start #Type:Point (x1,y1)
self.end = end #Type:Point (x2,y2)
self.latitude = abs(self.end.eastings - self.start.eastings)
self.departure = abs(self.end.northings - self.start.northings)
self.distance = math.sqrt((self.latitude)**2 + (self.departure)**2)
self.azimuth = math.degrees(math.atan2(self.departure,self.latitude))
def __getitem__(self,key):
if key == 0:
ans = self.start
elif key == 1:
ans = self.end
else:
print("invalid index")
return ans
#test code
a = Point(0,0)
b = Point(1,1)
c = Point(1,0.5)
line1 = a+b
print((type(line1))
The test code is supposed to print out the type as class line.
There's nothing that says the __add__() method has to return a the same type as the instance — which means you could this:
class Point:
...
def __add__(self, other):
if isinstance(other, Point):
return Line(self, other) # Line from this Point to the other.
else:
raise TypeError(f"Can't add a non-Point to a Point}")
Be careful doing this however, because the Line class will inherit the method (so you probably need to modify its version of it).
Add a self.getCoords() call to your Point.__init__() method.
Add return Line(self, new_point) to your Point.__add__() method.
Testing:
a = Point(0,0)
b = Point(1,1)
c = Point(1,0.5)
line1 = a+b
print(type(line1)) # I have removed a round bracket on the left
Output: <class '__main__.Line'>
In case you want to run a block of code, where a function/method has not one line in it, you have to add a pass to it. Otherwise you will get an error, because the structure requires it. Or you comment the function declaration out.
There are a lot of answers saying this is unadvisable, but I found a scenario where I think it's useful. Please correct me if I'm wrong and there's a better way.
I'm building a chess game, where individual pieces inherit from the superclass Chesspiece:
class ChessPiece:
def __init__(self, pos, color, num, piece):
...
Each piece has a method that defines the moves it can take:
class Knight(ChessPiece):
def __init__(self, pos, color=None, num=''):
ChessPiece.__init__(self, pos, color, num, self.__class__.__name__)
def possible_moves(self):
pos_moves = []
# Up, Right (1 space, 2 spaces)
try:
if 1 <= self.x + 2 <= len(Config.board) and 1 <= self.y - 1 <= len(Config.board):
if Config.board[self.x + 2][self.y - 1] == '___':
pos_moves.append(f'{Config.tile_convert(self.x + 2)}{Config.tile_convert(self.y - 1, True)}')
except Exception: pass
#Up, Left
...
return pos_moves
I'd like to implement a move() function. The code for the move() function will be the same for each piece, except for the fact that it has to compare the suggested move with the possible moves, which vary for each piece. I could make a move() function for each piece, but that would just be repeating code 6 times.
So, I'd like to define move() in Chesspiece and reference each piece's possible_moves() function.
It is simpler to implement an empty possible_moves in the parent:
class ChessPiece:
...
def possible_moves(self):
raise NotImplementedError
def move(self, pos):
if pos in self.possible_moves():
...
Or even return an empty set of movements in the parent class:
def possible_moves(self):
return set()
But I think the first is better, so it forces all subclasses to implement it in order to been useful.
So I have a school project where we need to make a few classes for a GPS system. I'm having an issue figuring out the function dist(self,other): shown at the bottom of my code. Other definitions later in the project heavily rely on it, but i'm stumped at this point. The dist function calculates the Manhattan distance (x1-x2)+(y1-y2) of a location defined by instance variables x and y, and another location other which is given as a Tuple
class GPS_Location:
def __init__(self,x,y):
self.x=x
self.y=y
def __str__(self):
return '(%s,%s)' % (self.x,self.y)
def __repr__(self):
return 'GPS_Location(%s,%s)' % (self.x,self.y)
def __eq__(self,other):
self.other = other
if (self.x,self.y) == other:
return True
else:
return False
def dist(self,other):
self.other = other
return abs(self.x - (other[0])) + abs(self.y - (other[1])) #TypeError
When testing the code, I keep getting "TypeError: 'GPS_Location' object is not iterable". I have tried so many tweaks, and I just can't figure out what i'm doing wrong.
Any help would be greatly appreciated!
Ensure that line 8 is indented by 4 spaces like the rest of the methods.
There doesn't seem to be any reason to assign other to self.other in __eq__() and dist().
The only other issue you might be having could be related to how you are calling these methods (you mentioned that the argument other is just a tuple), this works:
x = GPS_Location(1, 1)
x == (1, 1)
# True
x == (2, 2)
# False
x.dist((1, 1))
# 0
x.dist((2, 2))
# 2
If you in fact need to pass a second GPS_Location as the other argument to dist, then it needs to be updated as follows:
def dist(self, other):
return abs(self.x - other.x) + abs(self.y - other.y)
Call it like so:
x = GPS_Location(1, 1)
y = GPS_Location(2, 2)
x.dist(y)
# 2
..trying to define a method within my Point Class that checks interaction with objects of my Rectangle class on interior or boundary using type based dispatch. I tried the code below, but yields: AttributeError: 'set' object has no attribute 'intersects'.
Also, seeking a way to clearly set what intersects at boundary vs. interior. Please advise.
class Point(object):
def __init__(self, x, y, height=0):
self.x = float(x)
self.y = float(y)
self.height = float(height)
def intersects(self, other):
if isinstance(other, Point):
s1=set([self.x, self.y])
s2=set([other.x, other.y])
if s1.intersection(s2):
return True
else:
return False
elif isinstance(other, Rectangle):
s1=set([self.x, self.y])
s2=set(other.pt_ll, other.pt_ur)
if s1.intersection(s2):
return True
else:
return False
class Rectangle(object):
def __init__(self, pt_ll, pt_ur):
"""Constructor.
Takes the lower left and upper right point defining the Rectangle.
"""
self.ll = pt_ll
self.lr = Point(pt_ur.x, pt_ll.y)
self.ur = pt_ur
self.ul = Point(pt_ll.x, pt_ur.y)
these are my calling statements:
pt0 = (.5, .5)
r=Rectangle(Point(0, 0),Point(10, 10))
s1 = set([pt0])
s2 = set([r])
print s1.intersects(s2)
it would be intersection() s1.intersection(s2), you are using a set not a Point object:
s1 = set([pt0]) # <- creates a python set
To use your intersects method you need Point objects:
p = Point(3,5) # <- creates a Point object that has intersects method
p2 = Point(3,5)
print(p.intersects(p2))
So using your example, you need to access the Point objects using the attributes of the Rectangle class:
r = Rectangle(Point(0, 0),Point(10, 10))
print(r.lr.intersects(r.ul)) # <- the Rectangle attributes lr and ul are Point objects because you passed in Point's when you initialised the instance r
You can simplify the assignments in Rectangle:
class Rectangle(object):
def __init__(self, pt_ll, pt_ur):
"""Constructor.
Takes the lower left and upper right point defining the Rectangle.
"""
self.lr = Point(pt_ur.x, pt_ll.y)
self.ul = Point(pt_ll.x, pt_ur.y)
You can also just use set literals:
s1 = {self.x, self.y}
s2 = {other.x, other.y}
I have a lab assignment in my Python Programming class that I am having a little trouble with. Our instructor gave us source code GeometricObject.py as a reference.
class GeometricObject(object):
def __init__(self, color = "white", filled = True):
self.color = color
self.filled = filled
def getColor(self):
return self.color
def setColor(self, color):
self.color = color
def isFilled(self):
return self.filled
def setFilled(self, filled):
self.filled = filled
def __str__(self):
return "color: " + self.color + \
" and filled: " + str(self.filled)
Now I'm supposed to use this class, to create a subclass that applies this information to different objects. I have to make a class to calculate the area and perimeter among other things of a circle, as well as a triangle.
I am having trouble understanding when I need to copy and paste from the source code or if I don't need to. Here is the first class I made, that deals with a Circle. Simple question: Is it named correctly? Should the class be called GeometricObject(circle):???
import math
class GeometricObject(object):
'''Class using a Circle'''
def __init__(self, color = "white", filled = True):
self.radius = 1
self.color = color
self.filled = filled
def getColor(self):
return self.Color
def setColor(self, color):
self.color = color
def isFilled(self):
return self.filled
def setFilled(self, filled):
self.filled = filled
def getArea(self):
self.area = math.pi(self.radius)**2
return self.area
def getPerimeter(self):
r = radius
self.perimeter = 2(math.pi)(r)
return self.perimeter
def __str__(self):
return "color: " + self.color + \
" and filled: " + str(self.filled)
Note: In the def_str_ method, It is supposed to print Circle: radius = 3 color: red and filled: True" even though it previously states to set the default values as 1, and the color: white. I am confused by this.
That's pretty much the jist of it. I'm hoping my coding is correct so far!
I then have to do the same thing for the Triangle class, but I'm pretty sure it's similiar.
class GeometricObject(object):
'''Class using a Triangle'''
def __init__(self, color = "white", filled = True):
self.side1 = 1
self.side2 = 1
self.side3 = 1
def getArea(self):
s = (self.side1 + self.side2 + self.side3)/2
area = math.sqrt(s(s - self.side1)(s - self.side2)(s - self.side3))
return area
def getPerimeter(self)
perimeter = self.side1 +self.side2 + self.side3
return perimeter
def __str__(self):
return "color: " + self.color + \
" and filled: " + str(self.filled)
def getColor(self):
return self.Color
def setColor(self, color):
self.color = color
def isFilled(self):
return self.filled
def setFilled(self, filled):
self.filled = filled
So I guess my main questions are:
+Am I supposed to copypaste the source code from GeometricObject() over and over, or is it already there?
+The string method is confusing to me because it is asking for different values than previously specified.
+The code. I think I implemented the area and perimeter formulas for each correctly?
Thanks in advance. Any help is greatly appreciated!!
I think you want to do it like this:
class Circle(GeometricObject):
.
.
.
class Triangle(GeometricObject):
.
.
.
You only need to implement those things in the Circle and Triangle classes that are different from the GeometricObject class.
Vaughn's got the right idea on subclassing Geometric Objects, but check your work on the getArea function:
s(s - self.side1)
will raise the following traceback:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
In order to use the GeometricObject.py file you're going to want to import the file so that you can access it's methods, make sure that both files are in the same directory:
import GeometricObject from GeometricObject
Put that at the top of your current file if you wish to keep it separate. You can also simply copy-paste the source code from that file as well if you wish.
Next, you're going to want to create the class of GeometricObject. In Python, it is implied that any class that does not have a specified inheritance has object as it's superclass. The cleanest way to write out this problem would be simply:
class GeometricObject:
instead of
class GeometricObject(object):
All following classes that wish to inherit the methods in the GeometricObject class would be written like this. You must include
super().__init__()
in your initializer for your subclass in order to initialize all the data fields in the GeometricObject superclass so that you can use them. That way you can delete the isFilled and getColor and setColor methods out of your Triangle class and keep them in your GeometricObject class.
class Triangle(GeometricObject):
def __init__(self, color = "white", filled = True):
super().__init__()
-
-
-
class Circle(GeometricObject):
-
-
-
Also, keep an eye out for
area = math.sqrt(s(s - self.side1)(s - self.side2)(s - self.side3))
This will return an error. In Python (x)(x) does not mean x * x. This instead will need to be written out like:
area = math.sqrt(s*(s - self.side1)*(s - self.side2)*(s - self.side3))