1######################################################################## 2## 3## Copyright (C) 1996-2021 The Octave Project Developers 4## 5## See the file COPYRIGHT.md in the top-level directory of this 6## distribution or <https://octave.org/copyright/>. 7## 8## This file is part of Octave. 9## 10## Octave is free software: you can redistribute it and/or modify it 11## under the terms of the GNU General Public License as published by 12## the Free Software Foundation, either version 3 of the License, or 13## (at your option) any later version. 14## 15## Octave is distributed in the hope that it will be useful, but 16## WITHOUT ANY WARRANTY; without even the implied warranty of 17## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18## GNU General Public License for more details. 19## 20## You should have received a copy of the GNU General Public License 21## along with Octave; see the file COPYING. If not, see 22## <https://www.gnu.org/licenses/>. 23## 24######################################################################## 25 26## -*- texinfo -*- 27## @deftypefn {} {} plot3 (@var{x}, @var{y}, @var{z}) 28## @deftypefnx {} {} plot3 (@var{x}, @var{y}, @var{z}, @var{prop}, @var{value}, @dots{}) 29## @deftypefnx {} {} plot3 (@var{x}, @var{y}, @var{z}, @var{fmt}) 30## @deftypefnx {} {} plot3 (@var{x}, @var{cplx}) 31## @deftypefnx {} {} plot3 (@var{cplx}) 32## @deftypefnx {} {} plot3 (@var{hax}, @dots{}) 33## @deftypefnx {} {@var{h} =} plot3 (@dots{}) 34## Produce 3-D plots. 35## 36## Many different combinations of arguments are possible. The simplest 37## form is 38## 39## @example 40## plot3 (@var{x}, @var{y}, @var{z}) 41## @end example 42## 43## @noindent 44## in which the arguments are taken to be the vertices of the points to 45## be plotted in three dimensions. If all arguments are vectors of the 46## same length, then a single continuous line is drawn. If all arguments 47## are matrices, then each column of is treated as a separate line. No attempt 48## is made to transpose the arguments to make the number of rows match. 49## 50## If only two arguments are given, as 51## 52## @example 53## plot3 (@var{x}, @var{cplx}) 54## @end example 55## 56## @noindent 57## the real and imaginary parts of the second argument are used 58## as the @var{y} and @var{z} coordinates, respectively. 59## 60## If only one argument is given, as 61## 62## @example 63## plot3 (@var{cplx}) 64## @end example 65## 66## @noindent 67## the real and imaginary parts of the argument are used as the @var{y} 68## and @var{z} values, and they are plotted versus their index. 69## 70## Arguments may also be given in groups of three as 71## 72## @example 73## plot3 (@var{x1}, @var{y1}, @var{z1}, @var{x2}, @var{y2}, @var{z2}, @dots{}) 74## @end example 75## 76## @noindent 77## in which each set of three arguments is treated as a separate line or 78## set of lines in three dimensions. 79## 80## To plot multiple one- or two-argument groups, separate each group 81## with an empty format string, as 82## 83## @example 84## plot3 (@var{x1}, @var{c1}, "", @var{c2}, "", @dots{}) 85## @end example 86## 87## Multiple property-value pairs may be specified which will affect the line 88## objects drawn by @code{plot3}. If the @var{fmt} argument is supplied it 89## will format the line objects in the same manner as @code{plot}. 90## The full list of properties is documented at 91## @ref{Line Properties}. 92## 93## If the first argument @var{hax} is an axes handle, then plot into this axes, 94## rather than the current axes returned by @code{gca}. 95## 96## The optional return value @var{h} is a graphics handle to the created plot. 97## 98## Example: 99## 100## @example 101## @group 102## z = [0:0.05:5]; 103## plot3 (cos (2*pi*z), sin (2*pi*z), z, ";helix;"); 104## plot3 (z, exp (2i*pi*z), ";complex sinusoid;"); 105## @end group 106## @end example 107## @seealso{ezplot3, plot} 108## @end deftypefn 109 110function h = plot3 (varargin) 111 112 [hax, varargin, nargs] = __plt_get_axis_arg__ ("plot3", varargin{:}); 113 114 if (nargs < 1) 115 print_usage (); 116 endif 117 118 oldfig = []; 119 if (! isempty (hax)) 120 oldfig = get (0, "currentfigure"); 121 endif 122 unwind_protect 123 hax = newplot (hax); 124 125 x_set = 0; 126 y_set = 0; 127 z_set = 0; 128 property_set = 0; 129 fmt_set = 0; 130 properties = {}; 131 tlgnd = {}; 132 hlgnd = []; 133 htmp = []; 134 idx = 0; 135 136 ## Gather arguments, decode format, and plot lines. 137 arg = 0; 138 while (arg++ < nargs) 139 new = varargin{arg}; 140 new_cell = varargin(arg); 141 142 if (property_set) 143 properties = [properties, new_cell]; 144 property_set = 0; 145 continue; 146 endif 147 148 if (ischar (new)) 149 if (! z_set) 150 if (! y_set) 151 if (! x_set) 152 error ("plot3: needs X, [ Y, [ Z ] ]"); 153 else 154 y = real (x); 155 z = imag (x); 156 y_set = 1; 157 z_set = 1; 158 if (rows (x) > 1) 159 x = repmat ((1:rows (x))', 1, columns (x)); 160 else 161 x = 1:columns (x); 162 endif 163 endif 164 else 165 z = imag (y); 166 y = real (y); 167 z_set = 1; 168 endif 169 endif 170 171 if (! fmt_set) 172 [options, valid] = __pltopt__ ("plot3", new, false); 173 if (! valid) 174 properties = [properties, new_cell]; 175 property_set = 1; 176 continue; 177 else 178 fmt_set = 1; 179 while (arg < nargs && ischar (varargin{arg+1})) 180 if (nargs - arg < 2) 181 error ("plot3: properties must appear followed by a value"); 182 endif 183 properties = [properties, varargin(arg+1:arg+2)]; 184 arg += 2; 185 endwhile 186 endif 187 else 188 properties = [properties, new_cell]; 189 property_set = 1; 190 continue; 191 endif 192 193 if (isvector (x) && isvector (y)) 194 if (isvector (z)) 195 x = x(:); 196 y = y(:); 197 z = z(:); 198 elseif (length (x) == rows (z) && length (y) == columns (z)) 199 [x, y] = meshgrid (x, y); 200 else 201 error ("plot3: [length(X), length(Y)] must match size (Z)"); 202 endif 203 endif 204 205 if (! size_equal (x, y, z)) 206 error ("plot3: X, Y, and Z must have the same shape"); 207 elseif (ndims (x) > 2) 208 error ("plot3: X, Y, and Z must not have more than two dimensions"); 209 endif 210 211 for i = 1 : columns (x) 212 linestyle = options.linestyle; 213 marker = options.marker; 214 if (isempty (marker) && isempty (linestyle)) 215 [linestyle, marker] = __next_line_style__ (); 216 endif 217 color = options.color; 218 if (isempty (color)) 219 color = __next_line_color__ (); 220 endif 221 222 htmp(++idx) = __go_line__ (hax, "xdata", x(:, i), "ydata", y(:, i), 223 "zdata", z(:, i), 224 "color", color, "linestyle", linestyle, 225 "marker", marker, properties{:}); 226 key = options.key; 227 if (! isempty (key)) 228 hlgnd = [hlgnd, htmp(idx)]; 229 tlgnd = {tlgnd{:}, key}; 230 endif 231 endfor 232 233 x_set = 0; 234 y_set = 0; 235 z_set = 0; 236 fmt_set = 0; 237 properties = {}; 238 elseif (! x_set) 239 x = new; 240 x_set = 1; 241 elseif (! y_set) 242 y = new; 243 y_set = 1; 244 elseif (! z_set) 245 z = new; 246 z_set = 1; 247 else 248 if (isvector (x) && isvector (y)) 249 if (isvector (z)) 250 x = x(:); 251 y = y(:); 252 z = z(:); 253 elseif (length (x) == rows (z) && length (y) == columns (z)) 254 [x, y] = meshgrid (x, y); 255 else 256 error ("plot3: [length(X), length(Y)] must match size (Z)"); 257 endif 258 endif 259 260 if (! size_equal (x, y, z)) 261 error ("plot3: X, Y, and Z must have the same shape"); 262 elseif (ndims (x) > 2) 263 error ("plot3: X, Y, and Z must not have more than two dimensions"); 264 endif 265 266 options = __default_plot_options__ (); 267 for i = 1 : columns (x) 268 linestyle = options.linestyle; 269 marker = options.marker; 270 if (isempty (marker) && isempty (linestyle)) 271 [linestyle, marker] = __next_line_style__ (); 272 endif 273 color = options.color; 274 if (isempty (color)) 275 color = __next_line_color__ (); 276 endif 277 278 htmp(++idx) = __go_line__ (hax, "xdata", x(:, i), "ydata", y(:, i), 279 "zdata", z(:, i), 280 "color", color, "linestyle", linestyle, 281 "marker", marker, properties{:}); 282 key = options.key; 283 if (! isempty (key)) 284 hlgnd = [hlgnd, htmp(idx)]; 285 tlgnd = {tlgnd{:}, key}; 286 endif 287 endfor 288 289 x = new; 290 y_set = 0; 291 z_set = 0; 292 fmt_set = 0; 293 properties = {}; 294 endif 295 296 endwhile 297 298 if (property_set) 299 error ("plot3: properties must appear followed by a value"); 300 endif 301 302 ## Handle last plot. 303 304 if (x_set) 305 if (y_set) 306 if (! z_set) 307 z = imag (y); 308 y = real (y); 309 z_set = 1; 310 endif 311 else 312 y = real (x); 313 z = imag (x); 314 y_set = 1; 315 z_set = 1; 316 if (rows (x) > 1) 317 x = repmat ((1:rows (x))', 1, columns (x)); 318 else 319 x = 1:columns (x); 320 endif 321 endif 322 323 if (isvector (x) && isvector (y)) 324 if (isvector (z)) 325 x = x(:); 326 y = y(:); 327 z = z(:); 328 elseif (length (x) == rows (z) && length (y) == columns (z)) 329 [x, y] = meshgrid (x, y); 330 else 331 error ("plot3: [length(X), length(Y)] must match size (Z)"); 332 endif 333 endif 334 335 if (! size_equal (x, y, z)) 336 error ("plot3: X, Y, and Z must have the same shape"); 337 elseif (ndims (x) > 2) 338 error ("plot3: X, Y, and Z must not have more than two dimensions"); 339 endif 340 341 options = __default_plot_options__ (); 342 343 for i = 1 : columns (x) 344 linestyle = options.linestyle; 345 marker = options.marker; 346 if (isempty (marker) && isempty (linestyle)) 347 [linestyle, marker] = __next_line_style__ (); 348 endif 349 color = options.color; 350 if (isempty (color)) 351 color = __next_line_color__ (); 352 endif 353 354 htmp(++idx) = __go_line__ (hax, "xdata", x(:, i), "ydata", y(:, i), 355 "zdata", z(:, i), 356 "color", color, "linestyle", linestyle, 357 "marker", marker, properties{:}); 358 key = options.key; 359 if (! isempty (key)) 360 hlgnd = [hlgnd, htmp(idx)]; 361 tlgnd = {tlgnd{:}, key}; 362 endif 363 endfor 364 endif 365 366 if (! isempty (hlgnd)) 367 legend (hax, hlgnd, tlgnd); 368 endif 369 370 if (! ishold ()) 371 set (hax, "view", [-37.5, 30]); 372 endif 373 374 unwind_protect_cleanup 375 if (! isempty (oldfig)) 376 set (0, "currentfigure", oldfig); 377 endif 378 end_unwind_protect 379 380 if (nargout > 0) 381 h = htmp; 382 endif 383 384endfunction 385 386 387%!demo 388%! clf; 389%! z = [0:0.05:5]; 390%! plot3 (cos (2*pi*z), sin (2*pi*z), z); 391%! legend ("helix"); 392%! title ("plot3() of a helix"); 393 394%!demo 395%! clf; 396%! z = [0:0.05:5]; 397%! plot3 (z, exp (2i*pi*z)); 398%! legend ("complex sinusoid"); 399%! title ("plot3() with complex input"); 400