如何在复杂折线旁边创建随机点?

时间:2016-02-23 21:55:59

标签: matlab

我想在2D绘图上填充随机点,使得这些点落在" C"异形折线。

我设法完成了一个相当简单的方形" C":

scatter and polyline

我就这样做了:

% Marker color
c = 'k';    % Black

% Red "C" polyline
xl = [8,2,2,8];
yl = [8,8,2,2];
plot(xl,yl,'r','LineWidth',2);
hold on;

% Axis settings
axis equal;
axis([0,10,0,10]);
set(gca,'xtick',[],'ytick',[]);

step = 0.05;    % Affects point quantity
coeff = 0.9;    % Affects point density

% Top Horizontal segment
x = 2:step:9.5;
y = 8 + coeff*randn(size(x));
scatter(x,y,'filled','MarkerFaceColor',c);

% Vertical segment
y = 1.5:step:8.5;
x = 2 + coeff*randn(size(y));
scatter(x,y,'filled','MarkerFaceColor',c);

% Bottom Horizontal segment
x = 2:step:9.5;
y = 2 + coeff*randn(size(x));
scatter(x,y,'filled','MarkerFaceColor',c);

hold off;

正如您在代码中看到的,对于折线的每个片段,我使用randn人工生成散点图坐标。

对于前面的示例,将折线分割成段并手动生成点很好。但是,如果我想尝试更复杂的" C"形状像这样:

polyline

请注意,使用我目前的方法,当折线的几何复杂度增加时,编码工作也会增加。

在继续之前,是否有更好的方法解决这个问题?

2 个答案:

答案 0 :(得分:1)

一种更简单的方法,可以推广到任何折线,就是在线段上运行循环。对于每个段,r是其长度,m是沿该段放置的点数(它与规定的步长紧密对应,如果步长不具有轻微偏差)均匀划分长度)。请注意,x和y都会受到随机扰动。

for n = 1:numel(xl)-1 
    r = norm([xl(n)-xl(n+1), yl(n)-yl(n+1)]);
    m = round(r/step) + 1;
    x = linspace(xl(n), xl(n+1), m) + coeff*randn(1,m);
    y = linspace(yl(n), yl(n+1), m) + coeff*randn(1,m);
    scatter(x,y,'filled','MarkerFaceColor',c);
end

输出:

output

更复杂的示例,使用coeff = 0.4;xl = [8,4,2,2,6,8]; yl = [8,6,8,2,4,2];

example

如果您认为此点云在端点附近太薄,则可以在运行循环之前人为地延长第一个和最后一个段。但我没有看到需要:模糊的曲线在四肢变薄是有道理的。

答案 1 :(得分:1)

使用原始方法,可以以不同的概率对距离相同距离的两个位置进行采样,尤其是在两条线相交的角落处。我试图修改这个改编随机实验。我的代码所做的随机实验是:“选择一个随机点。接受它的概率为normpdf(d)<rand,其中d是到下一行的距离”。这是rejection sampling strategy

xl = [8,4,2,2,6,8];
yl = [8,6,8,2,4,2];
resolution=50;
points_to_sample=200;
step=.5;
sigma=.4; %lower value to get points closer to the line.
xmax=(max(xl)+2);
ymax=(max(yl)+2);
dist=zeros(xmax*resolution+1,ymax*resolution+1);
x=[];
y=[];
for n = 1:numel(xl)-1 
    r = norm([xl(n)-xl(n+1), yl(n)-yl(n+1)]);
    m = round(r/step) + 1;
    x = [x,round(linspace(xl(n)*resolution+1, xl(n+1)*resolution+1, m*resolution))];
    y = [y,round(linspace(yl(n)*resolution+1, yl(n+1)*resolution+1, m*resolution))];
end
%dist contains the lines:
dist(sub2ind(size(dist),x,y))=1;
%dist contains the normalized distance of each rastered pixel to the line.
dist=bwdist(dist)/resolution;
pseudo_pdf=normpdf(dist,0,sigma);
%scale up to have acceptance rate of 1 for most likely pixels.
pseudo_pdf=pseudo_pdf/max(pseudo_pdf(:));
sampled_points=zeros(0,2);

while size(sampled_points,1)<points_to_sample
    %sample a random point
    sx=rand*xmax;
    sy=rand*ymax;
    %accept it if criteria based on normal distribution matches.
    if pseudo_pdf(round(sx*resolution)+1,round(sy*resolution)+1)>rand
        sampled_points(end+1,:)=[sx,sy];
    end
end
plot(xl,yl,'r','LineWidth',2);
hold on
scatter(sampled_points(:,1),sampled_points(:,2),'filled');

enter image description here