* Bug 16304 fixed: implicitplot() => plotimplicit() improved 63/21263/5
Samuel GOUGEON [Tue, 28 Jan 2020 23:11:48 +0000 (00:11 +0100)]
  http://bugzilla.scilab.org/16304
  plotimplicit overhauled page (PDF): http://bugzilla.scilab.org/attachment.cgi?id=5055

  This commit supersedes https://codereview.scilab.org/#/c/20956/

  Vectorization enhancement:
--> clf, tic(), implicitplot("x*(x^2 + y^2) - 5*(x^2 - y^2)",-3:0.01:6,-5:0.01:5), toc()
 ans  =
   19.354552

--> clf, tic(), plotimplicit("x*(x^2 + y^2) - 5*(x^2 - y^2)",-3:0.01:6,-5:0.01:5), toc()
 ans  =
   1.5225525

Change-Id: I167b7aa37450ed103f610ae3a8680a13abadd32f

21 files changed:
scilab/CHANGES.md
scilab/modules/graphics/help/en_US/2d_plot/implicitplot.xml [deleted file]
scilab/modules/graphics/help/en_US/2d_plot/plotimplicit.xml [new file with mode: 0644]
scilab/modules/graphics/macros/implicitplot.sci [deleted file]
scilab/modules/graphics/macros/plotimplicit.sci [new file with mode: 0644]
scilab/modules/graphics/tests/unit_tests/implicitplot.dia.ref [deleted file]
scilab/modules/graphics/tests/unit_tests/implicitplot.tst [deleted file]
scilab/modules/graphics/tests/unit_tests/plotimplicit.dia.ref [new file with mode: 0644]
scilab/modules/graphics/tests/unit_tests/plotimplicit.tst [new file with mode: 0644]
scilab/modules/helptools/data/configuration/scilab_macros.txt
scilab/modules/helptools/data/pages/homepage-en_US.html
scilab/modules/helptools/etc/images_md5.txt
scilab/modules/helptools/images/_LaTeX_implicitplot.xml_1.png [deleted file]
scilab/modules/helptools/images/implicitplot_1.png [deleted file]
scilab/modules/helptools/images/implicitplot_2.png [deleted file]
scilab/modules/helptools/images/implicitplot_3.png [deleted file]
scilab/modules/helptools/images/implicitplot_4.png [deleted file]
scilab/modules/helptools/images/plotimplicit_1.png [new file with mode: 0644]
scilab/modules/helptools/images/plotimplicit_2.png [new file with mode: 0644]
scilab/modules/helptools/images/plotimplicit_3.png [new file with mode: 0644]
scilab/modules/helptools/images/plotimplicit_4.png [new file with mode: 0644]

index 6b389cc..99c3f55 100644 (file)
@@ -158,6 +158,7 @@ Feature changes and additions
 * `twinkle` can now blink together several hierarchically independent objects, like a curve and its labels, etc.
 * `repmat` has been rewritten. It is 7 times faster now.
 * `plot` can now work in semi or bi-logarithmic mode with some input logflag.
+* `plotimplicit()` function added.
 
 
 Help pages:
