genius r699 - in trunk: . help/C src



Author: jirka
Date: Sun Feb  1 06:11:54 2009
New Revision: 699
URL: http://svn.gnome.org/viewvc/genius?rev=699&view=rev

Log:

Sun Feb 01 00:11:32 2009  Jiri (George) Lebl <jirka 5z com>

	* src/graphing.c: do Runge-Kutta instead of Euler for the graphical
	  slopefield solver.  Whack VectorfieldCPlot (never implemented,
	  should not be a separate function anyway).  Implement
	  VectorfieldPlot and SlopefieldPlot.

	* help/C/genius.xml, help/C/gel-function-list.xml: update for all
	  the new changes



Modified:
   trunk/ChangeLog
   trunk/help/C/gel-function-list.xml
   trunk/help/C/genius.txt
   trunk/help/C/genius.xml
   trunk/src/graphing.c

Modified: trunk/help/C/gel-function-list.xml
==============================================================================
--- trunk/help/C/gel-function-list.xml	(original)
+++ trunk/help/C/gel-function-list.xml	Sun Feb  1 06:11:54 2009
@@ -524,7 +524,19 @@
          <term>LinePlotWindow</term>
          <listitem>
           <synopsis>LinePlotWindow = [x1,x2,y1,y2]</synopsis>
-          <para>Sets the limits for line plotting (See <link linkend="gel-function-LinePlot"><function>LinePlot</function></link>).</para>
+          <para>Sets the limits for <link linkend="genius-gel-function-list-plotting">line plotting
+	  functions</link> such as <link linkend="gel-function-LinePlot"><function>LinePlot</function></link>.
+          </para>
+         </listitem>
+        </varlistentry>
+
+        <varlistentry id="gel-function-LinePlotDrawLegends">
+         <term>LinePlotDrawLegends</term>
+         <listitem>
+          <synopsis>LinePlotDrawLegends = true</synopsis>
+          <para>Tells genius to draw the legends for <link linkend="genius-gel-function-list-plotting">line plotting
+	  functions</link> such as <link linkend="gel-function-LinePlot"><function>LinePlot</function></link>.
+          </para>
          </listitem>
         </varlistentry>
 
@@ -668,6 +680,16 @@
          </listitem>
         </varlistentry>
 
+        <varlistentry id="gel-function-VectorfieldNormalized">
+         <term>VectorfieldNormalized</term>
+         <listitem>
+          <synopsis>VectorfieldNormalized = true</synopsis>
+          <para>Should the vectorfield plotting have normalized arrow length.  If true, vector fields will only show direction
+	   and not magnitude.  (See <link linkend="gel-function-VectorfieldPlot"><function>VectorfieldPlot</function></link>).
+          </para>
+         </listitem>
+        </varlistentry>
+
       </variablelist>
     </sect1>
 
@@ -4746,6 +4768,11 @@
 	    (See <link linkend="gel-function-LinePlotWindow"><function>LinePlotWindow</function></link>)
           </para>
           <para>
