How can I create a 3d object/class in Python? - python

My end goal right now is to take points that are read from a text file, and turn them into 3d objects. They do not need to be visualized, but they need to be stored in objects instead of just a string containing the x, y, and z values. The file gives me six numbers, two of each x, y, and z, and I was wondering how I would go about creating a point class/object that will take all three variables and then a line object/class that will take two of the points.

Just define a Point and a Line class:
class Point(object):
def __init__(self, x=0, y=0 ,z=0):
self.x = x
self.y = y
self.z = z
class Line(object):
def __init__(self, point1=None, point2=None):
self.point1 = point1 or Point() # (0,0,0) by default
self.point2 = point2 or Point() # (0,0,0) by default
To create points and lines objects:
>>> p1 = Point(1, 2, 3)
>>> p2 = Point(4, 5, 6)
>>> line = Line(p1, p2)

Once you have got the data from the file (for this Regular Expressions are applicable), you will want to input that into a class which is defined as to store the two points (which can be objects themselves) e.g.
class Point(tuple):
#property
def x:
return self[0]
#property
def y:
return self[1]
#property
def z:
return self[2]
class Vector(object):
def __init__(self, x1, y1, z1, x2, y2, z2):
self._a = Point(x1, y1, z1)
self._b = Point(x2, y2, z2)
#property
def a(self):
return self._a
#property
def b(self):
return self._b
# Other methods here e.g.
#property
def i(self):
return self.b.x - self.a.x
#property
def j(self):
return self.b.y - self.a.y
#property
def k(self):
return self.b.z - self.a.z
def length(self):
return ( self.i**2 + self.j**2 + self.k**2 ) ** (1/2)

Related

Unexpected representation for class's instance

I have following code:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
#classmethod
def zero(cls):
return cls(0, 0)
point = Point.zero()
I am not getting the expected output: Point(0, 0).
you are getting the correct Point object. To confirm, print type(point) and print point.x or point.y. But its representation defaults to what object.__repr__ provides(all classes inherit this from object class). Implement your own __str__ or __repr__. (See the difference here):
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
#classmethod
def zero(cls):
return cls(0, 0)
def __repr__(self) -> str:
return f"Point{self.x, self.y}"
point = Point.zero()
print(point)
You do, but what you generate is a Class Object:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
#classmethod
def zero(cls):
return cls(0, 0)
origin = Point.zero()
origin.x -> 0
origin.y -> 0

Where does the value of the variable in the subclass go?

class A(object):
def __init__(self, x):
self.x = x
def f(self, x):
return 2*x
def g(self, x):
return self.f(x)
class B(A):
def g(self, y):
return 3*y + self.x
class C1(B):
def __init__(self, x, y):
B.__init__(self,x)
self.y = y
def f(self, x):
return self.x + self.y
class C2(B):
def __init__(self, x, y):
B.__init__(self,x)
self.y = y
def f(self, x):
return x + self.x + self.y
a = A(5)
b = B(2)
c1 = C1(3,5)
c2 = C2(3,5)
When I do "What does the expression c2.f(4) evaluate to?", I was not sure where self.x in the f function in class C2 points to.
Could you give me some suggestions?
c2.f(4) makes 12. The value of x in function f is 4 because that is the argument in c2.f(4). The value of c2's self.x is 3 because C2 inherits from B, which inherits from A, where the line self.x = x occurs. In this line, x is what is entered in the line c2 = C2(3,5) and because it is assigned to self.x, c2's self.x is 3. Because of the line self.y = y in class C2, the instance c2's y value is what is entered in the line c2 = C2(3,5), 5. 4 + 3 + 5 makes 12.

How to make a class act as two element tuple and unpack elements?