diff --git a/scilab/modules/graphics/help/en_US/2d_plot/implicitplot.xml b/scilab/modules/graphics/help/en_US/2d_plot/implicitplot.xml
deleted file mode 100644 (file)
index c72b81e..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
- * Copyright (C) 2014 - Scilab Enterprises - Pierre-Aimé Agnel
- *
- * 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
- *
- -->
-<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org"  xml:lang="en" xml:id="implicitplot">
-    <refnamediv>
-        <refname>implicitplot</refname>
-        <refpurpose>Implicit plot</refpurpose>
-    </refnamediv>
-    <refsynopsisdiv>
-        <title>Calling Sequence</title>
-        <synopsis>
-            implicitplot(fun, [x_range, [y_range]])
-            implicitplot(fun, x_range, y_range, [options])
-            implicitplot(f_eval, x_range, y_range, [options])
-        </synopsis>
-    </refsynopsisdiv>
-    <refsection>
-        <title>Arguments</title>
-        <variablelist>
-            <varlistentry>
-                <term>fun</term>
-                <listitem>
-                    <para>
-                        a string or a function of variables x and y. The function to plot.
-                        
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>f_eval</term>
-                <listitem>
-                    <para>
-                        a real matrix of size <literal>[length(x_range), length(y_range)]</literal>. The evaluation of the function to plot on all points in <literal>x_range</literal> and <literal>y_range</literal>.
-                        
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>x_range</term>
-                <listitem>
-                    <para>
-                        a real vector. The x values over which the function is sampled.
-                        
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>y_range</term>
-                <listitem>
-                    <para>
-                        a real vector. The y values over which the function is sampled.
-                        
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>options</term>
-                <listitem>
-                    <para>
-                        a list of options. The plot optional parameters.
-                        
-                    </para>
-                </listitem>
-            </varlistentry>
-        </variablelist>
-    </refsection>
-    <refsection>
-        <title>Description</title>
-        <para>
-            <literal>implicitplot(fun, x_range, y_range)</literal> draws the implicit function defined by
-            <literal>fun(x, y) = 0</literal> by evaluating <literal>fun</literal> over
-            <varname>x_range</varname> and <varname>y_range</varname>.
-        </para>
-        <para>
-            If <varname>x_range</varname> or <varname>y_range</varname> is omitted, the range chosen is 100 points taken in <latex>$[-1, 1]$</latex>.
-        </para>
-        <para>
-            The function <varname>fun</varname> may be defined as a compiled scilab function, an uncompiled function or a string. The function must
-            take <literal>x</literal> and <literal>y</literal> as input parameters.
-        </para>
-        <para>
-            The options defined by the <varname>options</varname> parameter can be any options of the <link linkend="plot">plot</link> function.
-        </para>
-    </refsection>
-    <refsection>
-        <title>Examples</title>
-        <programlisting role="example"><![CDATA[
-            // Draw a circle of radius 1
-            implicitplot("x^2 + y^2 - 1")
- ]]></programlisting>
-        <scilab:image>
-            implicitplot("x^2 + y^2 - 1")
-        </scilab:image>
-        <programlisting role="example"><![CDATA[
-            function z = F(x, y)
-                z = x*(x^2 + y^2) - 5*(x^2 - y^2);
-            endfunction
-
-            x_range = -3:0.1:6;
-            y_range = -5:0.1:5;
-
-            // Draw the curve in the [-3 6] x [-5 5] range
-            implicitplot(F, x_range, y_range)
- ]]></programlisting>
-        <scilab:image>
-            function z = F(x, y)
-            z = x*(x^2 + y^2) - 5*(x^2 - y^2);
-            endfunction
-            
-            x_range = -3:0.1:6;
-            y_range = -5:0.1:5;
-            
-            implicitplot(F, x_range, y_range)
-        </scilab:image>
-        <programlisting role="example"><![CDATA[
-            function result = fun(x, y)
-                result = 3*x^2*exp(x) - x*y^2 +  exp(y)/(y^2 + 1) - 1
-            endfunction
-
-            x_range = -1:0.1:1;
-            y_range = -10:0.1:10;
-
-            // Draw curve with red dashed line
-            implicitplot(fun, x_range, y_range, "r--")
- ]]></programlisting>
-        <scilab:image>
-            function result = fun(x, y)
-            result = 3*x^2*exp(x) - x*y^2 +  exp(y)/(y^2 + 1) - 1
-            endfunction
-            
-            x_range = -1:0.1:1;
-            y_range = -10:0.1:10;
-            
-            implicitplot(fun, x_range, y_range, "r--")
-        </scilab:image>
-        <programlisting role="example"><![CDATA[
-        function z = ocho(x, y)
-            z = x*sin(x) - y^2*cos(y);
-        endfunction
-
-        x_range = linspace(-%pi/2, %pi/2, 200);
-        y_range = x_range;
-
-        f_eval = feval(x_range, y_range, ocho);
-
-        // Draws f_eval = 0
-        implicitplot(f_eval, x_range, y_range)
- ]]></programlisting>
-        <scilab:image>
-            function z = ocho(x, y)
-            z = x*sin(x) - y^2*cos(y);
-            endfunction
-            
-            x_range = linspace(-%pi/2, %pi/2, 200);
-            y_range = x_range;
-            
-            f_eval = feval(x_range, y_range, ocho);
-            
-            // Draws f_eval = 0
-            implicitplot(f_eval, x_range, y_range)
-        </scilab:image>
-    </refsection>
-    <refsection role="see also">
-        <title>See Also</title>
-        <simplelist type="inline">
-            <member>
-                <link linkend="plot">plot</link>
-            </member>
-        </simplelist>
-    </refsection>
-</refentry>
diff --git a/scilab/modules/graphics/help/en_US/2d_plot/plotimplicit.xml b/scilab/modules/graphics/help/en_US/2d_plot/plotimplicit.xml
new file mode 100644 (file)
index 0000000..9458c06
--- /dev/null
@@ -0,0 +1,326 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+ * Copyright (C) 2014 - Scilab Enterprises - Pierre-Aimé Agnel
+ * Copyright (C) 2020 - Samuel GOUGEON
+ *
+ * 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
+ *
+ -->
+<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink"
+          xmlns:svg="http://www.w3.org/2000/svg" xmlns:mml="http://www.w3.org/1998/Math/MathML"
+          xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org"
+          xml:lang="en" xml:id="plotimplicit">
+    <refnamediv>
+        <refname>plotimplicit</refname>
+        <refpurpose>Plots the (x,y) lines solving an implicit equation or Function(x,y)=0</refpurpose>
+    </refnamediv>
+    <refsynopsisdiv>
+        <title>Syntax</title>
+        <synopsis>
+            plotimplicit(fun)
+            plotimplicit(fun, x_grid)
+            plotimplicit(fun, x_grid, y_grid)
+            plotimplicit(fun, x_grid, y_grid, plotOptions)
+        </synopsis>
+    </refsynopsisdiv>
+    <refsection>
+        <title>Arguments</title>
+        <variablelist>
+            <varlistentry>
+                <term>fun</term>
+                <listitem>
+                    <para>
+                        It may be one of the following:
+                        <itemizedlist>
+                            <listitem>
+                                A single Scilab-executable string expression of literal scalar
+                                variables "x" and "y" representing two scalar real numbers.
+                                Examples: <literal>"x^3 + 3*y^2 = 1/(2+x*y)"</literal>,
+                                <literal>"(x-y)*(sin(x)-sin(y))"</literal> (implicitly = 0).
+                            </listitem>
+                            <listitem>
+                                The identifier of an existing function of two variables x and y.
+                                Example: <literal>besselj</literal> (not <literal>"besselj"</literal>).
+                            </listitem>
+                            <listitem>
+                                A list, gathering a Scilab or built-in function identifier,
+                                followed by the series of its parameters.
+                                Example: After
+                                <literal>function r = test(x,y,a), r = x.*(y-a), endfunction</literal>,
+                                <varname>fun</varname> can be <literal>list(test, 3.5)</literal>
+                                to consider and compute <literal>test(x, y, 3.5)</literal>.
+                            </listitem>
+                        </itemizedlist>
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>x_grid, y_grid</term>
+                <listitem>
+                    <para>
+                        <varname>x_grid</varname> and <varname>y_grid</varname> define the cartesian
+                        grid of nodes where <varname>fun</varname>(x,y) must be computed.
+                    </para>
+                    <para>
+                        By default, <literal>x_grid = [-1,1]</literal> and
+                        <literal>y_grid = x_grid</literal> are used. To use default values,
+                        just specify nothing. Example skipping <varname>y_grid</varname>:
+                        <literal>plotimplicit(fun, x_grid, , plotOptions)</literal>.
+                    </para>
+                    <para>
+                        Explicit <varname>x_grid</varname> and <varname>y_grid</varname> values
+                        can be specified as follow:
+                        <itemizedlist>
+                            <listitem>
+                                A vector of 2 real numbers = bounds of the x or y domain. Example:
+                                <literal>[-2, 3.5]</literal>. Then the given interval is sampled
+                                with 201 points.
+                            </listitem>
+                            <listitem>
+                                A vector of more than 2 real numbers = values where the function
+                                is computed. Example: <literal>-1:0.1:2</literal>.
+                            </listitem>
+                            <listitem>
+                                The colon <literal>:</literal>. Then the considered interval
+                                is given by the data bounds of the current or default axes.
+                                This allows to overplot solutions of multiple equations on a shared
+                                (x,y) domain, with as many call to <literal>plotimplicit(..)</literal>
+                                as required.
+                            </listitem>
+                        </itemizedlist>
+                    </para>
+                    <para>
+                        <warning>
+                            The bounds of the 1st plot drawn by <literal>plotimplicit(..)</literal>
+                            are set according to the bounds <emphasis>of the solutions of
+                            <varname>fun</varname></emphasis>. Most often they are (much) narrower
+                            than <varname>x_grid</varname> and <varname>y_grid</varname> bounds.
+                        </warning>
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>plotOptions</term>
+                <listitem>
+                        List of <link linkend="plot">plot()</link> line-styling options used when
+                        plotting the solutions curves.
+                    <para/>
+                </listitem>
+            </varlistentry>
+        </variablelist>
+    </refsection>
+    <refsection>
+        <title>Description</title>
+        <para>
+            <literal>plotimplicit(fun, x_grid, y_grid)</literal> evaluates <literal>fun</literal>
+            on the nodes (<varname>x_grid</varname>, <varname>y_grid</varname>), and then
+            draws the (x,y) contours solving the equation <literal>fun</literal> or such that
+            <literal>fun(x,y) = 0</literal>.
+        </para>
+        <para>
+            When no root curve exists on the considered grid, <literal>plotimplicit</literal>
+            yields a warning and plots an empty axes.
+        </para>
+        <note>
+            <itemizedlist>
+                <listitem>
+                    <literal>plotimplicit(..)</literal> can be used in a subplot.
+                    <para/>
+                </listitem>
+                <listitem>
+                    <literal>plotimplicit(..)</literal> can be called several times for the same
+                    axes, to overplot the solutions of several implicit equations (and show their
+                    possible intersections).
+                    <para/>
+                </listitem>
+                <listitem>
+                    Before returning, <literal>plotimplicit</literal> bundles all plotted curves
+                    into a graphical compound addressable as <literal>gce().children</literal>.
+                    If no solution exists, <literal>gce()</literal> is set to <literal>gca()</literal>.
+                    <para/>
+                </listitem>
+            </itemizedlist>
+        </note>
+    </refsection>
+    <refsection>
+        <title>Examples</title>
+        <para>
+            <emphasis role="bold">
+                With the literal expression of the cartesian equation to plot:
+            </emphasis>
+        </para>
+        <programlisting role="example"><![CDATA[
+            // Draw a circle of radius 1 according to its cartesian equation:
+            plotimplicit "x^2 + y^2 = 1"
+
+            xgrid(color("grey"),1,7)
+            isoview
+     ]]></programlisting>
+        <scilab:image>
+            plotimplicit "x^2 + y^2 = 1"
+            xgrid(color("grey"),1,7)
+            isoview
+            gcf().axes_size = [420 420];
+        </scilab:image>
+        <para/>
+        <para>
+            <emphasis role="bold">With the identifier of the function</emphasis> whose root lines
+            must be plotted:
+        </para>
+        <programlisting role="example"><![CDATA[
+            clf
+            // 1) With a function in Scilab language (macro)
+            function z = F(x, y)
+                z = x.*(x.^2 + y.^2) - 5*(x.^2 - y.^2);
+            endfunction
+
+            // Draw the curve in the [-3 6] x [-5 5] range
+            subplot(1,2,1)
+            plotimplicit(F, -3:0.1:6, -5:0.1:5)
+
+            title("$\text{macro:  }x.(x^2 + y^2) - 5(x^2 - y^2) = 0$", "fontsize",4)
+            xgrid(color("grey"),1,7)
+
+            // 2) With a native Scilab builtin
+            subplot(1,2,2)
+            plotimplicit(besselj, -15:0.1:15, 0.1:0.1:19.9)
+
+            title("$\text{built-in:  } besselj(x,y) = 0$", "fontsize",4)
+            xgrid(color("grey"),1,7)
+    ]]></programlisting>
+        <scilab:image>
+            clf
+            // 1) With a function in Scilab language (macro)
+            function z = F(x, y)
+                z = x.*(x.^2 + y.^2) - 5*(x.^2 - y.^2);
+            endfunction
+
+            // Draw the curve in the [-3 6] x [-5 5] range
+            subplot(1,2,1)
+            plotimplicit(F, -3:0.1:6, -5:0.1:5)
+
+            title("$\text{macro:  }x.(x^2 + y^2) - 5(x^2 - y^2) = 0$", "fontsize",4)
+            xgrid(color("grey"),1,7)
+
+            // 2) With a native Scilab builtin
+            subplot(1,2,2)
+            plotimplicit(besselj, -15:0.1:15, 0.1:0.1:19.9)
+
+            title("$\text{built-in:  } besselj(x,y) = 0$", "fontsize",4)
+            xgrid(color("grey"),1,7)
+
+            gcf().axes_size = [800 420];
+        </scilab:image>
+        <para/>
+        <para>
+            <emphasis role="bold">
+                Using the default x_grid, a plotting option, and some post-processing
+            </emphasis>:
+        </para>
+        <programlisting role="example"><![CDATA[
+            equation = "3*x^2*exp(x) - x*y^2 +  exp(y)/(y^2 + 1) = 1"
+            plotimplicit(equation, , -10:0.1:10, "r--")
+
+            // Increase the contours thickness afterwards:
+            gce().children.thickness = 2;
+
+            // Setting titles and grids
+            title("$3x^2 e^x - x y^2 +  {{e^y}\over{(y^2 + 1)}} - 1 = 0$", "fontsize",4)
+            xgrid(color("grey"),1,7)
+     ]]></programlisting>
+        <scilab:image>
+            expression = "3*x^2*exp(x) - x*y^2 +  exp(y)/(y^2 + 1) = 1"
+            plotimplicit(expression, , -10:0.1:10, "r--")
+
+            // Get the contours identifiers, and use them to increase contours thickness:
+            gce().children.thickness = 2;
+
+            // Setting titles and grids
+            title("$3x^2 e^x - x y^2 +  {{e^y}\over{(y^2 + 1)}} - 1 = 0$", "fontsize",4)
+            xgrid(color("grey"),1,7)
+            gcf().axes_size = [600 440];
+        </scilab:image>
+        <para/>
+        <para>
+            <emphasis role="bold">
+                Overplotting
+            </emphasis>:
+        </para>
+        <programlisting role="example"><![CDATA[
+clf
+plotimplicit("x*sin(x) = y^2*cos(y)", [-2,2])
+
+t1 = gca().title.text;
+c1 = gce().children(1);
+title("")
+
+plotimplicit("y*sin(y) = x^2*cos(x)", [-2,2], ,"r")
+t2 = gca().title.text;
+c2 = gce().children(1);
+title("$plotimplicit()$")
+
+legend([c1 c2],[t1 t2]);
+gce().font_size = 3;
+xgrid(color("grey"),1,7)
+    ]]></programlisting>
+        <scilab:image>
+        clf
+        plotimplicit("x*sin(x) = y^2*cos(y)", [-2,2])
+
+        t1 = gca().title.text;
+        c1 = gce().children(1);
+        title("")
+
+        plotimplicit("y*sin(y) = x^2*cos(x)", [-2,2], ,"r")
+        t2 = gca().title.text;
+        c2 = gce().children(1);
+        title("$plotimplicit()$")
+
+        legend([c1 c2],[t1 t2]);
+        gce().font_size = 3;
+        xgrid(color("grey"),1,7)
+        </scilab:image>
+    </refsection>
+    <refsection role="see also">
+        <title>See Also</title>
+        <simplelist type="inline">
+            <member>
+                <link linkend="fsolve">fsolve</link>
+            </member>
+            <member>
+                <link linkend="contour">contour2d</link>
+            </member>
+            <member>
+                <link linkend="contour2di">contour2di</link>
+            </member>
+            <member>
+                <link linkend="contour2dm">contour2dm</link>
+            </member>
+            <member>
+                <link linkend="LineSpec">LineSpec</link>
+            </member>
+            <member>
+                <link linkend="GlobalProperty">GlobalProperty</link>
+            </member>
+            <member>
+                <link linkend="plot">plot</link>
+            </member>
+        </simplelist>
+    </refsection>
+    <refsection role="history">
+        <title>History</title>
+        <revhistory>
+            <revision>
+                <revnumber>6.1.0</revnumber>
+                <revdescription>
+                    Function introduced.
+                </revdescription>
+            </revision>
+        </revhistory>
+    </refsection>
+</refentry>
diff --git a/scilab/modules/graphics/macros/implicitplot.sci b/scilab/modules/graphics/macros/implicitplot.sci
deleted file mode 100644 (file)
index 382a03d..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-// =============================================================================
-// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
-// Copyright (C) INRIA
-// Copyright (C) 2011 - DIGITEO - Michael Baudin
-// Copyright (C) 2012 - SCILAB ENTERPRISES - Claude Gomez
-// Copyright (C) Scilab Enterprises - 2014 - Pierre-Aime Agnel
-//
-// 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 implicitplot(fun, x_range, y_range, varargin)
-
-    [lhs, rhs] = argn(0);
-
-    if rhs == 0 then
-        scf();
-        implicitplot("rand() - 0.5", 1:10, 1:10);
-        return;
-    end
-
-    // x and y must be constants
-    if rhs == 1 then
-        x_range = linspace(-1, 1, 101);
-        y_range = linspace(-1, 1, 101);
-        varargin = [];
-    end
-    if rhs == 2 then
-        y_range = linspace(-1, 1, 101);
-        varargin = [];
-    end
-
-    if rhs >= 2 then
-        if type(x_range) <> 1 then
-            error(999, msprintf(gettext("%s: Wrong type for input argument #%d: Real vector expected.\n"), "implicitplot", 2));
-        end
-        if ~isvector(x_range) then
-            error(999, msprintf(gettext("%s: Wrong size for input argument #%d: Real vector expected.\n"), "implicitplot", 2));
-        end
-        if ~isreal(x_range) then
-            error(999, msprintf(gettext("%s: Wrong value for input argument #%d: Real value expected.\n"), "implicitplot", 2));
-        end
-    end
-
-    if rhs >= 3 then
-        if type(y_range) <> 1 then
-            error(999, msprintf(gettext("%s: Wrong type for input argument #%d: Real vector expected.\n"), "implicitplot", 3));
-        end
-        if ~isvector(y_range) then
-            error(999, msprintf(gettext("%s: Wrong size for input argument #%d: Real vector expected.\n"), "implicitplot", 3));
-        end
-        if ~isreal(y_range) then
-            error(999, msprintf(gettext("%s: Wrong value for input argument #%d: Real value expected.\n"), "implicitplot", 3));
-        end
-    end
-
-    // fun is a string or a function
-    fun_type = type(fun);
-    if ~or(fun_type == [1 10 11 13]) then
-        error(999, msprintf(gettext("%s: Wrong type for input argument #%d: Real matrix or String or Scilab function expected.\n"), "implicitplot", 1));
-    end
-
-    if fun_type == 1 then
-        if or(size(fun) ~= [length(x_range), length(y_range)])
-            error(999, msprintf(gettext("%s: Wrong size for input argument #%d: %d-by-%d matrix expected.\n"), "implicitplot", 1, length(x_range), length(y_range)));
-        end
-    else
-        if fun_type == 10
-            if size(fun, "*") ~= 1
-                error(999, msprintf(gettext("%s: Wrong size for input argument #%d: Scalar string expected.\n"), "implicitplot", 1));
-            end
-        end
-    end
-
-    // Do not signal INF and NAN
-    old_ieee = ieee();
-    ieee(2);
-
-    if type(fun) ~= 1
-        // Define the function
-        if type(fun) == 10 then
-            deff("[%z] = internal_fun(x, y)", "%z = " + fun);
-        else
-            internal_fun = fun;
-            if type(fun) == 11 then
-                comp(internal_fun);
-            end
-        end
-        %z = feval(x_range, y_range, internal_fun);
-    else
-        %z = fun;
-    end
-
-    [xc, yc] = contour2di(x_range, y_range, %z, [0, 0]);
-    clear z;
-
-    // xc and yc might be empty: no zeros were found in x_range X y_range
-    if size(xc, "*") == 0
-        error(999, msprintf(gettext("%s: Function evaluation in selected range does not cross any zeros.\n"), "implicitplot"));
-    end
-
-    // Cleaning results of contour2di
-    // The function might return several times the same contour
-    k = 1;
-    i = 1;
-    list_coord = list();
-    n = yc(k);
-    list_coord(i) = [xc(k + (1:n)); yc(k + (1:n))];
-    k = k + n + 1;
-
-    while k < length(xc)
-        n = yc(k);
-        exist_in_list = %f;
-        new_coord = [xc(k + (1:n)); yc(k + (1:n))];
-
-        for it = 1:i
-            if and(list_coord(it) == new_coord)
-                exist_in_list = %t;
-                break;
-            end
-        end
-        if ~exist_in_list
-            i = i + 1;
-            list_coord(i) = new_coord;
-        end
-        k = k + n + 1;
-    end
-
-    clear xc, yc;
-    // Now list_coord contains each path for the contour drawing
-    // Draw each polyline element inside a compound
-    fig = gcf();
-    a = gca();
-
-    v = fig.immediate_drawing;
-    fig.immediate_drawing = "off";
-    cnt = 0;
-
-    for it = 1:i
-
-        err = execstr("plot(list_coord(it)(1,:), list_coord(it)(2,:), varargin(:))", "errcatch", "m");
-
-        // add a test to see if plot2d call succeed
-        if err <> 0
-            mprintf(gettext("Error %d : in plot called by implicitplot"), err);
-            fig.immediate_drawing = v;
-            clear list_coord
-            return;
-        end
-
-        // unfold the Compound created after plot into its Polyline content
-        unglue(a.children(1))
-        cnt = cnt + 1;
-    end
-
-    if cnt > 0 then
-        // glue all Polylines together into a Compound
-        glue(a.children(1:cnt));
-    end
-    set("current_entity", a);
-    fig.immediate_drawing = v;
-    ieee(old_ieee);
-    clear list_coord
-endfunction
diff --git a/scilab/modules/graphics/macros/plotimplicit.sci b/scilab/modules/graphics/macros/plotimplicit.sci
new file mode 100644 (file)
index 0000000..177e6d7
--- /dev/null
@@ -0,0 +1,257 @@
+// ===================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) INRIA
+// Copyright (C) 2011 - DIGITEO - Michael Baudin
+// Copyright (C) 2012 - SCILAB ENTERPRISES - Claude Gomez
+// Copyright (C) Scilab Enterprises - 2014 - Pierre-Aime Agnel
+// Copyright (C) 2019-2020 - Samuel GOUGEON
+//
+// 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 plotimplicit(fun, x_grid, y_grid, varargin)
+
+    fname = "plotimplicit"
+    [lhs, rhs] = argn(0);
+
+    if rhs == 0 then
+        ab = gca().axes_bounds
+        delete(gca())
+        xsetech(ab)
+        plotimplicit("rand() = 0.5", 1:10, 1:10);
+        return
+    end
+
+    // CHECKING INPUT ARGUMENTS
+    // ------------------------
+    if winsid()<>[] then
+        db = gca().data_bounds
+    else
+        db = gda().data_bounds
+    end
+    // x_grid
+    // --------
+    if ~isdef("x_grid","l") then
+        x_grid = linspace(-1, 1, 201);
+    else
+        if type(x_grid) <> 1 & ..
+            (typeof(x_grid)<> "implicitlist" | x_grid <> :) then
+            error(msprintf(gettext("%s: Argument #%d: Real vector or colon : expected.\n"), fname, 2));
+        end
+        if typeof(x_grid)=="implicitlist" & x_grid == :
+            //if ~isdef("y_grid","l")
+            //    y_grid = :
+            //end
+            x_grid = db(1:2)
+        end
+        if ~isvector(x_grid) then
+            error(msprintf(gettext("%s: Argument #%d: Vector expected.\n"), fname, 2));
+        end
+        if ~isreal(x_grid) then
+            error(msprintf(gettext("%s: Argument #%d: Real value expected.\n"), fname, 2));
+        end
+        if length(x_grid)==2
+            x_grid = linspace(min(x_grid), max(x_grid), 201)
+        end
+    end
+
+    // y_grid
+    // --------
+    if ~isdef("y_grid","l") then
+        y_grid = x_grid;
+    else
+        if type(y_grid) <> 1 & ..
+            (typeof(y_grid)<> "implicitlist" | y_grid <> :)then
+            error(msprintf(gettext("%s: Argument #%d: Real vector or colon : expected.\n"), fname, 3));
+        end
+        if typeof(y_grid)=="implicitlist" & y_grid == :
+            y_grid = db(3:4)
+        end
+        if ~isvector(y_grid) then
+            error(msprintf(gettext("%s: Argument #%d: Vector expected.\n"), fname, 3));
+        end
+        if ~isreal(y_grid) then
+            error(msprintf(gettext("%s: Argument #%d: Real value expected.\n"), fname, 3));
+        end
+        if length(y_grid)==2
+            y_grid = linspace(min(y_grid), max(y_grid), 201)
+        end
+    end
+
+    // Implicit function | equation
+    // ----------------------------
+    // fun is a string (literal expression of a function),
+    //        a function handle,
+    //        a list(fun, parameters(:))
+    fun_type = type(fun)
+    fun0 = fun
+    if ~or(fun_type == [10 13 15 130]) then
+        error(msprintf(gettext("%s: Argument #%d: Real matrix or String or Scilab function or list expected.\n"), fname, 1));
+    elseif fun_type == 10
+        fun = fun(:)
+        fun(fun=="") = []
+        if size(fun, "*") ~= 1
+            error(msprintf(gettext("%s: Argument #%d: Scalar (1 element) expected.\n"), fname, 1));
+        end
+        fun = tokens(fun, "=")
+        if size(fun,1)==2
+            fun = fun(1) + " - (" + fun(2) + ")"
+        end
+        // Vectorizing * / ^ => .* ./ .^
+        for o = ["*" "/" "^"]
+            fun = strsubst(fun, "."+o, "€£")
+            fun = strsubst(fun, o, "."+o)
+            fun = strsubst(fun, "€£", "."+o)
+        end
+        deff("z = internal_fun(x, y)", "z = " + fun);
+
+    elseif or(type(fun)==[13 130])
+        internal_fun = fun
+
+    elseif type(fun)==15  // list(fun, params(:))
+        internal_fun = fun(1)
+        if and(type(internal_fun) <> [13 130])
+            msg = gettext("%s: Argument #%d(#%d): Identifier of a Scilab or built-in function expected.\n")
+            error(msprintf(msg, fname, 1, 1))
+        end
+        if size(fun) > 1
+            params = fun
+            params(1) = null()
+        end
+    end
+
+    // Computation of Z = internal_fun(x,y,..)
+    // ---------------------------------------
+    // We try in a vectorized way
+    try
+        nx = min(size(x_grid,"*"),2)
+        ny = min(size(y_grid,"*"),3)
+        [x, y] = ndgrid(x_grid(1:nx), y_grid(1:ny))
+        if ~isdef("params","l")
+            z = internal_fun(x, y);
+            if or(size(z) <> [2 3]) then
+                z = feval(x_grid, y_grid, internal_fun)
+            else
+                [x, y] = ndgrid(x_grid, y_grid)
+                z = internal_fun(x, y)
+            end
+        else
+            z = internal_fun(x, y, params(:))
+            if or(size(z) <> [2 3]) then
+                z = feval(x_grid, y_grid, fun)
+            else
+                [x, y] = ndgrid(x_grid, y_grid)
+                z = internal_fun(x, y, params(:))
+            end
+        end
+        clear x y
+    catch
+        // internal_fun() is not vectorized => we call feval()
+        if ~isdef("params","l")
+            z = feval(x_grid, y_grid, internal_fun)
+        else
+            z = feval(x_grid, y_grid, fun)
+        end
+    end
+
+
+    // PLOT NITIALIZATION
+    // ------------------
+    fig = gcf();
+    ax = gca();
+
+    v = fig.immediate_drawing;
+    fig.immediate_drawing = "off";
+
+
+    // COMPUTING ROOT CONTOURS
+    // -----------------------
+    [xc, yc] = contour2di(x_grid, y_grid, z, [0, 0]);
+    clear z
+
+    // xc and yc might be empty: no zeros were found in x_grid X y_grid
+    cnt = 0
+    if size(xc, "*") == 0
+        warning(msprintf(gettext("%s: Function evaluation in selected range does not cross any zeros.\n"), fname));
+        plotframe([min(x_grid) min(y_grid) max(x_grid) max(y_grid)])
+
+    else
+        // Cleaning results of contour2di
+        // The function might return several times the same contour
+        k = 1;
+        i = 1;
+        list_coord = list();
+        n = yc(k);
+        list_coord(i) = [xc(k + (1:n)); yc(k + (1:n))];
+        k = k + n + 1;
+
+        while k < length(xc)
+            n = yc(k);
+            exist_in_list = %f;
+            new_coord = [xc(k + (1:n)); yc(k + (1:n))];
+
+            for it = 1:i
+                if and(list_coord(it) == new_coord)
+                    exist_in_list = %t;
+                    break;
+                end
+            end
+            if ~exist_in_list
+                i = i + 1;
+                list_coord(i) = new_coord;
+            end
+            k = k + n + 1;
+        end
+
+        // Now list_coord contains each path for the contour drawing
+        // Draw each polyline element inside a compound
+        for it = 1:i
+            err = execstr("plot(list_coord(it)(1,:), list_coord(it)(2,:), varargin(:))", "errcatch", "m");
+
+            // add a test to see if plot2d call succeed
+            if err <> 0
+                mprintf(gettext("Error %d : in plot called by plotimplicit"), err);
+            else
+                // unfold the Compound created after plot into its Polyline content
+                unglue(ax.children(1))
+                cnt = cnt + 1;
+            end
+        end
+
+        if cnt > 0 then
+            // glue all Polylines together into a Compound
+            a = glue(ax.children(1:cnt));
+            // Otherwise: a remains the axes handle
+        end
+    end
+
+
+    // Titles
+    if ax.x_label.text=="" then
+        xlabel("$x$", "fontsize",4)
+    end
+    if ax.y_label.text=="" then
+        ylabel("$y$", "fontsize",4)
+    end
+    if ax.title.text=="" & fun_type==10 then
+        if grep(fun0, "=")==[]
+            fun0 = fun0 + "= 0"
+        end
+        fun0 = strsubst(fun0, ".*", "\cdot ")
+        fun0 = strsubst(fun0, "*", "\cdot ")
+        fun0 = strsubst(fun0, "./", "/")
+        //fun0 = strsubst(fun0, "^ [^\s]+ ", "^{}")
+        title("$"+fun0+"$", "fontsize",4)
+    end
+    //
+    if cnt > 0 then
+        set("current_entity", a);
+    else
+        set("current_entity", ax);
+    end
+    fig.immediate_drawing = v;
+endfunction
diff --git a/scilab/modules/graphics/tests/unit_tests/implicitplot.dia.ref b/scilab/modules/graphics/tests/unit_tests/implicitplot.dia.ref
deleted file mode 100644 (file)
index 5f2b1e8..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-// =============================================================================
-// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
-// Copyright (C) 2014 - Scilab Enterprises - Pierre-Aime Agnel
-//
-//  This file is distributed under the same license as the Scilab package.
-// =============================================================================
-//
-// <-- Unit test for function implicitplot -->
-//
-// <-- Short Description -->
-//
-// <-- TEST WITH GRAPHIC -->
-// Error checking
-//x_range and y_range are constant matrices
-err_msg = msprintf(gettext("%s: Wrong type for input argument #%d: Real vector expected.\n"), "implicitplot", 2);
-assert_checkerror("implicitplot(""does not work"", ""not_a_real_matrix"")", err_msg);
-err_msg = msprintf(gettext("%s: Wrong type for input argument #%d: Real vector expected.\n"), "implicitplot", 3);
-assert_checkerror("implicitplot(""does not work"", [0 1], ""not_a_real_matrix"")", err_msg);
-//x_range and y_range are vectors
-err_msg = msprintf(gettext("%s: Wrong size for input argument #%d: Real vector expected.\n"), "implicitplot", 2);
-assert_checkerror("implicitplot(""does not work"", [0 1; 0 1], [0 1])", err_msg);
-err_msg = msprintf(gettext("%s: Wrong size for input argument #%d: Real vector expected.\n"), "implicitplot", 3);
-assert_checkerror("implicitplot(""does not work"", [0 1], [0 1; 0 1])", err_msg);
-//x_range and y_range are real
-err_msg = msprintf(gettext("%s: Wrong value for input argument #%d: Real value expected.\n"), "implicitplot", 2);
-assert_checkerror("implicitplot(""does not work"", [0, %i], [0, %i])", err_msg);
-err_msg = msprintf(gettext("%s: Wrong value for input argument #%d: Real value expected.\n"), "implicitplot", 3);
-assert_checkerror("implicitplot(""does not work"", [0 1], [0, %i])", err_msg);
-// Input argument 1 must be text or function or compiled function
-err_msg = msprintf(gettext("%s: Wrong type for input argument #%d: Real matrix or String or Scilab function expected.\n"), "implicitplot", 1);
-assert_checkerror("implicitplot(%s, [0 1], [0 1])", err_msg);
-// Function in input argument 1 must cross a zero
-err_msg = msprintf(gettext("%s: Function evaluation in selected range does not cross any zeros.\n"), "implicitplot");
-assert_checkerror("implicitplot(""10"", [0 1], [0 1])", err_msg);
-// if fun is real, must be of size length(x) * length(y);
-err_msg = msprintf(gettext("%s: Wrong size for input argument #%d: %d-by-%d matrix expected.\n"), "implicitplot", 1, 3, 3);
-assert_checkerror("implicitplot([0 1 -1 ;-1 1 -1], 1:3, 1:3)", err_msg);
-// if fun is not real (string or scilab function) must be of size 1
-err_msg = msprintf(gettext("%s: Wrong size for input argument #%d: Scalar string expected.\n"), "implicitplot", 1);
-assert_checkerror("implicitplot([""test"", ""fail""], 1:3, 1:3)", err_msg);
-// Nominal behaviour
-function result = fun(x, y)
-    result = 3 * x^2 * exp(x) - x * y^2 +  exp(y) / (y^2 + 1) -1
-endfunction
-x_range = -1:0.01:1;
-y_range = -10:0.01:10;
-implicitplot(fun, x_range, y_range, "r--");
-a = gca();
-// This plot is a compound of two polylines
-data1 = a.children(1).children(1).data;
-data2 = a.children(1).children(2).data;
-for i = 1:size(data1, "r")
-    // Check polyline is sufficiently close to 0
-    assert_checktrue(abs(fun(data1(i, 1), data1(i, 2))) < 0.01);
-end
-for i = 1:size(data2, "r")
-    // Check polyline is sufficiently close to 0
-    assert_checktrue(abs(fun(data2(i, 1), data2(i, 2))) < 0.01);
-end
diff --git a/scilab/modules/graphics/tests/unit_tests/implicitplot.tst b/scilab/modules/graphics/tests/unit_tests/implicitplot.tst
deleted file mode 100644 (file)
index 8a23213..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-// =============================================================================
-// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
-// Copyright (C) 2014 - Scilab Enterprises - Pierre-Aime Agnel
-//
-//  This file is distributed under the same license as the Scilab package.
-// =============================================================================
-//
-// <-- Unit test for function implicitplot -->
-//
-// <-- Short Description -->
-//
-// <-- TEST WITH GRAPHIC -->
-
-// Error checking
-//x_range and y_range are constant matrices
-err_msg = msprintf(gettext("%s: Wrong type for input argument #%d: Real vector expected.\n"), "implicitplot", 2);
-assert_checkerror("implicitplot(""does not work"", ""not_a_real_matrix"")", err_msg);
-
-err_msg = msprintf(gettext("%s: Wrong type for input argument #%d: Real vector expected.\n"), "implicitplot", 3);
-assert_checkerror("implicitplot(""does not work"", [0 1], ""not_a_real_matrix"")", err_msg);
-
-//x_range and y_range are vectors
-err_msg = msprintf(gettext("%s: Wrong size for input argument #%d: Real vector expected.\n"), "implicitplot", 2);
-assert_checkerror("implicitplot(""does not work"", [0 1; 0 1], [0 1])", err_msg);
-
-err_msg = msprintf(gettext("%s: Wrong size for input argument #%d: Real vector expected.\n"), "implicitplot", 3);
-assert_checkerror("implicitplot(""does not work"", [0 1], [0 1; 0 1])", err_msg);
-
-//x_range and y_range are real
-err_msg = msprintf(gettext("%s: Wrong value for input argument #%d: Real value expected.\n"), "implicitplot", 2);
-assert_checkerror("implicitplot(""does not work"", [0, %i], [0, %i])", err_msg);
-
-err_msg = msprintf(gettext("%s: Wrong value for input argument #%d: Real value expected.\n"), "implicitplot", 3);
-assert_checkerror("implicitplot(""does not work"", [0 1], [0, %i])", err_msg);
-
-// Input argument 1 must be text or function or compiled function
-err_msg = msprintf(gettext("%s: Wrong type for input argument #%d: Real matrix or String or Scilab function expected.\n"), "implicitplot", 1);
-assert_checkerror("implicitplot(%s, [0 1], [0 1])", err_msg);
-
-// Function in input argument 1 must cross a zero
-err_msg = msprintf(gettext("%s: Function evaluation in selected range does not cross any zeros.\n"), "implicitplot");
-assert_checkerror("implicitplot(""10"", [0 1], [0 1])", err_msg);
-
-// if fun is real, must be of size length(x) * length(y);
-err_msg = msprintf(gettext("%s: Wrong size for input argument #%d: %d-by-%d matrix expected.\n"), "implicitplot", 1, 3, 3);
-assert_checkerror("implicitplot([0 1 -1 ;-1 1 -1], 1:3, 1:3)", err_msg);
-
-// if fun is not real (string or scilab function) must be of size 1
-err_msg = msprintf(gettext("%s: Wrong size for input argument #%d: Scalar string expected.\n"), "implicitplot", 1);
-assert_checkerror("implicitplot([""test"", ""fail""], 1:3, 1:3)", err_msg);
-
-// Nominal behaviour
-function result = fun(x, y)
-    result = 3 * x^2 * exp(x) - x * y^2 +  exp(y) / (y^2 + 1) -1
-endfunction
-
-x_range = -1:0.01:1;
-y_range = -10:0.01:10;
-
-implicitplot(fun, x_range, y_range, "r--");
-
-a = gca();
-// This plot is a compound of two polylines
-data1 = a.children(1).children(1).data;
-data2 = a.children(1).children(2).data;
-
-for i = 1:size(data1, "r")
-    // Check polyline is sufficiently close to 0
-    assert_checktrue(abs(fun(data1(i, 1), data1(i, 2))) < 0.01);
-end
-
-for i = 1:size(data2, "r")
-    // Check polyline is sufficiently close to 0
-    assert_checktrue(abs(fun(data2(i, 1), data2(i, 2))) < 0.01);
-end
diff --git a/scilab/modules/graphics/tests/unit_tests/plotimplicit.dia.ref b/scilab/modules/graphics/tests/unit_tests/plotimplicit.dia.ref
new file mode 100644 (file)
index 0000000..0432020
--- /dev/null
@@ -0,0 +1,92 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2014 - Scilab Enterprises - Pierre-Aime Agnel
+// Copyright (C) 2020 - Scilab Enterprises - Samuel GOUGEON
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- Unit test for function plotimplicit -->
+//
+// <-- TEST WITH GRAPHIC -->
+// <-- ENGLISH IMPOSED -->
+// Error checking
+// --------------
+fname = "plotimplicit";
+// fun: string, macro, built-in, list expected
+msg = msprintf("%s: Argument #%d: Real matrix or String or Scilab function or list expected.\n", fname, 1);
+assert_checkerror("plotimplicit($)", msg);
+msg = msprintf("%s: Argument #%d: Scalar (1 element) expected.\n", fname, 1);
+assert_checkerror("plotimplicit([""x^2+y^2=1"",""x^2+y^2=1.2""])", msg);
+msg = msprintf("%s: Argument #%d(#%d): Identifier of a Scilab or built-in function expected.\n", fname, 1, 1);
+assert_checkerror("plotimplicit(list($))", msg);
+// Function in input argument #1 must cross a zero
+plotimplicit("10")  // Warning displayed
+WARNING: plotimplicit: Function evaluation in selected range does not cross any zeros.
+// x_grid: 
+msg = msprintf("%s: Argument #%d: Real vector or colon : expected.\n", fname, 2);
+assert_checkerror("plotimplicit(""x^2+y^2=1"", ""not_a_real_vector"")", msg);
+msg = msprintf("%s: Argument #%d: Real value expected.\n", fname, 2);
+assert_checkerror("plotimplicit(""x^2+y^2=1"", [1 %i])", msg);
+msg = msprintf("%s: Argument #%d: Vector expected.\n", fname, 2);
+assert_checkerror("plotimplicit(""x^2+y^2=1"", rand(2,3))", msg);
+// y_grid:
+msg = msprintf("%s: Argument #%d: Real vector or colon : expected.\n", fname, 3);
+assert_checkerror("plotimplicit(""x^2+y^2=1"", , ""not_a_real_vector"")", msg);
+msg = msprintf("%s: Argument #%d: Real value expected.\n", fname, 3);
+assert_checkerror("plotimplicit(""x^2+y^2=1"", , [1 %i])", msg);
+msg = msprintf("%s: Argument #%d: Vector expected.\n", fname, 3);
+assert_checkerror("plotimplicit(""x^2+y^2=1"", , rand(2,3))", msg);
+// Nominal behaviour
+// -----------------
+function result = fun(x, y)
+    result = 3 * x.^2 .* exp(x) - x .* y.^2 +  exp(y) ./ (y.^2 + 1) -1
+endfunction
+x_range = -1:0.01:1;
+y_range = -10:0.01:10;
+plotimplicit(fun, x_range, y_range, "r--");
+a = gce();
+// This plot is a compound of two polylines
+data1 = a.children(1).data;
+data2 = a.children(2).data;
+for i = 1:size(data1, "r")
+    // Check polyline is sufficiently close to 0
+    assert_checktrue(abs(fun(data1(i, 1), data1(i, 2))) < 0.01);
+end
+for i = 1:size(data2, "r")
+    // Check polyline is sufficiently close to 0
+    assert_checktrue(abs(fun(data2(i, 1), data2(i, 2))) < 0.01);
+end
+// Possible inputs
+// ---------------
+// fun
+clf
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=1"")", "errcatch"), 0);
+ax = gca();
+h = [ax.title ax.x_label ax.y_label]
+ h  = 
+1 by 3 matrix of handles:
+=========================
+Label Label Label 
+assert_checkequal(h.text, ["$x^2+y^2=1$", "$x$", "$y$"]');
+assert_checkequal(h.font_size, [4 4 4]');
+xlabel("x");
+assert_checkequal(execstr("plotimplicit(""x^2+y^2-2"")", "errcatch"), 0);
+assert_checkequal(h.text, ["$x^2+y^2=1$", "x", "$y$"]');
+clear fun
+function result = fun(x, y, a, b, c)
+    result = a * x.^2 .* exp(x) - x .* y.^2 +  exp(y) ./ (y.^2 + b) - c
+endfunction
+assert_checkequal(execstr("plotimplicit(list(fun,3,1,1))", "errcatch"), 0);
+// x_grid
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=6"",[-2,3])", "errcatch"), 0);
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=6"",[3,-2])", "errcatch"), 0);
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=6"",-2:0.1:4)", "errcatch"), 0);
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=7"",:)", "errcatch"), 0);
+// y_grid
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=6"",[-2,3],[-1 2])", "errcatch"), 0);
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=6"",      ,[-1 2])", "errcatch"), 0);
+WARNING: plotimplicit: Function evaluation in selected range does not cross any zeros.
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=6"",[-2,3], :)", "errcatch"), 0);
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=6"",[-2,3],-1:0.1:2)", "errcatch"), 0);
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=0.5"",[-2,3],,""r"")", "errcatch"), 0);
diff --git a/scilab/modules/graphics/tests/unit_tests/plotimplicit.tst b/scilab/modules/graphics/tests/unit_tests/plotimplicit.tst
new file mode 100644 (file)
index 0000000..cfbef17
--- /dev/null
@@ -0,0 +1,102 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2014 - Scilab Enterprises - Pierre-Aime Agnel
+// Copyright (C) 2020 - Scilab Enterprises - Samuel GOUGEON
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- Unit test for function plotimplicit -->
+//
+// <-- TEST WITH GRAPHIC -->
+// <-- ENGLISH IMPOSED -->
+
+// Error checking
+// --------------
+fname = "plotimplicit";
+// fun: string, macro, built-in, list expected
+msg = msprintf("%s: Argument #%d: Real matrix or String or Scilab function or list expected.\n", fname, 1);
+assert_checkerror("plotimplicit($)", msg);
+msg = msprintf("%s: Argument #%d: Scalar (1 element) expected.\n", fname, 1);
+assert_checkerror("plotimplicit([""x^2+y^2=1"",""x^2+y^2=1.2""])", msg);
+msg = msprintf("%s: Argument #%d(#%d): Identifier of a Scilab or built-in function expected.\n", fname, 1, 1);
+assert_checkerror("plotimplicit(list($))", msg);
+
+// Function in input argument #1 must cross a zero
+plotimplicit("10")  // Warning displayed
+
+// x_grid: 
+msg = msprintf("%s: Argument #%d: Real vector or colon : expected.\n", fname, 2);
+assert_checkerror("plotimplicit(""x^2+y^2=1"", ""not_a_real_vector"")", msg);
+msg = msprintf("%s: Argument #%d: Real value expected.\n", fname, 2);
+assert_checkerror("plotimplicit(""x^2+y^2=1"", [1 %i])", msg);
+msg = msprintf("%s: Argument #%d: Vector expected.\n", fname, 2);
+assert_checkerror("plotimplicit(""x^2+y^2=1"", rand(2,3))", msg);
+
+// y_grid:
+msg = msprintf("%s: Argument #%d: Real vector or colon : expected.\n", fname, 3);
+assert_checkerror("plotimplicit(""x^2+y^2=1"", , ""not_a_real_vector"")", msg);
+msg = msprintf("%s: Argument #%d: Real value expected.\n", fname, 3);
+assert_checkerror("plotimplicit(""x^2+y^2=1"", , [1 %i])", msg);
+msg = msprintf("%s: Argument #%d: Vector expected.\n", fname, 3);
+assert_checkerror("plotimplicit(""x^2+y^2=1"", , rand(2,3))", msg);
+
+
+// Nominal behaviour
+// -----------------
+function result = fun(x, y)
+    result = 3 * x.^2 .* exp(x) - x .* y.^2 +  exp(y) ./ (y.^2 + 1) -1
+endfunction
+
+x_range = -1:0.01:1;
+y_range = -10:0.01:10;
+
+plotimplicit(fun, x_range, y_range, "r--");
+
+a = gce();
+// This plot is a compound of two polylines
+data1 = a.children(1).data;
+data2 = a.children(2).data;
+
+for i = 1:size(data1, "r")
+    // Check polyline is sufficiently close to 0
+    assert_checktrue(abs(fun(data1(i, 1), data1(i, 2))) < 0.01);
+end
+
+for i = 1:size(data2, "r")
+    // Check polyline is sufficiently close to 0
+    assert_checktrue(abs(fun(data2(i, 1), data2(i, 2))) < 0.01);
+end
+
+// Possible inputs
+// ---------------
+// fun
+clf
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=1"")", "errcatch"), 0);
+ax = gca();
+h = [ax.title ax.x_label ax.y_label]
+assert_checkequal(h.text, ["$x^2+y^2=1$", "$x$", "$y$"]');
+assert_checkequal(h.font_size, [4 4 4]');
+xlabel("x");
+
+assert_checkequal(execstr("plotimplicit(""x^2+y^2-2"")", "errcatch"), 0);
+assert_checkequal(h.text, ["$x^2+y^2=1$", "x", "$y$"]');
+
+clear fun
+function result = fun(x, y, a, b, c)
+    result = a * x.^2 .* exp(x) - x .* y.^2 +  exp(y) ./ (y.^2 + b) - c
+endfunction
+assert_checkequal(execstr("plotimplicit(list(fun,3,1,1))", "errcatch"), 0);
+
+// x_grid
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=6"",[-2,3])", "errcatch"), 0);
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=6"",[3,-2])", "errcatch"), 0);
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=6"",-2:0.1:4)", "errcatch"), 0);
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=7"",:)", "errcatch"), 0);
+
+// y_grid
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=6"",[-2,3],[-1 2])", "errcatch"), 0);
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=6"",      ,[-1 2])", "errcatch"), 0);
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=6"",[-2,3], :)", "errcatch"), 0);
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=6"",[-2,3],-1:0.1:2)", "errcatch"), 0);
+assert_checkequal(execstr("plotimplicit(""x^2+y^2=0.5"",[-2,3],,""r"")", "errcatch"), 0);
index 21aad47..59a05ac 100644 (file)
             <li><code>twinkle</code> can now blink together several hierarchically independent objects, like a curve and its labels, etc.</li>
             <li><code>repmat</code> is improved: more neutral default frame color; improved labels positioning; colors can now be specified by their predefined name or "#RRGGBB" hexa code; a structure of handles is now returned to easily post-process both subframes and the set of labels.</li>
             <li><code>plot</code> can now work in semi or bi-logarithmic mode with some input logflag.</li>
