【问题标题】:How to order points anti clockwise如何逆时针排列点
【发布时间】:2011-10-06 11:16:55
【问题描述】:

让我们拿分吧。

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}}]

但我们需要像下图那样订购它们。

有没有人建议一种算法以逆时针方向对此类二维点进行排序,以便我们可以重新排列点列表以创建像最后一张图片一样的几何图形,只需在重新排列的点上使用ListLinePlot? ?

使用 suggestion 我们会得到如下结果。

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

【问题讨论】:

  • "顺时针"需要一个中心和一个空间方向......问题是中心......
  • 请允许我提醒一下我们通常在这里做的三件事:1) 当您获得帮助时,请尝试在您的专业领域回答问题 2) Read the FAQs 3) 当你看到好的问答时,给他们投票using the gray triangles,因为系统的可信度是基于用户通过分享他们的知识而获得的声誉。还记得接受更好地解决您的问题的答案,如果有的话,by pressing the checkmark sign
  • 谢谢@belisarius,我会尽力遵循建议。顺便说一句,您认为FindShortestTour 的答案对一般凹点簇有效吗?
  • 没有,但我认为您不会找到通用解决方案

标签: sorting wolfram-mathematica


【解决方案1】:

我在您的问题下方发表了以下评论: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】:

    也许你可以用FindShortestTour 做点什么。例如

    ptsorted = pt[[FindShortestTour[pt][[2]]]];
    ListPlot[ptsorted, Joined -> True, Frame -> True, PlotMarkers -> Automatic]
    

    产生类似的东西

    【讨论】:

      【解决方案3】:

      你为什么不把分数排序?:

      center = Mean[pt];
      pts = SortBy[pt, Function[p, {x, y} = p - center; ArcTan[x, y]]]
      Show[ListPlot[pt], ListPlot[pts, Joined -> True]]
      

      请注意,您最后一个图中的多边形是凹的,所以这些点不是顺时针排列的!

      【讨论】:

      • 排序后仍然不是我想要的阵型。这不像我帖子的最后一张照片。不过谢谢你的回答。
      • @PlatoManiac:这就是我用最后一句话试图告诉你的:你展示的情节是不是顺时针的。你想要什么样的订单?你需要这个做什么?
      • 查看这一点,只需取最右边的点,然后按逆时针方向而不是顺时针方向排列其余点,然后回到最右边的点。这通过从最右边的点开始并在同一点结束来形成一个闭环。我需要为 2D 翼型订购此点。 enda1312.files.wordpress.com/2011/03/airfoil.gif
      • @PlatoManiac:你想要的多边形是凹的。它有拐点。有的地方是顺时针,有的地方是逆时针。
      • 你完全正确。实际上,似乎没有针对此问题的通用解决方案。有时您的解决方案可能有效,有时无效。
      【解决方案4】:

      我刚刚在nikie's answer 的评论中读到,您真正想要的是翼型算法。所以,我发布了另一个(不相关的)这个问题的答案:

      似乎比一般问题更容易,因为它“几乎是凸的”。我认为以下算法降低了 FindShortestTour 在急性顶点固有的风险:

      1. 找到ConvexHull(占上层和攻击面)
      2. 从集合中删除凸包中的点
      3. 对剩余点执行FindShortestTour
      4. 在最近的端点处加入两条曲线

      像这样:

      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}]
      

      【讨论】:

        【解决方案5】:

        这是一个逆时针排列点的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
        

        【讨论】:

          猜你喜欢
          • 2012-08-09
          • 1970-01-01
          • 2021-11-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-12-31
          • 2012-12-11
          • 1970-01-01
          相关资源
          最近更新 更多