+	    The parameter
+	    <link linkend="gel-function-LinePlotDrawLegends"><function>LinePlotDrawLegends</function></link>
+	    controls the drawing of the legend.
+	  </para>
+          <para>
 	    Examples:
           <screen><prompt>genius></prompt> <userinput>LinePlot(sin,cos)</userinput>
 <prompt>genius></prompt> <userinput>LinePlot(`(x)=x^2,-1,1,0,1)</userinput>
@@ -4803,6 +4830,16 @@
 for <varname>x</varname> and <varname>y</varname> then optionally the <varname>t</varname> limits as <userinput>t1,t2,tinc</userinput>, then optionally the
 limits as <userinput>x1,x2,y1,y2</userinput>.
           </para>
+	  <para>
+	    If limits are not
+	    specified, then the currently set limits apply
+	    (See <link linkend="gel-function-LinePlotWindow"><function>LinePlotWindow</function></link>).
+          </para>
+          <para>
+	    The parameter
+	    <link linkend="gel-function-LinePlotDrawLegends"><function>LinePlotDrawLegends</function></link>
+	    controls the drawing of the legend.
+	  </para>
          </listitem>
         </varlistentry>
 
@@ -4818,6 +4855,74 @@
 then optionally the <varname>t</varname> limits as <userinput>t1,t2,tinc</userinput>, then
 optionally the limits as <userinput>x1,x2,y1,y2</userinput>.
           </para>
+	  <para>
+	    If limits are not
+	    specified, then the currently set limits apply
+	    (See <link linkend="gel-function-LinePlotWindow"><function>LinePlotWindow</function></link>).
+          </para>
+          <para>
+	    The parameter
+	    <link linkend="gel-function-LinePlotDrawLegends"><function>LinePlotDrawLegends</function></link>
+	    controls the drawing of the legend.
+	  </para>
+         </listitem>
+        </varlistentry>
+
+        <varlistentry id="gel-function-SlopefieldClearSolutions">
+         <term>SlopefieldClearSolutions</term>
+         <listitem>
+          <synopsis>SlopefieldClearSolutions ()</synopsis>
+          <para>
+	    Clears the solutions drawn by the
+	    <link linkend="gel-function-SlopefieldDrawSolution"><function>SlopefieldDrawSolution</function></link>
+	    function.
+          </para>
+         </listitem>
+        </varlistentry>
+
+        <varlistentry id="gel-function-SlopefieldDrawSolution">
+         <term>SlopefieldDrawSolution</term>
+         <listitem>
+          <synopsis>SlopefieldDrawSolution (x, y, dx)</synopsis>
+          <para>
+	    When a slope field plot is active, draw a solution with
+	    the specified initial condition.  The standard
+	    Runge-Kutta method is used with increment <varname>dx</varname>.
+	    Solutions stay on the graph until a different plot is shown or until
+	    you call 
+	    <link linkend="gel-function-SlopefieldClearSolutions"><function>SlopefieldClearSolutions</function></link>.
+	    You can also use the graphical interface to draw solutions and specify
+	    initial conditions with the mouse.
+          </para>
+         </listitem>
+        </varlistentry>
+
+        <varlistentry id="gel-function-SlopefieldPlot">
+         <term>SlopefieldPlot</term>
+         <listitem>
+          <synopsis>SlopefieldPlot (func)</synopsis>
+          <synopsis>SlopefieldPlot (func,x1,x2,y1,y2)</synopsis>
+          <para>
+	    Plot a slope field.  The function <varname>func</varname>
+	    should take two real numbers <varname>x</varname>
+	    and <varname>y</varname>, or a single complex
+	    number.
+            Optionally you can specify the limits of the plotting window as
+	    <varname>x1</varname>, <varname>x2</varname>,
+	    <varname>y1</varname>, <varname>y2</varname>.  If limits are not
+	    specified, then the currently set limits apply
+	    (See <link linkend="gel-function-LinePlotWindow"><function>LinePlotWindow</function></link>).
+          </para>
+          <para>
+	    The parameter
+	    <link linkend="gel-function-LinePlotDrawLegends"><function>LinePlotDrawLegends</function></link>
+	    controls the drawing of the legend.
+	  </para>
+          <para>
+	    Examples:
+          <screen><prompt>genius></prompt> <userinput>Slopefield(`(x,y)=sin(x-y),-5,5,-5,5)</userinput>
+</screen>
+          </para>
          </listitem>
         </varlistentry>
 
@@ -4844,5 +4949,43 @@
          </listitem>
         </varlistentry>
 
+        <varlistentry id="gel-function-VectorfieldPlot">
+         <term>VectorfieldPlot</term>
+         <listitem>
+          <synopsis>VectorfieldPlot (funcx, funcy)</synopsis>
+          <synopsis>VectorfieldPlot (funcx, funcy, x1, x2, y1, y2)</synopsis>
+          <para>
+	    Plot a two dimensional vector field.  The function
+	    <varname>funcx</varname>
+	    should be the dx/dt of the vectorfield and the function
+	    <varname>funcy</varname> should be the dy/dt of the vectorfield.
+	    The functions
+	    should take two real numbers <varname>x</varname>
+	    and <varname>y</varname>, or a single complex
+	    number.  When the parameter
+	    <link linkend="gel-function-VectorfieldNormalized"><function>VectorfieldNormalized</function></link>
+	    is <constant>true</constant>, then the magnitude of the vectors is normalized.  That is, only
+	    the direction and not the magnitude is shown.
+	  </para>
+	  <para>
+            Optionally you can specify the limits of the plotting window as
+	    <varname>x1</varname>, <varname>x2</varname>,
+	    <varname>y1</varname>, <varname>y2</varname>.  If limits are not
+	    specified, then the currently set limits apply
+	    (See <link linkend="gel-function-LinePlotWindow"><function>LinePlotWindow</function></link>).
+          </para>
+          <para>
+	    The parameter
+	    <link linkend="gel-function-LinePlotDrawLegends"><function>LinePlotDrawLegends</function></link>
+	    controls the drawing of the legend.
+	  </para>
+          <para>
+	    Examples:
+          <screen><prompt>genius></prompt> <userinput>VectorfieldPlot(`(x,y)=x^2-y, `(x,y)=y^2-x, -1, 1, -1, 1)</userinput>
+</screen>
+          </para>
+         </listitem>
+        </varlistentry>
+
       </variablelist>
     </sect1>

