使粒子在圆内随机移动 [英] Making Particles Move Randomly Within A Circle

查看:81
本文介绍了使粒子在圆内随机移动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使绘制的点在已知半径和中心的圆内移动.目前,我可以在边界内生成点,但是现在需要使它们移动.

I am attempting to make plotted points move around within a circle of a known radius and center. At the moment I am able to generate points within the boundary, but now I need to make them move.

我有以下脚本来生成粒子的初始位置.

I have the following script to generate the initial locations of the particles.

function [particle_gen] = generate(n,centre,radius)
    %generates n particles in a circle with specified centre and radius

    angle = 2 * pi * rand(n,1);
    r = radius * sqrt(rand(n,1));
    X = r.*cos(angle) + centre(1);
    Y = r.*sin(angle) + centre(2);
    plot(X,Y,'.k')
end

我想给它们设置动画,以便粒子以恒定的速度沿直线传播,直到它们撞到圆形边界并弹起.我需要所有这些都在同一个情节中发生.

I want to animate them so that the particles travel in a straight line at a constant velocity until they hit the circular boundary and bounce off. I need this to all happen within the same plot.

推荐答案

好的,因此,我将单独解决这个问题.

Ok so there are a few facets to this question that I'm going to address separately.

就创建图并更新图的值而言,您可以使用返回处理图以更新图.

As far as the logistics of creating a plot and updating the values of the plot, you can do all of this using MATLAB's handle graphics. If you create a plot object, you can use the returned handle to the plot to update the plot.

plt = plot(x, y, 'k.');
set(plt, 'XData', newx, 'YData', newy)

在您的情况下,将循环计算newxnewy值,然后可以对其进行分配.这样一来,您就不会不断创建新的图形对象,而使用MATLAB可能会变得非常昂贵.

In your case, the newx and newy values will be computed in a loop and then you can assign them. By doing this, you won't constantly be creating new graphics objects which can get very expensive with MATLAB.

由于您要进行大量计算,因此您还需要使用

Since you're doing a lot of computation, you'll also want to use drawnow each time through your loop to force MATLAB to render the graphics.

您将需要计算用于更新绘图的xnewynew值.您可以通过多种方法来确定这些轨迹,但是我在这里提出了一种方法来确定这些轨迹.

You will need to compute the xnew and ynew values that you are going to update your plot with. There are a number of ways that you could determine these trajectories, but I have presented one way to do that here.

  1. 应用位移.使用速度和方向,可以将位移应用于每个粒子.
  2. 确定点是否在圆之外.如果位移将点放置在圆的外部(基本公式此处),那么我们需要将其重新放回圆中.如果圆外没有任何点,则返回步骤1.
  3. 对于圆外的每个点,找到其路径与圆的交点.使用此解决方案作为参考,这是一个非常简单的练习.
  4. 在此点找到圆的切线.同样,这很简单,因为我们可以从圆心到圆上的交点画一条线.此线的斜率的负逆是切线相对于相交点的曲线的斜率.通过将其与交点结合,我们可以得到一条直线方程.
  5. 通过该切线反映圆外的点,以将其反弹"回圆.可以使用
  1. Apply Displacements. Using the velocity and direction, you can apply the displacements to each of the particles.
  2. Determine if point is outside of the circle. If the displacement places the point outside of the circle (basic equation here), then we need to get it back into the circle. If there are no points outside of the circle, then go back to step 1.
  3. For each point outside of the circle, find the intersection of its path with the circle. This is a pretty trivial exercise using this solution as a reference.
  4. Find the tangent line of the circle at this point. Again this is trivial as we can draw a line from the center of the circle to the intersection point on the circle. the negative inverse of the slope of this line is the slope of the tangent line to the curve at the intersection point. By combining this with the intersection point, we have the equation of a line.
  5. Reflect the point that is outside of the circle across this tangent line to "bounce" it back into the circle. This reflection of a point across a line can be performed using the equations provided here.

示例解决方案

我已经执行了上述步骤.尽管这可能不是计算效率最高的方法,但它可以提供理想的结果.

Example Solution

I have implemented the above steps. Although this may not be the most computationally-efficient method it provides the desired result.

function bounce(npts, vmin, vmax, radius, center)

    % Initial direction/velocity of the points
    direction = rand(npts, 1) * 2 *pi;
    velocity = (rand(npts, 1) * (vmax - vmin)) + vmin;

    % Create random starting locations within the circle
    theta = rand(npts, 1) * 2*pi;
    r = radius * sqrt(rand(npts, 1));

    XY = [r .* cos(theta(:)) + center(1), ...
          r .* sin(theta(:)) + center(2)];

    % Initial plot objects
    hfig = figure('Color', 'w');
    hax = axes('Parent', hfig);

    % Plot the dots as black markers
    hdots = plot(XY(:,1), XY(:,2), ...
                'Parent', hax, ...
                'Marker', '.', ...
                'Color', 'k', ...
                'LineStyle', 'none', ...
                'MarkerSize', 12);

    hold(hax, 'on')
    axis(hax, 'equal')

    % Plot the circle as a reference
    t = linspace(0, 2*pi, 100);
    plot(radius * cos(t) + center(1), ...
         radius * sin(t) + center(2))

    % Keep simulating until we actually close the window
    while ishghandle(hfig);
        % Determine new dot locations
        [XY, direction] = step(XY, direction, velocity, radius, center);

        % Update the dot plot to reflect new locations
        set(hdots, 'XData', XY(:,1), 'YData', XY(:,2))

        % Force a redraw
        drawnow
    end
end

function [XYnew, direction] = step(XY, direction, velocity, radius, center)
    % Compute the next position of the points
    DX = [cos(direction(:)) .* velocity, ...
          sin(direction(:)) .* velocity];
    XYnew = XY + DX;

    % Now check that they are all inside circle
    isOutside = sum(bsxfun(@minus, XYnew, center).^2, 2) > radius^2;

    % The ones that are outside should "bounce" back into the circle
    if any(isOutside)        
        orig  = XY(isOutside,:);
        new   = XYnew(isOutside,:);
        delta = -DX(isOutside,:);

        % Find intersection of this path with the circle
        % Taken from: https://math.stackexchange.com/a/311956
        a = sum(delta.^2, 2);
        b = sum(2 .* delta .* bsxfun(@minus, orig, center), 2);
        c = sum(bsxfun(@minus, orig, center).^2, 2) - radius^2;

        t = (2 * c) ./ (-b + sqrt(b.^2 - 4 .* a .* c)); 
        xintersect = orig(:,1) + delta(:,1) .* t;
        yintersect = orig(:,2) + delta(:,2) .* t;

        % Get tangent at this intersection (slope/intercept form)
        m = - 1 ./ ((yintersect - center(2)) ./ (xintersect - center(1)));
        b = yintersect - m .* xintersect;

        % "Reflect" outside points across the tangent line to "bounce" them
        % Equations from: https://stackoverflow.com/a/3307181/670206
        d = (new(:,1) + (new(:,2) - b) .* m) ./ (1 + m.^2);

        XYnew(isOutside,1) = 2 * d - new(:,1);
        XYnew(isOutside,2) = 2 .* d .* m - new(:,2) + 2 .* b;

        % Recompute the direction of the particles that "bounced"
        direction(isOutside) = atan2(XYnew(isOutside,2) - yintersect, ...
                                     XYnew(isOutside,1) - xintersect);
    end
end

结果

通过运行以下命令,我可以获得以下结果.

The Result

By running the following command I was able to obtain the following result.

bounce(100, 0.01, 0.2, 5, [0 0]);

这篇关于使粒子在圆内随机移动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