【问题标题】:Plot equally spaced markers along a spiral沿螺旋线绘制等距标记
【发布时间】:2017-07-05 03:35:07
【问题描述】:

我想沿着螺旋轨迹移动一个红色星形标记,其圆周上的红色星点之间等距离为 5 个单位,如下图所示。

vertspacing = 10;
horzspacing = 10;
thetamax = 10*pi;
% Calculation of (x,y) - underlying archimedean spiral.
b = vertspacing/2/pi;
theta = 0:0.01:thetamax;
x = b*theta.*cos(theta)+50;
y = b*theta.*sin(theta)+50;

% Calculation of equidistant (xi,yi) points on spiral.
smax = 0.5*b*thetamax.*thetamax;
s = 0:horzspacing:smax;
thetai = sqrt(2*s/b);
xi = b*thetai.*cos(thetai);
yi = b*thetai.*sin(thetai);
plot(x,y,'b-');
hold on

我想得到如下图:

这是我的圆轨迹代码:

% Initialization steps.
format long g;
format compact;
fontSize = 20;
r1 = 50;
r2 = 35;
r3=  20;
xc = 50;
yc = 50;
% Since arclength = radius * (angle in radians),
% (angle in radians) = arclength / radius = 5 / radius.
deltaAngle1 = 5 / r1;
deltaAngle2 = 5 / r2;
deltaAngle3 = 5 / r3;
theta1 = 0 : deltaAngle1 : (2 * pi);
theta2 = 0 : deltaAngle2 : (2 * pi);
theta3 = 0 : deltaAngle3 : (2 * pi);
x1 = r1*cos(theta1) + xc;
y1 = r1*sin(theta1) + yc;
x2 = r2*cos(theta2) + xc;
y2 = r2*sin(theta2) + yc;
x3 = r3*cos(theta3) + xc;
y3 = r3*sin(theta3) + yc;
plot(x1,y1,'color',[1 0.5 0])
hold on
plot(x2,y2,'color',[1 0.5 0])
hold on
plot(x3,y3,'color',[1 0.5 0])
hold on

% Connecting Line:
plot([70 100], [50 50],'color',[1 0.5 0])
% Set up figure properties:
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0, 0, 1, 1]);
drawnow;
axis square;
for i = 1 : length(theta1)
    plot(x1(i),y1(i),'r*')
    pause(0.1)
end
for i = 1 : length(theta2)
    plot(x2(i),y2(i),'r*')
    pause(0.1)
end
for i = 1 : length(theta3)
    plot(x3(i),y3(i),'r*')    
    pause(0.1)
end

【问题讨论】:

  • 你试过什么?你有螺旋路径的数据/代码吗?
  • 嗨 zein,欢迎来到 SO。请查看此内容以改善您的问题:stackoverflow.com/help/how-to-ask
  • 我想在 SPIRAL 轨迹上移动一个星形标记,如下面的代码,红色星形标记移动一个圆形轨迹我不知道如何编写它的代码。 dropbox.com/s/tr8dyutzie72rr4/Circle%20trajectory.txt?dl=0
  • 感谢您的帮助。
  • @zein - 当您说“距离为 5”时,您是指平面(即 dx^2+dy^2==5)还是“沿螺旋”?

标签: matlab plot geometry coordinates spiral


【解决方案1】:

我想不出一种方法来计算沿螺旋的距离,所以我用圆圈来近似它,希望它仍然有用。

我的解决方案依赖于 FEX 的 InterX 函数,以找到圆与螺旋的交点。我提供了一个动画,这样更容易理解。

代码(在 R2017a 上测试):

function [x,y,xi,yi] = q44916610(doPlot)
%% Input handling:
if nargin < 1 || isempty(doPlot)
  doPlot = false;
end
%% Initialization:
origin = [50,50];
vertspacing = 10;
thetamax = 5*(2*pi);
%% Calculation of (x,y) - underlying archimedean spiral.
b = vertspacing/(2*pi);
theta = 0:0.01:thetamax;
x = b*theta.*cos(theta) + origin(1);
y = b*theta.*sin(theta) + origin(2);
%% Calculation of equidistant (xi,yi) points on spiral.
DST = 5; cRes = 360; 
numPts = ceil(vertspacing*thetamax); % Preallocation
[xi,yi] = deal(NaN(numPts,1));

if doPlot && isHG2() % Plots are only enabled if the MATLAB version is new enough.
  figure(); plot(x,y,'b-'); hold on; axis equal; grid on; grid minor;
  hAx = gca; hAx.XLim = [-5 105]; hAx.YLim = [-5 105];
  hP = plot(xi,yi,'r*');
else
  hP = struct('XData',xi,'YData',yi);
