[chronojump] RaceAnalyzer capture pos/time, speed/time graphs WIP



commit a9ac39f090eb731a9974206ae5e673a10fef8e4b
Author: Xavier de Blas <xaviblas gmail com>
Date:   Mon Mar 29 17:10:32 2021 +0200

    RaceAnalyzer capture pos/time, speed/time graphs WIP

 glade/app1.glade              |  49 ++++++++++++++++++++
 src/Makefile.am               |   1 +
 src/gui/app1/runEncoder.cs    |  83 +++++++++++++++++++++++++++++++--
 src/gui/cairo/raceAnalyzer.cs | 104 ++++++++++++++++++++++++++++++++++++++++++
 src/gui/cairo/xy.cs           |   7 ++-
 5 files changed, 239 insertions(+), 5 deletions(-)
---
diff --git a/glade/app1.glade b/glade/app1.glade
index a7e5f668..53296824 100644
--- a/glade/app1.glade
+++ b/glade/app1.glade
@@ -11660,6 +11660,12 @@ EncoderInertialCapture</property>
                                                             <property name="can_focus">False</property>
                                                             <property name="border_width">8</property>
                                                             <child>
+                                                            <widget class="GtkHBox" id="hbox502">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <property name="spacing">16</property>
+                                                            <property name="homogeneous">True</property>
+                                                            <child>
                                                             <widget class="GtkDrawingArea" 
id="drawingarea_race_analyzer_capture">
                                                             <property name="visible">True</property>
                                                             <property name="can_focus">False</property>
@@ -11671,6 +11677,49 @@ EncoderInertialCapture</property>
                                                             <property name="position">0</property>
                                                             </packing>
                                                             </child>
+                                                            <child>
+                                                            <widget class="GtkVBox" id="vbox255">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <property name="homogeneous">True</property>
+                                                            <child>
+                                                            <widget class="GtkDrawingArea" 
id="drawingarea_race_analyzer_capture_position_time">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <signal name="expose_event" 
handler="on_drawingarea_race_analyzer_capture_position_time_expose_event" swapped="no"/>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">True</property>
+                                                            <property name="fill">True</property>
+                                                            <property name="position">0</property>
+                                                            </packing>
+                                                            </child>
+                                                            <child>
+                                                            <widget class="GtkDrawingArea" 
id="drawingarea_race_analyzer_capture_speed_time">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <signal name="expose_event" 
handler="on_drawingarea_race_analyzer_capture_speed_time_expose_event" swapped="no"/>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">True</property>
+                                                            <property name="fill">True</property>
+                                                            <property name="position">1</property>
+                                                            </packing>
+                                                            </child>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">True</property>
+                                                            <property name="fill">True</property>
+                                                            <property name="position">1</property>
+                                                            </packing>
+                                                            </child>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">True</property>
+                                                            <property name="fill">True</property>
+                                                            <property name="position">0</property>
+                                                            </packing>
+                                                            </child>
                                                             </widget>
                                                             <packing>
                                                             <property name="position">8</property>
diff --git a/src/Makefile.am b/src/Makefile.am
index ad815bbd..c33e9bb6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -41,6 +41,7 @@ SOURCES = \
        gui/cairo/jumpsProfile.cs\
        gui/cairo/jumpsRjFatigue.cs\
        gui/cairo/jumpsWeightFVProfile.cs\
+       gui/cairo/raceAnalyzer.cs\
        gui/cairo/radial.cs\
        gui/cairo/util.cs\
        gui/cairo/xy.cs\
diff --git a/src/gui/app1/runEncoder.cs b/src/gui/app1/runEncoder.cs
index 8fcd4701..857fcf64 100644
--- a/src/gui/app1/runEncoder.cs
+++ b/src/gui/app1/runEncoder.cs
@@ -50,6 +50,8 @@ public partial class ChronoJumpWindow
        [Widget] Gtk.Button button_raceAnalyzer_table_save;
        //[Widget] Gtk.Label label_race_analyzer_capture_speed;
        [Widget] Gtk.DrawingArea drawingarea_race_analyzer_capture;
