How to stop plotting once line touches perimeter of predefined square?

落花浮王杯 提交于 2019-12-11 05:05:29

问题


I am trying to recreate a Voronoi diagram without actually using the Voronoi function plot. I have a predefined 1x1 square that acts as my "test" area. My code knows where the lines of the diagram intersect the perimeter, but the line doesn't stop there. It keeps going until it reaches a random point.

x1 = 6
y1 = x1
x = gallery('uniformdata',[1,x1],0)
y = gallery('uniformdata',[1,y1],1)
sizeofx = size(x,2)
sizeofy = size(y,2)
reshapedx = reshape(x,sizeofx,1)
reshapedy = reshape(y,sizeofy,1)
[vxx,vyy] = voronoi(x,y)

hold on
[v,c] = voronoin([x(:) y(:)]) %intersection point matrix
for i=1:numel(c)
    v(c{i},:)
    ans = ans( ~any( isnan( ans ) | isinf( ans ), 2 ),: )%deletes infs or nans from polygon points
    plot(ans(:,1),ans(:,2),'b-','linewidth',2) %%this code plots the points 
end

%for our test purposes , the voronoi diagram will only be in a 1x1 square.
v(v<0) = inf
v(v>1) = inf
v = v( ~any( isnan( v ) | isinf( v ), 2 ),: ) %deletes the inf or nan

DT = delaunayTriangulation(reshapedx,reshapedy)
[V,R] = voronoiDiagram(DT)
sizeofR = size(R,1)
rectangle('Position',[0,0,1,1])
axis equal

xlimit = [0 1];
ylimit = [0 1];
xbox = xlimit([1 1 2 2 1]);
ybox = ylimit([1 2 2 1 1]);

%finds intersection from diagram to square
for j=1:length(vxx(1,:))
    line([vxx(1,j) vxx(2,j)],[vyy(1,j) vyy(2,j)]);
    [xi, yi, ii] = ...
      polyxpoly([vxx(1,j) vxx(2,j)], [vyy(1,j) vyy(2,j)], xbox, ybox);
        if ~isempty(xi)
                intersectx(j) = xi
                intersecty(j) = yi
                plot(xi,yi,'r*');
                axis equal
        end
 end

I want the line to stop plotting once it reaches a perimeter point.


回答1:


You can replace the coordinate of line's edge with the intersection point.

Assume line goes from (x1,y1) to (x2,y2).
Check if (x1,y1) is outside the boundaries of the rectangle.
I your case (x1,y1) is outside the boundaries if (x1<0) || (y1<0) || (x1>1) || (y1>1).
In case (x1,y1) is outside, replace (x1,y1) with intersection point (xi,yi).
Note: Replace it only if there is an intersection point.

I ignored the case of two intersection points, because this case never happens in your case (in that case, you need to replace both).

Here is the complete code with the modifications:

x1 = 6;
y1 = x1;
x = gallery('uniformdata',[1,x1],0);
y = gallery('uniformdata',[1,y1],1);
sizeofx = size(x,2);
sizeofy = size(y,2);
reshapedx = reshape(x,sizeofx,1);
reshapedy = reshape(y,sizeofy,1);
[vxx,vyy] = voronoi(x,y);

hold on
[v,c] = voronoin([x(:) y(:)]); %intersection point matrix
for i=1:numel(c)
    v(c{i},:);
    ans = ans( ~any( isnan( ans ) | isinf( ans ), 2 ),: );%deletes infs or nans from polygon points
    plot(ans(:,1),ans(:,2),'b-','linewidth',2); %%this code plots the points 
end

%for our test purposes , the voronoi diagram will only be in a 1x1 square.
v(v<0) = inf;
v(v>1) = inf;
v = v( ~any( isnan( v ) | isinf( v ), 2 ),: ); %deletes the inf or nan

DT = delaunayTriangulation(reshapedx,reshapedy);
[V,R] = voronoiDiagram(DT);
sizeofR = size(R,1);
rectangle('Position',[0,0,1,1]);
axis equal

xlimit = [0 1];
ylimit = [0 1];
xbox = xlimit([1 1 2 2 1]);
ybox = ylimit([1 2 2 1 1]);

%Vxx and Vyy are going to be a new set of line coordinates, replacing vxx and vyy.
Vxx = vxx;
Vyy = vyy;

%finds intersection from diagram to square
for j=1:length(vxx(1,:))

    %line([vxx(1,j) vxx(2,j)],[vyy(1,j) vyy(2,j)]);

    [xi, yi, ii] = ...
      polyxpoly([vxx(1,j) vxx(2,j)], [vyy(1,j) vyy(2,j)], xbox, ybox);
        if ~isempty(xi)
                intersectx(j) = xi;
                intersecty(j) = yi;
                plot(xi,yi,'r*', 'MarkerSize', 10);
                axis equal

                %Replace line edges outsize the rectangle with the inersection point.
                %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                x1 = vxx(1,j);
                x2 = vxx(2,j);
                y1 = vyy(1,j);
                y2 = vyy(2,j);
                is_outsize1 = (x1 < 0) || (y1 < 0) || (x1 > 1) || (y1 > 1);
                is_outsize2 = (x2 < 0) || (y2 < 0) || (x2 > 1) || (y2 > 1);

                %Assume rectangle's boundaries are (0,0) to (1,1)
                if is_outsize1
                    %Replace the coordinate [vxx(1,j), vyy(1,j)] with [xi, yi].
                    Vxx(1,j) = xi;
                    Vyy(1,j) = yi;
                end

                if is_outsize2
                    %Replace the coordinate [vxx(2,j), vyy(2,j)] with [xi, yi].
                    Vxx(2,j) = xi;
                    Vyy(2,j) = yi;
                end
                %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        end

    %Plot the line with the replaces coordinates
    line([Vxx(1,j) Vxx(2,j)],[Vyy(1,j) Vyy(2,j)], 'color', 'g', 'LineWidth', 1, 'Marker', '+');
end

Result:

Original plot:



来源:https://stackoverflow.com/questions/56783324/how-to-stop-plotting-once-line-touches-perimeter-of-predefined-square

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!