1

I want to rewrite my code from structural form to object. This script contains two classes: Point which contains x and y of point, and Curve with list of Points. I need to get this list of Points in the right order, because I want to draw this. The code worked in structural form, so there is only problem with classes. There is the most important piece of code:

# -*- coding: utf-8 -*-
__author__ = 'Piotr Michalski University of Wroclaw'
from turtle import *
import random
import math

def binomial(i, n):
    """Newton"""
    return math.factorial(n) / float(
        math.factorial(i) * math.factorial(n - i))

def bernstein(t, i, n):
    """Bernstein"""
    return binomial(i, n) * (t ** i) * ((1 - t) ** (n - i))

def bezier(t, points):
    """Calculating coordinates of bezier curve"""
    n = len(points) - 1
    x = y = 0
    for i, pos in enumerate(points):
        bern = bernstein(t, i, n)
        x += pos[0] * bern
        y += pos[1] * bern
    return x, y

def bezier_curve_range(n, points):
    """Amount of points on bezier curve"""
    for i in range(n):
        t = i / float(n - 1)
        yield bezier(t, points)

def init():
    """Screen, turtle etc"""
    global tur, screen, litery, krzywe
    tur = Turtle()
    screen = Screen()
    screen.title('Generowanie tekstu')
    screen.setup(width=1400, height=400, startx=20, starty=200)
    screen.setworldcoordinates(0,400,1400,-150)
    tur.hideturtle()

def calculatespace(x):
    """Changing max x during drawing curve"""
    global max_x
    if x > max_x:
        max_x = x

def paint_event(ksztalt, steps=80, colorofdot='lightblue', colorofbezier='black',
                colorofguideline='lightgray'):
    """Drawing function"""
    global tur, screen
    print('Zainicjowano rysowanie {0}.\nIlość kroków'
          ' {1}'.format(ksztalt,steps))

        #No i rysujemy

    controlPoints = ksztalt
    oldPoint = controlPoints[0]

    tur.pen(pensize=1, pencolor=colorofdot)
    tur.up()
    tur.goto(oldPoint[0], oldPoint[1])
    tur.down()
    tur.dot()
    tur.up()

    for point in controlPoints[1:]:
        tur.pen(pencolor=colorofguideline, speed=3)
        tur.goto(oldPoint[0], oldPoint[1])
        tur.down()
        tur.goto(point[0], point[1])
        tur.pen(pencolor=colorofdot)
        tur.dot()
        tur.up()
        oldPoint = point

    tur.pen(pensize= 2,pencolor=colorofbezier,speed=0)
    oldPoint=ksztalt[0]

    for point in bezier_curve_range(steps, controlPoints):
        tur.goto(oldPoint[0], oldPoint[1])
        tur.down()
        tur.goto(point[0], point[1])
        tur.up
        calculatespace(point[0])
        oldPoint = point

class point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __str__(self):
        return str((self.x,self.y))
    def __repr__(self):
        return repr((self.x,self.y))

class curve:
    def __init__(self, *points):
        self.ListOfPoints = []
        for p in points:
            self.ListOfPoints.append(p)
    def __str__(self):
        return str(self.ListOfPoints)
    def __repr__(self):
        return repr(self.ListOfPoints)
    def __iter__(self):
        return iter(self.ListOfPoints)

p1 = point(10, 20)
p2 = point(5, 15)
p3 = point(70, 100)

k1 = curve(p1, p2, p3)
print(enumerate(k1))
init()
paint_event(k1)

I have this error:

print(enumerate(k1))
TypeError: 'curve' object is not iterable
2
  • Why write a curve class when it doesn't do anything? Can't you just keep the points in an ordinary list? Commented Feb 9, 2016 at 14:16
  • This code will be using for drawing handwrite-like letters. So in the next step I will write class "letter" which will contain curves with certain parameter Commented Feb 9, 2016 at 14:21

1 Answer 1

1

I would just use an ordinary list:

k1 = [p1,p2]
print(enumerate(k1))

... But if you're really dead-set on making your own collection class, implement an __iter__ method.

class curve:
    def __init__(self, *points):
        self.ListOfPoints = []
        for p in points:
            self.ListOfPoints.append(p)
    def __str__(self):
        return str(self.ListOfPoints)
    def __repr__(self):
        return repr(self.ListOfPoints)
    def __iter__(self):
        return iter(self.ListOfPoints)

From your edited code, it looks like you're now getting TypeError: 'curve' object does not support indexing, I want to emphasize again that there's no reason to make your own class if you're just going to treat it exactly like a list. But if you're really super committed to the idea of creating extra work for yourself with no benefit, then implement __getitem__.

class curve:
    def __init__(self, *points):
        self.ListOfPoints = []
        for p in points:
            self.ListOfPoints.append(p)
    def __str__(self):
        return str(self.ListOfPoints)
    def __repr__(self):
        return repr(self.ListOfPoints)
    def __iter__(self):
        return iter(self.ListOfPoints)
    def __getitem__(self, key):
        return self.ListOfPoints[key]

You may have to implement some other methods, such as __len__, but at this point I think you can figure out how that ought to be done.

Sign up to request clarification or add additional context in comments.

2 Comments

Are you still getting the same error? When I run your code as it exists now, I don't get TypeError: 'curve' object is not iterable
Now I get TypeError: 'curve' object does not support indexing Parameter "ksztalt" need to get list of tuples which cointain coordinates.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.