1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) 2004-2006 - INRIA - Fabrice Leray
3 // Copyright (C) 2012 - 2016 - Scilab Enterprises
5 // This file is hereby licensed under the terms of the GNU GPL v2.0,
6 // pursuant to article 5.3.4 of the CeCILL v.2.1.
7 // This file was originally licensed under the terms of the CeCILL v2.1,
8 // and continues to be available under such terms.
9 // For more information, see the COPYING file which you should have received
10 // along with this program.
12 function surf(varargin)
19 0.0001 0.0013 0.0053 -0.0299 -0.1809 -0.2465 -0.1100 -0.0168 -0.0008 -0.0000
20 0.0005 0.0089 0.0259 -0.3673 -1.8670 -2.4736 -1.0866 -0.1602 -0.0067 0.0000
21 0.0004 0.0214 0.1739 -0.3147 -4.0919 -6.4101 -2.7589 -0.2779 0.0131 0.0020
22 -0.0088 -0.0871 0.0364 1.8559 1.4995 -2.2171 -0.2729 0.8368 0.2016 0.0130
23 -0.0308 -0.4313 -1.7334 -0.1148 3.0731 0.4444 2.6145 2.4410 0.4877 0.0301
24 -0.0336 -0.4990 -2.3552 -2.1722 0.8856 -0.0531 2.6416 2.4064 0.4771 0.0294
25 -0.0137 -0.1967 -0.8083 0.2289 3.3983 3.1955 2.4338 1.2129 0.2108 0.0125
26 -0.0014 -0.0017 0.3189 2.7414 7.1622 7.1361 3.1242 0.6633 0.0674 0.0030
27 0.0002 0.0104 0.1733 1.0852 2.6741 2.6725 1.1119 0.1973 0.0152 0.0005
28 0.0000 0.0012 0.0183 0.1099 0.2684 0.2683 0.1107 0.0190 0.0014 0.0000];
30 if size(f.children)==1
31 f.color_map = jetcolormap(64);
33 s = gca().axes_bounds; delete(gca()); xsetech(s) // clears the current axes
34 surf(Z,"edgeco","b","marker","d","markersiz",9,"markeredg","red","markerfac","k");
38 // Detects and sets the current axes now
39 // -------------------------------------
41 argShift = 0; // To correctly address argins # in error messages
42 if type(ListArg(1)) == 9
44 if (hdle.type == "Axes")
46 ListArg(1) = null(); // remove this parameter from the list
49 msg = gettext("%s: Wrong type for input argument #%d: An ''Axes'' handle expected.\n")
50 error(msprintf(msg, "surf", 1))
61 CurColor = 0; // current color used if no color specified via LineSpec
63 typeOfPlot = "surf"; // used in called functions ?
65 nv = size(ListArg); // Number of input arguments
67 // Types of input arguments
70 T(k) = type(ListArg(k))
72 T = [T' 0 0 0 0] // Padding to have at least 5 values
74 // delay the drawing commands: smart drawlater
75 current_figure = gcf();
76 cur_draw_mode = current_figure.immediate_drawing;
77 current_figure.immediate_drawing = "off";
79 colormap_size = size(current_figure.color_map,1);
81 // PARSING INPUT ARGUMENTS
82 // =======================
88 //surf(X,Y,fun, colors)
89 //surf(X,Y,list(fun,params))
90 //surf(X,Y,list(fun,params), colors)
92 // Identifying X and Y
93 // -------------------
94 if and(T(1:2)==[1 0]) | and(T(1:2)==[1 10]) | .. // surf(Z)
95 and(T(1:3)==[1 1 0]) | and(T(1:3)==[1 1 10])then // surf(Z, colors)
96 Z = ListArg(1)'; // here a transposition is needed
100 ResetFigureDDM(current_figure, cur_draw_mode);
101 msg = gettext("%s: Wrong size for input argument #%d: A matrix of size greater than %d-by-%d expected.\n")
102 error(msprintf(msg, "surf", 1+argShift, 2, 2));
105 else // surf(X,Y, ..)
107 if T(1)~=1 | ~isreal(X) then
108 msg = gettext("%s: Argument #%d: Decimal numbers expected.\n")
109 error(msprintf(msg, "surf", 1+argShift));
113 if T(2)~=1 | ~isreal(Y) then
114 msg = gettext("%s: Argument #%d: Decimal numbers expected.\n")
115 error(msprintf(msg, "surf", 2+argShift));
118 msg = gettext("%s: Argument #%d: At least %d components expected.\n")
119 error(msprintf(msg, "surf", 2+argShift, 2));
121 if (~isvector(X) & ~isscalar(X)) | (~isvector(Y) & ~isscalar(Y))
122 if or(size(X)~=size(Y))
123 msg = gettext("%s: Arguments #%d and #%d: Incompatible sizes.\n")
124 error(msprintf(msg, "surf", 1+argShift, 2+argShift));
129 // Generating Z from fun() or list(fun(), params)
130 // ----------------------------------------------
131 // Separating the function and its parameters
132 withParams = T(3)==15
137 if size(tmp)<2 | and(type(tmp(1))~=[13 130])
138 ResetFigureDDM(current_figure, cur_draw_mode);
139 msg = _("%s: Argument #%d: Wrong list() specification.\n")
140 error(msprintf(msg, "surf", 3))
146 params = list(params)
148 elseif or(T(3)==[13 130])
149 buildFunc = ListArg(3)
151 // Generating Z. Managing a possible inner error. Checking consistency of Z sizes:
152 if type(buildFunc)~=1 then // ~=[]
153 if isvector(X) | isvector(Y) then
155 Z = buildFunc(X,Y,params(:))
157 // May be buildFunc() expects X and Y as matrices:
163 Z = buildFunc(X,Y,params(:))
165 ResetFigureDDM(current_figure, cur_draw_mode);
168 [err_message, err_number, err_line, err_func] = lasterror(%t);
171 if err_func~="", err_func = """"+err_func+"()""", end
172 msg = gettext("%s: Argument #%d : Unable to evaluate Z: Error %d at line %d in %s: ''%s''")
173 error(msprintf(msg, "surf", 3, err_number, err_line, err_func, err_message));
177 if isvector(X) | isvector(Y) then
183 if or(size(Z)~=[nr nc])
184 msg = gettext("%s: Argument #%d: Inconsistent size of the result.\n")
185 error(msprintf(msg, "surf", 3));
188 clear buildFunc params withParams
189 // Z extraction from surf(X,Y,Z) and surf(X,Y,Z,colors)
190 if Z==[] & and(T(2:3)==[1 1]) then
194 // Colors extraction and checking
195 // ------------------------------
196 if and(T(2:3)==[1 0]) | and(T(2:3)==[1 10]) then //surf(Z,colors)
199 elseif and(T(2:4)==[1 1 1]) | .. // surf(X, Y, Z, colors)
200 and(T(2:4)==[1 15 1]) | .. // surf(X, Y, list(fun,params), colors)
201 and(T(2:4)==[1 13 1]) | .. // surf(X, Y, macro, colors)
202 and(T(2:4)==[1 130 1]) then // surf(X, Y, builtin, colors)
207 if ((size(Z) <> size(C)) & (size(Z)-1 <> size(C)))
208 ResetFigureDDM(current_figure, cur_draw_mode);
209 msg = gettext("%s: Wrong size for input argument #%d: A %d-by-%d or %d-by-%d matrix expected.\n")
210 error(msprintf(msg,"surf", i+argShift, size(Z,2), size(Z,1), size(Z,2)-1, size(Z,1)-1))
217 P1 = 0 // Position of the first PropertyName field
220 if and(T(1:2)==[1 0]) | and(T(1:2)==[1 10]) then
221 [XX,YY,ZZ] = genfac3d(X,Y,Z);
222 CC = ZZ; // Add a color matrix based on Z values
229 elseif and(T(1:3)==[1 1 0]) | and(T(1:3)==[1 1 10])
230 [XX, YY, ZZ] = genfac3d(X, Y, Z);
231 if (size(C)==size(Z)) // color number == zdata number
232 [XX,YY,CC] = genfac3d(X,Y,C); // CC must be a color matrix of size nf x n
233 elseif (size(C) == (size(Z)-1)) // color number -1 == zdata number => ONLY flat mode can be enabled
236 Ctmp = [Ctmp; Ctmp($,:)]
237 [XX,YY,CC] = genfac3d(X,Y,Ctmp); // CC must be a color matrix of size nf x n
243 // check if the call is OK
245 err = execstr("[XX,YY,ZZ,CC] = CreateFacetsFromXYZ(X,Y,Z,current_figure, cur_draw_mode)","errcatch","n");
250 err = execstr("[XX,YY,ZZ,CC] = CreateFacetsFromXYZColor(X,Y,Z,C,current_figure, cur_draw_mode)","errcatch","n");
257 processSurfError(current_figure, cur_draw_mode);
262 // PARSING THE (PROPERTY - VALUE) SERIES
263 // =====================================
264 // P1 is the position of the first PropertyName field.
267 while ((Property <> 0) & (Property <= nv-1))
268 PropertyName = ListArg(Property);
269 PropertyValue = ListArg(Property+1);
272 PName = getSurfPropertyName(PropertyName);
273 if (PName == "xdata")
275 if (type(PropertyValue)<>1)
276 ResetFigureDDM(current_figure, cur_draw_mode);
277 error(msprintf(gettext("%s: Wrong type for input argument ''%s'': A Real matrix expected.\n"), "surf", "xdata"));
281 [XX,tmp2,tmp3] = CreateFacetsFromXYZ(PropertyValue,Y,Z,current_figure, cur_draw_mode);
284 elseif (PName == "ydata")
286 if (type(PropertyValue)<>1)
287 ResetFigureDDM(current_figure, cur_draw_mode);
288 error(msprintf(gettext("%s: Wrong type for input argument ''%s'': A Real matrix expected.\n"), "surf", "ydata"));
292 [tmp1,YY,tmp3] = CreateFacetsFromXYZ(X,PropertyValue,Z,current_figure, cur_draw_mode);
295 elseif (PName == "zdata")
297 if (type(PropertyValue)<>1) then
298 ResetFigureDDM(current_figure, cur_draw_mode);
299 error(msprintf(gettext("%s: Wrong type for input argument ''%s'': A Real matrix expected.\n"), "surf", "zdata"));
301 if (or(size(PropertyValue)==1)) then
302 ResetFigureDDM(current_figure, cur_draw_mode);
303 error(msprintf(gettext("%s: Wrong size for input argument ''%s'': A matrix of size greater than %d-by-%d expected.\n"), "surf", "zdata", 2, 2));
307 [tmp1,tmp2,ZZ] = CreateFacetsFromXYZ(X,Y,PropertyValue,current_figure, cur_draw_mode);
311 Property = Property+2;
314 if isempty(XX) | isempty(YY) | isempty(ZZ) then
315 // Nothing will be drawn so return (see http://bugzilla.scilab.org/13180 )
319 // surf is made now !
322 // PLOTTING THE SURFACE
323 // ====================
324 err = execstr("plot3d(XX,YY,list(ZZ,CC))","errcatch","n");
326 processSurfError(current_figure, cur_draw_mode);
328 // Default options (as Matlab ones)
330 a.cube_scaling = "on";
331 a.rotation_angles = [51 -125];
333 e.hiddencolor = 0; // to avoid painting the hidden facets
334 e.color_flag = 4; // Matlab special flat mode by default (different from mode 2)
335 e.cdata_mapping = "scaled"
340 // XYZ-DataMode under Matlab seems really bugged (see following samples and read Matlab doc.):
342 // surf(X,Y,Z,'XDataMode','auto')
343 // surf(X,Y,Z,'XDataMode','auto')
344 // surf(X+20,Y,Z,'XDataMode','auto')
345 // surf(X+20,Y,Z,'XDataMode','man')
346 // surf(X+20,Y,Z,'XDataMode','auto')
347 // surf(X+20,Y,Z,'Xdata',X-100,'XDataMode','auto')
348 // surf(X+20,Y,Z,'Xdata',X-100,'XDataMode','man')
349 // surf(X+20,Y,Z,'XData',X-100,'XDataMode','auto')
350 // surf(X+20,Y,Z,'XData',X-100,'XDataMode','man')
351 // surf(Z,'XData',X-100,'XDataMode','man')
352 // surf(Z,'XData',X-100,'XDataMode','auto')
353 // surf(X+20,Y,Z,'XDataMode','man')
354 // surf(X+20,Y,Z,'XDataMode','auto')
356 // That is why I do not support those properties.
357 // Below and in comment is the code we could add to treat those properties.
358 // by giving XYZ-DataModeVal to setSurfProperty (to better treat XYZ-Data input).
366 // XdataMode = getIndexInStringTable('xdatam',ListArg([Property nv]))
367 // if XdataMode <> []
368 // XdataModeVal = getIndexInStringTable(ListArg(XdataMode+1),['auto','manual'])
369 // if size(XdataModeVal,'*') <> 1
370 // disp("Error: Bad XdataMode selected");
375 // YdataMode = getIndexInStringTable('ydatam',ListArg([Property nv]))
376 // if YdataMode <> []
377 // YdataModeVal = getIndexInStringTable(ListArg(YdataMode+1),['auto','manual'])
378 // if size(YdataModeVal,'*') <> 1
379 // disp("Error: Bad YdataMode selected");
384 // ZdataMode = getIndexInStringTable('zdatam',ListArg([Property nv]))
385 // if ZdataMode <> []
386 // ZdataModeVal = getIndexInStringTable(ListArg(ZdataMode+1),['auto','manual'])
387 // if size(ZdataModeVal,'*') <> 1
388 // disp("Error: Bad ZdataMode selected");
396 // SETTING SPECIFIED PROPERTIES
397 // ============================
398 current_surface = gce(); // get the newly created fac3d
399 current_surface.mark_size_unit = "point";
400 Property = P1; // Position of the first PropertyName field.
401 while ((Property <> 0) & (Property <= nv-1))
402 setSurfProperty(ListArg(Property),ListArg(Property+1),current_surface,X,Y,Z,C,current_figure,cur_draw_mode)
403 Property = Property+2;
406 //postponed drawings are done now !
408 ResetFigureDDM(current_figure, cur_draw_mode);
413 //function [C] = build_interp_color(C,colormap_size)
414 //// C is considered as a data value in Matlab
418 //NCOLMAX = colormap_size;
421 // C = (NCOLMIN-NCOLMAX)/(MIN-MAX) * C + (MIN*NCOLMAX - NCOLMIN*MAX)/(MIN-MAX);
424 // C = ones(C) * (NCOLMIN+NCOLMAX)/2;
431 //function k=getIndexInStringTable(pattern,table)
433 // str = convstr(pattern);
434 // k=find(part(table,1:length(str))==str);
438 function [XX,YY,ZZ,CC] = CreateFacetsFromXYZ(X,Y,Z,current_figure, cur_draw_mode)
440 if or(size(X)==1) & or(size(Y)==1) // X and Y are vector
446 if size(X,"*") ~= size(Z,1) then
447 ResetFigureDDM(current_figure, cur_draw_mode);
448 error(msprintf(gettext("%s: Wrong size for input argument ''%s'': A vector of size %d expected.\n"), "surf", "Y", size(Z,1)));
452 if size(Y,"*") ~= size(Z,2) then
453 ResetFigureDDM(current_figure, cur_draw_mode);
454 error(msprintf(gettext("%s: Wrong size for input argument ''%s'': A vector of size %d expected.\n"), "surf", "X", size(Z,2)));
458 [XX,YY,ZZ] = genfac3d(Y,X,Z');
463 elseif and(size(X)>1) & and(size(Y)>1) // X and Y are matrix
465 if or(size(X) ~= size(Y)) then
466 ResetFigureDDM(current_figure, cur_draw_mode);
467 error(msprintf(gettext("%s: Wrong size for input arguments ''%s'' and ''%s'': Matrices of same size expected.\n"), "surf", "X", "Y"));
471 if or(size(X) ~= size(Z)) then
472 ResetFigureDDM(current_figure, cur_draw_mode);
473 error(msprintf(gettext("%s: Wrong size for input arguments ''%s'' and ''%s'': Matrices of same size expected.\n"), "surf", "X", "Z"));
477 [XX,YY,ZZ] = nf3d(X,Y,Z);
482 elseif or(size(X)==1) & and(size(Y)>1) // X is a vector and Y is a matrix
484 if size(X,"*") ~= size(Z,2) then
485 ResetFigureDDM(current_figure, cur_draw_mode);
486 error(msprintf(gettext("%s: Wrong size for input argument ''%s'': A vector of size %d expected.\n"), "surf", "X", size(Z,2)));
490 if or(size(Y) ~= size(Z)) then
491 ResetFigureDDM(current_figure, cur_draw_mode);
492 error(msprintf(gettext("%s: Wrong size for input arguments ''%s'' and ''%s'': Matrices of same size expected.\n"), "surf", "Y", "Z"));
500 X=X(:)'; // X is forced to be a row vector
507 [XX,YY,ZZ] = nf3d(XMAT,Y,Z);
512 elseif or(size(Y)==1) & and(size(X)>1) // Y is a vector and X is a matrix
514 if or(size(X) ~= size(Z)) then
515 ResetFigureDDM(current_figure, cur_draw_mode);
516 error(msprintf(gettext("%s: Wrong size for input arguments ''%s'' and ''%s'': Matrices of same size expected.\n"), "surf", "X", "Z"));
520 if size(Y,"*") ~= size(Z,2) then
521 ResetFigureDDM(current_figure, cur_draw_mode);
522 error(msprintf(gettext("%s: Wrong size for input argument ''%s'': A vector of size %d expected.\n"), "surf", "Y", size(Z,2)));
530 Y=Y(:); // Y is forced to be a column vector
537 [XX,YY,ZZ] = nf3d(X,YMAT,Z);
543 ResetFigureDDM(current_figure, cur_draw_mode);
544 error(msprintf(gettext("%s: Wrong size for input arguments ''%s'' and ''%s'': Same size expected.\n"), "surf", "X", "Y"));
550 function [XX,YY,ZZ,CC] = CreateFacetsFromXYZColor(X,Y,Z,C,current_figure, cur_draw_mode)
552 if or(size(X)==1) & or(size(Y)==1) // X and Y are vector
554 Z = Z'; // here a transposition is needed
555 C = C'; // here a transposition is needed
557 if size(X,"*") ~= size(Z,1) then
558 ResetFigureDDM(current_figure, cur_draw_mode);
559 error(msprintf(gettext("%s: Wrong size for input argument ''%s'': A vector of size %d expected.\n"), "surf", "X", size(Z,1)));
563 if size(Y,"*") ~= size(Z,2) then
564 ResetFigureDDM(current_figure, cur_draw_mode);
565 error(msprintf(gettext("%s: Wrong size for input argument ''%s'': A vector of size %d expected.\n"), "surf", "Y", size(Z,2)));
569 [XX,YY,ZZ] = genfac3d(X,Y,Z);
572 if (size(C) == size(Z)) // color number == zdata number
573 [XX,YY,CC] = genfac3d(X,Y,C); // CC must be a color matrix of size nf x n
574 elseif (size(C) == size(Z)-1) // color number -1 == zdata number => ONLY flat mode can be enabled
576 Ctmp = [C [C(:,$)]] ;
577 Ctmp = [Ctmp; Ctmp($,:)];
578 [XX,YY,CC] = genfac3d(X,Y,Ctmp); // CC must be a color matrix of size nf x n
581 elseif and(size(X)>1) & and(size(Y)>1) // X and Y are matrices
583 if or(size(X) ~= size(Y)) then
584 ResetFigureDDM(current_figure, cur_draw_mode);
585 error(msprintf(gettext("%s: Wrong size for input arguments ''%s'' and ''%s'': Matrices of same size expected.\n"), "surf", "X", "Y"));
589 if or(size(X) ~= size(Z)) then
590 ResetFigureDDM(current_figure, cur_draw_mode);
591 error(msprintf(gettext("%s: Wrong size for input arguments ''%s'' and ''%s'': Matrices of same size expected.\n"), "surf", "X", "Z"));
595 [XX,YY,ZZ] = nf3d(X,Y,Z);
598 if (size(C) == size(Z)) // color number == zdata number
599 [XX,YY,CC] = nf3d(X,Y,C); // CC must be a color matrix of size nf x n
600 elseif (size(C) == size(Z)-1) // color number -1 == zdata number => ONLY flat mode can be enabled
602 Ctmp = [C [C(:,$)]] ;
603 Ctmp = [Ctmp; Ctmp($,:)];
604 [XX,YY,CC] = nf3d(X,Y,Ctmp); // CC must be a color matrix of size nf x n
607 elseif or(size(X)==1) & and(size(Y)>1) // X is a vector and Y is a matrix
609 if size(X,"*") ~= size(Z,2) then
610 ResetFigureDDM(current_figure, cur_draw_mode);
611 error(msprintf(gettext("%s: Wrong size for input argument ''%s'': A vector of size %d expected.\n"), "surf", "X", size(Z,2)));
615 if or(size(Y) ~= size(Z)) then
616 ResetFigureDDM(current_figure, cur_draw_mode);
617 error(msprintf(gettext("%s: Wrong size for input arguments ''%s'' and ''%s'': Matrices of same size expected.\n"), "surf", "Y", "Z"));
625 X=X(:)'; // X is forced to be a row vector
634 [XX,YY,ZZ] = nf3d(XMAT,Y,Z);
637 if (size(C) == size(Z)) // color number == zdata number
638 [XX,YY,CC] = nf3d(XMAT,Y,C); // CC must be a color matrix of size nf x n
639 elseif (size(C) == size(Z)-1) // color number -1 == zdata number => ONLY flat mode can be enabled
641 Ctmp = [C [C(:,$)]] ;
642 Ctmp = [Ctmp; Ctmp($,:)];
643 [XX,YY,CC] = nf3d(XMAT,Y,Ctmp); // CC must be a color matrix of size nf x n
646 elseif or(size(Y)==1) & and(size(X)>1) // Y is a vector and X is a matrix
648 if or(size(X) ~= size(Z)) then
649 ResetFigureDDM(current_figure, cur_draw_mode);
650 error(msprintf(gettext("%s: Wrong size for input arguments ''%s'' and ''%s'': Matrices of same size expected.\n"), "surf", "X", "Z"));
654 if size(Y,"*") ~= size(Z,2) then
655 ResetFigureDDM(current_figure, cur_draw_mode);
656 error(msprintf(gettext("%s: Wrong size for input argument ''%s'': A vector of size %d expected.\n"), "surf", "Y", size(Z,2)));
665 Y=Y(:); // Y is forced to be a column vector
672 [XX,YY,ZZ] = nf3d(X,YMAT,Z);
675 if (size(C) == size(Z)) // color number == zdata number
676 [XX,YY,CC] = nf3d(X,YMAT,C); // CC must be a color matrix of size nf x n
677 elseif (size(C) == size(Z)-1) // color number -1 == zdata number => ONLY flat mode can be enabled
679 Ctmp = [C [C(:,$)]] ;
680 Ctmp = [Ctmp; Ctmp($,:)];
681 [XX,YY,CC] = nf3d(X,YMAT,Ctmp); // CC must be a color matrix of size nf x n
685 ResetFigureDDM(current_figure, cur_draw_mode);
686 error(msprintf(gettext("%s: Wrong size for input arguments ''%s'' and ''%s'': Matrices of same size expected.\n"), "surf", "X", "Y"));
692 // If an error occurs in the surf code, we need to catch it
693 // order to reset some default values
694 function processSurfError(cur_figure, cur_draw_mode)
696 ResetFigureDDM(current_figure, cur_draw_mode);
699 [err_message, err_number, err_line, err_func] = lasterror(%t);
703 // for now error can only have a single string as input.
704 // If there are several lines we need to concatane them.
705 err_message_nbLines = size(err_message, "*");
706 if (err_message_nbLines > 1) then
707 // put a \n betwee, each string
708 err_message(1) = strcat(err_message, "\n");
710 error(err_message(1), err_number);