[chronojump] Initial coder for force sensor realtime graph



commit 5a4ea61ce6f1dba8b77fd82fd0b7609012e57792
Author: Xavier de Blas <xaviblas gmail com>
Date:   Mon Oct 23 16:33:15 2017 +0200

    Initial coder for force sensor realtime graph

 glade/app1.glade       |   19 +++++++
 src/forceSensor.cs     |   78 +++++++++++++++++++++++++++
 src/gui/forceSensor.cs |  137 +++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 232 insertions(+), 2 deletions(-)
---
diff --git a/glade/app1.glade b/glade/app1.glade
index be3a7a5..9488ca9 100644
--- a/glade/app1.glade
+++ b/glade/app1.glade
@@ -1396,6 +1396,9 @@
                                                             <placeholder/>
                                                             </child>
                                                             <child>
+                                                            <placeholder/>
+                                                            </child>
+                                                            <child>
                                                             <widget class="GtkLabel" 
id="label_start_selector_jumps">
                                                             <property name="visible">True</property>
                                                             <property name="can_focus">False</property>
@@ -11129,6 +11132,19 @@ after time</property>
                                                             <property name="position">2</property>
                                                             </packing>
                                                             </child>
+                                                            <child>
+                                                            <widget class="GtkDrawingArea" 
id="force_capture_drawingarea">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <signal name="configure_event" 
handler="on_force_capture_drawingarea_configure_event" swapped="no"/>
+                                                            <signal name="expose_event" 
handler="on_force_capture_drawingarea_expose_event" swapped="no"/>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">True</property>
+                                                            <property name="fill">True</property>
+                                                            <property name="position">3</property>
+                                                            </packing>
+                                                            </child>
                                                             </widget>
                                                             <packing>
                                                             <property name="expand">True</property>
@@ -21598,6 +21614,9 @@ then click this button.</property>
                                                             <child>
                                                             <placeholder/>
                                                             </child>
+                                                            <child>
+                                                            <placeholder/>
+                                                            </child>
                                                             </widget>
                                                             <packing>
                                                             <property name="expand">False</property>
diff --git a/src/forceSensor.cs b/src/forceSensor.cs
index 8a00c33..ed9463d 100644
--- a/src/forceSensor.cs
+++ b/src/forceSensor.cs
@@ -23,6 +23,84 @@ using System.IO;             //for detect OS
 using System.Collections.Generic; //List<T>
 using Mono.Unix;
 
