问题
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