end
hP.XData(1) = origin(1); hP.YData(1) = origin(2);
for ind = 2:numPts
  P = InterX([x;y], makeCircle([hP.XData(ind-1),hP.YData(ind-1)],DST/2,cRes));  
  [~,I] = max(abs(P(1,:)-origin(1)+1i*(P(2,:)-origin(2))));
  if doPlot, pause(0.1); end
  hP.XData(ind) = P(1,I); hP.YData(ind) = P(2,I);
  if doPlot, pause(0.1); delete(hAx.Children(1)); end
end
xi = hP.XData(~isnan(hP.XData)); yi = hP.YData(~isnan(hP.YData));

%% Nested function(s):
function [XY] = makeCircle(cnt, R, nPts)
  P = (cnt(1)+1i*cnt(2))+R*exp(linspace(0,1,nPts)*pi*2i);
  if doPlot, plot(P,'Color',lines(1)); end
  XY = [real(P); imag(P)];
end

end

%% Local function(s):
function tf = isHG2()
  try
    tf = ~verLessThan('MATLAB', '8.4');
  catch
    tf = false;
  end
end

function P = InterX(L1,varargin)
    % DOCUMENTATION REMOVED. For a full version go to:
    % https://www.mathworks.com/matlabcentral/fileexchange/22441-curve-intersections

    narginchk(1,2);
    if nargin == 1
        L2 = L1;    hF = @lt;   %...Avoid the inclusion of common points
    else
        L2 = varargin{1}; hF = @le;
    end

    %...Preliminary stuff
    x1  = L1(1,:)';  x2 = L2(1,:);
    y1  = L1(2,:)';  y2 = L2(2,:);
    dx1 = diff(x1); dy1 = diff(y1);
    dx2 = diff(x2); dy2 = diff(y2);

    %...Determine 'signed distances'   
    S1 = dx1.*y1(1:end-1) - dy1.*x1(1:end-1);
    S2 = dx2.*y2(1:end-1) - dy2.*x2(1:end-1);

    C1 = feval(hF,D(bsxfun(@times,dx1,y2)-bsxfun(@times,dy1,x2),S1),0);
    C2 = feval(hF,D((bsxfun(@times,y1,dx2)-bsxfun(@times,x1,dy2))',S2'),0)';

    %...Obtain the segments where an intersection is expected
    [i,j] = find(C1 & C2); 
    if isempty(i), P = zeros(2,0); return; end

    %...Transpose and prepare for output
    i=i'; dx2=dx2'; dy2=dy2'; S2 = S2';
    L = dy2(j).*dx1(i) - dy1(i).*dx2(j);
    i = i(L~=0); j=j(L~=0); L=L(L~=0);  %...Avoid divisions by 0

    %...Solve system of eqs to get the common points
    P = unique([dx2(j).*S1(i) - dx1(i).*S2(j), ...
                dy2(j).*S1(i) - dy1(i).*S2(j)]./[L L],'rows')';

    function u = D(x,y)
        u = bsxfun(@minus,x(:,1:end-1),y).*bsxfun(@minus,x(:,2:end),y);
    end
end

结果:

请注意,在上面的动画中,圆的直径(以及红点之间的距离)是 10 而不是 5。

【讨论】:

  • 感谢您的回答,亲爱的 Dev-iL,但我希望红色星形标记沿着类似于我在问题末尾添加的圆形轨迹的螺旋轨迹移动(遍历)。我不知道怎么做。我还希望图形圆周上星点之间的距离等于5个单位。
  • 谢谢,不幸的是,它不起作用,只显示第一个图并显示以下错误:警告:结构字段赋值用“double”类覆盖值。有关详细信息,请参阅 MATLAB R14SP2 发行说明,将非结构变量分配为结构显示警告。 'double' 类型的输入参数的未定义函数 'InterX'。 q44916610 中的错误(第 22 行) P = InterX([x;y], makeCircle([hP.XData(ind-1),hP.YData(ind-1)],DST/2,cRes));
  • @zein 我对代码进行了一些更改,使其更有可能在较旧的 MATLAB 版本上运行 - 现在试一试。
  • 谢谢,我在 2016 a 和 2013 a 上都运行过,你的新代码没有错误,但它只显示命令窗口中的坐标,但没有显示数字。
  • @zein 您应该收集输出(例如[x1,y1,x2,y2] = q44916610()),然后根据您的喜好自行绘制它们。函数内的绘图是动画的,这将无缘无故地花费额外的时间。
猜你喜欢
  • 1970-01-01
  • 2019-05-02
  • 2018-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-20
  • 2016-04-13
  • 2023-03-28
相关资源
最近更新 更多