comparison scripts/geometry/voronoi.m @ 18202:5646f999245d

voronoi.m: Add special handling for 2-point input (bug #40996). * voronoi.m: Check for 2-point input and find single bisection line between them amongs the edges output from QHull. Add %!test for special case. Change input validation and %!tests to accept 2-point input.
author Rik <rik@octave.org>
date Fri, 03 Jan 2014 10:52:41 -0800
parents 0ecd4618b1fc
children 0e1f5a750d00
comparison
equal deleted inserted replaced
18201:ec87e965c246 18202:5646f999245d
105 linespec = varargin(narg); 105 linespec = varargin(narg);
106 endif 106 endif
107 107
108 if (length (x) != length (y)) 108 if (length (x) != length (y))
109 error ("voronoi: X and Y must be vectors of the same length"); 109 error ("voronoi: X and Y must be vectors of the same length");
110 elseif (length (x) < 3) 110 elseif (length (x) < 2)
111 ## See bug #40996. 111 error ("voronoi: minimum of 2 points needed");
112 ## For 2 points it would be nicer to just calculate the bisection line.
113 error ("voronoi: minimum of 3 points needed");
114 endif 112 endif
115 113
116 ## Add box to approximate rays to infinity. For Voronoi diagrams the 114 ## Add box to approximate rays to infinity. For Voronoi diagrams the
117 ## box can (and should) be close to the points themselves. To make the 115 ## box can (and should) be close to the points themselves. To make the
118 ## job of finding the exterior edges it should be at least two times the 116 ## job of finding the exterior edges it should be at least two times the
143 ## Identify the unique edges of the Voronoi diagram 141 ## Identify the unique edges of the Voronoi diagram
144 edges = sortrows (sort (edges).').'; 142 edges = sortrows (sort (edges).').';
145 edges = edges(:, [(edges(1, 1 :end - 1) != edges(1, 2 : end) | ... 143 edges = edges(:, [(edges(1, 1 :end - 1) != edges(1, 2 : end) | ...
146 edges(2, 1 :end - 1) != edges(2, 2 : end)), true]); 144 edges(2, 1 :end - 1) != edges(2, 2 : end)), true]);
147 145
148 ## Eliminate the edges of the diagram representing the box 146 if (numel (x) > 2)
149 poutside = (1:rows (p)) ... 147 ## Eliminate the edges of the diagram representing the box
150 (p(:, 1) < xmin - xdelta | p(:, 1) > xmax + xdelta | ... 148 poutside = (1:rows (p)) ...
151 p(:, 2) < ymin - ydelta | p(:, 2) > ymax + ydelta); 149 (p(:, 1) < xmin - xdelta | p(:, 1) > xmax + xdelta | ...
152 edgeoutside = ismember (edges(1, :), poutside) & ... 150 p(:, 2) < ymin - ydelta | p(:, 2) > ymax + ydelta);
153 ismember (edges(2, :), poutside); 151 edgeoutside = ismember (edges(1, :), poutside) & ...
154 edges(:, edgeoutside) = []; 152 ismember (edges(2, :), poutside);
153 edges(:, edgeoutside) = [];
154 else
155 ## look for the edge between the two given points
156 for edge = edges(1:2,:)
157 if (det ([[[1;1],p(edge,1:2)];1,x(1),y(1)])
158 * det ([[[1;1],p(edge,1:2)];1,x(2),y(2)]) < 0)
159 edges = edge;
160 break;
161 endif
162 endfor
163 ## Use larger plot limits to make it more likely single bisector is shown.
164 xdelta = ydelta = max (xdelta, ydelta);
165 endif
155 166
156 ## Get points of the diagram 167 ## Get points of the diagram
157 Vvx = reshape (p(edges, 1), size (edges)); 168 Vvx = reshape (p(edges, 1), size (edges));
158 Vvy = reshape (p(edges, 2), size (edges)); 169 Vvy = reshape (p(edges, 2), size (edges));
159 170
183 %! [x,y] = pol2cart (phi, 1); 194 %! [x,y] = pol2cart (phi, 1);
184 %! [vx,vy] = voronoi (x,y); 195 %! [vx,vy] = voronoi (x,y);
185 %! assert (vx(2,:), zeros (1, columns (vx)), eps); 196 %! assert (vx(2,:), zeros (1, columns (vx)), eps);
186 %! assert (vy(2,:), zeros (1, columns (vy)), eps); 197 %! assert (vy(2,:), zeros (1, columns (vy)), eps);
187 198
199 %!testif HAVE_QHULL
200 %! ## Special case of just 2 points
201 %! x = [0 1]; y = [1 0];
202 %! [vx, vy] = voronoi (x,y);
203 %! assert (vx, [-0.7; 1.7], eps);
204 %! assert (vy, [-0.7; 1.7], eps);
205
188 %% Input validation tests 206 %% Input validation tests
189 %!error voronoi () 207 %!error voronoi ()
190 %!error voronoi (ones (3,1)) 208 %!error voronoi (ones (3,1))
191 %!error voronoi (ones (3,1), ones (3,1), "bogus1", "bogus2", "bogus3") 209 %!error voronoi (ones (3,1), ones (3,1), "bogus1", "bogus2", "bogus3")
192 %!error <HAX argument must be an axes object> voronoi (0, ones (3,1), ones (3,1)) 210 %!error <HAX argument must be an axes object> voronoi (0, ones (3,1), ones (3,1))
193 %!error <X and Y must be vectors of the same length> voronoi (ones (3,1), ones (4,1)) 211 %!error <X and Y must be vectors of the same length> voronoi (ones (3,1), ones (4,1))
194 %!error <minimum of 3 points needed> voronoi (2.5, 3.5) 212 %!error <minimum of 2 points needed> voronoi (2.5, 3.5)
195 %!error <minimum of 3 points needed> voronoi ([2.5, 3.5], [2.5, 3.5]) 213
196