+       [Widget] Gtk.DrawingArea drawingarea_race_analyzer_capture_position_time;
+       [Widget] Gtk.DrawingArea drawingarea_race_analyzer_capture_speed_time;
 
        int race_analyzer_distance;
        int race_analyzer_temperature;
@@ -417,7 +419,7 @@ public partial class ChronoJumpWindow
                contactsShowCaptureDoingButtons(true);
 
                //runEncoderCaptureSimulated = menuitem_check_race_encoder_capture_simulate.Active; //TODO: 
show this in some way on 2.0
-               runEncoderCaptureSimulated = true; //note that on simulated we need to click finish not so 
late
+               runEncoderCaptureSimulated = false; //note that on simulated we need to click finish not so 
late
 
                /*
                //initialize
@@ -532,6 +534,8 @@ public partial class ChronoJumpWindow
                Stopwatch sw = new Stopwatch();
 
                int rowsCount = 0;
+               cairoGraphRaceAnalyzerPoints_dt_l = new List<PointF>();
+               cairoGraphRaceAnalyzerPoints_st_l = new List<PointF>();
                while(! runEncoderProcessFinish && ! runEncoderProcessCancel && ! runEncoderProcessError)
                {
                        /*
@@ -576,6 +580,15 @@ public partial class ChronoJumpWindow
 
                                        runEncoderCaptureDistance += runEncoderCaptureDistanceAtThisSample;
 
+                                       //distance/time
+                                       cairoGraphRaceAnalyzerPoints_dt_l.Add(new PointF(
+                                                               UtilAll.DivideSafe(time, 1000000),
+                                                               runEncoderCaptureDistance));
+                                       //speed/time
+                                       cairoGraphRaceAnalyzerPoints_st_l.Add(new PointF(
+                                                               UtilAll.DivideSafe(time, 1000000),
+                                                               runEncoderCaptureSpeed));
+
                                        LogB.Information(string.Format("encoderDisplacement: {0}; 
runEncoderCaptureDistanceAtThisSample: {1}, runEncoderDistance: {2}, runEncoderCaptureSpeed: {3}; time: {4}; 
timePre: {5}",
                                                                encoderDisplacement,
                                                                runEncoderCaptureDistanceAtThisSample,
@@ -850,6 +863,19 @@ public partial class ChronoJumpWindow
                        return;
                }
 
+               /*
+               //TODO: continue to show position and speed graphs on load
+               cairoGraphRaceAnalyzerPoints_dt_l = new List<PointF>();
+               cairoGraphRaceAnalyzerPoints_st_l = new List<PointF>();
+               foreach(string line in contents)
+               {
+               cairoGraphRaceAnalyzerPoints_dt_l.Add
+               cairoGraphRaceAnalyzerPoints_st_l.Add
+               }
+               updateRaceAnalyzerCapturePositionTime();
+               updateRaceAnalyzerCaptureSpeedTime();
+               */
+
                currentRunEncoder = re;
                lastRunEncoderFile = Util.RemoveExtension(re.Filename);
                lastRunEncoderFullPath = re.FullURL;
@@ -1339,7 +1365,10 @@ public partial class ChronoJumpWindow
                                        //if drawingarea has still not shown, don't paint graph because GC 
screen is not defined
                                        if(force_sensor_ai_drawingareaShown)
                                                forceSensorDoGraphAI();
-                                       */
+                                        */
+
+                                       updateRaceAnalyzerCapturePositionTime();
+                                       updateRaceAnalyzerCaptureSpeedTime();
                                }
                                LogB.Information(" re C finish 2");
                        } else if(runEncoderProcessCancel || runEncoderProcessError)
