[genius] Wed Aug 13 17:06:29 2014 Jiri (George) Lebl <jirka 5z com>



commit 5ec9e43d939639e3decb1b40602d7f9052dfa799
Author: Jiri (George) Lebl <jiri lebl gmail com>
Date:   Wed Aug 13 17:08:35 2014 -0500

    Wed Aug 13 17:06:29 2014  Jiri (George) Lebl <jirka 5z com>
    
         * gtkextra/gtkplotdata.c: Fix drawing data with no connector, then
           plot the points only, also fix plotting data with one value only,
           finally fix clipping if both endpoints of a segment are out of
           bounds.
    
         * src/graphing.c: Add LinePlotDrawPoints function
    
         * help/C/genius.xml: Document LinePlotDrawPoints, Also add
           documentation and examples for EulersMethodFull and RungeKuttaFull
           on how to use LinePlotDrawLine or LinePlotDrawPoints.  YELP IS
           BROKEN so the links don't work.  The reason for shouting here
           is that filing bugs for yelp is useless (these bugs have been filed
           for well over a year, and nobody touched them at all).  I'm
           thinking of just installing html docs.  Actually I'm thinking of
           moving away from this incredibly broken DocBook nonsense and
           moving to LaTeX, where I could actually do more math to explain
           things and it would be a lot easier to edit.

 ChangeLog              |   20 ++++
 NEWS                   |    4 +-
 gtkextra/gtkplotdata.c |   99 ++++++++++++++++--
 help/C/genius.xml      |  119 ++++++++++++++++++++-
 help/genius.txt        |  116 ++++++++++++++++++--
 src/graphing.c         |  276 ++++++++++++++++++++++++++++++++++++++++++++++--
 6 files changed, 598 insertions(+), 36 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index ad93120..fec33d7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+Wed Aug 13 17:06:29 2014  Jiri (George) Lebl <jirka 5z com>
+
+        * gtkextra/gtkplotdata.c: Fix drawing data with no connector, then
+          plot the points only, also fix plotting data with one value only,
+          finally fix clipping if both endpoints of a segment are out of
+          bounds.
+
+        * src/graphing.c: Add LinePlotDrawPoints function
+
+        * help/C/genius.xml: Document LinePlotDrawPoints, Also add
+          documentation and examples for EulersMethodFull and RungeKuttaFull
+          on how to use LinePlotDrawLine or LinePlotDrawPoints.  YELP IS
+          BROKEN so the links don't work.  The reason for shouting here
+          is that filing bugs for yelp is useless (these bugs have been filed
+          for well over a year, and nobody touched them at all).  I'm
+          thinking of just installing html docs.  Actually I'm thinking of
+          moving away from this incredibly broken DocBook nonsense and
+          moving to LaTeX, where I could actually do more math to explain
+          things and it would be a lot easier to edit.
+
 Mon May 05 17:00:38 2014  Jiri (George) Lebl <jirka 5z com>
 
        * src/gnome_genius.[ch], src/graphing.c: export the calc_running
diff --git a/NEWS b/NEWS
index e86d6c6..e595656 100644
--- a/NEWS
+++ b/NEWS
@@ -5,12 +5,14 @@ Changes to 1.0.18
   DisplayVariables, PrintTable
 * New PlotCanvasFreeze/PlotCanvasThaw functions to improve flicker
   if doing animations with genius.
+* Add LinePlotDrawPoints function to draw just points without the line
 * Allow setting color in LinePlotDrawLine with RGB vector.
 * Implement subsecond precision in wait function.
 * Fix memory corruption error triggered in nested floating point
   for loops with a floating point step
 * Few minor bug fixes and fix some more compile warnings in gtkextra
-* A few minor improvements to the documentation.
+* A few improvements to the documentation (yelp sucks donkeyballs!
+  Just had to say that).
 * FIXME
 
 Changes to 1.0.17
diff --git a/gtkextra/gtkplotdata.c b/gtkextra/gtkplotdata.c
index cbf1549..1b67de8 100644
--- a/gtkextra/gtkplotdata.c
+++ b/gtkextra/gtkplotdata.c
@@ -2817,8 +2817,16 @@ gtk_plot_data_draw_legend(GtkPlotData *data, gint x, gint y)
                             y + area.y + lheight / 2,
                             x + area.x + roundint(plot->legends_line_width * m),
                             y + area.y + lheight / 2);
+    else
+    /*if(data->line_connector == GTK_PLOT_CONNECT_NONE &&
+       data->symbol.symbol_type != GTK_PLOT_SYMBOL_IMPULSE)*/
+         gtk_plot_draw_line(plot, data->line,
+                            x + area.x + roundint(plot->legends_line_width * m)/2,
+                            y + area.y + lheight / 2,
+                            x + area.x + roundint(plot->legends_line_width * m)/2,
+                            y + area.y + lheight / 2);
 
