让我们拿点数。
pt={{-4.65371,0.1},{-4.68489,0.103169},{-4.78341,0.104834},{-4.83897,0.100757},
{-4.92102,0.0949725},{-4.93456,0.100181},{-4.89166,0.122666},{-4.78298,0.129514},
{-4.72723,0.121442},{-4.68355,0.11023},{-4.65371,0.1},{-4.66924,0.10173},
{-4.93059,0.0966989},{-4.93259,0.105094},{-4.91074,0.116966},{-4.90635,0.094878},
{-4.66846,0.105327},{-4.92647,0.0956182},{-4.93433,0.102498},{-4.9333,0.0982262},
{-4.66257,0.10102}};
现在他们按照一定的顺序(对我来说是一种疾病!),如果我们看一下ListLinePLot
picUnorder=ListLinePlot[pt,Frame-> True,Mesh-> All,MeshStyle-> PointSize[Large]];
SeepicUnorder=ListLinePlot[pt,Frame-> True,Mesh-> All,MeshStyle->
PointSize[Large]]/.Line[rest_]:>{Arrowheads[Table[0.02,{i,0,1,.02}]],Arrow[rest]};
GraphicsGrid[{{picUnorder,SeepicUnorder}}]
但是我们需要像下图那样订购它们。
是否有人建议使用算法对逆时针方向的2D点进行排序,以便我们可以重新排列点列表,只需在重新排列的点上使用ListLinePlot
来创建像最后一张图片一样的几何图形? ???
使用建议,我们会得到以下内容。
center=Mean[pt];
pts=SortBy[pt,Function[p,{x,y}=p-center;ArcTan[x,y]]];
Show[ListPlot[pt],ListLinePlot[pts,Mesh-> All,MeshStyle->
PointSize[Large]],Frame-> True]
BR
答案 0 :(得分:10)
也许你可以用FindShortestTour
做点什么。例如
ptsorted = pt[[FindShortestTour[pt][[2]]]];
ListPlot[ptsorted, Joined -> True, Frame -> True, PlotMarkers -> Automatic]
产生类似
的东西
答案 1 :(得分:10)
我在您的问题下方发布了以下评论:I don't think you'll find a general solution
。这个答案试图挖掘一点。
Heike的解决方案似乎公平,但FindShortestTour
基于集合的度量属性,而您的要求可能更多地位于拓扑方面。
以下是两个点集和FindShortestTour
可用方法的比较:
pl[method_, k_] :=
Module[{ptsorted, pt,s},
little[x_] := {{1, 0}, {2, 1}, {1, 2}, {0, 1}}/x - (1/x) + 2;
pt = Join[{{0, 0}, {4, 4}, {4, 0}, {0, 4}}, little[k]];
ptsorted = Join[s = pt[[FindShortestTour[pt,Method->method][[2]]]], {s[[1]]}];
ListPlot[ptsorted, Joined -> True, Frame -> True,
PlotMarkers -> Automatic,
PlotRange -> {{-1, 5}, {-1, 5}},
Axes -> False, AspectRatio -> 1, PlotLabel -> method]];
GraphicsGrid@
Table[pl[i, j],
{i, {"AllTours", "CCA", "Greedy", "GreedyCycle",
"IntegerLinearProgramming", "OrOpt", "OrZweig", "RemoveCrossings",
"SpaceFillingCurve", "SimulatedAnnealing", "TwoOpt"}},
{j, {1, 1.8}}]
正如您所看到的,有几种方法可以在左列上传递预期结果,而只有一种方法在右侧列上传递预期结果。此外,对于右侧的集合,唯一有用的方法是完全关闭左侧的列。
答案 2 :(得分:9)
为什么不对点进行排序?:
center = Mean[pt];
pts = SortBy[pt, Function[p, {x, y} = p - center; ArcTan[x, y]]]
Show[ListPlot[pt], ListPlot[pts, Joined -> True]]
请注意,最后一个绘图中的多边形是凹的,因此这些点不是顺时针排序的!
答案 3 :(得分:4)
我刚刚在nikie's answer的评论中读到你真正想要的是翼型的算法。所以,我发布了另一个(不相关的)这个问题的答案:
似乎比一般问题更容易,因为它“几乎凸出”。我认为以下算法可以降低FindShortestTour在锐角顶点固有的风险:
- 找到
ConvexHull
(占上层和攻击面)- 从集合中移除凸包中的点
- 使用余下的分数执行
FindShortestTour
- 将两条曲线连接到最近的端点
- Voilà
醇>
像这样:
pt1 = Union@pt;
<< ComputationalGeometry`
convexhull = ConvexHull[pt1, AllPoints -> True];
pt2 = pt1[[convexhull]];
pt3 = Complement[pt1, pt2];
pt4 = pt3[[(FindShortestTour@pt3)[[2]]]];
If[Norm[Last@pt4 - First@pt2] > Norm[Last@pt4 - Last@pt2], pt4 = Reverse@pt4];
pt5 = Join[pt4, pt2, {pt4[[1]]}];
Graphics[{Arrowheads[.02], Arrow@Partition[pt5, 2, 1],
Red, PointSize[Medium], Point@pt1}]
答案 4 :(得分:-1)
这是一个python函数,它逆时针命令点。它是格雷厄姆的扫描定理。我写这篇文章是因为我误解了家庭作业。但它需要优化。
def order(a):
from math import atan2
arctangents=[]
arctangentsandpoints=[]
arctangentsoriginalsandpoints=[]
arctangentoriginals=[]
centerx=0
centery=0
sortedlist=[]
firstpoint=[]
k=len(a)
for i in a:
x,y=i[0],i[1]
centerx+=float(x)/float(k)
centery+=float(y)/float(k)
for i in a:
x,y=i[0],i[1]
arctangentsandpoints+=[[i,atan2(y-centery,x-centerx)]]
arctangents+=[atan2(y-centery,x-centerx)]
arctangentsoriginalsandpoints+=[[i,atan2(y,x)]]
arctangentoriginals+=[atan2(y,x)]
arctangents=sorted(arctangents)
arctangentoriginals=sorted(arctangentoriginals)
for i in arctangents:
for c in arctangentsandpoints:
if i==c[1]:
sortedlist+=[c[0]]
for i in arctangentsoriginalsandpoints:
if arctangentoriginals[0]==i[1]:
firstpoint=i[0]
z=sortedlist.index(firstpoint)
m=sortedlist[:z]
sortedlist=sortedlist[z:]
sortedlist.extend(m)
return sortedlist