@@ -1400,7 +1429,12 @@ public partial class ChronoJumpWindow
                {
                        event_execute_label_message.Text = runEncoderPulseMessage;
 
-                       cairoRadial.GraphSpeedAndDistance(runEncoderCaptureSpeed, runEncoderCaptureDistance);
+                       if(cairoRadial != null)
+                               cairoRadial.GraphSpeedAndDistance(runEncoderCaptureSpeed, 
runEncoderCaptureDistance);
+
+                       //TODO: activate again when there's a real time update (not repaint all) method
+                       //updateRaceAnalyzerCapturePositionTime();
+                       //updateRaceAnalyzerCaptureSpeedTime();
 
                        if(runEncoderPulseMessage == capturingMessage)
                                event_execute_button_finish.Sensitive = true;
@@ -1447,7 +1481,7 @@ public partial class ChronoJumpWindow
                }
                LogB.Information(" re R ");
 
-               Thread.Sleep (25);
+               Thread.Sleep (50);
                //LogB.Information(" RunEncoder:"+ runEncoderCaptureThread.ThreadState.ToString());
                return true;
        }
@@ -1772,4 +1806,45 @@ public partial class ChronoJumpWindow
        {
                cairoRadial = new CairoRadial(drawingarea_race_analyzer_capture, 
preferences.fontType.ToString());
        }
+
+       CairoGraphRaceAnalyzer cairoGraphRaceAnalyzer_dt;
+       static List<PointF> cairoGraphRaceAnalyzerPoints_dt_l; //distancetime
+       private void on_drawingarea_race_analyzer_capture_position_time_expose_event (object o, 
ExposeEventArgs args)
+       {
+               updateRaceAnalyzerCapturePositionTime();
+       }
+
+       CairoGraphRaceAnalyzer cairoGraphRaceAnalyzer_st;
+       static List<PointF> cairoGraphRaceAnalyzerPoints_st_l;  //speed/time
+       private void on_drawingarea_race_analyzer_capture_speed_time_expose_event (object o, ExposeEventArgs 
args)
+       {
+               updateRaceAnalyzerCaptureSpeedTime();
+       }
+
+       private void updateRaceAnalyzerCapturePositionTime()
+       {
+               if(cairoGraphRaceAnalyzer_dt == null)
+                       cairoGraphRaceAnalyzer_dt = new CairoGraphRaceAnalyzer(
+                                       drawingarea_race_analyzer_capture_position_time, "title",
+                                       Catalog.GetString("Distance"), "m");
+
+               if(cairoGraphRaceAnalyzerPoints_dt_l != null)
+               {
+                       if(cairoGraphRaceAnalyzer_dt.PassData(cairoGraphRaceAnalyzerPoints_dt_l))
+                               cairoGraphRaceAnalyzer_dt.Do(preferences.fontType.ToString());
+               }
+       }
+       private void updateRaceAnalyzerCaptureSpeedTime()
+       {
+               if(cairoGraphRaceAnalyzer_st == null)
+                       cairoGraphRaceAnalyzer_st = new CairoGraphRaceAnalyzer(
+                                       drawingarea_race_analyzer_capture_speed_time, "title",
+                                       Catalog.GetString("Speed"), "m");
+
+               if(cairoGraphRaceAnalyzerPoints_st_l != null)
+               {
+                       if(cairoGraphRaceAnalyzer_st.PassData(cairoGraphRaceAnalyzerPoints_st_l))
+                               cairoGraphRaceAnalyzer_st.Do(preferences.fontType.ToString());
+               }
+       }
 }
