Here's an idea that will give okay-ish results if your point cloud is already ring-shaped like your example:
- Determine a centre point; this can either be the centre of gravity of all points or the centre of the bounding box.
- Represent all points in radial coordinates (radius, angle) with reference to the centre
- Sort by angle
This will, of course, produce jagged stars for random clouds, but it is not clear, what exactly a "ring" is. You could probably use this as a first draft and start swapping nodes if that gives you a shorter overall distance. Maybe this simple code is all you need short of implementing the minimum distance over all nodes of a graph.
Anayway, here goes:
import math
points = [(0, 4), (2, 2), ...] # original points in Cartesian coords
radial = [] # list of tuples(index, angle)
# find centre point (centre of gravity)
x0, y0 = 0, 0
for x, y in points:
x0 += x
y0 += y
x0 = 1.0 * x0 / len(points)
y0 = 1.0 * y0 / len(points)
# calculate angles
for i, p in enumerate(points):
x, y = p
phi = math.atan2(y - y0, x - x0)
radial += [(i, phi)]
# sort by angle
def rsort(a, b):
"""Sorting criterion for angles"""
return cmp(a[1], b[1])
radial.sort(rsort)
# extract indices
ring = [a[0] for a in radial]
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…