+            <li><code>v</code> function added.</li>
         </ul>
         <h2 class="title">Help pages</h2>
         <ul>
index a0df767..6946d84 100644 (file)
@@ -304,7 +304,6 @@ _LaTeX_grand.xml_2.png=4065036eed5d60beaa7f246c013cbff0
 _LaTeX_hank.xml_1.png=fc6c604bc8c86af20a8f0673047332db
 _LaTeX_histc.xml_1.png=f1c5acc5939d55326dfab4af50e13f97
 _LaTeX_histplot.xml_1.png=f1c5acc5939d55326dfab4af50e13f97
-_LaTeX_implicitplot.xml_1.png=43ca5ad9e1f094a31392f860ef481e5c
 _LaTeX_interp.xml_1.png=b99c07a3557a83033fdeedd84352b082
 _LaTeX_interp.xml_10.png=e257b3b19cc16006687169337c38dc2a
 _LaTeX_interp.xml_11.png=b99c07a3557a83033fdeedd84352b082
@@ -803,10 +802,6 @@ householder_1.png=8a7bce8cfadfbf5d70436734b66ec20d
 hsv2rgb_1.png=7d20c259e94301d9763fbddb7bff4784
 hsvcolormap_1.png=11918d88bcc793200af0b9f1b58b0554
 iir_1.png=e675c2755f68ddc4611c849895b63012
