scatterScanVargin and ScatterSetPolyline moved to scatter3
[scilab.git] / scilab / modules / graphics / macros / scatter3.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) Scilab Enterprises - 2015 - 2012 - Juergen Koch <juergen.koch@hs-esslingen.de>
3 // 
4 // This file must be used under the terms of the CeCILL.
5 // This source file is licensed as described in the file COPYING, which
6 // you should have received as part of this distribution.  The terms
7 // are also available at    
8 // http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
9
10 function polyLine = scatter3(varargin)
11
12     polyLine = 0;
13     [lhs,rhs] = argn(0);
14
15     if ~rhs
16         clf;
17         z = linspace(0,25,200);
18         x = z.*cos(z);
19         y = z.*sin(z);
20         polyLine = scatter3(x,y,z,z,z,"fill","markerEdgeColor","darkblue");
21         set(gca(),"rotation_angles",[60,45])
22         return;
23     end
24
25    //detect and set the current axes now:
26     if type(varargin(1)) == 9 then // graphic handle
27         hdle = varargin(1);
28         if hdle.type == "Axes" then
29             if size(varargin) < 4 then
30                 warning("Not enough input arguments.")
31                 return;
32             else
33                 axesHandle = varargin(1);
34                 X = varargin(2);
35                 Y = varargin(3);
36                 Z = varargin(4);
37                 nextArgin = 5;
38             end
39         else
40             warning("Handle should be an Axes handle.")
41             return;
42         end
43     else
44         if size(varargin) < 3 then
45             warning("Not enough input arguments.")
46             return;
47         else
48             axesHandle = [];
49             X = varargin(1);
50             Y = varargin(2);
51             Z = varargin(3);
52             nextArgin = 4;
53         end
54     end
55
56     if (isempty(X) & isempty(Y) & isempty(Z)) then
57         // nothing has to be done
58         return;
59     end
60     
61     if ( isempty(Z) ) then
62         if (~isvector(X) | ~isvector(Y) | size(X) ~= size(Y)) then
63             warning("X and Y must be vectors of the same length.")
64             return;
65         end
66     else
67         if (~isvector(X) | ~isvector(Y) | ~isvector(Z) | or(size(X) ~= size(Y)) | or(size(X) ~= size(Z))) then
68             warning("X, Y and Z must be vectors of the same length.")
69             return;
70         end
71     end
72         
73     n = length(X);
74     [S,C,thickness,markStyle,markFg,markBg,fill,scanFailed] = scatterScanVargin(varargin,nextArgin,n);
75     if (scanFailed) then
76         return;
77     end
78     
79     drawlater();
80
81     if isempty(Z) then 
82         if isempty(axesHandle) then
83             plot(X,Y);
84         else
85             plot(axesHandle,X,Y);
86         end
87         currentEntity = gce();
88         polyLine = currentEntity.children;
89     else
90         if isempty(axesHandle) then
91             param3d(X,Y,Z);
92         else
93             set("current_axes",axesHandle)
94             param3d(X,Y,Z);
95         end
96         polyLine = gce();
97     end
98     
99     if polyLine.Type <> "Polyline" then
100         warning("Handle should be a Polyline handle.");
101         return;
102     end
103
104     scatterSetPolyline(polyLine,S,C,thickness,markStyle,markFg,markBg,fill);
105     
106     if ~isempty(Z) then
107         set(gca(),"cube_scaling","on");
108         set(gca(),"grid",[1 1 1]);
109     end
110     
111     drawnow();
112
113 endfunction
114
115 function [S,C,thickness,markStyle,markFg,markBg,fill,scanFailed] = scatterScanVargin(argins,nextArgin,n)
116
117     scanFailed = %F;
118     
119     // check for size argument
120     S = [];
121     if  size(argins) >= nextArgin then
122         if isempty(argins(nextArgin)) then
123             nextArgin = nextArgin + 1;
124         else
125             if type(argins(nextArgin)) == 1 then
126                 [n1,n2] = size(argins(nextArgin));
127                 if (n1 == 1 & n2 == 1) | (n1 == n & n2 == 1) | (n1 == 1 & n2 == n) then
128                     S = argins(nextArgin);
129                     if iscolumn(S) then
130                         S = S.';
131                     end
132                     nextArgin = nextArgin + 1;
133                 else
134                     warning("S must be a scalar or a vector of the same length as X.");
135                     scanFailed = %T;
136                     return;
137                 end
138             end
139         end
140     end
141
142     // check for color argument
143     C = [];
144     if  size(argins) >= nextArgin then
145         if isempty(argins(nextArgin)) then
146             nextArgin = nextArgin + 1;
147         else
148             [n1,n2] = size(argins(nextArgin));
149             if type(argins(nextArgin)) == 1 then
150                 if (n1 == n & n2 == 1) | (n1 == 1 & n2 == n) then
151                     C = scatterLinearColorMap(argins(nextArgin));
152                     nextArgin = nextArgin + 1;
153                 elseif n1 == n & n2 == 3 then
154                     C = addcolor(argins(nextArgin));            
155                     nextArgin = nextArgin + 1;
156                 else
157                     warning("C must be a vector or a matrix of the same length as X.");
158                     scanFailed = %T;
159                     return;
160                 end
161                 if iscolumn(C) then
162                     C = C.';
163                 end
164             elseif type(argins(nextArgin)) == 10 then
165                 if n1 == 1 & n2 == 1 then
166                     // check if string specifies a color
167                     colorRGB = name2rgb(argins(nextArgin));
168                     if ~isempty(colorRGB) then
169                         C = addcolor(colorRGB/255);
170                         nextArgin = nextArgin + 1;
171                     end        
172                 elseif (n1 == n & n2 == 1) | (n1 == 1 & n2 == n) then
173                     C = addcolor(name2rgb(argins(nextArgin))/255);
174                     if isempty(C) then
175                         warning("Wrong color specified.");
176                         scanFailed = %T;
177                         return;
178                     else
179                          nextArgin = nextArgin + 1;
180                     end
181                 end
182             end
183         end
184     end
185
186     // check for "fill" argument
187     fill = %F;
188     if  size(argins) >= nextArgin then
189         if type(argins(nextArgin)) == 10 then
190             if argins(nextArgin) == "fill" then
191                 fill = %T;
192                 nextArgin = nextArgin + 1;
193             end
194         end
195     end
196
197     // check for marker argument
198     markStyle = 9; // default circle
199     if  size(argins) >= nextArgin then
200         if type(argins(nextArgin)) == 10 then
201             ms = getMarkStyle(argins(nextArgin));
202             if ms >= 0 & ms <= 14 then
203                 markStyle = ms;
204                 nextArgin = nextArgin + 1;
205             end
206         end
207     end
208
209     // check for property-value pairs
210     markFg = -1;
211     markBg = -1;
212     thickness = 1.0; // default
213     while  size(argins) >= nextArgin do
214         if size(argins) == nextArgin then
215             warning("Incorrect number of inputs for property-value pairs.");
216             scanFailed = %T;
217             return;
218         else
219             select argins(nextArgin)
220             case "marker"
221                 markStyle = getMarkStyle(argins(nextArgin+1));
222                 if markStyle == -1 then
223                     warning(strcat([argins(nextArgin+1) " is not a valid value for property marker."]));
224                     scanFailed = %T;
225                     return;
226                 end
227             case "markerStyle"
228                 markStyle = getMarkStyle(argin(nextArgin+1));
229                 if markStyle == -1 then
230                     warning(strcat([argins(nextArgin+1) " is not a valid value for property markerStyle."]));
231                     scanFailed = %T;
232                     return;
233                 end
234             case "markerEdgeColor"
235                 markFg = colorIndex(argins(nextArgin+1));
236                 if markFg == -1 then
237                     warning(strcat([argins(nextArgin+1) " is not a valid value for property markerEdgeColor."]));
238                     scanFailed = %T;
239                     return;
240                 end;
241             case "markerForeground"
242                 markFg = colorIndex(argins(nextArgin+1));
243                 if markFg == -1 then
244                     warning(strcat([argins(nextArgin+1) " is not a valid value for property markerForeground."]));
245                     scanFailed = %T;
246                     return;
247                 end;
248             case "markerFaceColor"
249                 fill = %T;
250                 markBg = colorIndex(argins(nextArgin+1));
251                 if markBg == -1 then
252                     warning(strcat([argins(nextArgin+1) " is not a valid value for property markerFaceColor."]));
253                     scanFailed = %T;
254                     return;
255                 end;
256             case "markerBackground"
257                 fill = %T;
258                 markBg = colorIndex(argins(nextArgin+1));
259                 if markBg == -1 then
260                     warning(strcat([argins(nextArgin+1) " is not a valid value for property markerBackground."]));
261                     scanFailed = %T;
262                     return;
263                 end;
264             case "linewidth"
265                 if type(argins(nextArgin+1)) == 1 then
266                     thickness = argins(nextArgin+1);
267                 else
268                     warning(strcat([argins(nextArgin+1) " is not a valid value for property linewidth."]));
269                     scanFailed = %T;
270                     return;
271                 end 
272             case "thickness"
273                 if type(argins(nextArgin+1)) == 1 then
274                     thickness = argins(nextArgin+1);
275                 else
276                     warning(strcat([argins(nextArgin+1) " is not a valid value for property thickness."]));
277                     scanFailed = %T;
278                     return;
279                 end
280             else
281                 warning(strcat(["There is no " argins(nextArgin) " property on the Scatter class."]));
282                 scanFailed = %T;
283                 return;
284             end
285         end
286         nextArgin = nextArgin + 2;
287     end
288
289 endfunction
290
291 function colorInd = colorIndex(colorSpec)
292     colorInd = -1;
293     if type(colorSpec) == 10 & size(colorSpec) == [1 1] then
294         colorRGB = name2rgb(colorSpec);
295         if ~isempty(colorRGB) then
296             colorInd = addcolor(colorRGB/255);
297             return;
298         end
299     elseif type(colorSpec) == 1 & (size(colorSpec) == [1 3] | size(colorSpec) == [3 1]) then
300         colorInd = addcolor(colorSpec);
301         return; 
302     end
303     warning("Specified string is an invalid color value.");
304 endfunction
305
306 function markStyle = getMarkStyle(name)
307     if type(name) ~= 10 then
308         markStyle = -1;
309     else
310         select name
311         case "."
312             markStyle = 0;
313         case "+"
314             markStyle = 1;
315         case "x"
316             markStyle = 2;
317         case "circle plus"
318             markStyle = 3;
319         case "filled diamond"
320             markStyle = 4;
321         case "d"
322             markStyle = 5;
323         case "diamond"
324             markStyle = 5;
325         case "^"
326             markStyle = 6;
327         case "v"
328             markStyle = 7;
329         case "diamond plus"
330             markStyle = 8;
331         case "o"
332             markStyle = 9;
333         case "*"
334             markStyle = 10;
335         case "s"
336             markStyle = 11;
337         case "square"
338             markStyle = 11;
339         case ">"
340             markStyle = 12;
341         case "<"
342             markStyle = 13;
343         case "p"
344             markStyle = 14;
345         case "pentagram"
346             markStyle = 14;
347         else
348             markStyle = -1;
349         end
350     end
351 endfunction
352
353 function colorIndex = scatterLinearColorMap(colorValue)
354     cMin = min(colorValue);
355     cMax = max(colorValue);
356     cmap = get(gcf(),"color_map");
357     numColors = size(cmap,1);
358     if (cMax-cMin > %eps) then
359         colorIndex = (numColors-1)*(colorValue - cMin)/(cMax - cMin) + 1;
360     else
361         colorIndex = 1; // default color index
362     end
363 endfunction
364
365 function scatterSetPolyline(polyLine,S,C,thickness,markStyle,markFg,markBg,fill)
366
367     // set mark mode
368     polyLine.line_mode = "off";
369     polyLine.mark_mode = "on";
370
371     // set thickness
372     polyLine.thickness = thickness;
373
374     // set mark style
375     polyLine.mark_style = markStyle;
376
377     // set mark size
378     polyLine.mark_size_unit = "point";
379     if isempty(S) then
380         polyLine.mark_size = 7;
381     else
382         if size(S) == [1 1] | size(S) == [1 n]
383             polyLine.mark_size = ceil(sqrt(4*S/%pi));
384         else
385             warning("S must be a scalar or a vector of the same length as X.");
386             return;
387         end
388     end
389
390     // set mark foreground and background color
391     if isempty(C) then
392         if markFg == -1 then
393             markFg = addcolor(name2rgb("blue")/255); // default
394         end
395         polyLine.mark_foreground = markFg;
396         if markBg == -1 then
397             markBg = markFg;
398         end
399         if fill == %T then
400             polyLine.mark_background = markBg;
401         else
402             polyLine.mark_background = 0; // transparent
403         end
404      else
405         if size(C) == [1 1] then
406             polyLine.mark_foreground = C; 
407             if fill == %T then
408                 polyLine.mark_background = C;
409             else
410                 if markBg == -1 then
411                     polyLine.mark_background = 0; // transparent
412                 else
413                     polyLine.mark_background = markBg;
414                 end
415             end
416         else
417             if fill == %T then
418                 if markFg == -1 then
419                     polyLine.mark_foreground = C; // transparent
420                 else
421                     polyLine.mark_foreground = markFg;
422                 end
423                 polyLine.mark_background = C;
424             else
425                 polyLine.mark_foreground = C;
426                 if markBg == -1 then
427                     polyLine.mark_background = 0; // transparent
428                 else
429                     polyLine.mark_background = markBg;
430                 end
431             end
432         end
433     end
434
435 endfunction