Простое решение - пройтись по краю многоугольника. При заданном текущем ребре на границе, соединяющей точки P0 и P1, следующей точкой на границе P2 будет точка с наименьшим возможным A, где
H01 = bearing from P0 to P1
H12 = bearing from P1 to P2
A = fmod( H12-H01+360, 360 )
|P2-P1| <= MaxEdgeLength
Тогда вы установите
P0 <- P1
P1 <- P2
и повторяйте, пока не вернетесь к тому, с чего начали.
Это все еще O (N ^ 2), так что вы захотите немного отсортировать список точек. Вы можете ограничить набор точек, которые необходимо учитывать на каждой итерации, если вы сортируете точки, скажем, по их отношению к центроиду города.