Modified: trunk/help/C/genius.txt
==============================================================================
--- trunk/help/C/genius.txt	(original)
+++ trunk/help/C/genius.txt	Sun Feb  1 06:11:54 2009
@@ -12,7 +12,7 @@
 
     <kaiw itee uq edu au> 
 
-   Copyright (c) 1997-2008 Jiri (George) Lebl
+   Copyright (c) 1997-2009 Jiri (George) Lebl
 
    Copyright (c) 2004 Kai Willadsen
 
@@ -95,7 +95,11 @@
 
                 4.2. Parametric Plots
 
-                4.3. Surface Plots
+                4.3. Slopefield Plots
+
+                4.4. Vectorfield Plots
+
+                4.5. Surface Plots
 
    5. GEL Basics
 
@@ -513,7 +517,45 @@
 
      ----------------------------------------------------------------------
 
-4.3. Surface Plots
+4.3. Slopefield Plots
+
+   In the create plot window, you can also choose the Slope field notebook
+   tab to create a two dimensional slope field plot. Similar operations can
+   be done on such graphs as can be done on the other line plots. For
+   plotting using the command line see the documentation of the
+   SlopefieldPlot function.
+
+   When a slope field is active, there is an extra Solver menu available,
+   through which you can bring up the solver dialog. Here you can have Genius
+   plot specific solutions for the given initial conditions. You can either
+   specify initial conditions in the dialog, or you can click on the plot
+   directly to specify the initial point. While the solver dialog is active,
+   the zooming by clicking and dragging does not work. You have to close the
+   dialog first if you want to zoom using the mouse.
+
+   The solver uses the standard Runge-Kutta method. The plots will stay on
+   the screen until cleared. The solver will stop whenever it reaches the
+   boundary of the plot window. Zooming does not change the limits or
+   parameters of the solutions, you will have to clear and redraw them with
+   appropriate parameters. You can also use the SlopefieldDrawSolution
+   function to draw solutions from the command line or programs.
+
+     ----------------------------------------------------------------------
+
+4.4. Vectorfield Plots
+
+   In the create plot window, you can also choose the Vector field notebook
+   tab to create a two dimensional vector field plot. Similar operations can
+   be done on such graphs as can be done on the other line plots. For
+   plotting using the command line see the documentation of the
+   VectorfieldPlot function.
+
+   By default only the direction of the vector field is shown. To show the
+   magnitude, uncheck the appropriate checkbox.
+
+     ----------------------------------------------------------------------
+
+4.5. Surface Plots
 
    Genius can also plot surfaces. Select the Surface plot tab in the main
    notebook of the Create Plot window. Here you can specify a single
@@ -2282,7 +2324,14 @@
 
  LinePlotWindow = [x1,x2,y1,y2]
 
-           Sets the limits for line plotting (See LinePlot).
+           Sets the limits for line plotting functions such as LinePlot.
+
+   LinePlotDrawLegends
+
+ LinePlotDrawLegends = true
+
+           Tells genius to draw the legends for line plotting functions such
+           as LinePlot.
 
    MaxDigits
 
@@ -2385,6 +2434,14 @@
 
            Sets the limits for surface plotting (See SurfacePlot).
 
+   VectorfieldNormalized
+
+ VectorfieldNormalized = true
+
+           Should the vectorfield plotting have normalized arrow length. If
+           true, vector fields will only show direction and not magnitude.
+           (See VectorfieldPlot).
+
      ----------------------------------------------------------------------
 
 11.4. Constants
@@ -5366,6 +5423,9 @@
            specified, then the currently set limits apply (See
            LinePlotWindow)
 
+           The parameter LinePlotDrawLegends controls the drawing of the
+           legend.
+
            Examples:
 
  genius> LinePlot(sin,cos)
@@ -5408,6 +5468,12 @@
            for x and y then optionally the t limits as t1,t2,tinc, then
            optionally the limits as x1,x2,y1,y2.
 
+           If limits are not specified, then the currently set limits apply
+           (See LinePlotWindow).
+
+           The parameter LinePlotDrawLegends controls the drawing of the
+           legend.
+
    LinePlotCParametric
 
  LinePlotCParametric (func,...)
