Search code examples
pythonclassvariable-assignment

What python Class should I use for my problem?


Short explanation:

I have some coordinates, each has a corresponding label, like so:

[((22, 108), 'A'), ((24, -57), 'A'), ((32, -141), 'B')]

Throughout my task I will need to change the coordinates values (e.g. cartesian to polar) and reorder them (e.g. ascending order of theta), while preserving their labels. What Class of variable should I use?

Long explanation:

In an image I have 16 sets of cartesian coordinates, each has a corresponding label, like so:

[((122, 400), 'A'), ((135, 354), 'A'), ((79, 328), 'A'), ((192, 326), 'A'), ((85, 280), 'A'), ((131, 272), 'A'), ((91, 365), 'B'), ((170, 361), 'B'), ((49, 298), 'B'), ((207, 287), 'B'), ((168, 274), 'B'), ((160, 403), 'C'), ((198, 398), 'C'), ((213, 363), 'C'), ((155, 313), 'C'), ((117, 313), 'C')]

My job is to sort the coordinates so that I end up with a final 16 letter array.

These coordinates map two roughed circles in an image, an outer with 12 set of coordinates, and an inner with 4.

In order to sort them out I cannot directly use X or/and Y, because some sets are too close to each other and in future images they can switch places.

So, I made the center of mass the point (0, 0), and changed the coordinates from cartesian (x,y) to polar (r, theta). Knowing that I will always have 4 points much closer to (0, 0) than the rest, I sorted them in ascending order of 'r' and divided them in 2 arrays, then I sorted both arrays in ascending order of 'theta', like so:

outer_coords = sorted(coords[4:], key=lambda th: th[1])
inner_coords = sorted(coords[:4], key=lambda th: th[1])

All that's left to know is what label each coordinate represents, they should always be in pairs and never separated.

Thank you in advance.

  1. I tried zip() but it is not subscriptable, so it makes it hard to process the coordinates alone.
  2. I thought of never changing the coordinates of the zip, and sort an index and then use the sorted indices to reorder the zipped variable:
    sorted_indices = sorted(range(len(coordinates)), key=lambda i: (coordinates[i][0], coordinates[i][1], labels[i]))
    sorted_zipped_variable = [(coordinates[i], labels[i]) for i in sorted_indices]

Solution

  • I recommend encapsulating your labeled points in objects instead of using generic tuple-of-tuple containers. Then you can more easily define functions to provide sort keys.

    The result would look something like

    import math
    
    class LabeledPoint:
        def __init__(self, coord, label):
            self.coord = coord
            self.label = label
    
        def theta_from(self, center):
            (x0, y0) = center
            (x, y) = self.coord
            return math.atan((x - x0) / (y - y0))
    
    points = [LabeledPoint(coord, label) for (coord, label) in data]
    center = compute_center(points)
    points.sort(key=lambda p: p.theta_from(center))
    print(''.join(point.label for point in points))