// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab // Copyright (C) 2004-2006 - INRIA - Fabrice Leray // Copyright (C) 2008 - INRIA - Jean-Baptiste Silvy // This file must be used under the terms of the CeCILL. // This source file is licensed as described in the file COPYING, which // you should have received as part of this distribution. The terms // are also available at // http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt function plot(varargin) // Try to build a new better parser that could manage things like: // plot(x,y,'X',1:10); // where X stands for Xdata (Matlab recognizes //it and treats it well...) [lhs,rhs]=argn(0); if ~rhs //LineSpec and PropertySpec examples: t = 0:%pi/20:2*%pi; tt = t'; drawlater(); subplot(211); plot(tt, sin(tt), "ro-.", tt, cos(tt), "cya+", tt, abs(sin(tt)), "--mo"); subplot(212); plot([t ;t],[sin(t); cos(t)],"xdat",[1:2]); drawnow(); return; end CurColor = 0; // current color used if no color specified via LineSpec // nor PropertyName ListArg = varargin; //detect and set the current axes now: if type(ListArg(1)) == 9 hdle = ListArg(1); if (hdle.type == "Axes") sca(ListArg(1)); ListArg(1) = null(); // remove this parameter from the list else warning("Handle should be an Axes handle") return; end end nv = size(ListArg) argTypes=[]; couple=[]; typeOfPlot = "plot"; provided_data = 2; for curArgIndex=1:nv argTypes(curArgIndex,1) = type(ListArg(curArgIndex)) end Ttmp=argTypes; for i=1:nv-1 acceptedTypes=[]; acceptedTypes=find(Ttmp(i,1)==1 & or(Ttmp(i+1,1)==[1,13,130])) // to accept double, macro function or primitive as second argument if (acceptedTypes<>[]) then couple=[couple i]; Ttmp(i,1) = 99; // Replace a known type by 99 (no meaning) to count it once only! Ttmp(i+1,1)= 99; // to avoid having (x1,y1,x2,y2) ->couple=[1,2,3] // With this trick, couple=[1,3]; end end if (couple==[]) // No data couple found // Search for at least a single data , i.e.: plot(y) if ((argTypes(1,1)==1 | argTypes(1,1)==8) & ListArg(1)<>[]) then // case plot(SINGLE y,...) couple = 1; provided_data = 1; if (modulo(nv-couple,2)<>0) then P1 = couple+2 // Position of the first PropertyName field else P1 = couple+1 end else warning("Error inside input argument : no data"); return; end else // Some test to check wrong inputs // // 1. Test if 2 data couples (first : type==1, second : type=[1,13,130]) // are at least separated by 2 indices if (couple(2:$)-couple(1:$-1)<2) warning("Error inside input argument !"); return; end // 2. Test if no string couples happen before P1 (see below for P1 definition) for index=1:couple($) acceptedTypes=[]; acceptedTypes=find(Ttmp(index,1)==10 & Ttmp(index+1,1)==10) if (acceptedTypes<>[]) then warning("Error inside input argument : String argument is an unknown option."); return; end end if (modulo(nv-(couple($)+1),2)<>0) then P1 = couple($)+3 // Position of the first PropertyName field else P1 = couple($)+2 end end numplot = size(couple,"*"); xyIndexLineSpec = zeros(numplot,3); // xyIndexLineSpec is a matrix storing the index of x, y and linespec // if one of these indices is 0 => it does not exist // (which is possible for x and linepsec, not for y) if (provided_data == 2) then for curCouple=1:size(couple,"*") xyIndexLineSpec(curCouple,1:2) = couple(curCouple) +[0,1] // x,y index storage if (couple(curCouple)+2 < P1) if (argTypes(couple(curCouple)+2,1)==10) then // LineSpec treatment xyIndexLineSpec(curCouple,3) = couple(curCouple)+2; end end end else // we are in the case where: plot(SINGLE y,... x not specified // or plot(handle,SINGLE y,... xyIndexLineSpec(1,1) = 0; // no x specified xyIndexLineSpec(1,2) = couple; //pause; if (couple+1 < P1) if (argTypes(couple+1,1)==10) then // LineSpec treatment xyIndexLineSpec(1,3) = couple+1; end end end // delay the drawing commands // smart drawlater current_figure=gcf(); cur_draw_mode = current_figure.immediate_drawing; current_figure.immediate_drawing = "off"; // check wether this is the first plot for the axes in which we will draw curAxes = gca(); // save auto_clear state. OldAutoClear = curAxes.auto_clear; isFirstPlot = (curAxes.children == []) //Now, we plot the decomposed plots one by one with their own linespec // provided_data = 2 : x and y are provided FinalAgreg=[]; // Final Compound containing all the new created plots. //for i=numplot:-1:1 for i=1:numplot // Set off auto_clear for allowing multiple graphics entity // will be restored behond if i>1 then curAxes.auto_clear="off"; end //default values Marker=[]; MarkerSize=1; Color=[]; LineStyle=1; Line = %F; Marker = %F; if (provided_data == 2) then if (type(ListArg(xyIndexLineSpec(i,2))) == 13 | type(ListArg(xyIndexLineSpec(i,2))) == 130) // A function (macro or primitive) is given. We need to build the vector or matrix. sizefirstarg = size(ListArg(xyIndexLineSpec(i,1))); buildFunc = ListArg(xyIndexLineSpec(i,2)); firstarg = ListArg(xyIndexLineSpec(i,1)); tmp = []; for ii=1:sizefirstarg(1,2) for jj=1:sizefirstarg(1,1) // function evaluation may fail // try/cacth is buggy for now // so use execstr until the bug is fixed err = execstr("tmp(jj,ii) = buildFunc(firstarg(jj,ii))","errcatch","n"); if (err <> 0) then // reset data ResetFigureDDM(current_figure, cur_draw_mode); // get error [err_message, err_number, err_line, err_func] = lasterror(%t); clear buildFunc; // print it if (err_func <> "") then // ascii(10) = \n error(msprintf(gettext("%s: Error : unable to evaluate input function ''%s''.") + ascii(10) + gettext("Error %d at line %d of the function: ''%s''"), "plot", err_func,err_number, err_line, err_message)); else error(msprintf(gettext("%s: Error : unable to evaluate input function.") + ascii(10) + gettext("Error %d at line %d of the function: ''%s''"), "plot", err_number, err_line, err_message)); end // exit function return; end end end ListArg(xyIndexLineSpec(i,2)) = tmp; // if there is an other iteration, we will have error message redefining function. // we need to clear here and not before, because user must see the warning if needed. clear buildFunc; end [X,Y] = checkXYPair(typeOfPlot,ListArg(xyIndexLineSpec(i,1)),ListArg(xyIndexLineSpec(i,2)),current_figure,cur_draw_mode) else if or(size(ListArg(xyIndexLineSpec(1,2)))==1) // If this is a vector if size(ListArg(xyIndexLineSpec(1,2)), "r") == 1 then X=1:length(ListArg(xyIndexLineSpec(1,2))); // insert a column abcsissa vector of same length, else X=(1:length(ListArg(xyIndexLineSpec(1,2))))'; // insert a row abcsissa vector of same length, end else // if this is a matrix, X=(1:size(ListArg(xyIndexLineSpec(1,2)),1))'; // insert a row abcsissa vector with same size end // In both cases (matrix/vector), transpose it now so no warning is issued in checkXYPair(). [X,Y] = checkXYPair(typeOfPlot,X,ListArg(xyIndexLineSpec(1,2)),current_figure,cur_draw_mode) end // Case if 'Xdata', 'Ydata' or 'Zdata' have been set in (PropertyName,Propertyvalue) couples // must be taken into account now // P1 is the position of the first PropertyName field. Property = P1; while (Property <= nv-1) PropertyName = ListArg(Property); PropertyValue = ListArg(Property+1); // Xdata can ONLY be a vector (cf. Matlab help) PName = getPlotPropertyName(PropertyName,current_figure,cur_draw_mode); if (PName == "xdata") if (type(PropertyValue)<>1 | and(size(PropertyValue)<>1)) warning("Xdata value must be a column or row vector."); ResetFigureDDM(current_figure, cur_draw_mode); return; else PropertyValue = PropertyValue(:); // force if or(size(X))==1 // If X is a vector (inevitably a column vector because checkXYPair always returns a column vector) X = PropertyValue; // X is replaced by PropertyValue [X,Y] = checkXYPair(typeOfPlot,X,Y,current_figure,cur_draw_mode) else // X is a matrix if size(PropertyValue,"*") == size(X,1) for j=1:size(PropertyValue,"*") X(j,:) = PropertyValue(j,1); end else str="plot : incompatible dimensions in input arguments"; warning(str); ResetFigureDDM(current_figure, cur_draw_mode); end end end // Ydata ONLY be a vector (contrary to what is said by the Matlab help) elseif (PName == "ydata") if (type(PropertyValue)<>1 | and(size(PropertyValue)<>1)) warning("Ydata value must be a column or row vector."); ResetFigureDDM(current_figure, cur_draw_mode); return; else PropertyValue = PropertyValue(:); // force if or(size(Y))==1 // If Y is a vector (inevitably a column vector because checkXYPair always returns a column vector) Y = PropertyValue; // Y is replaced by PropertyValue [X,Y] = checkXYPair(typeOfPlot,X,Y,current_figure,cur_draw_mode) else // Y is a matrix if size(PropertyValue,"*") == size(Y,1) for j=1:size(PropertyValue,"*") Y(j,:) = PropertyValue(j); end else str="plot : incompatible dimensions in input arguments"; warning(str); ResetFigureDDM(current_figure, cur_draw_mode); end end end // Zdata will be treated after plot building end Property = Property+2; end //Now we have an array xyIndexLineSpec [numplot x 3] containing indices pointing on T for : // - x (<>0 if existing) // - y // - linespec (<>0 if existing) // for each plot passed in argument // x | y | linespec // ---------------- //plot1 0|i1 |0 <=> plot(y) //plot2 i2|i3 |0 <=> plot(x,y) //plot3 i4|i5 |i6 <=> plot(x,y,LINESPEC) //... if (xyIndexLineSpec(i,3)<>0) then // if we have a line spec <=> index <> 0 [Color,Line,LineStyle,Marker,MarkerStyle,MarkerSize,fail] = getLineSpec(ListArg(xyIndexLineSpec(i,3)),current_figure,cur_draw_mode); end // The plot is made now : err = execstr("plot2d(X,Y)","errcatch","m"); if err <> 0 mprintf("Error %d : in plot2d called by plot",err); ResetFigureDDM(current_figure, cur_draw_mode); return; end agreg=gce(); // when using plot2d, we always have an Compound as the current entity FinalAgreg = [agreg FinalAgreg]; if Color==[] DefaultColor = %T; else DefaultColor = %F; end for ii=size(agreg.children,"*"):-1:1 curPolyline=agreg.children(ii); // we apply linespec to the lines // Color treatment : if no color specified by LineSpec nor PropertyName // Set the default color to the curve if DefaultColor == %T [Color,CurColor] = setDefaultColor(CurColor); end if (Marker == %T) curPolyline.mark_style=MarkerStyle; curPolyline.mark_mode ="on"; curPolyline.mark_foreground = Color; curPolyline.mark_style=MarkerStyle; curPolyline.mark_size=MarkerSize; else curPolyline.mark_mode ="off" end if (Line == %T) curPolyline.line_mode="on"; curPolyline.foreground = Color; curPolyline.line_style = LineStyle; else curPolyline.line_mode="off" end if (Line == %F & Marker ==%F) // no linespec nor PropertyName set curPolyline.line_mode="on"; curPolyline.foreground = Color; curPolyline.line_style = LineStyle; end end end //Reset auto_clear Property curAxes.auto_clear = OldAutoClear; /////////////////////////////////// //Global Property treatment // //PropertyName and PropertyValue // /////////////////////////////////// // Those properties will be applied to Agreg children Agreg = glue(FinalAgreg(1:$)) nbCompound = find(Agreg.children.type=="Compound") while (nbCompound<>[]) nbCompound=nbCompound(1); unglue(Agreg.children(nbCompound)); nbCompound=find(Agreg.children.type=="Compound") end // P1 is the position of the first PropertyName field. Property = P1; Curves = Agreg.children //Curves(:,1) = Curves(:,$:-1:1); // set mark_size_unit to 'point' for all the curves Curves.mark_size_unit="point"; while (Property <= nv-1) setPlotProperty(ListArg(Property),ListArg(Property+1),Curves,current_figure,cur_draw_mode) Property = Property+2; end // force drawing of box like in matlab // for a first plot // unless we are using centered axes // to keep compatibility with Scilab 4 if isFirstPlot & curAxes.x_location <> "origin" & curAxes.y_location <> "origin" then curAxes.box = "on"; end //postponed drawings are done now ! // smart drawnow ResetFigureDDM(current_figure, cur_draw_mode) endfunction