contour2d corrected.
[scilab.git] / scilab / modules / graphics / macros / contour2d.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) INRIA
3 // Copyright (C) 2011 - DIGITEO - Michael Baudin
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.1-en.txt
9
10 function levels = contour2d(x, y, z, nz, style, strf, leg, rect, nax, void)
11
12     [lhs, rhs] = argn(0);
13
14     if rhs == 0 then
15         scf();
16         levels = contour2d(1:10, 1:10, rand(10,10), 5, rect = [0, 0, 11, 11]);
17         return;
18     end
19
20     if rhs < 4 then
21         error(msprintf(gettext("%s: Wrong number of input argument(s): At least %d expected.\n"), "contour2d", 4));
22     end
23
24     if type(x) <> 1 then
25         error(999, msprintf(gettext("%s: Wrong type for input argument #%d: Real vector expected.\n"), "contour2d", 1));
26     end
27
28     if type(y) <> 1 then
29         error(999, msprintf(gettext("%s: Wrong type for input argument #%d: Real vector expected.\n"), "contour2d", 2));
30     end
31
32     if type(z) <> 1 & type(z) <> 13 then
33         error(999, msprintf(gettext("%s: Wrong type for input argument #%d: Real matrix or Scilab function expected.\n"), "contour2d", 3));
34     end
35
36     if type(nz) <> 1 then
37         error(999, msprintf(gettext("%s: Wrong type for input argument #%d: Real matrix expected.\n"), "contour2d", 4));
38     end
39
40     if ~isvector(x) then
41         error(999, msprintf(gettext("%s: Wrong size for input argument #%d: Real vector expected.\n"), "contour2d", 1));
42     end
43
44     if ~isvector(y) then
45         error(999, msprintf(gettext("%s: Wrong size for input argument #%d: Real vector expected.\n"), "contour2d", 2));
46     end
47
48     opts = [];
49     levels = [];
50
51     if ~exists("style", "local") then
52         if size(nz, "*") == 1 then
53             style = 1:nz;
54         else
55             style = 1:size(nz, "*");
56         end
57     end
58
59     if exists("strf", "local") then
60         yflag = part(strf, 2);
61         if or(yflag == ["2" "4" "6" "8"]) then
62             rect = [min(x), min(y), max(x), max(y)];
63             yflag = string(evstr(yflag) - 1);
64             strf = part(strf, 1) + yflag + part(strf, 3);
65         end
66         opts = [opts,"strf=strf"];
67     end
68
69     if exists("leg", "local") then
70         opts = [opts, "leg=leg"];
71     end
72     rectSpecified = %f;
73     if exists("rect","local") then
74         opts = [opts, "rect=rect"];
75         rectSpecified = %t;
76     end
77     if exists("nax","local") then
78         opts = [opts, "nax=nax"];
79     end
80     if exists("logflag","local") then
81         opts = [opts, "logflag=logflag"];
82     end
83     if exists("frameflag","local") then
84         opts = [opts,"frameflag=frameflag"];
85     else
86         frameflag = [];
87     end
88     if exists("axesflag","local") then
89         opts = [opts, "axesflag=axesflag"];
90     end
91     opts = strcat([opts, "style=style(c)"], ",");
92
93     if or(type(z) == [11 13]) then
94         fun = z;
95         //to avoid redfinition warning
96         clear z
97         if type(fun) == 11 then
98             comp(fun);
99         end
100         z = feval(x, y, fun);
101     end
102
103     [xc, yc] = contour2di(x, y, z, nz);
104     fpf = xget("fpf");
105     if fpf == "" then
106         fpf = "%.3g";
107     end
108
109     fig = gcf();
110     a = gca();
111     autoc = a.auto_clear;
112     if autoc == "on" then
113         if ~isempty(a.children) then
114             delete(a.children);
115         end
116     end
117     v = fig.immediate_drawing;
118     fig.immediate_drawing = "off";
119     a.auto_clear = "off";
120     cnt = 0;
121
122
123     // we draw the contour with call to plot2d for each level line
124     // however the data_bounds will be always reset after each plot
125     // so we must compute before the bounding rectangle (xmin,ymin,xmax,ymax)
126     // and give it to each plot2d. This is useful for frameflag = (2,4,6,8)
127     // since the data_bounds are given by the extrema of x and y
128     if ( frameflag == 2 | frameflag == 4 | frameflag == 6 | frameflag == 8 )
129         // get the bounding rectangle
130         rect = [min(x), min(y), max(x), max(y)];
131         // set the option accordingly
132         if ~rectSpecified then
133             opts = strcat([opts, "rect=rect"], ",");
134         end
135         // the rect will be taken into account
136         frameflag = frameflag - 1 ;
137     elseif (~rectSpecified) then
138         // get rect any way for clipping
139         rect = [min(x), min(y), max(x), max(y)];
140     end
141
142     k = 1;
143     n = yc(k);
144     c = 0;
145     level = %inf;
146     while k < length(xc)
147         n = yc(k);
148         if xc(k) ~= level then
149             c = c + 1;
150             level = xc(k);
151             levels = [level levels];
152             if cnt>0 then
153                 glue(a.children(1:cnt));
154                 cnt = 0;
155             end
156         end
157         err = execstr("plot2d(xc(k + (1:n)), yc(k + (1:n))," + opts + ")", "errcatch", "m");
158         frameflag = 0;
159
160         // add a test to see if plot2d call succeed
161         // and, if not, restore good figure property values before exiting
162         if err <> 0
163             mprintf(gettext("Error %d : in plot2d called by contour2d"), err);
164             fig.immediate_drawing = v;
165             a.auto_clear = autoc;
166             return;
167         end
168
169         unglue(a.children(1))
170         cnt = cnt + 1;
171
172         if stripblanks(fpf) <> "" then
173             labelText = " " + msprintf(fpf, level);
174             labelPos = [xc(k + 1 + n/2), yc(k + 1 + n/2)];
175             labelBox = stringbox(labelText, labelPos(1), labelPos(2));
176             // check that the text is not outside the box
177             // better than clipping to avoid half cut strings
178             if labelBox(1,1) > rect(1) & labelBox(2,1) > rect(2) & ..
179                 labelBox(1,3) < rect(3) & labelBox(2,3) < rect(4) then
180                 xstring(labelPos(1), labelPos(2), labelText)
181                 e = gce();
182                 e.clip_state = "off";
183                 cnt = cnt + 1;
184             end
185         end
186         k = k + n + 1;
187     end
188
189     if cnt > 0 then
190         glue(a.children(1:cnt));
191         cnt = 0;
192     end
193     set("current_entity", a);
194     fig.immediate_drawing = v;
195 endfunction