-    if(data->symbol.symbol_type != GTK_PLOT_SYMBOL_IMPULSE){
+    if(data->symbol.symbol_type != GTK_PLOT_SYMBOL_IMPULSE) {
          GtkPlotSymbol aux_symbol;
          gint x1, y1;
 
@@ -2833,7 +2841,7 @@ gtk_plot_data_draw_legend(GtkPlotData *data, gint x, gint y)
          if(data->symbol.symbol_style == GTK_PLOT_SYMBOL_OPAQUE)
             gtk_plot_data_draw_symbol_private (data, x1, y1, aux_symbol);
 
-         if(data->symbol.symbol_style == GTK_PLOT_SYMBOL_FILLED){
+         if(data->symbol.symbol_style == GTK_PLOT_SYMBOL_FILLED) {
             aux_symbol.color = data->symbol.color;
             gtk_plot_data_draw_symbol_private (data, x1, y1, aux_symbol);
          }
@@ -4289,6 +4297,9 @@ line_on_screen (double x1, double y1, double x2, double y2,
  * There is some loss when the line ends are way too far in either direction.
  * Perhaps roundoff error?  Above?
  *
+ * FIXME: no this is because of the clipping already done I think.
+ * I think I fixed it by simply not clipping at all before
+ *
  * But this works better than the alternative of failing completely.
  */
 static void
@@ -4351,6 +4362,32 @@ gtk_plot_data_draw_lines (GtkPlotData *dataset,
 }
 
 static void
+gtk_plot_data_draw_just_the_points (GtkPlotData *dataset,
+                                   GtkPlotPoint *points,
+                                   int numpoints)
+{
+  GtkPlot *plot;
+  GtkWidget *widget;
+  int i;
+  int lx1, lx2, ly1, ly2;
+
+  plot = dataset->plot;
+  widget = GTK_WIDGET (plot);
+
+  lx1 = widget->allocation.x;
+  lx2 = lx1 + widget->allocation.width;
+  ly1 = widget->allocation.y;
+  ly2 = ly1 + widget->allocation.height;
+
+  for(i = 0; i < numpoints; i++){
+       if (points[i].x >= lx1 && points[i].y >= ly1 &&
+           points[i].x <= lx2 && points[i].y <= ly2) {
+               gtk_plot_pc_draw_point (plot->pc, points[i].x, points[i].y);
+       }
+  }
+}
+
+static void
 gtk_plot_data_draw_errbars(GtkPlotData *dataset,
                            gdouble x, gdouble y, gdouble z,
                            gdouble dx, gdouble dy, gdouble dz)
@@ -4625,6 +4662,7 @@ gtk_plot_data_draw_star(GtkPlotData *data, gdouble x, gdouble y, gdouble size)
                         x-s2, y+s2, x+s2, y-s2);
 }
 
+  /* FIXME: if connecter none, draw points, so perhaps bad naming */
 static void
 gtk_plot_data_connect_points(GtkPlotData *dataset, gint npoints)
 {
@@ -4653,6 +4691,9 @@ gtk_plot_data_connect_points(GtkPlotData *dataset, gint npoints)
   area.width = allocation.width;
   area.height = allocation.height;
 
+  /* sanity? */
+  if (num_points <= 0) return;
+
   clip_area.x = area.x + roundint(plot->x * allocation.width);
   clip_area.y = area.y + roundint(plot->y * allocation.height);
   clip_area.width = roundint(plot->width * allocation.width);
@@ -4672,8 +4713,9 @@ gtk_plot_data_connect_points(GtkPlotData *dataset, gint npoints)
   array_z = gtk_plot_data_get_z(dataset, &n);
 
   switch(dataset->line_connector){
+   case GTK_PLOT_CONNECT_NONE:
    case GTK_PLOT_CONNECT_STRAIGHT:
-       if(npoints == 1) break;
+       /*if(npoints == 1) break;*/
        num_points = 0;
        for(n=n0; n<dataset->num_points; n++)
         {
@@ -4681,7 +4723,10 @@ gtk_plot_data_connect_points(GtkPlotData *dataset, gint npoints)
           x = array_x[n];
           y = array_y[n];
           if(array_z != NULL) z = array_z[n];
-          if(gtk_plot_data_point_clipped(dataset, x, y, z, 0.0, TRUE)) continue;
+         /*FIXME: this is the wrong way of doing it, but we are already
+          * clipping below.  But this might screw up the area things ...
+          * hmmm, though it seemed wrong for the polygon anyway */
+          /*if(gtk_plot_data_point_clipped(dataset, x, y, z, 0.0, TRUE)) continue;*/
           if(num_points == 0) first = n;
           if(GTK_IS_PLOT3D(plot)){
             gdouble pz;
@@ -4698,7 +4743,14 @@ gtk_plot_data_connect_points(GtkPlotData *dataset, gint npoints)
        break;
    case GTK_PLOT_CONNECT_HV_STEP:
        if(GTK_IS_PLOT3D(plot)) break;
-       if(dataset->num_points == 1) break;
+       if(dataset->num_points == 1) {
+              x = array_x[0];
+              y = array_y[0];
+              gtk_plot_get_pixel(plot, x, y, &px, &py);
+              points[0].x = px;
+              points[0].y = py;
+              break;
+       }
        num_points=0;
        for(n=0; n < dataset->num_points; n++)
         {
@@ -4722,7 +4774,14 @@ gtk_plot_data_connect_points(GtkPlotData *dataset, gint npoints)
        break;
     case GTK_PLOT_CONNECT_VH_STEP:
        if(GTK_IS_PLOT3D(plot)) break;
-       if(dataset->num_points == 1) break;
+       if(dataset->num_points == 1) {
+              x = array_x[0];
+              y = array_y[0];
+              gtk_plot_get_pixel(plot, x, y, &px, &py);
+              points[0].x = px;
+              points[0].y = py;
+              break;
+       }
        num_points=0;
        for(n=0; n < dataset->num_points; n++)
         {
@@ -4746,7 +4805,14 @@ gtk_plot_data_connect_points(GtkPlotData *dataset, gint npoints)
        break;
      case GTK_PLOT_CONNECT_MIDDLE_STEP:
        if(GTK_IS_PLOT3D(plot)) break;
-       if(dataset->num_points == 1) break;
+       if(dataset->num_points == 1) {
+              x = array_x[0];
+              y = array_y[0];
+              gtk_plot_get_pixel(plot, x, y, &px, &py);
+              points[0].x = px;
+              points[0].y = py;
+              break;
+       }
        num_points=1;
        for(n=1; n < dataset->num_points; n++)
         {
@@ -4780,8 +4846,16 @@ gtk_plot_data_connect_points(GtkPlotData *dataset, gint npoints)
          g_free(points);
          return;
        }
+       if(dataset->num_points == 1) {
+              x = array_x[0];
+              y = array_y[0];
+              gtk_plot_get_pixel(plot, x, y, &px, &py);
+              points[0].x = px;
+              points[0].y = py;
+              break;
+       }
        spline = *dataset;
-       if(dataset->num_points <= 1) break;
+       /*if(dataset->num_points <= 1) break;*/
        spline_coef = (gdouble *)g_malloc(dataset->num_points*sizeof(gdouble));
        spline_points = (GtkPlotPoint *)g_malloc(sizeof(GtkPlotPoint));
        spline_solve(dataset->num_points, array_x, array_y, spline_coef);
@@ -4822,7 +4896,7 @@ gtk_plot_data_connect_points(GtkPlotData *dataset, gint npoints)
        g_free(points);
        if(plot->clip_data && !GTK_IS_PLOT3D(plot)) gtk_plot_pc_clip(plot->pc, NULL);
        return;
-     case GTK_PLOT_CONNECT_NONE:
+     /*case GTK_PLOT_CONNECT_NONE:*/
      default:
        if(plot->clip_data && !GTK_IS_PLOT3D(plot)) gtk_plot_pc_clip(plot->pc, NULL);
        g_free(points);
@@ -4863,7 +4937,12 @@ gtk_plot_data_connect_points(GtkPlotData *dataset, gint npoints)
      * in more places than here, but I'm not sure if it is necessarily safe
      * elsewhere
      * -Jiri */
-    gtk_plot_data_draw_lines(dataset, points, num_points);
+    if (dataset->line_connector == GTK_PLOT_CONNECT_NONE ||
+       num_points == 1) {
+      gtk_plot_data_draw_just_the_points(dataset, points, num_points);
+    } else {
+      gtk_plot_data_draw_lines(dataset, points, num_points);
+    }
   }
 
   if(plot->clip_data && !GTK_IS_PLOT3D(plot)) gtk_plot_pc_clip(plot->pc, NULL);
diff --git a/help/C/genius.xml b/help/C/genius.xml
index c749238..afaf318 100644
--- a/help/C/genius.xml
+++ b/help/C/genius.xml
@@ -4,7 +4,7 @@
   <!ENTITY app "<application>Genius Mathematics Tool</application>">
   <!ENTITY appname "Genius">
   <!ENTITY appversion "1.0.18">
-  <!ENTITY date "March 2014">
+  <!ENTITY date "August 2014">
 
   <!ENTITY legal SYSTEM "legal.xml">
 
@@ -7693,6 +7693,10 @@ and has period <userinput>b-a</userinput>.</para>
            initial <varname>x0</varname>, <varname>y0</varname> going to
            <varname>x1</varname> with <varname>n</varname> increments,
            returns <varname>y</varname> at <varname>x1</varname>.
+           Unless you explicitly want to use Euler's method, you should really
+           think about using
+           <link linkend="gel-function-RungeKutta">RungeKutta</link>
+           for solving ODE.
          </para>
          <para>
            Systems can be solved by just having <varname>y</varname> be a
@@ -7718,9 +7722,22 @@ and has period <userinput>b-a</userinput>.</para>
            initial <varname>x0</varname>, <varname>y0</varname> going to
            <varname>x1</varname> with <varname>n</varname> increments,
            returns a 2 by <userinput>n+1</userinput> matrix with the
-           <varname>x</varname> and <varname>y</varname> values.  Suitable
+           <varname>x</varname> and <varname>y</varname> values.
+           Unless you explicitly want to use Euler's method, you should really
+           think about using
+           <link linkend="gel-function-RungeKuttaFull">RungeKuttaFull</link>
+           for solving ODE.
+           Suitable
            for plugging into 
-           <link linkend="gel-function-LinePlotDrawLine">LinePlotDrawLine</link>.
+           <link linkend="gel-function-LinePlotDrawLine">LinePlotDrawLine</link> or
+           <link linkend="gel-function-LinePlotDrawPoints">LinePlotDrawPoints</link>.
+         </para>
+         <para>
+           Example:
+          <screen><prompt>genius></prompt> <userinput>LinePlotClear();</userinput>
+<prompt>genius></prompt> <userinput>line = EulersMethodFull(`(x,y)=y,0,1.0,3.0,50);</userinput>
+<prompt>genius></prompt> 
<userinput>LinePlotDrawLine(line,"window","fit","color","blue","legend","Exponential growth");</userinput>
+</screen>
          </para>
          <para>
            Systems can be solved by just having <varname>y</varname> be a
@@ -7729,6 +7746,21 @@ and has period <userinput>b-a</userinput>.</para>
            <varname>x</varname> and a vector of the same size for the second
            argument and should return a vector of the same size.
          </para>
+         <para>
+                 The output for a system is still a n by 2 matrix with the second
+                 entry being a vector.  If you wish to plot the line, make sure to use row vectors, and then 
flatten the matrix with
+                 <link linkend="gel-function-ExpandMatrix">ExpandMatrix</link>,
+                 and pick out the right columns.  Example:
+          <screen><prompt>genius></prompt> <userinput>LinePlotClear();</userinput>
+<prompt>genius></prompt> <userinput>lines = 
EulersMethodFull(`(x,y)=[y@(2),-y@(1)],0,[1.0,1.0],10.0,500);</userinput>
+<prompt>genius></prompt> <userinput>lines = ExpandMatrix(lines);</userinput>
+<prompt>genius></prompt> <userinput>firstline = lines@(,[1,2]);</userinput>
+<prompt>genius></prompt> <userinput>secondline = lines@(,[1,3]);</userinput>
+<prompt>genius></prompt> <userinput>LinePlotWindow = [0,10,-2,2];</userinput>
+<prompt>genius></prompt> <userinput>LinePlotDrawLine(firstline,"color","blue","legend","First");</userinput>
+<prompt>genius></prompt> 
<userinput>LinePlotDrawPoints(secondline,"color","red","thickness",3,"legend","Second");</userinput>
+</screen>
+         </para>
           <para>
            See
            <ulink url="http://mathworld.wolfram.com/EulerForwardMethod.html";>Mathworld</ulink>, or
@@ -7936,7 +7968,15 @@ and has period <userinput>b-a</userinput>.</para>
            returns a 2 by <userinput>n+1</userinput> matrix with the
            <varname>x</varname> and <varname>y</varname> values.  Suitable
            for plugging into 
-           <link linkend="gel-function-LinePlotDrawLine">LinePlotDrawLine</link>.
+           <link linkend="gel-function-LinePlotDrawLine">LinePlotDrawLine</link> or
+           <link linkend="gel-function-LinePlotDrawPoints">LinePlotDrawPoints</link>.
+         </para>
+         <para>
+           Example:
+          <screen><prompt>genius></prompt> <userinput>LinePlotClear();</userinput>
+<prompt>genius></prompt> <userinput>line = RungeKuttaFull(`(x,y)=y,0,1.0,3.0,50);</userinput>
+<prompt>genius></prompt> 
<userinput>LinePlotDrawLine(line,"window","fit","color","blue","legend","Exponential growth");</userinput>
+</screen>
          </para>
          <para>
            Systems can be solved by just having <varname>y</varname> be a
@@ -7945,6 +7985,21 @@ and has period <userinput>b-a</userinput>.</para>
            <varname>x</varname> and a vector of the same size for the second
            argument and should return a vector of the same size.
          </para>
+         <para>
+                 The output for a system is still a n by 2 matrix with the second
+                 entry being a vector.  If you wish to plot the line, make sure to use row vectors, and then 
flatten the matrix with
+                 <link linkend="gel-function-ExpandMatrix">ExpandMatrix</link>,
+                 and pick out the right columns.  Example:
+          <screen><prompt>genius></prompt> <userinput>LinePlotClear();</userinput>
+<prompt>genius></prompt> <userinput>lines = 
RungeKuttaFull(`(x,y)=[y@(2),-y@(1)],0,[1.0,1.0],10.0,100);</userinput>
+<prompt>genius></prompt> <userinput>lines = ExpandMatrix(lines);</userinput>
+<prompt>genius></prompt> <userinput>firstline = lines@(,[1,2]);</userinput>
+<prompt>genius></prompt> <userinput>secondline = lines@(,[1,3]);</userinput>
+<prompt>genius></prompt> <userinput>LinePlotWindow = [0,10,-2,2];</userinput>
+<prompt>genius></prompt> <userinput>LinePlotDrawLine(firstline,"color","blue","legend","First");</userinput>
+<prompt>genius></prompt> 
<userinput>LinePlotDrawPoints(secondline,"color","red","thickness",3,"legend","Second");</userinput>
+</screen>
+         </para>
           <para>
            See
            <ulink url="http://mathworld.wolfram.com/Runge-KuttaMethod.html";>Mathworld</ulink>, or
@@ -8470,7 +8525,7 @@ and has period <userinput>b-a</userinput>.</para>
            <userinput>"thickness"</userinput>,
            <userinput>"window"</userinput>, 
            <userinput>"arrow"</userinput>, or <userinput>"legend"</userinput>, and after it specify
-           the color, the thicknes, the window
+           the color, the thickness, the window
            as 4-vector, type of arrow, or the legend.
          </para>
          <para>
@@ -8506,7 +8561,7 @@ and has period <userinput>b-a</userinput>.</para>
           <screen><prompt>genius></prompt> 
<userinput>LinePlotDrawLine(0,0,1,1,"color","blue","thickness",3)</userinput>
 <prompt>genius></prompt> <userinput>LinePlotDrawLine([0,0;1,-1;-1,-1])</userinput>
 <prompt>genius></prompt> <userinput>LinePlotDrawLine([0,0;1,1],"arrow","end")</userinput>
-<prompt>genius></prompt> 
<userinput>LinePlotDrawLine(EulersMethodFull(`(x,y)=y,0,3,100),"color","blue","legend","The 
Solution")</userinput>
+<prompt>genius></prompt> 
<userinput>LinePlotDrawLine(RungeKuttaFull(`(x,y)=y,0,3,100),"color","blue","legend","The 
Solution")</userinput>
 <prompt>genius></prompt> <userinput>for r=0.0 to 1.0 by 0.1 do 
LinePlotDrawLine([0,0;1,r],"color",[r,(1-r),0.5],"window",[0,1,0,1])</userinput>
 </screen>
           </para>
@@ -8514,6 +8569,58 @@ and has period <userinput>b-a</userinput>.</para>
         </varlistentry>
 
         <varlistentry>
+         <term><anchor id="gel-function-LinePlotDrawPoints"/>LinePlotDrawPoints</term>
+         <listitem>
+          <synopsis>LinePlotDrawPoints (x,y,...)</synopsis>
+          <synopsis>LinePlotDrawPoints (v,...)</synopsis>
+          <para>
+                 Draw a point at <varname>x</varname>,<varname>y</varname>.
+                 The input can be an <varname>n</varname> by 2 matrix
+                 for <varname>n</varname> different points.  This function has essentially the same
+                 input as <link linkend="gel-function-LinePlotDrawLine">LinePlotDrawLine</link>.
+          </para>
+          <para>
+           Extra parameters can be added to specify line color, thickness,
+           the plotting window, or legend.
+           You can do this by adding an argument string <userinput>"color"</userinput>, 
+           <userinput>"thickness"</userinput>,
+           <userinput>"window"</userinput>, 
+           or <userinput>"legend"</userinput>, and after it specify
+           the color, the thickness, the window
+           as 4-vector, or the legend.
+         </para>
+         <para>
+           The color should be either a string indicating the common english word for the color
+           that GTK will recognize such as 
+            <userinput>"red"</userinput>, <userinput>"blue"</userinput>, <userinput>"yellow"</userinput>, 
etc...
+           Alternatively the color can be specified in RGB format as
+           <userinput>"#rgb"</userinput>, <userinput>"#rrggbb"</userinput>, or
+           <userinput>"#rrrrggggbbbb"</userinput>, where the r, g, or b are hex digits of the red, green, 
and blue
+           components of the color.  Finally the color can also be specified as a real vector specifying the 
red green
+           and blue components where the components are between 0 and 1.
+         </para>
+         <para>
+           The window should be given as usual as <userinput>[x1,x2,y1,y2]</userinput>, or
+           alternatively can be given as a string
+           <userinput>"fit"</userinput> in which case,
+           the x range will be set precisely and the y range will be set with
+           five percent borders around the line.
+         </para>
+         <para>
+           Finally, legend should be a string that can be used as the legend in the
+           graph.  That is, if legends are being printed.
+          </para>
+         <para>
+         Examples:
+          <screen><prompt>genius></prompt> 
<userinput>LinePlotDrawPoints(0,0,"color","blue","thickness",3)</userinput>
+<prompt>genius></prompt> <userinput>LinePlotDrawPoints([0,0;1,-1;-1,-1])</userinput>
+<prompt>genius></prompt> 
<userinput>LinePlotDrawPoints(RungeKuttaFull(`(x,y)=y,0,3,100),"color","blue","legend","The 
Solution")</userinput>
+</screen>
+          </para>
+         </listitem>
+        </varlistentry>
+
+        <varlistentry>
          <term><anchor id="gel-function-LinePlotParametric"/>LinePlotParametric</term>
          <listitem>
           <synopsis>LinePlotParametric (xfunc,yfunc,...)</synopsis>
diff --git a/help/genius.txt b/help/genius.txt
index 70017c0..e57191d 100644
--- a/help/genius.txt
+++ b/help/genius.txt
@@ -1,6 +1,6 @@
 Genius Manual
 
-Jiří Lebl
+Jiř Lebl
 
    Oklahoma State University
 
@@ -12,7 +12,7 @@ Kai Willadsen
 
     <kaiw itee uq edu au>
 
-   Copyright © 1997-2013 Jiří (George) Lebl
+   Copyright © 1997-2013 Jiř (George) Lebl
 
    Copyright © 2004 Kai Willadsen
 
@@ -5834,7 +5834,9 @@ EulersMethod (f,x0,y0,x1,n)
 
           Use classical Euler's method to numerically solve
           y'=f(x,y) for initial x0, y0 going to x1 with n
-          increments, returns y at x1.
+          increments, returns y at x1. Unless you explicitly want
+          to use Euler's method, you should really think about
+          using RungeKutta for solving ODE.
 
           Systems can be solved by just having y be a (column)
           vector everywhere. That is, y0 can be a vector in which
@@ -5851,7 +5853,17 @@ EulersMethodFull (f,x0,y0,x1,n)
           Use classical Euler's method to numerically solve
           y'=f(x,y) for initial x0, y0 going to x1 with n
           increments, returns a 2 by n+1 matrix with the x and y
-          values. Suitable for plugging into LinePlotDrawLine.
+          values. Unless you explicitly want to use Euler's
+          method, you should really think about using
+          RungeKuttaFull for solving ODE. Suitable for plugging
+          into LinePlotDrawLine or LinePlotDrawPoints.
+
+          Example:
+
+genius> LinePlotClear();
+genius> line = EulersMethodFull(`(x,y)=y,0,1.0,3.0,50);
+genius> LinePlotDrawLine(line,"window","fit","color","blue","legend","Ex
+ponential growth");
 
           Systems can be solved by just having y be a (column)
           vector everywhere. That is, y0 can be a vector in which
@@ -5859,6 +5871,23 @@ EulersMethodFull (f,x0,y0,x1,n)
           size for the second argument and should return a vector
           of the same size.
 
+          The output for a system is still a n by 2 matrix with
+          the second entry being a vector. If you wish to plot the
+          line, make sure to use row vectors, and then flatten the
+          matrix with ExpandMatrix, and pick out the right
+          columns. Example:
+
+genius> LinePlotClear();
+genius> lines = EulersMethodFull(`(x,y)=[y@(2),-y@(1)],0,[1.0,1.0],10.0,
+500);
+genius> lines = ExpandMatrix(lines);
+genius> firstline = lines@(,[1,2]);
+genius> secondline = lines@(,[1,3]);
+genius> LinePlotWindow = [0,10,-2,2];
+genius> LinePlotDrawLine(firstline,"color","blue","legend","First");
+genius> LinePlotDrawPoints(secondline,"color","red","thickness",3,"legen
+d","Second");
+
           See Mathworld, or Wikipedia for more information.
 
    FindRootBisection
@@ -6011,7 +6040,14 @@ RungeKuttaFull (f,x0,y0,x1,n)
           method to numerically solve y'=f(x,y) for initial x0, y0
           going to x1 with n increments, returns a 2 by n+1 matrix
           with the x and y values. Suitable for plugging into
-          LinePlotDrawLine.
+          LinePlotDrawLine or LinePlotDrawPoints.
+
+          Example:
+
+genius> LinePlotClear();
+genius> line = RungeKuttaFull(`(x,y)=y,0,1.0,3.0,50);
+genius> LinePlotDrawLine(line,"window","fit","color","blue","legend","Ex
+ponential growth");
 
           Systems can be solved by just having y be a (column)
           vector everywhere. That is, y0 can be a vector in which
@@ -6019,6 +6055,23 @@ RungeKuttaFull (f,x0,y0,x1,n)
           size for the second argument and should return a vector
           of the same size.
 
+          The output for a system is still a n by 2 matrix with
+          the second entry being a vector. If you wish to plot the
+          line, make sure to use row vectors, and then flatten the
+          matrix with ExpandMatrix, and pick out the right
+          columns. Example:
+
+genius> LinePlotClear();
+genius> lines = RungeKuttaFull(`(x,y)=[y@(2),-y@(1)],0,[1.0,1.0],10.0,10
+0);
+genius> lines = ExpandMatrix(lines);
+genius> firstline = lines@(,[1,2]);
+genius> secondline = lines@(,[1,3]);
+genius> LinePlotWindow = [0,10,-2,2];
+genius> LinePlotDrawLine(firstline,"color","blue","legend","First");
+genius> LinePlotDrawPoints(secondline,"color","red","thickness",3,"legen
+d","Second");
+
           See Mathworld, or Wikipedia for more information.
      __________________________________________________________
 
@@ -6424,7 +6477,7 @@ LinePlotDrawLine (v,...)
           thickness, arrows, the plotting window, or legend. You
           can do this by adding an argument string "color",
           "thickness", "window", "arrow", or "legend", and after
-          it specify the color, the thicknes, the window as
+          it specify the color, the thickness, the window as
           4-vector, type of arrow, or the legend.
 
           The color should be either a string indicating the
@@ -6455,11 +6508,54 @@ LinePlotDrawLine (v,...)
 genius> LinePlotDrawLine(0,0,1,1,"color","blue","thickness",3)
 genius> LinePlotDrawLine([0,0;1,-1;-1,-1])
 genius> LinePlotDrawLine([0,0;1,1],"arrow","end")
-genius> LinePlotDrawLine(EulersMethodFull(`(x,y)=y,0,3,100),"color","blu
-e","legend","The Solution")
+genius> LinePlotDrawLine(RungeKuttaFull(`(x,y)=y,0,3,100),"color","blue"
+,"legend","The Solution")
 genius> for r=0.0 to 1.0 by 0.1 do LinePlotDrawLine([0,0;1,r],"color",[r
 ,(1-r),0.5],"window",[0,1,0,1])
 
+   LinePlotDrawPoints
+
+LinePlotDrawPoints (x,y,...)
+
+LinePlotDrawPoints (v,...)
+
+          Draw a point at x,y. The input can be an n by 2 matrix
+          for n different points. This function has essentially
+          the same input as LinePlotDrawLine.
+
+          Extra parameters can be added to specify line color,
+          thickness, the plotting window, or legend. You can do
+          this by adding an argument string "color", "thickness",
+          "window", or "legend", and after it specify the color,
+          the thickness, the window as 4-vector, or the legend.
+
+          The color should be either a string indicating the
+          common english word for the color that GTK will
+          recognize such as "red", "blue", "yellow", etc...
+          Alternatively the color can be specified in RGB format
+          as "#rgb", "#rrggbb", or "#rrrrggggbbbb", where the r,
+          g, or b are hex digits of the red, green, and blue
+          components of the color. Finally the color can also be
+          specified as a real vector specifying the red green and
+          blue components where the components are between 0 and
+          1.
+
+          The window should be given as usual as [x1,x2,y1,y2], or
+          alternatively can be given as a string "fit" in which
+          case, the x range will be set precisely and the y range
+          will be set with five percent borders around the line.
+
+          Finally, legend should be a string that can be used as
+          the legend in the graph. That is, if legends are being
+          printed.
+
+          Examples:
+
+genius> LinePlotDrawPoints(0,0,"color","blue","thickness",3)
+genius> LinePlotDrawPoints([0,0;1,-1;-1,-1])
+genius> LinePlotDrawPoints(RungeKuttaFull(`(x,y)=y,0,3,100),"color","blu
+e","legend","The Solution")
+
    LinePlotParametric
 
 LinePlotParametric (xfunc,yfunc,...)
@@ -6954,7 +7050,7 @@ Chapter 13. Settings
 
 Chapter 14. About Genius Mathematics Tool
 
-   Genius Mathematics Tool was written by Jiří (George) Lebl
+   Genius Mathematics Tool was written by Jiř (George) Lebl
    (<jirka 5z com>). The history of Genius Mathematics Tool goes
    back to late 1997. It was the first calculator program for
    GNOME, but it then grew beyond being just a desktop calculator.
@@ -6972,7 +7068,7 @@ Chapter 14. About Genius Mathematics Tool
    in the file COPYING included with the source code of this
    program.
 
-   Jiří Lebl was during various parts of the development partially
+   Jiř Lebl was during various parts of the development partially
    supported for the work by NSF grant DMS 0900885, the University
    of Illinois at Urbana-Champaign, the University of California
    at San Diego, and the University of Wisconsin-Madison. The
diff --git a/src/graphing.c b/src/graphing.c
index 5f920d3..04d351b 100644
--- a/src/graphing.c
+++ b/src/graphing.c
@@ -1,5 +1,5 @@
 /* GENIUS Calculator
- * Copyright (C) 2003-2013 Jiri (George) Lebl
+ * Copyright (C) 2003-2014 Jiri (George) Lebl
  *
  * Author: Jiri (George) Lebl
  *
@@ -3733,6 +3733,43 @@ draw_line (double *x, double *y, int len, int thickness, GdkColor *color,
        return data;
 }
 
+static GtkPlotData *
+draw_points (double *x, double *y, int len, int thickness, GdkColor *color,
+            char *legend)
+{
+       GtkPlotData *data;
+
+       data = GTK_PLOT_DATA (gtk_plot_data_new ());
+       gtk_plot_data_set_points (data, x, y, NULL, NULL, len);
+       g_object_set_data_full (G_OBJECT (data),
+                               "x", x, (GDestroyNotify)g_free);
+       g_object_set_data_full (G_OBJECT (data),
+                               "y", y, (GDestroyNotify)g_free);
+       gtk_plot_add_data (GTK_PLOT (line_plot), data);
+       if (legend == NULL)
+               gtk_plot_data_hide_legend (data);
+       else
+               gtk_plot_data_set_legend (data,
+                                         legend);
+
+       color_alloc (color); 
+
+       gtk_plot_data_set_line_attributes (data,
+                                          GTK_PLOT_LINE_SOLID,
+                                          GDK_CAP_ROUND, 
+                                          GDK_JOIN_ROUND,
+                                          thickness, color);
+
+       gtk_plot_data_set_connector (data, GTK_PLOT_CONNECT_NONE);
+
+       gtk_widget_show (GTK_WIDGET (data));
+
+       gtk_plot_canvas_paint (GTK_PLOT_CANVAS (plot_canvas));
+       gtk_plot_canvas_refresh (GTK_PLOT_CANVAS (plot_canvas));
+
+       return data;
+}
+
 #if 0
 static void
 clip_line_ends (double xx[], double yy[], int len)
@@ -8127,7 +8164,8 @@ update_lineplot_window (double x1, double x2, double y1, double y2)
 
 static gboolean
 get_line_numbers (GelETree *a, double **x, double **y, int *len,
-                 double *minx, double *maxx, double *miny, double *maxy)
+                 double *minx, double *maxx, double *miny, double *maxy,
+                 const char *funcname, int minn)
 {
        int i;
        GelMatrixW *m;
@@ -8146,9 +8184,9 @@ get_line_numbers (GelETree *a, double **x, double **y, int *len,
        m = a->mat.matrix;
 
        if G_UNLIKELY ( ! gel_is_matrix_value_only_real (m)) {
-               gel_errorout (_("%s: Line should be given as a real, n by 2 matrix "
-                               "with columns for x and y, n>=2"),
-                             "LinePlotDrawLine");
+               gel_errorout (_("%s: Points should be given as a real, n by 2 matrix "
+                               "with columns for x and y, n>=%d"),
+                             funcname, minn);
                return FALSE;
        }
 
@@ -8200,9 +8238,9 @@ get_line_numbers (GelETree *a, double **x, double **y, int *len,
                        UPDATE_MINMAX
                }
        } else {
-               gel_errorout (_("%s: Line should be given as a real, n by 2 matrix "
-                               "with columns for x and y, n>=2"),
-                             "LinePlotDrawLine");
+               gel_errorout (_("%s: Points should be given as a real, n by 2 matrix "
+                               "with columns for x and y, n>=%d"),
+                             funcname, minn);
                return FALSE;
        }
 
@@ -8341,7 +8379,9 @@ LinePlotDrawLine_op (GelCtx *ctx, GelETree * * a, int *exception)
 
        if (a[0]->type == GEL_MATRIX_NODE) {
                if G_UNLIKELY ( ! get_line_numbers (a[0], &x, &y, &len,
-                                                   &minx, &maxx, &miny, &maxy))
+                                                   &minx, &maxx, &miny, &maxy,
+                                                   "LinePlotDrawLine",
+                                                   2))
                        return NULL;
                nextarg = 1;
        } else {
@@ -8595,6 +8635,223 @@ LinePlotDrawLine_op (GelCtx *ctx, GelETree * * a, int *exception)
        return gel_makenum_null ();
 }
 
+static GelETree *
+LinePlotDrawPoints_op (GelCtx *ctx, GelETree * * a, int *exception)
+{
+       int len;
+       int nextarg;
+       double *x, *y;
+       double minx = 0, miny = 0, maxx = 0, maxy = 0;
+       GdkColor color;
+       int thickness;
+       int i;
+       gboolean update = FALSE;
+       char *legend = NULL;
+
+       if G_UNLIKELY (plot_in_progress != 0) {
+               gel_errorout (_("%s: Plotting in progress, cannot call %s"),
+                             "LinePlotDrawPoints", "LinePlotDrawPoints");
+               return NULL;
+       }
+
+       ensure_window (FALSE /* do_window_present */);
+
+       if (a[0]->type == GEL_MATRIX_NODE) {
+               if G_UNLIKELY ( ! get_line_numbers (a[0], &x, &y, &len,
+                                                   &minx, &maxx, &miny, &maxy,
+                                                   "LinePlotDrawPoints",
+                                                   1))
+                       return NULL;
+               nextarg = 1;
+       } else {
+               double x1, y1;
+               if G_UNLIKELY (gel_count_arguments (a) < 2) {
+                       gel_errorout (_("%s: Wrong number of arguments"),
+                                     "LinePlotDrawPoints");
+                       return NULL;
+               }
+               GET_DOUBLE(x1, 0, "LinePlotDrawPoints");
+               GET_DOUBLE(y1, 1, "LinePlotDrawPoints");
+               len = 1;
+               x = g_new (double, 1);
+               x[0] = x1;
+               y = g_new (double, 1);
+               y[0] = y1;
+               nextarg = 2;
+
+               minx = x1;
+               maxx = x1;
+               miny = y1;
+               maxy = y1;
+       }
+
+       gdk_color_parse ("black", &color);
+       thickness = 2;
+
+       for (i = nextarg; a[i] != NULL; i++) {
+               if G_LIKELY (a[i]->type == GEL_STRING_NODE ||
+                            a[i]->type == GEL_IDENTIFIER_NODE) {
+                       GelToken *id;
+                       static GelToken *colorid = NULL;
+                       static GelToken *thicknessid = NULL;
+                       static GelToken *windowid = NULL;
+                       static GelToken *fitid = NULL;
+                       static GelToken *legendid = NULL;
+
+                       if (colorid == NULL) {
+                               colorid = d_intern ("color");
+                               thicknessid = d_intern ("thickness");
+                               windowid = d_intern ("window");
+                               fitid = d_intern ("fit");
+                               legendid = d_intern ("legend");
+                       }
+
+                       if (a[i]->type == GEL_STRING_NODE)
+                               id = d_intern (a[i]->str.str);
+                       else
+                               id = a[i]->id.id;
+                       if (id == colorid) {
+                               if G_UNLIKELY ( ! get_color (a[i+1], &color, "LinePlotDrawPoints")) {
+                                       g_free (legend);
+                                       g_free (x);
+                                       g_free (y);
+                                       return NULL;
+                               }
+                               i++;
+                       } else if (id == thicknessid) {
+                               if G_UNLIKELY (a[i+1] == NULL)  {
+                                       gel_errorout (_("%s: No thickness specified"),
+                                                     "LinePlotDrawPoints");
+                                       g_free (legend);
+                                       g_free (x);
+                                       g_free (y);
+                                       return NULL;
+                               }
+                               if G_UNLIKELY ( ! check_argument_positive_integer (a, i+1,
+                                                                                  "LinePlotDrawPoints")) {
+                                       g_free (legend);
+                                       g_free (x);
+                                       g_free (y);
+                                       return NULL;
+                               }
+                               thickness = gel_get_nonnegative_integer (a[i+1]->val.value,
+                                                                        "LinePlotDrawPoints");
+                               i++;
+                       } else if (id == windowid) {
+                               double x1, x2, y1, y2;
+                               if G_UNLIKELY (a[i+1] == NULL ||
+                                              (a[i+1]->type != GEL_STRING_NODE &&
+                                               a[i+1]->type != GEL_IDENTIFIER_NODE &&
+                                               a[i+1]->type != GEL_MATRIX_NODE)) {
+                                       gel_errorout (_("%s: No window specified"),
+                                                     "LinePlotDrawPoints");
+                                       g_free (legend);
+                                       g_free (x);
+                                       g_free (y);
+                                       return NULL;
+                               }
+                               if ((a[i+1]->type == GEL_STRING_NODE &&
+                                    fitid == d_intern (a[i+1]->str.str)) ||
+                                   (a[i+1]->type == GEL_IDENTIFIER_NODE &&
+                                    fitid == a[i+1]->id.id)) {
+                                       x1 = minx;
+                                       x2 = maxx;
+                                       y1 = miny;
+                                       y2 = maxy;
+                                       if G_UNLIKELY (x1 == x2) {
+                                               x1 -= 0.1;
+                                               x2 += 0.1;
+                                       }
+
+                                       /* assume line is a graph so x fits tightly */
+
+                                       if G_UNLIKELY (y1 == y2) {
+                                               y1 -= 0.1;
+                                               y2 += 0.1;
+                                       } else {
+                                               /* Make window 5% larger on each vertical side */
+                                               double height = (y2-y1);
+                                               y1 -= height * 0.05;
+                                               y2 += height * 0.05;
+                                       }
+
+                                       update = update_lineplot_window (x1, x2, y1, y2);
+                               } else if (get_limits_from_matrix (a[i+1], &x1, &x2, &y1, &y2)) {
+                                       update = update_lineplot_window (x1, x2, y1, y2);
+                               } else {
+                                       g_free (legend);
+                                       g_free (x);
+                                       g_free (y);
+                                       return NULL;
+                               }
+                               i++;
+                       } else if (id == legendid) {
+                               if G_UNLIKELY (a[i+1] == NULL)  {
+                                       gel_errorout (_("%s: No legend specified"),
+                                                     "LinePlotDrawPoints");
+                                       g_free (legend);
+                                       g_free (x);
+                                       g_free (y);
+                                       return NULL;
+                               }
+                               if (a[i+1]->type == GEL_STRING_NODE) {
+                                       g_free (legend);
+                                       legend = g_strdup (a[i+1]->str.str);
+                               } else if (a[i+1]->type == GEL_IDENTIFIER_NODE) {
+                                       g_free (legend);
+                                       legend = g_strdup (a[i+1]->id.id->token);
+                               } else {
+                                       gel_errorout (_("%s: Legend must be a string"),
+                                                     "LinePlotDrawPoints");
+                                       g_free (legend);
+                                       g_free (x);
+                                       g_free (y);
+                                       return NULL;
+                               }
+                               i++;
+                       } else {
+                               gel_errorout (_("%s: Unknown style"), "LinePlotDrawPoints");
+                               g_free (legend);
+                               g_free (x);
+                               g_free (y);
+                               return NULL;
+                       }
+               } else {
+                       gel_errorout (_("%s: Bad parameter"), "LinePlotDrawPoints");
+                       g_free (legend);
+                       g_free (x);
+                       g_free (y);
+                       return NULL;
+               }
+       }
+
+       if (plot_mode != MODE_LINEPLOT &&
+           plot_mode != MODE_LINEPLOT_PARAMETRIC &&
+           plot_mode != MODE_LINEPLOT_SLOPEFIELD &&
+           plot_mode != MODE_LINEPLOT_VECTORFIELD) {
+               plot_mode = MODE_LINEPLOT;
+               clear_graph ();
+               update = FALSE;
+       }
+
+
+       if (line_plot == NULL) {
+               add_line_plot ();
+               plot_setup_axis ();
+               update = FALSE;
+       }
+
+       if (update) {
+               plot_axis ();
+       }
+
+       draw_points (x, y, len, thickness, &color, legend);
+
+       g_free(legend);
+
+       return gel_makenum_null ();
+}
+
 static gboolean
 get_surface_data (GelETree *a, double **x, double **y, double **z, int *len,
                  double *minx, double *maxx,
@@ -9614,6 +9871,7 @@ gel_add_graph_functions (void)
 
        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"));
+       VFUNC (LinePlotDrawPoints, 2, "x,y,args", "plotting", N_("Draw a points at x,y.  x,y can be replaced 
by a n by 2 matrix for more points"));
 
        FUNC (PlotCanvasFreeze, 0, "", "plotting", N_("Freeze the plot canvas, that is, inhibit drawing"));
        FUNC (PlotCanvasThaw, 0, "", "plotting", N_("Thaw the plot canvas and redraw the plot immediately"));



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