diff --git a/src/gui/cairo/raceAnalyzer.cs b/src/gui/cairo/raceAnalyzer.cs
new file mode 100644
index 00000000..b3b78748
--- /dev/null
+++ b/src/gui/cairo/raceAnalyzer.cs
@@ -0,0 +1,104 @@
+
+/*
+ * This file is part of ChronoJump
+ *
+ * ChronoJump is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or   
+ *    (at your option) any later version.
+ *    
+ * ChronoJump is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ *    GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Copyright (C) 2021   Xavier de Blas <xaviblas gmail com> 
+ */
+
+using System;
+using System.Collections.Generic; //List
+using Gtk;
+using Cairo;
+
+
+public class CairoGraphRaceAnalyzer : CairoXY
+{
+       /*
+       //constructor when there are no points
+       public CairoGraphRaceAnalyzer (DrawingArea area, string jumpType, string font)//, string title, 
string jumpType, string date)
+       {
+               this.area = area;
+
+               initGraph(font);
+
+               g.SetFontSize(16);
+               printText(area.Allocation.Width /2, area.Allocation.Height /2, 24, textHeight,
+                               needToExecuteJumpsStr + " " + jumpType + ".", g, alignTypes.CENTER);
+
+               endGraphDisposing(g);
+       }
+       */
+
+       //to avoid to have new data on PassData while the for is working on plotRealPoints
+       static bool doing;
+       //regular constructor
+       public CairoGraphRaceAnalyzer (
+//                     List<PointF> point_l,
+                       DrawingArea area, string title,
+                       string yVariable, string yUnits)
+       {
+//             this.point_l = point_l;
+               this.area = area;
+               this.title = title;
+               this.colorBackground = colorFromGdk(Config.ColorBackground); //but note if we are using 
system colors, this will not match
+
+               xVariable = timeStr;
+               this.yVariable = yVariable;
+               xUnits = "s";
+               this.yUnits = yUnits;
+               
+               doing = false;
+       }
+
+       public override bool PassData (List<PointF> point_l)
+       {
+               if(doing)
+                       return false;
+               else
+                       doing = true;
+
+               this.point_l = point_l;
+               return true;
+       }
+
+       public override void Do (string font)
+       {
+               LogB.Information("at RaceAnalyzerGraph.Do");
+               initGraph(font, .9);
+
+               //because point_l is updated while foreach in findPointMaximums() and plotRealPoints()
+               //TODO: on realtime do something better in order to just pass the new points and redo the 
graph just if margins changed
+               //this new method will not have problems of changing the point_l list while iterating it
+               try {
+                       findPointMaximums(false);
+                       //TODO: have a way to pass the x min max if we want to have two graphs with same x
+                       paintGrid(gridTypes.BOTH, true);
+                       paintAxis();
+
+                       pointsRadius = 1;
+                       plotRealPoints(false);
+               } catch {}
+
+               endGraphDisposing(g);
+               doing = false;
+       }
+
+       protected override void writeTitle()
+       {
+       }
+
+}
diff --git a/src/gui/cairo/xy.cs b/src/gui/cairo/xy.cs
index 30562e42..6de8b0e0 100644
--- a/src/gui/cairo/xy.cs
+++ b/src/gui/cairo/xy.cs
@@ -417,21 +417,26 @@ public abstract class CairoXY : CairoGeneric
                        g.Stroke ();
                }
 
+//             lock (point_l) {
+//             List<PointF> point_l_copy = point_l>;
+//             foreach(PointF p in point_l_copy)
                foreach(PointF p in point_l)
                {
+                       LogB.Information("point: " + p.ToString());
                        double xgraph = calculatePaintX(p.X);
                        double ygraph = calculatePaintY(p.Y);
                        g.Arc(xgraph, ygraph, pointsRadius, 0.0, 2.0 * Math.PI); //full circle
                        g.Color = colorBackground;
                        g.FillPreserve();
                        g.SetSourceRGB(0, 0, 0);
-                       g.Stroke ();
+                       g.Stroke ();    //can this be done at the end?
 
                        /*
                        //print X, Y of each point
                        printText(xgraph, graphHeight - Convert.ToInt32(bottomMargin/2), 0, textHeight, 
Util.TrimDecimals(p.X, 2), g, true);
                        printText(Convert.ToInt32(leftMargin/2), ygraph, 0, textHeight, 
Util.TrimDecimals(p.Y, 2), g, true);
                        */
+//             }
                }
                //getMinMaxXDrawable(graphWidth, absoluteMaxX, minX, totalMargins, totalMargins);
        }


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