0

I'm struggling to understand following code snippet:

@metric
def area(prev, nxt):
    """Area of a polygon with points in clockwise order."""
    return area_piece(prev, nxt) / 2

def centroid(points):
    a = area(points)
    return [center_x_helper(points)/a, center_y_helper(points)/a]

@metric
def center_x_helper(prev, nxt):
    return (prev[0] + nxt[0]) * area_piece(prev, nxt) / 6

@metric
def center_y_helper(prev, nxt):
    return (prev[1] + nxt[1]) * area_piece(prev, nxt) / 6

def area_piece(prev, nxt):
    return nxt[0] * prev[1] - prev[0] * nxt[1]

The full code is located here.

I assume that points is some kind of 2D array/list, where each item contains a pair of X- and Y-coordinates. Somehow though, points is passed to area(prev, nxt) to perform the calculations on each pair of coordinates.

When I try one of following

centroid([[150, 200], [0, 300], [0, 400], [3, 1]])

centroid([150, 200, 0, 300, 0, 400, 3, 1])

I get this error:

TypeError: area() missing 1 required positional argument: 'nxt'

Am I missing something here or is this code simply not runnable this way?

5
  • The arrays you used, what kind were they. Length shape etc..? Commented Jan 26, 2017 at 10:53
  • @ljetibo exemplary method calls added with last edit Commented Jan 26, 2017 at 11:33
  • @ljetibo so @metric is defined by the function def metric(function) and is executed each time before the "annotated" (decorated?) function itself is executed? and the annotated function then receives the return-value of metric(function) as parameter(s)? Commented Jan 26, 2017 at 13:56
  • That's usually how decorators work, they take in a function, do something and then call the function. They return a function so that when you start the program the function you decorated gets "replaced" with this new function of the same name but that also does something before the original function is called. see this Commented Jan 26, 2017 at 14:38
  • Well, that's something I did not know before. Now I think, I will be able to understand the entire code. If you write an answer, I will accept it. Thanks! Commented Jan 26, 2017 at 19:59

2 Answers 2

1

The issue you're having, I believe, is not sending the list in correct format.

I don't know in the full code where the shape comes from. What happens when centroid is called is that area is called. But before area is actually executed decorator metric is called (line 77 in the original code). metric then re-arranges the input lists (line 85, 86) called points and then calls the original function area on those re-arranged lists.

Except metric doesn't act on "points" and works with something called shape the definition of which I can't find but has to be somewhere in the original code. There's a lot of methods shape has that aren't a part of list, for example .points, .parts, .tolist etc...

For area you need to send two "points" which seem to be just lists of length 2 as in: area([1,2], [4,5]). I base this on his docstring text function should take two points (each lists of length 2) and return some....

But because of the decorator you can also call the function area with shape. This is because before anything is done, metric is called and shape is re-arranged so that area is called on just two "points". So what you need to do is find what shape is and then call centroid with that. I'm not willing to dig deeper to find what exactly shape is or how to get the code working properly, so if anyone else pulls the code and tests it you need to accept his answer.

Additionally, the way you can think about how decorators usually is that they take in a function, maybe do something before, then call the function, and then maybe do something after it. They return a function so that when you start the program the function you decorated gets "replaced" with this new function of the same name but that also maybe does something else/different. See this for more on decorators.

For posterity - this was in the comments and was edited a bit to fit the form of an answer after which comments were deleted. Also I like points.

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

Comments

0

Your function area(prev, nxt) takes two arguments, however in your centroid(points) function, you assign a variable a to be the result of of your area(prev, nxt) function, but you're only passing it one argument, namely points.

def centroid(points):
    a = area(points, secondArgumentNeedsToGoHere)

1 Comment

You're not completely correct as the function area has a decorator that will call it with two arguments.

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.