-implicitplot_1.png=d2d7b1b26a127ab8775517c742824770
-implicitplot_2.png=5371e2b77a74a8b2b2d139379e41c0a5
-implicitplot_3.png=5201f1980df1b1ba7afb7b3a92b68611
-implicitplot_4.png=74aeae6ec05b661c78c12c90d50b3aec
 intdec_1.png=da3896e7d2e8468dd33edf57ccbe4480
 interp1_1.png=0e9a3f4319b2818ce4921b9bc3008d80
 interp2d_1.png=f4af61bc3faf493d778169ec7decc7ae
@@ -974,6 +969,10 @@ plot_multiscaled_1.png=139dc4c6fd62728b6f08e4529fc775fa
 plot_multiscaled_2.png=8ea6f9394968a8d02d09e1a66064c718
 plot_multiscaled_3.png=97b20f253d676c6d66fe322172b960ac
 plot_multiscaled_4.png=b30c7820c6e5d9d5e418f1638be429bd
+plotimplicit_1.png=1df44be6be9fafdf02a7ccbf3898616c
+plotimplicit_2.png=093023d1fc2796a86689cf3d7f65878f
+plotimplicit_3.png=a94acd37c43dd09841e44b07d0b18511
+plotimplicit_4.png=dd2abe1ebe56819696eeaeb82751a0a7
 polarplot_1.png=92b1189dd351372e587b472bad213e09
 polarplot_2.png=7a5f1cd3ef07687170c0de62231a2b5c
 polarplot_3.png=f11a25552a72c4454001c29b97073379