+/*
+ * TODO: this class only contains points plot stuff
+ * currently all the code relevant to force sensor actions is on gui/forcesensor.cs
+ * that code should be here and there only the gui stuff
+ */
+public class ForceSensorCapturePoints
+{
+       //ForceCapturePoints stored to be realtime displayed
+       public List<Gdk.Point> Points;
+       public int NumCaptured;
+       public int NumPainted;
+
+       //used to redo all points if change RealWidthG or RealHeightG
+       private List<double> times;
+       private List<double> forces;
+
+       public int RealWidthG = 10000000; //width of graph in microseconds (will be upgraded if needed)
+       public int RealHeightG = 200; //Newtons (will be upgraded if needed)
+
+       private int widthG;
+       private int heightG;
+
+       //initialize
+       public ForceSensorCapturePoints(int widthG, int heightG)
+       {
+               Points = new List<Gdk.Point>();
+               NumCaptured = 0;
+               NumPainted = 0;         //-1 means delete screen
+               times = new List<double>();
+               forces = new List<double>();
+
+               this.widthG = widthG;
+               this.heightG = heightG;
+       }
+//     int xCount = 10; //just for debugging!!
+
+       public void Add(double time, double force)
+       {
+               times.Add(time);
+               forces.Add(force);
+               Points.Add(new Gdk.Point(
+                                       Convert.ToInt32(widthG * time / RealWidthG),
+                                       Convert.ToInt32( (heightG/2) - ( force * heightG / RealHeightG) )
+                                       ));
+       }
+
+       private Gdk.Point getLastPoint()
+       {
+               return Points[Points.Count -1];
+       }
+
+       public bool OutsideGraph()
+       {
+               Gdk.Point p = getLastPoint();
+               if(p.X > widthG)
+               {
+                       RealWidthG *= 2;
+                       return true;
+               }
+               if(p.Y > heightG /2)
+               {
+                       RealHeightG *= 2;
+                       return true;
+               }
+               return false;
+       }
+
+       //reprocess all points with new RealWidthG, RealHeightG
+       public void Redo()
+       {
+               for(int i=0; i < NumCaptured; i ++)
+                       Points[i] = new Gdk.Point(
+                                       Convert.ToInt32(widthG * times[i] / RealWidthG),
+                                       Convert.ToInt32( (heightG/2) - ( forces[i] * heightG / RealHeightG) )
+                                       );
+       }
+}
+
 public class ForceSensorRFD
 {
        //if these names change, change FunctionPrint() below
diff --git a/src/gui/forceSensor.cs b/src/gui/forceSensor.cs
index 0badf35..04c7218 100644
--- a/src/gui/forceSensor.cs
+++ b/src/gui/forceSensor.cs
@@ -41,10 +41,13 @@ public partial class ChronoJumpWindow
        [Widget] Gtk.Image image_force_sensor_graph;
        [Widget] Gtk.SpinButton spin_force_sensor_calibration_kg_value;
        [Widget] Gtk.Button button_force_sensor_image_save;
+       [Widget] Gtk.DrawingArea force_capture_drawingarea;
+       Gdk.Pixmap force_capture_pixmap = null;
        
        Thread forceCaptureThread;
        static bool forceProcessFinish;
        static bool forceProcessCancel;
+       ForceSensorCapturePoints fscPoints;
 
        Thread forceOtherThread; //for messages on: capture, tare, calibrate
        static string forceSensorOtherMessage = "";
@@ -69,6 +72,8 @@ public partial class ChronoJumpWindow
        SerialPort portFS;
        bool portFSOpened;
 
+       Gdk.GC pen_black_force_capture;
+
        //Don't reopen port because arduino makes reset and tare, calibration... is lost
 
        private bool forceSensorConnect()
@@ -303,7 +308,11 @@ public partial class ChronoJumpWindow
                forceProcessFinish = false;
                forceProcessCancel = false;
                forceSensorLast = 0;
-               
+
+               pen_black_force_capture = new Gdk.GC(force_capture_drawingarea.GdkWindow);
+               pen_black_force_capture.Foreground = UtilGtk.BLACK;
+               //pen_black_force_capture.SetLineAttributes (2, Gdk.LineStyle.Solid, Gdk.CapStyle.NotLast, 
Gdk.JoinStyle.Miter);
+
                event_execute_ButtonFinish.Clicked -= new EventHandler(on_finish_clicked);
                event_execute_ButtonFinish.Clicked += new EventHandler(on_finish_clicked);
                
@@ -347,6 +356,13 @@ public partial class ChronoJumpWindow
                writer.WriteLine("Time (s);Force(N)");
                str = "";
                double firstTime = 0;
+               fscPoints = new ForceSensorCapturePoints(
+                               force_capture_drawingarea.Allocation.Width,
+                               force_capture_drawingarea.Allocation.Height
+                               );
+               UtilGtk.ErasePaint(force_capture_drawingarea, force_capture_pixmap);
+
+               int count = 0;
                while(! forceProcessFinish && ! forceProcessCancel)
                {
                        str = portFS.ReadLine();
@@ -381,6 +397,14 @@ public partial class ChronoJumpWindow
                        writer.WriteLine(time.ToString() + ";" + force.ToString());
                        forceSensorLast = force;
 
+                       fscPoints.Add(time, force);
+                       fscPoints.NumCaptured = count ++;
+                       if(fscPoints.OutsideGraph())
+                       {
+                               fscPoints.Redo();
+                               fscPoints.NumPainted = -1;
+                       }
+
                        //changeSlideIfNeeded(time, force);
                }
                portFS.WriteLine("end_capture:");