Let's say I have a following piece of code
(x1, y1), (x2, y2) = foo()
class Bar:
def __init__(self, x, y):
self.x = x
self.y = y
bar1 = Bar(x1, y1)
bar2 = Bar(x2, y2)
Is there any way to avoid having x1, x2 etc and unpack is directly to Bar instance, e.g. like this:
bar1 = Bar()
bar2 = Bar()
bar1, bar2 = foo()
I would expect some magic method like:
class Bar:
def __init__(self):
self.x = None
self.y = None
def __unpack__(self, x, y):
self.x = x
self.y = y
But there is no such a method (or am I wrong?). How can I accomplish it another way?
Assume that foo is given and I cannot change it to return objects directly.
Here's a way, but it's not particularly readable (I'm fond of tuplify though!)
def tuplify(seq, tuple_len):
"""
Groups elements of sequence to tuples of length tuple_len
"""
return [tuple(el for idx, el in g[1]) for g in itertools.groupby(enumerate(seq), key=lambda x: x[0]//tuple_len)]
bar1, bar2 = (Bar(*tup) for tup in tuplify(foo(), 2)))

SierpinskiTriangle() takes exactly 1 argument (4 given)

I'm trying to initialize sT from an imported module. And getting the error:
sT = SierpinskiTriangle(self.dimensions, 50000, 0.5, vertices)
TypeError: SierpinskiTriangle() takes exactly 1 argument (4 given)
and I'm not really sure why or what I've done wrong.
sT = SierpinskiTriangle(self.dimensions, 50000, 0.5, vertices)
And I've imported this from another file:
class Fractal(Canvas, Point):
def __init__(self, dimensions, num_points, ratio, vertices):
self.dimensions = dimensions
self.num_points = num_points
self.r = ratio
self.vertices = vertices
def frac_x(self, r):
return int((self.dimensions["max_x"] - \
self.dimensions["min_x"]) * r) + \
self.dimensions["min_x"]
def frac_y(self, r):
return int((self.dimensions["max_y"] - \
self.dimensions["min_y"]) * r) + \
self.dimensions["min_y"]
def SierpinskiTriangle(Fractal):
def __init__(self, dimensions, num_points, ratio, vertices):
Fractal.__init__(self, dimensions, num_points, ratio, vertices)
Edit, here's the Point class:
class Point(object):
def __init__(self, x = 0.0, y = 0.0):
self.x = float(x)
self.y = float(y)
#property
def x(self):
return self._x
#x.setter
def x(self, value):
self._x = value
#property
def y(self):
return self._y
#y.setter
def y(self, value):
self._y = value
def dist(self, secondPoint):
#get the self x values from self.x and the values
#of the seecond point from secondPoint.x
#same with y
dist = math.sqrt(((self.x - secondPoint.x)**2)+ ((self.y - secondPoint.y)**2))
return dist
def midpt(self, secondPoint):
#same as the dist
midpointx = (self.x + secondPoint.x)/2
midpointy = (self.y + secondPoint.y)/2
midpoint = Point(midpointx,midpointy)
return midpoint
def __str__(self):
return "({},{})".format(self.x,self.y)
I hope this also helps clarify things. I don't have the Canvas class because it is a part of Tkinter.
You used def instead of class for SierpinskiTriangle which means it only takes one argument (Fractal) instead of treating Fractal as its super class.
Change that to class like below and it will take 4 arguments.
class SierpinskiTriangle(Fractal):
def __init__(self, dimensions, num_points, ratio, vertices):
Fractal.__init__(self, dimensions, num_points, ratio, vertices)

How can I save an instance of a class in it's own class as a class variable in Python?

I'm trying to define a class that has an instance of itself as a class variable so I can reference a common instance of it all over the place.
How can I get something like this to work?
class Point():
ORIGIN = Point()
def __init__(self, x=0, y=0):
self.x = x
self.y = y
p0 = Point.ORIGIN
p1 = Point(3,4)
distance = (p1.x*p1.x + p1.y*p1.y) ** .5
print(distance)
You can add the class attribute after the class has been created:
class Point():
def __init__(self, x=0, y=0):
self.x = x
self.y = y
Point.ORIGIN = Point()
You can probably also make it work so that the origin is created lazily via descriptors, or you can probably do something funky using a metaclass -- but that seems unlikely to be worth your while.
You could use a meta class:
>>> class SingletonMeta(type):
... def __init__(cls, name, bases, dct):
... cls.ORIGIN = cls()
...
>>> class Point(metaclass=SingletonMeta):
... def __init__(self, x=0, y=0):
... self.x = x
... self.y = y
...
>>> p0 = Point.ORIGIN
>>> p1 = Point(3,4)
>>> p0
<__main__.Point object at 0x110b7e7b8>
>>> p0.x, p0.y
(0, 0)
Simply create class variables that represent the values you want instead of encapsulating those values in an instance:
class Point:
x = 0
y = 0
def __init__(self, x=0, y=0):
self.x = x
self.y = y
x,y = Point.x, Point.y
p1 = Point(3,4)
distance = ((p1.x-x)**2 + (p1.y-y)**2) ** .5
print(distance) # prints 5.0
Or, better yet:
class Point:
x = 0
y = 0
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def distance(self, other=None):
if other is None:
x,y = Point.x, Point.y
else:
x,y = other.x, other.y
return ((self.x-x)**2 + (self.y-y)**2) ** .5
And then you can do this:
>>> p1 = Point(3,4)
>>> p1.distance()
5.0
>>> p1.distance(Point(3,5))
1.0

Categories

Resources