class Point:
def __init__(self, initX, initY):
""" Create a new point at the given coordinates. """
self.x = initX
self.y = initY
def getX(self):
return self.x
def getY(self):
return self.y
def distanceFromOrigin(self):
return ((self.x ** 2) + (self.y ** 2))** 0.5
def __str__(self):
return "x=" + str(self.x) + ", y=" + str(self.y)
def get_line_to(self, target):
mx = (-target.x + self.x )
my = (-target.y + self.y)
grad=my/mx
c=-(grad*(self.x))+self.y
return grad
def halfway(self, target):
"""calculating midpoint"""
mx = (self.x + target.x) / 2
my = (self.y + target.y) / 2
return Point(mx, my)
def cencd(p1,p2,p3):
"""calculating the center of a circle"""
ma=(p2.getY-p1.getY)/(p2.getX-p1.getX)
mb=(p3.getY-p2.getY)/(p3.getX-p2.getX)
hw=p1.halfway(p2)
x=(ma*mb*(p1.getY-p3.getY)+mb*(p1.getX+p2.getX)-ma*(p2.getX+p3.getX))/2*(mb-ma)
ya=-(1/ma)*((x-hw.getX)+hw.getY)
return x,ya
"""defining the points for p1,p2 and p3"""
p = Point(5,5)
q = Point(6,-2)
r=Point(2,-4)
print(cencd(p,q,r))
I get this error message:SyntaxError: duplicate argument 'p1' in function definition on
Traceback (most recent call last):
File "python", line 45, in
File "python", line 34, in cencd
TypeError: unsupported operand type(s) for -: 'method' and 'method'
please assist.
"""working solution """"
ma=(p2.y-p1.y)/(p2.x-p1.x)
mb=(p3.y-p2.y)/(p3.x-p2.x)
hw=p1.halfway(p2)
x1=(ma*mb*(p1.y-p3.y)+mb*(p1.x+p2.x)-ma*(p2.x+p3.x))/(2*(mb-ma))
ya=-(1/ma)*((x1-hw.x))+hw.y
You don't need getters or setters in python nor is it pythonic to use them, you should access the attributes directly:
def cencd(p1, p2, p3):
"""calculating the center of a circle"""
ma = (p2.y - p1.y) / (p2.x - p1.x)
mb = (p3.y - p2.y) / (p3.x - p2.x)
hw = p1.halfway(p2)
x = (ma * mb * (p1.y - p3.y) + mb * (p1.x + p2.x) - ma * (p2.x + p3.x)) / 2 * (mb - ma)
ya = -(1 / ma) * ((x - hw.x) + hw.y)
return x, ya
Both getX and getY are methods in your code, not attributes. So you will need to call them using getX() and getY().
So ma=(p2.getY-p1.getY)/(p2.getX-p1.getX) becomes:
ma = (p2.getY()-p1.getY())/(p2.getX()-p1.getX())
And so on, the other code changes.
Otherwise, you can also define your methods as #property:
class Point:
...
...
#property
def getX(self):
return self.x
#property
def getY(self):
return self.y
...
And now you can access these as p1.getX and p2.getY and so on.
Note that the above #property decorator turns the method into a getter, which makes sense to use only with private variables (variables defined to start with _).
As such, since both x and y are normal attributes of your class, you can access them directly without using and property decorators or using getter methods, like p1.x and p2.y, as #Padraic points in his post.
As Padraic Cunningham said, we don't need getters or setters in Python, but as mu said we can make getters if we want, but normally they are used to get "fake" attributes that are actually computed from true attributes. For example, in the code below I've added a fake norm attribute to your Point class.
I've also added a few more double-underscore methods (aka dunder methods or magic methods) to your class. These methods are discussed in the official Python docs.
One of the most common dunder methods is __repr__() which should return a string that corresponds to how you create an instance of the class. This is especially handy when you're using a class in the interactive interpreter. FWIW, if a class doesn't define a __str__() method its __repr__() method will be used if you attempt to turn a class instance into a string. If a __repr__() method hasn't been defined a default one will be used.
The other dunder methods I've added make it easier to perform arithmetic operations on points; this can make code easier to write and to read. I think you'll agree that it makes the cencd() function a little clearer. (I'm not sure exactly what that function's supposed to do; I assume you've got the algebra correct :) ).
This code was tested on Python 2.6.6; it should run ok on Python 3 without modification.
#!/usr/bin/env python
''' Point class demo
From http://stackoverflow.com/q/28602056/4014959
Written by koseph, Padraic Cunningham, and PM 2Ring
2015.02.19
'''
from __future__ import print_function
from __future__ import division
class Point(object):
def __init__(self, initX, initY):
""" Create a new point at the given coordinates. """
self.x, self.y = initX, initY
#property
def norm(self):
return self.x ** 2 + self.y ** 2
def distance_from_origin(self):
return self.norm ** 0.5
def __repr__(self):
return 'Point({self.x}, {self.y})'.format(self=self)
def __str__(self):
return 'x={self.x}, y={self.y}'.format(self=self)
def __add__(self, other):
return Point(self.x + other.x, self.y + other.y)
def __mul__(self, scale):
return Point(self.x * scale, self.y * scale)
__rmul__ = __mul__
def __neg__(self):
return -1 * self
def __sub__(self, other):
return self + -other
def weighted_mean(self, other, weight):
cweight = 1.0 - weight
x = cweight * self.x + weight * other.x
y = cweight * self.y + weight * other.y
return Point(x, y)
def halfway(self, other):
return self.weighted_mean(other, 0.5)
def cencd(p1, p2, p3):
""" Calculate the center of a circle """
a = p2 - p1
b = p3 - p2
ma = a.y / a.x
mb = b.y / b.x
hw = p1.halfway(p2)
x = ma * mb * (p1 - p3).y + mb * (p1 + p2).x - ma * (p2 + p3).x
x /= 2.0 * (mb - ma)
y = -(x - hw.x + hw.y) / ma
return Point(x, y)
p1 = Point(3, 4)
print(p1)
print('p1 is {0!r}, its norm is {1}'.format(p1, p1.norm))
print('and its distance from the origin is', p1.distance_from_origin(), end='\n\n')
p2 = Point(7, 2)
print('p2 is', repr(p2), end='\n\n')
print('p1 + p2 is', repr(p1 + p2))
print('p1 * 0.1 is', repr(p1 * 0.1))
print('p2 - p1 is', repr(p2 - p1), end='\n\n')
p3 = 4 * p1
print('p3 is', repr(p3), end='\n\n')
print('Weighted means from p1 to p3')
for i in range(5):
weight = i / 4.0
print('{0} {1:4.2f} {2!r}'.format(i, weight, p1.weighted_mean(p3, weight)))
print()
print('center of a circle for p1, p2, & p3:', repr(cencd(p1, p2, p3)))
output
x=3, y=4
p1 is Point(3, 4), its norm is 25
and its distance from the origin is 5.0
p2 is Point(7, 2)
p1 + p2 is Point(10, 6)
p1 * 0.1 is Point(0.3, 0.4)
p2 - p1 is Point(4, -2)
p3 is Point(12, 16)
Weighted means from p1 to p3
0 0.00 Point(3.0, 4.0)
1 0.25 Point(5.25, 7.0)
2 0.50 Point(7.5, 10.0)
3 0.75 Point(9.75, 13.0)
4 1.00 Point(12.0, 16.0)
center of a circle for p1, p2, & p3: Point(8.22727272727, 12.4545454545)
Related
I'm trying to solve the tasks (text below), but I have a problem with the second point, i.e. method in it that displays the length of the segment and the positions of the start and end points.-
I don't really know how to write it, Could someone look at the code and give some hints?
Define a Point class with x, y fields and a method displaying the
point's position (eg "point (2,3)").
Then create a class Segment that will inherit from the class point.
Create a method in it that displays the length of the segment and the
positions of the start and end points.
Then define the Triangle class which will contain 3 Points,
automatically determined 3 Sections (walls) of them and included a
method for displaying the surface area of the perimeter.
code:
from math import sqrt, hypot
class Point:
def __init__(self, x_init, y_init):
self.x = x_init
self.y = y_init
def __str__(self):
return "Point(%s,%s)"%(self.x, self.y)
class Segment(Point):
def distance(self): **!-probably a badly written method**
return ((self.x ** 2) + (self.y ** 2)) ** 0.5
def position(self, p): **!-probably a badly written method**
dx = self.x - p.X
dy = self.y - p.Y
return hypot(dx, dy)
class Triangle(Point):
def __init__(self, x, y, z):
Point.__init__(self, x, y)
self.z = z
def __str__(self):
return "Point(x %s ,y %s, z %s )" % (self.x, self.y, self.z)
def __area__(a, b, c):
s = (a + b + c) / 2
return (s * (s - a) * (s - b) * (s - c)) ** 0.5
def __perimeter__(a, b, c):
s = (a + b + c)
return s
Task 2 is just wrong. Segment needs to contain 2 points, so it can't inherit from Point. It should be:
class Segment:
def __init__(self, start, end):
self.start = start
self.end = end
def distance(self):
dist = ((self.start.x - self.end.x) ** 2 + (self.start.y - self.end.y) ** 2) ** 0.5
print(f"distance from {self.start} to {self.end} is {dist}"
I have to write a code to find the different between two point by passing value via two objects as below.
But I am getting TypeError: init() missing 3 required positional arguments: 'x', 'y', and 'z'
class Point:
def __init__(self, x, y,z):
self.x = x
self.y = y
self.z = z
def __str__(self):
return '(point: {},{},{})'.format(self.x, self.y, self.z)
def distance(self, other):
return sqrt( (self.x-other.x)**2 + (self.y-other.y)**2 + (self.z -other.z)**2 )
p = Point()
p1 = Point(12, 3, 4)
p2 = Point(4, 5, 6)
p3 = Point(-2, -1, 4)
print(p.distance(p1,p3))
The problem comes from this line:
p = Point()
When you defined you class, you specified it has to be passed 3 parameters for it to be initialised (def __init__(self, x, y,z)).
If you still want to be able to create this Point object without having to pass those 3 parameters, you can make them optional like this :
def __init__(self, x=0, y=0, z=0):
self.x = x
self.y = y
self.z = z
This way, if you were to not specify these parameters (as you did), it will create a point with coordinates {0, 0, 0} by default.
You are not passing the required 3 arguments for p = Point()
fixed your errors
from math import sqrt
class Point:
def __init__(self, x, y,z):
self.x = x
self.y = y
self.z = z
def __str__(self):
return '(point: {},{},{})'.format(self.x, self.y, self.z)
def distance(self, other):
return sqrt( (self.x-other.x)**2 + (self.y-other.y)**2 + (self.z -other.z)**2 )
# p = Point() # not required
p1 = Point(12, 3, 4)
p2 = Point(4, 5, 6)
p3 = Point(-2, -1, 4)
print(p1.distance(p3)) # use this to find distance between p1 and any other point
# or use this
print(Point.distance(p1,p3))
class Point:
def __init__(self, x, y,z):
self.x = x
self.y = y
self.z = z
def __str__(self):
return '(point: {},{},{})'.format(self.x, self.y, self.z)
def distance(self, other):
return math.sqrt( (self.x-other.x)**2 + (self.y-other.y)**2 + (self.z -other.z)**2 )
p1 = Point(12, 3, 4)
p2 = Point(4, 5, 6)
p3 = Point(-2, -1, 4)
print(Point.distance(p1,p3))
It works like this.You should not define a P point seperate than the other three points. Every point is a seperate instance. But when you try to use the function just call the class.
The questions asks to "Write a method add_point that adds the position of the Point object given as an argument to the position of self". So far my code is this:
import math
epsilon = 1e-5
class Point(object):
"""A 2D point in the cartesian plane"""
def __init__(self, x, y):
"""
Construct a point object given the x and y coordinates
Parameters:
x (float): x coordinate in the 2D cartesian plane
y (float): y coordinate in the 2D cartesian plane
"""
self._x = x
self._y = y
def __repr__(self):
return 'Point({}, {})'.format(self._x, self._y)
def dist_to_point(self, other):
changex = self._x - other._x
changey = self._y - other._y
return math.sqrt(changex**2 + changey**2)
def is_near(self, other):
changex = self._x - other._x
changey = self._y - other._y
distance = math.sqrt(changex**2 + changey**2)
if distance < epsilon:
return True
def add_point(self, other):
new_x = self._x + other._x
new_y = self._y + other._y
new_point = new_x, new_y
return new_point
However, I got this error message:
Input: pt1 = Point(1, 2)
--------- Test 10 ---------
Expected Output: pt2 = Point(3, 4)
Test Result: 'Point(1, 2)' != 'Point(4, 6)'
- Point(1, 2)
? ^ ^
+ Point(4, 6)
? ^ ^
So I'm wondering what is the problem with my code?
Your solution returns a new tuple without modifying the attributes of the current object at all.
Instead, you need to actually change the object's attributes as per the instructions and don't need to return anything (ie, this is an "in-place" operation).
def add_point(self, other):
self._x += other._x
self._y += other._y
import math
class Vector:
def __init__(self,x,y):
self.x= x
self.y =y
def add(self,other):
new_x = self.x + other.x
new_y = self.y + other.y
return Vector(new_x,new_y)
def subtract(self,other):
new_x = self.x - other.x
new_y = self.y - other.y
return Vector(new_x,new_y)
def scale(self,factor):
new_x = self.x * factor
new_y = self.y * factor
return Vector(new_x,new_y)
def length(self,other):
r_squared = self.x ** 2 + self.y **2
return Vector(r_squared)
I've been trying to test this code that I was given, how am I able to test this using some numbers so that I am able to learn to understand what each function in this code actually does. I am able to see what it does from looking at the code but I also want to reassure that what I am predicting it to do is actually what it does.
Thank you in advance!
Add a checker for your code at the very end of yor file:
if __name__=="__main__":
vec1 = Vector(0, 0)
vec2 = Vector(2,2)
vec3 = vec1.add(vec2)
print(vec1, vec2, vec3)
#add other tests
You could add an override to a built in function in the Vector class for printing instances in a human readable way.
def __repr__(self):
return 'Vector: ({}, {})'.format(self.x, self.y)
Then you might want to fix the length function. It should only return a number and not another Vector. Additionally, it should return the square root of the sum. For example the vector (3, 4) should have a length of 5, not 25. Also, the length method does not need vector supplied as a param.
Once these are fixed up you can add this to the bottom of the file and run the script in the terminal like so: python vec.py
if __name__ == '__main__':
v1 = Vector(0,0)
v2 = Vector(3,4)
print('v1', v1)
print('v2', v2)
print('v1 + v2', v1.add(v2))
print('v2.length', v2.length())
I've been stuck on this annoying problems for eons. I'm trying to write code so that I can scale a line segment meaning if the amount that I was to scale by(for example) is 2 and the current length of the line is 33 it will increase the entire length to 67. Meaning I add half to the beginning and half to the end...
new front ---a--------b--- new back... But I'm having trouble translating it into code. Here is an example of the code.. The endpoints method should return the endpoints in a tuple such as (p1, p2)
from point import Point
import math
class Line:
def __init__(self,aPoint=Point(), bPoint=Point()):
self.firstPoint = aPoint
self.secondPoint = bPoint
def getEndPoints(self):
return (self.firstPoint, self.secondPoint)
def scale(self,factor):
if factor < 1:
x1 = self.firstPoint.x +(self.secondPoint.x - self.firstPoint.x) * (factor)
x2 = self.secondPoint.x +(self.firstPoint.x - self.secondPoint.x) * (factor)
print(str(x1))
y1 = self.firstPoint.y +(self.secondPoint.y - self.firstPoint.y) * (factor)
y2 = self.secondPoint.y +(self.firstPoint.y - self.secondPoint.y) * (factor)
else:
x1 = -(self.firstPoint.x +(self.secondPoint.x - self.firstPoint.x) * (factor))
x2 = -(self.secondPoint.x +(self.firstPoint.x - self.secondPoint.x) * (factor))
y1 = self.firstPoint.y +(self.secondPoint.y - self.firstPoint.y) * (factor)
y2 = self.secondPoint.y +(self.firstPoint.y - self.secondPoint.y) * (factor)
self.firstPoint = Point(x1, y1)
self.secondPoint = Point(x2, y2)
if __name__ == "__main__":
p1 = Point(5,5)
p2 = Point(20,35)
l1 = Line(p1,p2)
l1.scale(2)
p5 = Point(-2.5,-10)
p6 = Point(27.5,50)
assert l1.getEndPoints() == (p5,p6)
These tests are not working correctly but the above are.. I'm getting a(5.0, 5.0) and b(20.0, 35.0)
l1.scale(0.5)
p5 = Point(8.75,12.5)
p6 = Point(16.25,27.5)
class Point:
'''Point class represents and manipulates
x,y coordinates.'''
def __init__(self,x=0,y=0):
'''Create a new point with default
x,y coordinates at 0,0.'''
self.x = x
self.y = y
def distanceTo(self,aPoint):
return ((self.x-aPoint.x) ** 2 + (self.y-aPoint.y) ** 2)** .5
not sure if I get it right but
use linear interpolation (parametric line equation)
You got line defined by endpoints p0,p1 in form of vectors so any point on it is defined as:
p(t)=p0+(p1-p0)*t
where p(t) is the point (vector) and t is scalar parameter in range
t=<0.0,1.0>
if you do not know the vector math then rewrite it to scalars
x(t)=x0+(x1-x0)*t
y(t)=y0+(y1-y0)*t
so if t=0 then you get the point p0 and if t=1 then you get the point p1
Now just rescale the t range
so you have scale s
t0=0.5-(0.5*s)` ... move from half of line by scale towards p0
t1=0.5+(0.5*s)` ... move from half of line by scale towards p1
so new endpoints are
q0=p0+(p1-p0)*t0
q1=p0+(p1-p0)*t1
[edit1] I see it like this
def scale(self,factor):
t0=0.5*(1.0-factor)
t1=0.5*(1.0+factor)
x1 = self.firstPoint.x +(self.secondPoint.x - self.firstPoint.x) * t0
y1 = self.firstPoint.y +(self.secondPoint.y - self.firstPoint.y) * t0
x2 = self.firstPoint.x +(self.secondPoint.x - self.firstPoint.x) * t1
y2 = self.firstPoint.y +(self.secondPoint.y - self.firstPoint.y) * t1
self.firstPoint = Point(x1, y1)
self.secondPoint = Point(x2, y2)
Take in mind I do not code in python so handle with prejudice ...
For a scale factor s, the coordinates of the new points are given by
Xa' = Xa (1+s)/2 + Xb (1-s)/2
Ya' = Ya (1+s)/2 + Yb (1-s)/2
Xb' = Xb (1+s)/2 + Xa (1-s)/2
Yb' = Yb (1+s)/2 + Ya (1-s)/2
With the common metrik, you only need to adjust each dimension seperately.
I rewrote some parts of the code, to fit it better to the usual Python style
You might want to work through the things, you are unfamiliar with to save yourself a lot of time in the future.
class Line:
def __init__(self, point_one, point_two):
self.point_one = point_one
self.point_two = point_two
def __str__(self):
return 'Line(p1:{},p2:{})'.format(self.point_one, self.point_two)
#property
def points(self):
return self.point_one, self.point_two
#property
def length(self):
return ((self.point_one.x - self.point_two.x)**2 + (self.point_one.y - self.point_two.y)**2)**0.5
def scale(self, factor):
self.point_one.x, self.point_two.x = Line.scale_dimension(self.point_one.x, self.point_two.x, factor)
self.point_one.y, self.point_two.y = Line.scale_dimension(self.point_one.y, self.point_two.y, factor)
#staticmethod
def scale_dimension(dim1, dim2, factor):
base_length = dim2 - dim1
ret1 = dim1 - (base_length * (factor-1) / 2)
ret2 = dim2 + (base_length * (factor-1) / 2)
return ret1, ret2
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __str__(self):
return 'Point(x={},y={})'.format(self.x, self.y)
def __eq__(self, other):
return self.x == other.x and self.y == other.y
if __name__ == "__main__":
p1 = Point(5, 5)
p2 = Point(20, 35)
l1 = Line(p1, p2)
print(l1)
print(l1.length)
l1.scale(2)
print(l1)
print(l1.length)
p5 = Point(-2.5, -10)
p6 = Point(27.5, 50)
assert l1.points == (p5, p6)
Note, that the scale method modifies the orginal line and points. If you want to get a new line, the method should be:
def scale(self, factor):
x1, x2 = Line.scale_dimension(self.point_one.x, self.point_two.x, factor)
y1, y2 = Line.scale_dimension(self.point_one.y, self.point_two.y, factor)
return Line(Point(x1, y1), Point(x2, y2))