@@ -449,6 +473,7 @@ public partial class ChronoJumpWindow
 
                if(capturingForce == forceStatus.CAPTURING)
                {
+                       //------------------- vscale -----------------
                        //A) resize vscale if needed
                        int upper = Convert.ToInt32(vscale_force_sensor.Adjustment.Upper);
                        int lower = Convert.ToInt32(vscale_force_sensor.Adjustment.Lower);
@@ -474,13 +499,121 @@ public partial class ChronoJumpWindow
                                label_force_sensor_value_max.Text = forceSensorLast.ToString();
                        if(forceSensorLast < Convert.ToDouble(label_force_sensor_value_min.Text))
                                label_force_sensor_value_min.Text = forceSensorLast.ToString();
+
+
+                       //------------------- realtime graph -----------------
+                       if(fscPoints.Points == null || force_capture_drawingarea == null)
+                               return true;
+
+                       //mark meaning screen should be erased
+                       if(fscPoints.NumPainted == -1) {
+                               UtilGtk.ErasePaint(force_capture_drawingarea, force_capture_pixmap);
+                               fscPoints.NumPainted = 0;
+                       }
+
+                       int last = fscPoints.NumCaptured;
+                       int toDraw = fscPoints.NumCaptured - fscPoints.NumPainted;
+
+                       //LogB.Information("toDraw: " + toDraw.ToString());
+                       //fixes crash at the end
+                       if(toDraw == 0)
+                               return true;
+
+                       Gdk.Point [] paintPoints;
+                       if(fscPoints.NumPainted > 1)
+                               paintPoints = new Gdk.Point[toDraw +1]; // if something has been painted, 
connected first point with previous points
+                       else
+                               paintPoints = new Gdk.Point[toDraw];
+
+                       int jStart = 0;
+                       if(fscPoints.NumPainted > 1)
+                       {
+                               // if something has been painted, connected first point with previous points
+                               paintPoints[0] = fscPoints.Points[fscPoints.NumPainted];
+                               jStart = 1;
+                       }
+
+                       for(int j=jStart, i = fscPoints.NumPainted +1 ; i <= last ; i ++, j++)
+                       {
+                               paintPoints[j] = fscPoints.Points[i];
+                               LogB.Information("X: " + paintPoints[j].X.ToString() + "; Y: " + 
paintPoints[j].Y.ToString());
+                       }
+                       force_capture_pixmap.DrawLines(pen_black_force_capture, paintPoints);
+                       force_capture_drawingarea.QueueDraw(); // -- refresh
+                       fscPoints.NumPainted = fscPoints.NumCaptured;
                }
 
                Thread.Sleep (25);
-//             LogB.Information(" ForceSensor:"+ forceCaptureThread.ThreadState.ToString());
+               //LogB.Information(" ForceSensor:"+ forceCaptureThread.ThreadState.ToString());
                return true;
        }
 
+       int force_capture_allocationXOld;
+       bool force_capture_sizeChanged;
+       public void on_force_capture_drawingarea_configure_event(object o, ConfigureEventArgs args)
+       {
+//             if(force_capture_drawingarea == null)
+//                     return;
+
+               Gdk.EventConfigure ev = args.Event;
+               Gdk.Window window = ev.Window;
+
+               Gdk.Rectangle allocation = force_capture_drawingarea.Allocation;
+
+               if(force_capture_pixmap == null || force_capture_sizeChanged ||
+                               allocation.Width != force_capture_allocationXOld)
+               {
+                       force_capture_pixmap = new Gdk.Pixmap (window, allocation.Width, allocation.Height, 
-1);
+
+                       if(forceCaptureThread != null) //&& capturingCsharp == 
encoderCaptureProcess.CAPTURING)
+                               fscPoints.NumPainted = -1; //mark meaning screen should be erased and start 
painting from the beginning
+                       else
+                               UtilGtk.ErasePaint(force_capture_drawingarea, force_capture_pixmap);
+
+                       force_capture_sizeChanged = false;
+               }
+
+               force_capture_allocationXOld = allocation.Width;
+       }
+       public void on_force_capture_drawingarea_expose_event(object o, ExposeEventArgs args)
+       {
+//             if(force_capture_drawingarea == null)
+//                     return;
+
+               /* in some mono installations, configure_event is not called, but expose_event yes.
+                * Do here the initialization
+                */
+               //LogB.Debug("EXPOSE");
+
+               Gdk.Rectangle allocation = force_capture_drawingarea.Allocation;
+               if(force_capture_pixmap == null || force_capture_sizeChanged ||
+                               allocation.Width != force_capture_allocationXOld) {
+                       force_capture_pixmap = new Gdk.Pixmap (force_capture_drawingarea.GdkWindow,
+                                       allocation.Width, allocation.Height, -1);
+
+                       if(forceCaptureThread != null) //&& capturingCsharp == 
encoderCaptureProcess.CAPTURING)
+                               fscPoints.NumPainted = -1; //mark meaning screen should be erased and start 
painting from the beginning
+                       else
+                               UtilGtk.ErasePaint(force_capture_drawingarea, force_capture_pixmap);
+
+                       force_capture_sizeChanged = false;
+               }
+
+               Gdk.Rectangle area = args.Event.Area;
+
+               //sometimes this is called when paint is finished
+               //don't let this erase win
+               if(force_capture_pixmap != null) {
+                       args.Event.Window.DrawDrawable(force_capture_drawingarea.Style.WhiteGC, 
force_capture_pixmap,
+                               area.X, area.Y,
+                               area.X, area.Y,
+                               area.Width, area.Height);
+               }
+
+               force_capture_allocationXOld = allocation.Width;
+       }
+
+
        private void on_button_force_sensor_graph_clicked (object o, EventArgs args)
        {
                Gtk.FileChooserDialog filechooser = new Gtk.FileChooserDialog ("Choose file",


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