【问题标题】:Matlab, generate and plot a point cloud distributed within a triangleMatlab,生成并绘制分布在三角形内的点云
【发布时间】:2012-12-10 21:04:11
【问题描述】:

我正在尝试生成一个二维点云(均匀地)分布在一个三角形内。到目前为止,我已经实现了以下目标:

我使用的代码是这样的:

N = 1000;
X = -10:0.1:10;
for i=1:N
    j = ceil(rand() * length(X));
    x_i = X(j);
    y_i = (10 - abs(x_i)) * rand;

    E(:, i) = [x_i y_i];
end

但是,这些点并不是均匀分布的,左右角可以清楚地看到。我怎样才能改善这个结果?我也一直在尝试寻找不同的形状,但没有成功。

【问题讨论】:

    标签: matlab random uniform


    【解决方案1】:

    我们可以概括这种情况。如果您想从欧几里得空间中的某些 (n - 1) 维单纯形中均匀采样点(不一定是三角形 - 它可以是任何凸多面体),只需从参数为 1 的对称 n 维 Dirichlet 分布中采样一个向量 -这些是相对于多面体顶点的凸(或重心)坐标。

    【讨论】:

      【解决方案2】:

      您可以想象三角形被垂直分成两半,然后移动其中一半使其与另一半一起形成一个矩形。现在你在矩形中均匀采样,这很容易,然后将半三角形向后移动。

      此外,使用单位长度(矩形变成正方形)更容易,然后将三角形拉伸到所需的尺寸。

      x = [-10 10]; % //triangle base
      y = [0 10]; % //triangle height
      N = 1000; %// number of points
      
      points = rand(N,2); %// sample uniformly in unit square
      ind = points(:,2)>points(:,1); %// points to be unfolded 
      points(ind,:) = [2-points(ind,2) points(ind,1)]; %// unfold them
      points(:,1) = x(1) + (x(2)-x(1))/2*points(:,1); %// stretch x as needed
      points(:,2) = y(1) + (y(2)-y(1))*points(:,2); %// stretch y as needed
      plot(points(:,1),points(:,2),'.')
      

      【讨论】:

        【解决方案3】:

        你应该先问问自己,什么会使三角形内的点均匀分布。

        长话短说,给定三角形的所有三个顶点,您需要像这样变换两个均匀分布的随机值:

        N = 1000;                    % # Number of points
        V = [-10, 0; 0, 10; 10, 0];  % # Triangle vertices, pairs of (x, y)
        t = sqrt(rand(N, 1));
        s = rand(N, 1);
        P = (1 - t) * V(1, :) + bsxfun(@times, ((1 - s) * V(2, :) + s * V(3, :)), t);
        

        这将产生一组均匀分布在指定三角形内的点:

        scatter(P(:, 1), P(:, 2), '.')
        

        请注意,此解决方案不涉及对随机数的重复条件操作,因此它不可能陷入无限循环。

        如需进一步阅读,请查看this article

        【讨论】:

        • 您能解释一下您是如何计算 P 的吗?或者我在哪里可以读到你使用的公式?谢谢!
        • @Cyber​​Lingo 基本上,它随机化一个点 (x,y),在我们的例子中由 ts 表示,并将其重新映射到由三角形限制的空间(由 @987654329 表示@)。 P 是映射矩阵和 (x, y) 的乘积。请注意,随机化的t 中的sqrt 只是简化乘积最终计算的一种方式。但是,我认为向您指出一些可以更好地解释它的链接会更容易,例如this questionthis link...
        • @Cyber​​Lingo 哦,还要注意这个计算随机化了一个点数组(因此产生了一个点数组)。因此在P的计算中使用bsxfun
        • 感谢您的解释!
        【解决方案4】:

        从您构建积分的方式可以预期积分的集中度。您的点沿 X 轴均匀分布。在三角形的两端,三角形中心的点数量大致相同,但它们分布在一个小得多的区域。

        我能想到的第一个也是最好的方法:蛮力。将点平均分布在更大的区域周围,然后删除您感兴趣的区域之外的点。

        N = 1000;
        points = zeros(N,2);
        n = 0;
        while (n < N)
            n = n + 1;
            x_i = 20*rand-10; % generate a number between -10 and 10
            y_i = 10*rand; % generate a number between 0 and 10
            if (y_i > 10 - abs(x_i)) % if the points are outside the triangle
               n = n - 1; % decrease the counter to try to generate one more point
            else % if the point is inside the triangle
               points(n,:) = [x_i y_i]; % add it to a list of points
            end
        end
        
        % plot the points generated
        plot(points(:,1), points(:,2), '.');
        title ('1000 points randomly distributed inside a triangle');
        

        我发布的代码的结果:

        一个重要的免责声明:随机分布并不意味着“均匀”分布!如果您从均匀分布中随机生成数据,并不意味着它将沿三角形“均匀分布”。事实上,您会看到一些点簇。

        【讨论】:

        • 在 MATLAB 中手动更改 for 循环的迭代变量不是一个好主意。我不认为这表现得像您期望的那样。
        • @Castilho - 在 matlab 中,您不能更改 for 循环内的循环变量。试试下面的for ii=1:2, ii=1, end; 这个循环只会执行两次,并且不会导致无限循环。
        • 以上代码在 Matlab R2011a 中工作,如图所示。测试它;)
        • 是的,可以轻松更改循环以使用 while 循环。 For 是第一种方法,因为它更容易编写。根据我的经验,如果没有嵌套循环,您可以更改其中的循环变量。但我会将代码更改为 while 循环,因为它确实更好。 (ps:代码适用于5分、1000分和100000分)
        • 你是对的,循环不会重复。感谢您指出了这一点。经验教训 :) blogs.mathworks.com/loren/2006/07/19/how-for-works
        猜你喜欢
        • 2012-05-10
        • 1970-01-01
        • 2021-09-14
        • 2012-03-03
        • 2017-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多