diff --git a/scilab/modules/helptools/images/_LaTeX_implicitplot.xml_1.png b/scilab/modules/helptools/images/_LaTeX_implicitplot.xml_1.png
deleted file mode 100644 (file)
index 670d2fb..0000000
Binary files a/scilab/modules/helptools/images/_LaTeX_implicitplot.xml_1.png and /dev/null differ
diff --git a/scilab/modules/helptools/images/implicitplot_1.png b/scilab/modules/helptools/images/implicitplot_1.png
deleted file mode 100644 (file)
index 47cdcc8..0000000
Binary files a/scilab/modules/helptools/images/implicitplot_1.png and /dev/null differ
diff --git a/scilab/modules/helptools/images/implicitplot_2.png b/scilab/modules/helptools/images/implicitplot_2.png
deleted file mode 100644 (file)
index 237d070..0000000
Binary files a/scilab/modules/helptools/images/implicitplot_2.png and /dev/null differ
diff --git a/scilab/modules/helptools/images/implicitplot_3.png b/scilab/modules/helptools/images/implicitplot_3.png
deleted file mode 100644 (file)
index 6c12adb..0000000
Binary files a/scilab/modules/helptools/images/implicitplot_3.png and /dev/null differ
diff --git a/scilab/modules/helptools/images/implicitplot_4.png b/scilab/modules/helptools/images/implicitplot_4.png
deleted file mode 100644 (file)
index 293ac30..0000000
Binary files a/scilab/modules/helptools/images/implicitplot_4.png and /dev/null differ
diff --git a/scilab/modules/helptools/images/plotimplicit_1.png b/scilab/modules/helptools/images/plotimplicit_1.png
new file mode 100644 (file)
index 0000000..50f9b66
Binary files /dev/null and b/scilab/modules/helptools/images/plotimplicit_1.png differ
diff --git a/scilab/modules/helptools/images/plotimplicit_2.png b/scilab/modules/helptools/images/plotimplicit_2.png
new file mode 100644 (file)
index 0000000..c20ad19
Binary files /dev/null and b/scilab/modules/helptools/images/plotimplicit_2.png differ
diff --git a/scilab/modules/helptools/images/plotimplicit_3.png b/scilab/modules/helptools/images/plotimplicit_3.png
new file mode 100644 (file)
index 0000000..2764b83
Binary files /dev/null and b/scilab/modules/helptools/images/plotimplicit_3.png differ
diff --git a/scilab/modules/helptools/images/plotimplicit_4.png b/scilab/modules/helptools/images/plotimplicit_4.png
new file mode 100644 (file)
index 0000000..088f725
Binary files /dev/null and b/scilab/modules/helptools/images/plotimplicit_4.png differ