@@ -5420,6 +5486,48 @@
            the function that returns x+iy, then optionally the t limits as
            t1,t2,tinc, then optionally the limits as x1,x2,y1,y2.
 
+           If limits are not specified, then the currently set limits apply
+           (See LinePlotWindow).
+
+           The parameter LinePlotDrawLegends controls the drawing of the
+           legend.
+
+   SlopefieldClearSolutions
+
+ SlopefieldClearSolutions ()
+
+           Clears the solutions drawn by the SlopefieldDrawSolution function.
+
+   SlopefieldDrawSolution
+
+ SlopefieldDrawSolution (x, y, dx)
+
+           When a slope field plot is active, draw a solution with the
+           specified initial condition. The standard Runge-Kutta method is
+           used with increment dx. Solutions stay on the graph until a
+           different plot is shown or until you call
+           SlopefieldClearSolutions. You can also use the graphical interface
+           to draw solutions and specify initial conditions with the mouse.
+
+   SlopefieldPlot
+
+ SlopefieldPlot (func)
+
+ SlopefieldPlot (func,x1,x2,y1,y2)
+
+           Plot a slope field. The function func should take two real numbers
+           x and y, or a single complex number. Optionally you can specify
+           the limits of the plotting window as x1, x2, y1, y2. If limits are
+           not specified, then the currently set limits apply (See
+           LinePlotWindow).
+
+           The parameter LinePlotDrawLegends controls the drawing of the
+           legend.
+
+           Examples:
+
+ genius> Slopefield(`(x,y)=sin(x-y),-5,5,-5,5)
+
    SurfacePlot
 
  SurfacePlot (func)
@@ -5438,6 +5546,31 @@
  genius> SurfacePlot(`(x,y)=x^2+y,-1,1,-1,1,-2,2)
  genius> SurfacePlot(`(z)=|z|^2,-1,1,-1,1,0,2)
 
+   VectorfieldPlot
+
+ VectorfieldPlot (funcx, funcy)
+
+ VectorfieldPlot (funcx, funcy, x1, x2, y1, y2)
+
+           Plot a two dimensional vector field. The function funcx should be
+           the dx/dt of the vectorfield and the function funcy should be the
+           dy/dt of the vectorfield. The functions should take two real
+           numbers x and y, or a single complex number. When the parameter
+           VectorfieldNormalized is true, then the magnitude of the vectors
+           is normalized. That is, only the direction and not the magnitude
+           is shown.
+
+           Optionally you can specify the limits of the plotting window as
+           x1, x2, y1, y2. If limits are not specified, then the currently
+           set limits apply (See LinePlotWindow).
+
+           The parameter LinePlotDrawLegends controls the drawing of the
+           legend.
+
+           Examples:
+
+ genius> VectorfieldPlot(`(x,y)=x^2-y, `(x,y)=y^2-x, -1, 1, -1, 1)
+
      ----------------------------------------------------------------------
 
                       Chapter 12. Example Programs in GEL

Modified: trunk/help/C/genius.xml
==============================================================================
--- trunk/help/C/genius.xml	(original)
+++ trunk/help/C/genius.xml	Sun Feb  1 06:11:54 2009
@@ -4,8 +4,8 @@
   <!ENTITY app "<application>Genius Mathematics Tool</application>">
   <!ENTITY appname "Genius">
   <!ENTITY appversion "1.0.4">
-  <!ENTITY manrevision "0.2.2">
-  <!ENTITY date "September 2008">
+  <!ENTITY manrevision "0.2.3">
+  <!ENTITY date "January 2009">
 
   <!ENTITY legal SYSTEM "legal.xml">
 
@@ -28,7 +28,7 @@
     <title>&appname; Manual</title>       
 
     <copyright>
-      <year>1997-2008</year>
+      <year>1997-2009</year>
       <holder>Ji&#345;&iacute; (George) Lebl</holder>
     </copyright>
     <copyright>
@@ -559,6 +559,56 @@
 
     </sect1>
 
+    <sect1 id="genius-slopefield-plots">
+      <title>Slopefield Plots</title>
+      <para>
+	In the create plot window, you can also choose the <guilabel>Slope field</guilabel> notebook
+        tab to create a two dimensional slope field plot.
+	Similar operations can be
+	done on such graphs as can be done on the other line plots.
+	For plotting using the command line see the documentation of the
+        <link linkend="gel-function-SlopefieldPlot"><function>SlopefieldPlot</function></link> function.
+      </para>
+
+      <para>
+	When a slope field is active, there is an extra <guilabel>Solver</guilabel> menu available,
+	through which you can bring up the solver dialog.  Here you can have &appname; plot specific
+	solutions for the given initial conditions.  You can either specify initial conditions in the dialog,
+	or you can click on the plot directly to specify the initial point.  While the solver dialog
+	is active, the zooming by clicking and dragging does not work.  You have to close the dialog first
+	if you want to zoom using the mouse.
+      </para>
+
+      <para>
+	The solver uses the standard Runge-Kutta method.
+	The plots will stay on the screen until cleared.  The solver will stop whenever it reaches the boundary
+	of the plot window.  Zooming does not change the limits or parameters of the solutions,
+	you will have to clear and redraw them with appropriate parameters.
+	You can also use the
+        <link linkend="gel-function-SlopefieldDrawSolution"><function>SlopefieldDrawSolution</function></link>
+	function to draw solutions from the command line or programs.  
+      </para>
+
+    </sect1>
+
+    <sect1 id="genius-vectorfield-plots">
+      <title>Vectorfield Plots</title>
+      <para>
+	In the create plot window, you can also choose the <guilabel>Vector field</guilabel> notebook
+        tab to create a two dimensional vector field plot.
+	Similar operations can be
+	done on such graphs as can be done on the other line plots.
+	For plotting using the command line see the documentation of the
+        <link linkend="gel-function-VectorfieldPlot"><function>VectorfieldPlot</function></link> function.
+      </para>
+
+      <para>
+	By default only the direction of the vector field is shown.  To show the magnitude, uncheck the
+	appropriate checkbox.
+      </para>
+
+    </sect1>
+
     <sect1 id="genius-surface-plots">
       <title>Surface Plots</title>
       <para>

Modified: trunk/src/graphing.c
==============================================================================
--- trunk/src/graphing.c	(original)
+++ trunk/src/graphing.c	Sun Feb  1 06:11:54 2009
@@ -133,8 +133,11 @@
 static double deftinc = 0.01;
 
 static gboolean lineplot_draw_legends = TRUE;
+static gboolean lineplot_draw_legends_cb = TRUE;
+static gboolean lineplot_draw_legends_parameter = TRUE;
 static gboolean vectorfield_normalize_arrow_length = TRUE;
 static gboolean vectorfield_normalize_arrow_length_cb = TRUE;
+static gboolean vectorfield_normalize_arrow_length_parameter = TRUE;
 
 /* Replotting info */
 static GelEFunc *plot_func[MAXFUNC] = { NULL };
@@ -2886,12 +2889,23 @@
 	while (cx <= plotx2 && cy >= ploty1 && cy <= ploty2) {
 		double *pt;
 		gboolean ex = FALSE;
-		/* FIXME: Euler! too simple, just for show right now */
-		double sl = call_xy_or_z_function (slopefield_func,
-						   cx, cy, &ex);
-		if G_UNLIKELY (ex) {
-			break;
-		}
+		double k1, k2, k3, k4, sl;
+
+		/* standard Runge-Kutta */
+		k1 = call_xy_or_z_function (slopefield_func,
+					    cx, cy, &ex);
+		if G_UNLIKELY (ex) break;
+		k2 = call_xy_or_z_function (slopefield_func,
+					    cx+(dx/2), cy+(dx/2)*k1, &ex);
+		if G_UNLIKELY (ex) break;
+		k3 = call_xy_or_z_function (slopefield_func,
+					    cx+(dx/2), cy+(dx/2)*k2, &ex);
+		if G_UNLIKELY (ex) break;
+		k4 = call_xy_or_z_function (slopefield_func,
+					    cx+dx, cy+dx*k3, &ex);
+		if G_UNLIKELY (ex) break;
+
+		sl = (k1+2*k2+2*k3+k4)/6.0;
 
 		cy += sl * dx;
 		cx += dx;
@@ -2913,12 +2927,23 @@
 	while (cx >= plotx1 && cy >= ploty1 && cy <= ploty2) {
 		double *pt;
 		gboolean ex = FALSE;
-		/* FIXME: Euler! too simple, just for show right now */
-		double sl = call_xy_or_z_function (slopefield_func,
-						   cx, cy, &ex);
-		if G_UNLIKELY (ex) {
-			break;
-		}
+		double k1, k2, k3, k4, sl;
+
+		/* standard Runge-Kutta */
+		k1 = call_xy_or_z_function (slopefield_func,
+					    cx, cy, &ex);
+		if G_UNLIKELY (ex) break;
+		k2 = call_xy_or_z_function (slopefield_func,
+					    cx-(dx/2), cy-(dx/2)*k1, &ex);
+		if G_UNLIKELY (ex) break;
+		k3 = call_xy_or_z_function (slopefield_func,
+					    cx-(dx/2), cy-(dx/2)*k2, &ex);
+		if G_UNLIKELY (ex) break;
+		k4 = call_xy_or_z_function (slopefield_func,
+					    cx-dx, cy-dx*k3, &ex);
+		if G_UNLIKELY (ex) break;
+
+		sl = (k1+2*k2+2*k3+k4)/6.0;
 
 		cy -= sl* dx;
 		cx -= dx;
@@ -3261,8 +3286,6 @@
 
 	replot_fields ();
 
-	/* FIXME : vectorfield */
-
 	if (lineplot_draw_legends)
 		gtk_plot_show_legends (GTK_PLOT (line_plot));
 	else
@@ -3703,10 +3726,10 @@
 	w = gtk_check_button_new_with_mnemonic (_("_Draw legend"));
 	gtk_box_pack_start (GTK_BOX (mainbox), w, FALSE, FALSE, 0);
 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), 
-				      lineplot_draw_legends);
+				      lineplot_draw_legends_cb);
 	g_signal_connect (G_OBJECT (w), "toggled",
 			  G_CALLBACK (optioncb),
-			  (gpointer)&lineplot_draw_legends);
+			  (gpointer)&lineplot_draw_legends_cb);
 
 
 	frame = gtk_frame_new (_("Plot Window"));
@@ -4191,7 +4214,7 @@
 	d_freefunc (slopefield_func);
 	slopefield_func = NULL;
 	g_free (slopefield_name);
-	parametric_name = NULL;
+	slopefield_name = NULL;
 }
 
 static void
@@ -4621,6 +4644,9 @@
 plot_from_dialog (void)
 {
 	int function_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (function_notebook));
+
+	lineplot_draw_legends = lineplot_draw_legends_cb;
+
 	if (function_page == 0)
 		plot_from_dialog_lineplot ();
 	else if (function_page == 1)
@@ -4866,24 +4892,215 @@
 static GelETree *
 SlopefieldPlot_op (GelCtx *ctx, GelETree * * a, int *exception)
 {
-	/* FIXME: */
-	gel_errorout ("FIXME: implement");
+	double x1, x2, y1, y2;
+	GelEFunc *func = NULL;
+	int i;
+
+	if (a[0] == NULL ||
+	    a[0]->type != FUNCTION_NODE) {
+		gel_errorout (_("%s: First argument must be a function"),
+			      "SlopefieldPlot");
+		return NULL;
+	}
+
+	func = d_copyfunc (a[0]->func.func);
+	func->context = -1;
+
+	/* Defaults */
+	x1 = defx1;
+	x2 = defx2;
+	y1 = defy1;
+	y2 = defy2;
+
+	i = 1;
+
+	/* Get window limits */
+	if (a[i] != NULL) {
+		if (a[i]->type == MATRIX_NODE) {
+			if ( ! get_limits_from_matrix (a[i], &x1, &x2, &y1, &y2))
+				goto whack_copied_funcs;
+			i++;
+		} else {
+			GET_DOUBLE(x1, i, "SlopefieldPlot");
+			i++;
+			if (a[i] != NULL) {
+				GET_DOUBLE(x2, i, "SlopefieldPlot");
+				i++;
+				if (a[i] != NULL) {
+					GET_DOUBLE(y1, i, "SlopefieldPlot");
+					i++;
+					if (a[i] != NULL) {
+						GET_DOUBLE(y2, i, "SlopefieldPlot");
+						i++;
+					}
+				}
+			}
+			/* FIXME: what about errors */
+			if (error_num != 0) {
+				error_num = 0;
+				goto whack_copied_funcs;
+			}
+		}
+	}
+
+	if (x1 > x2) {
+		double s = x1;
+		x1 = x2;
+		x2 = s;
+	}
+
+	if (y1 > y2) {
+		double s = y1;
+		y1 = y2;
+		y2 = s;
+	}
+
+	if (x1 == x2) {
+		gel_errorout (_("%s: invalid X range"), "SlopefieldPlot");
+		goto whack_copied_funcs;
+	}
+
+	if (y1 == y2) {
+		gel_errorout (_("%s: invalid Y range"), "SlopefieldPlot");
+		goto whack_copied_funcs;
+	}
+
+	line_plot_clear_funcs ();
+
+	slopefield_func = func;
+
+	reset_plotx1 = plotx1 = x1;
+	reset_plotx2 = plotx2 = x2;
+	reset_ploty1 = ploty1 = y1;
+	reset_ploty2 = ploty2 = y2;
+
+	lineplot_draw_legends = lineplot_draw_legends_parameter;
+
+	plot_mode = MODE_LINEPLOT_SLOPEFIELD;
+	plot_functions (FALSE /* do_window_present */);
+
+	if (interrupted)
+		return NULL;
+	else
+		return gel_makenum_null ();
+
+whack_copied_funcs:
+	d_freefunc (func);
+	func = NULL;
+
 	return NULL;
 }
 
 static GelETree *
 VectorfieldPlot_op (GelCtx *ctx, GelETree * * a, int *exception)
 {
-	/* FIXME: */
-	gel_errorout ("FIXME: implement");
-	return NULL;
-}
+	double x1, x2, y1, y2;
+	GelEFunc *funcx = NULL;
+	GelEFunc *funcy = NULL;
+	int i;
+
+	/* FIXME: also accept just one function and then treat it as complex
+	 * valued */
+
+	if (a[0] == NULL || a[1] == NULL ||
+	    a[0]->type != FUNCTION_NODE ||
+	    a[1]->type != FUNCTION_NODE) {
+		gel_errorout (_("%s: First two arguments must be functions"), "VectorfieldPlot");
+		return NULL;
+	}
+
+	funcx = d_copyfunc (a[0]->func.func);
+	funcx->context = -1;
+	funcy = d_copyfunc (a[1]->func.func);
+	funcy->context = -1;
+
+	/* Defaults */
+	x1 = defx1;
+	x2 = defx2;
+	y1 = defy1;
+	y2 = defy2;
+
+	i = 2;
+
+	/* Get window limits */
+	if (a[i] != NULL) {
+		if (a[i]->type == MATRIX_NODE) {
+			if ( ! get_limits_from_matrix (a[i], &x1, &x2, &y1, &y2))
+				goto whack_copied_funcs;
+			i++;
+		} else {
+			GET_DOUBLE(x1, i, "VectorfieldPlot");
+			i++;
+			if (a[i] != NULL) {
+				GET_DOUBLE(x2, i, "VectorfieldPlot");
+				i++;
+				if (a[i] != NULL) {
+					GET_DOUBLE(y1, i, "VectorfieldPlot");
+					i++;
+					if (a[i] != NULL) {
+						GET_DOUBLE(y2, i, "VectorfieldPlot");
+						i++;
+					}
+				}
+			}
+			/* FIXME: what about errors */
+			if (error_num != 0) {
+				error_num = 0;
+				goto whack_copied_funcs;
+			}
+		}
+	}
+
+	if (x1 > x2) {
+		double s = x1;
+		x1 = x2;
+		x2 = s;
+	}
+
+	if (y1 > y2) {
+		double s = y1;
+		y1 = y2;
+		y2 = s;
+	}
+
+	if (x1 == x2) {
+		gel_errorout (_("%s: invalid X range"), "VectorfieldPlot");
+		goto whack_copied_funcs;
+	}
+
+	if (y1 == y2) {
+		gel_errorout (_("%s: invalid Y range"), "VectorfieldPlot");
+		goto whack_copied_funcs;
+	}
+
+	line_plot_clear_funcs ();
+
+	vectorfield_func_x = funcx;
+	vectorfield_func_y = funcy;
+
+	reset_plotx1 = plotx1 = x1;
+	reset_plotx2 = plotx2 = x2;
+	reset_ploty1 = ploty1 = y1;
+	reset_ploty2 = ploty2 = y2;
+
+	lineplot_draw_legends = lineplot_draw_legends_parameter;
+	vectorfield_normalize_arrow_length =
+		vectorfield_normalize_arrow_length_parameter;
+
+	plot_mode = MODE_LINEPLOT_VECTORFIELD;
+	plot_functions (FALSE /* do_window_present */);
+
+	if (interrupted)
+		return NULL;
+	else
+		return gel_makenum_null ();
+
+whack_copied_funcs:
+	d_freefunc (funcx);
+	funcx = NULL;
+	d_freefunc (funcy);
+	funcy = NULL;
 
-static GelETree *
-VectorfieldCPlot_op (GelCtx *ctx, GelETree * * a, int *exception)
-{
-	/* FIXME: */
-	gel_errorout ("FIXME: implement");
 	return NULL;
 }
 
@@ -4981,6 +5198,8 @@
 	reset_ploty1 = ploty1 = y1;
 	reset_ploty2 = ploty2 = y2;
 
+	lineplot_draw_legends = lineplot_draw_legends_parameter;
+
 	plot_mode = MODE_LINEPLOT;
 	plot_functions (FALSE /* do_window_present */);
 
@@ -5118,6 +5337,8 @@
 	plott2 = t2;
 	plottinc = tinc;
 
+	lineplot_draw_legends = lineplot_draw_legends_parameter;
+
 	plot_mode = MODE_LINEPLOT_PARAMETRIC;
 	plot_functions (FALSE /* do_window_present */);
 
@@ -5250,6 +5471,8 @@
 	plott2 = t2;
 	plottinc = tinc;
 
+	lineplot_draw_legends = lineplot_draw_legends_parameter;
+
 	plot_mode = MODE_LINEPLOT_PARAMETRIC;
 	plot_functions (FALSE /* do_window_present */);
 
@@ -5519,6 +5742,44 @@
 	return make_matrix_from_limits_surf ();
 }
 
+static GelETree *
+set_VectorfieldNormalized (GelETree * a)
+{
+	if G_UNLIKELY ( ! check_argument_bool (&a, 0, "set_VectorfieldNormalized"))
+		return NULL;
+	if (a->type == VALUE_NODE)
+		vectorfield_normalize_arrow_length_parameter
+			= ! mpw_zero_p (a->val.value);
+	else /* a->type == BOOL_NODE */
+		vectorfield_normalize_arrow_length_parameter = a->bool_.bool_;
+
+	return gel_makenum_bool (vectorfield_normalize_arrow_length_parameter);
+}
+static GelETree *
+get_VectorfieldNormalized (void)
+{
+	return gel_makenum_bool (vectorfield_normalize_arrow_length_parameter);
+}
+
+static GelETree *
+set_LinePlotDrawLegends (GelETree * a)
+{
+	if G_UNLIKELY ( ! check_argument_bool (&a, 0, "set_LinePlotDrawLegend"))
+		return NULL;
+	if (a->type == VALUE_NODE)
+		lineplot_draw_legends_parameter
+			= ! mpw_zero_p (a->val.value);
+	else /* a->type == BOOL_NODE */
+		lineplot_draw_legends_parameter = a->bool_.bool_;
+
+	return gel_makenum_bool (lineplot_draw_legends_parameter);
+}
+static GelETree *
+get_LinePlotDrawLegends (void)
+{
+	return gel_makenum_bool (lineplot_draw_legends_parameter);
+}
+
 void
 gel_add_graph_functions (void)
 {
@@ -5533,7 +5794,6 @@
 
 	VFUNC (SlopefieldPlot, 2, "func,args", "plotting", N_("Draw a slope field.  First comes the function dx/dy in terms of x and y (or a complex z) then optionally the limits as x1,x2,y1,y2"));
 	VFUNC (VectorfieldPlot, 3, "xfunc,yfunc,args", "plotting", N_("Draw a vector field.  First come the functions dx/dt and dy/dt in terms of x and y then optionally the limits as x1,x2,y1,y2"));
-	VFUNC (VectorfieldCPlot, 2, "zfunc,args", "plotting", N_("Draw a vector field.  First comes the complex function dz/dt in terms of a complex z (or x and y) then optionally the limits as x1,x2,y1,y2"));
 
 	FUNC (SlopefieldDrawSolution, 3, "x,y,dx", "plotting", N_("Draw a solution for a slope field starting at x,y and using dx as increment"));
 	FUNC (SlopefieldClearSolutions, 0, "", "plotting", N_("Clear all the slopefield solutions"));
@@ -5544,6 +5804,9 @@
 	FUNC (LinePlotClear, 0, "", "plotting", N_("Show the line plot window and clear out functions"));
 	VFUNC (LinePlotDrawLine, 2, "x1,y1,x2,y2,args", "plotting", N_("Draw a line from x1,y1 to x2,y2.  x1,y1,x2,y2 can be replaced by a n by 2 matrix for a longer line"));
 
+	PARAMETER (VectorfieldNormalized, N_("Normalize vectorfields if true.  That is, only show direction and not magnitude."));
+	PARAMETER (LinePlotDrawLegends, N_("If to draw legends or not on line plots."));
+
 	PARAMETER (LinePlotWindow, N_("Line plotting window (limits) as a 4-vector of the form [x1,x2,y1,y2]"));
 	PARAMETER (SurfacePlotWindow, N_("Surface plotting window (limits) as a 6-vector of the form [x1,x2,y1,y2,z1,z2]"));
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]