Algorithm 确定线段的方向是顺时针还是逆时针

Algorithm 确定线段的方向是顺时针还是逆时针,algorithm,matlab,math,geometry,Algorithm,Matlab,Math,Geometry,我有一个代表曲线段的2D点列表(x1,y1),(x2,y2)…(Xn,Yn),是否有公式确定绘制该段的方向是顺时针还是逆时针 任何帮助都是非常感谢的一种可能的方法。如果点列表所代表的线的采样足够均匀和平滑,并且线足够简单,那么它应该工作得相当好 减去平均值,使线居中 转换为极坐标以获取角度 展开角度,以确保其增量有意义 检查总增量是正增量还是负增量 我假设你有x和y向量中的数据 theta = cart2pol(x-mean(x), y-mean(y)); %// steps 1 and 2 t

我有一个代表曲线段的2D点列表(x1,y1),(x2,y2)…(Xn,Yn),是否有公式确定绘制该段的方向是顺时针还是逆时针


任何帮助都是非常感谢的

一种可能的方法。如果点列表所代表的线的采样足够均匀和平滑,并且线足够简单,那么它应该工作得相当好

  • 减去平均值,使线居中
  • 转换为极坐标以获取角度
  • 展开角度,以确保其增量有意义
  • 检查总增量是正增量还是负增量
  • 我假设你有
    x
    y
    向量中的数据

    theta = cart2pol(x-mean(x), y-mean(y)); %// steps 1 and 2
    theta = unwrap(theta); %// step 3
    clockwise = theta(end)<theta(1); %// step 4. Gives 1 if CW, 0 if ACW
    
    theta=cart2pol(x-均值(x),y-均值(y));%//步骤1和2
    θ=展开(θ);%//步骤3
    
    顺时针=θ(结束)或者,您可以使用一点线性代数。如果您有三个点a、b和c,请按顺序执行以下操作:

     1)  create the vectors u = (b-a) = (b.x-a.x,b.y-a.y) and v = (c-b) ...
     2) calculate the cross product uxv = u.x*v.y-u.y*v.x
     3) if uxv is -ve then a-b-c is curving in clockwise direction (and vice-versa).
    

    通过以相同的方式沿着较长的曲线,您甚至可以检测“s”形曲线何时从顺时针方向变为逆时针方向(如果有用的话)

    这是我的方法,正如在对问题的评论中提到的-

    另一种方法:从起点到终点画一条线。这条线实际上是一个向量。CW曲线的大部分部分位于该直线的右侧。《特定常规武器公约》,左

    我编写了一个示例代码来阐述这个想法。大部分解释可以在代码中的注释中找到

    clear;clc;close all
    
    %% draw a spiral curve
    N = 30;
    theta = linspace(0,pi/2,N); % a CCW curve
    rho = linspace(1,.5,N);
    [x,y] = pol2cart(theta,rho);
    clearvars theta rho N
    
    plot(x,y);
    hold on
    
    %% find "the vector"
    vec(:,:,1) = [x(1), y(1); x(end), y(end)]; % "the vector"
    
    scatter(x(1),y(1), 200,'s','r','fill') % square is the starting point
    scatter(x(end),y(end), 200,'^','r','fill') % triangle is the ending point
    line(vec(:,1,1), vec(:,2,1), 'LineStyle', '-', 'Color', 'r')
    
    %% find center of mass
    com = [mean(x), mean(y)]; % center of mass
    
    vec(:,:,2) = [x(1), y(1); com]; % secondary vector (start -> com)
    
    scatter(com(1), com(2), 200,'d','k','fill') % diamond is the com
    line(vec(:,1,2), vec(:,2,2), 'LineStyle', '-', 'Color', 'k')
    
    %% find rotation angle
    dif = diff(vec,1,1);
    [ang, ~] = cart2pol(reshape(dif(1,1,:),1,[]), reshape(dif(1,2,:),1,[]));
    clearvars dif
    
    % now you can tell the answer by the rotation angle
    if ( diff(ang)>0 )
        disp('CW!')
    else
        disp('CCW!')
    end
    

    通过比较两个向量,即旋转向量[起点->质心]与向量[起点->终点],然后将旋转角度与0进行比较,始终可以判断点位于定向线(向量)的哪一侧。几秒钟的头脑动画可以帮助理解

    一个线段如何具有顺时针/逆时针方向?确切的定义是什么?该段是手写阿拉伯语的一个弯曲部分character@LuisMendo-好的,我明白了。你可以做的一件事就是给定曲线,找到它的重心。完成此操作后,找到曲线上每个点与该质心的夹角。之后,使用
    diff
    查看点之间的相邻差异。如果此输出向量中每个元素的
    diff
    元素为正,则可将其视为顺时针方向,如果为负,则可将其视为逆时针方向。也许做一个正、负事件的柱状图,无论哪个箱子的计数更高,这就是方向chosen@rayryeng我认为可以通过展开相位来消除您提到的模糊性(前提是由点表示的采样足够精细)。这就是我在回答中所做的。@LuisMendo-正确。忘记了
    展开
    。好地方!是的。。。这几乎就是我写的建议方法!很不错的。我决定把所有的差异都分类,看看哪个符号的计数更高,我会选择那个。这仍然是一个很好的方法。路易斯,我试过你的方法,效果很好:)谢谢你的帮助@rayryeng非常感谢你的帮助谢谢too@LuisMendo-我喜欢这篇文章,主要是因为不同的SO用户(Yvon,你和我)之间的合作,最终得出了一个对OP有效的答案。谢谢@艾哈迈达博巴克-非常欢迎你。很高兴我们能帮你解决这个问题@路易斯门多-那根本没问题。老实说,我不确定我的方法是否有效。看到你发布了一个答案,OP接受了,这证实了我的想法是有效的。声誉积分只是次要的。我来这里主要是为了帮助人们,这篇文章和合作就是对这一点的证明。对我来说,这是迄今为止最好的解决方案+1@seb-没关系。我误读了算法。我要删除我的评论,因为这是胡说八道。@Penguino:我有N个点,我尝试了你的方法,但因为我有N个点,我对每两个连续的微分向量的叉积的结果进行了求和,对吗?@ahmed:是的,做一些类似x1=diff(x)y1=diff(y)的事情,那么x1的所有连续元素的X积y1@ahmed是的,如果曲线沿其整个长度是局部顺时针的,那么你会得到所有的横积,所以求和是可以的。但是,如果曲线在其整个长度上具有相同的曲率方向,则只需在前三个点上进行测试即可节省时间。这不是无用的+1从我这里。。。大约22分钟后。我已经达到了今天的最高票数。