Mercurial > octave-nkf
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 |