[chronojump] JumpsDjOptimalFall Cairo graph WIP (cont)
- From: Xavier de Blas <xaviblas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [chronojump] JumpsDjOptimalFall Cairo graph WIP (cont)
- Date: Wed, 18 Dec 2019 15:42:50 +0000 (UTC)
commit e6c230f13dfd6e7eccfad3225f70c47263e06878
Author: Xavier de Blas <xaviblas gmail com>
Date: Wed Dec 18 16:40:51 2019 +0100
JumpsDjOptimalFall Cairo graph WIP (cont)
src/gui/jumpsDjOptimalFall.cs | 229 ++++++++++++++++++++++++++++++++++++++++--
src/jumpsDjOptimalFall.cs | 42 ++++++--
2 files changed, 256 insertions(+), 15 deletions(-)
---
diff --git a/src/gui/jumpsDjOptimalFall.cs b/src/gui/jumpsDjOptimalFall.cs
index b92ff2f5..56749672 100644
--- a/src/gui/jumpsDjOptimalFall.cs
+++ b/src/gui/jumpsDjOptimalFall.cs
@@ -26,8 +26,10 @@ using Cairo;
public static class JumpsDjOptimalFallGraph
{
- public static void Do (List<Point> point_l, double pointsMaxY, DrawingArea area, string title, string
date)
+ public static void Do (List<Point> point_l, double[] coefs, double xAtMaxY,
+ double pointsMaxValue, DrawingArea area, string title, string date)
{
+ LogB.Information("at JumpsDjOptimalFallGraph.Do");
//1 create context
Cairo.Context g = Gdk.CairoHelper.Create (area.GdkWindow);
@@ -35,12 +37,32 @@ public static class JumpsDjOptimalFallGraph
g.SetSourceRGB(1,1,1);
g.Paint();
+ int topMargin = 30;
+ int bottomMargin = 30;
+ int leftMargin = 30;
+ int rightMargin = 30;
+ //int leftAxis = 40;
+ //int bottomAxis = 40;
+ int graphWidth = 500; //in the future check this is not bigger than area widt
+ int axisDist = 40; //distance from margin to graph
+
+ //calculate separation between series and bar width
+ int distanceBetweenCols = Convert.ToInt32((graphWidth - rightMargin)*(1+.5)/point_l.Count) -
+ Convert.ToInt32((graphWidth - rightMargin)*(0+.5)/point_l.Count);
+
+ int tctfSep = Convert.ToInt32(.3*distanceBetweenCols);
+ int barWidth = Convert.ToInt32(.3*distanceBetweenCols);
+ int barDesplLeft = Convert.ToInt32(.5*barWidth);
+
+ g.SetSourceRGB(0,0,0);
+ g.LineWidth = 2;
+
//4 prepare font
g.SelectFontFace("Helvetica", Cairo.FontSlant.Normal, Cairo.FontWeight.Normal);
int textHeight = 12;
g.SetFontSize(textHeight);
- if(pointsMaxY == 0)
+ if(pointsMaxValue == 0)
{
g.SetSourceRGB(0,0,0);
g.SetFontSize(16);
@@ -50,22 +72,215 @@ public static class JumpsDjOptimalFallGraph
return;
}
- Cairo.Color color = colorFromRGB(101,86,67);
+ Cairo.Color red = colorFromRGB(200,0,0);
+ Cairo.Color blue = colorFromRGB(178, 223, 238); //lightblue
+
+ /*
int i = 10;
+ int count = 0;
+ //note p.X is jump fall and p.Y jump height
+ //TODO: maybe this will be for a legend, because the graph wants X,Y points
foreach(Point p in point_l)
{
- drawRoundedRectangle (0, i , p.X, 20, 4, g, color);
- drawRoundedRectangle (10, i+20 , p.Y, 20, 4, g, color);
- i+= 40;
+ int x = Convert.ToInt32((graphWidth -
rightMargin)*(count+.5)/point_l.Count)-barDesplLeft;
+ int y = calculatePaintHeight(Convert.ToDouble(p.X), area.Allocation.Height,
pointsMaxValue, 0, topMargin, bottomMargin + bottomAxis);
+
+ LogB.Information(string.Format("red: {0}, {1}, {2}, {3}", Convert.ToDouble(p.X),
area.Allocation.Height, pointsMaxValue, y));
+ drawRoundedRectangle (x, y, barWidth, area.Allocation.Height - y, 4, g, red);
+
+ x = Convert.ToInt32((graphWidth -
rightMargin)*(count+.5)/point_l.Count)-barDesplLeft+tctfSep;
+ y = calculatePaintHeight(Convert.ToDouble(p.Y), area.Allocation.Height,
pointsMaxValue, 0, topMargin, bottomMargin + bottomAxis);
+
+ LogB.Information(string.Format("blue: {0}, {1}, {2}, {3}", Convert.ToDouble(p.Y),
area.Allocation.Height, pointsMaxValue, y));
+ drawRoundedRectangle (x, y, barWidth, area.Allocation.Height -y, 4, g, blue);
+
+ count ++;
+ }
+ */
+
+ LogB.Information(string.Format("coef length:{0}", coefs.Length));
+ if(coefs.Length == 3)
+ {
+ double minX = 1000000;
+ double maxX = 0;
+ double minY = 1000000;
+ int xgraph = 0;
+ int ygraph = 0;
+
+ foreach(Point p in point_l)
+ {
+ if(p.X < minX)
+ minX = p.X;
+ if(p.X > maxX)
+ maxX = p.X;
+ if(p.Y < minY)
+ minY = p.Y;
+ }
+
+ double absoluteMaxY = coefs[0] + coefs[1]*xAtMaxY + coefs[2]*Math.Pow(xAtMaxY,2);
+// g.Save ();
+
+ //double xstart = minX - (maxX - minX);
+ //TODO: use lineTo, and have (maybe) more than 20 points
+ bool firstValue = false;
+ for(double x = minX; x < maxX; x += (maxX-minX)/100)
+ {
+ xgraph = calculatePaintWidth(
+ ( x ),
+ graphWidth, maxX, minX, rightMargin, leftMargin + axisDist);
+ ygraph = calculatePaintHeight(
+ ( coefs[0] + coefs[1]*x + coefs[2]*Math.Pow(x,2) ),
+ area.Allocation.Height, absoluteMaxY, minY, topMargin,
bottomMargin + axisDist);
+
+ if(! firstValue)
+ g.LineTo(xgraph, ygraph);
+
+ g.MoveTo(xgraph, ygraph);
+ firstValue = false;
+ }
+ g.Stroke ();
+
+ foreach(Point p in point_l)
+ {
+ xgraph = calculatePaintWidth(
+ ( p.X ),
+ graphWidth, maxX, minX, rightMargin, leftMargin + axisDist);
+ ygraph = calculatePaintHeight(
+ ( p.Y ),
+ area.Allocation.Height, absoluteMaxY, minY, topMargin,
bottomMargin + axisDist);
+ g.MoveTo(xgraph+6, ygraph);
+ g.Arc(xgraph, ygraph, 6.0, 0.0, 2.0 * Math.PI); //full circle
+ g.Color = blue;
+ g.FillPreserve();
+ g.SetSourceRGB(0, 0, 0);
+ g.Stroke ();
+
+ /*
+ //print X, Y of each point
+ printText(xgraph, area.Allocation.Height - 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);
+ */
+ }
+
+ xgraph = calculatePaintWidth(
+ ( xAtMaxY ),
+ graphWidth, maxX, minX, rightMargin, leftMargin + axisDist);
+ ygraph = calculatePaintHeight(
+ absoluteMaxY,
+ area.Allocation.Height, absoluteMaxY, minY, topMargin, bottomMargin +
axisDist);
+
+ //paint axis
+ g.MoveTo(leftMargin, topMargin);
+ g.LineTo(leftMargin, area.Allocation.Height - bottomMargin);
+ g.LineTo(graphWidth - rightMargin, area.Allocation.Height - bottomMargin);
+ g.Stroke ();
+
+ printText(2, Convert.ToInt32(topMargin/2), 0, textHeight, "Height (cm)", g, false);
+ printText(graphWidth - Convert.ToInt32(rightMargin/2), area.Allocation.Height -
bottomMargin, 0, textHeight, "Fall (cm)", g, false);
+
+ //paint grid,
+ //TODO: fer el grid abns que pintar els punts
+ //horiz
+ paintCairoGrid (Convert.ToInt32(minY), Convert.ToInt32(absoluteMaxY), 5, graphWidth,
area.Allocation.Height, true,
+ leftMargin, rightMargin, topMargin, bottomMargin, axisDist, g,
textHeight);
+ //vertical
+ paintCairoGrid (Convert.ToInt32(minX), Convert.ToInt32(maxX), 5, graphWidth,
area.Allocation.Height, false,
+ leftMargin, rightMargin, topMargin, bottomMargin, axisDist, g,
textHeight);
+
+ /*
+ //print X, Y of maxY
+ //at axis
+ g.Save();
+ g.SetDash(new double[]{14, 6}, 0);
+ g.MoveTo(xgraph, area.Allocation.Height - bottomMargin);
+ g.LineTo(xgraph, ygraph);
+ g.LineTo(leftMargin, ygraph);
+ g.Stroke ();
+ g.Restore();
+
+ printText(xgraph, area.Allocation.Height - Convert.ToInt32(bottomMargin/2), 0,
textHeight, Util.TrimDecimals(xAtMaxY, 2), g, true);
+ printText(Convert.ToInt32(leftMargin/2), ygraph, 0, textHeight, Util.TrimDecimals(
+ absoluteMaxY, 2), g, true);
+ */
+
+ //at right
+ printText(graphWidth + axisDist, Convert.ToInt32(area.Allocation.Height/2) -
textHeight*2, 0, textHeight, "Optimal values:", g, false);
+ printText(graphWidth + axisDist, Convert.ToInt32(area.Allocation.Height/2), 0,
textHeight, "Fall: " + Util.TrimDecimals(xAtMaxY, 2) + " cm", g, false);
+ printText(graphWidth + axisDist, Convert.ToInt32(area.Allocation.Height/2) +
textHeight*2, 0, textHeight, "Jump height: " + Util.TrimDecimals(absoluteMaxY, 2) + " cm", g, false);
+
+ g.MoveTo(xgraph+8, ygraph);
+ g.Arc(xgraph, ygraph, 8.0, 0.0, 2.0 * Math.PI); //full circle
+ g.Color = red;
+ g.FillPreserve();
+ g.SetSourceRGB(0, 0, 0);
+ g.Stroke ();
}
+
//dispose
g.GetTarget().Dispose ();
g.Dispose ();
}
+ private static void paintCairoGrid (int min, int max, int seps, int horizontalSize, int verticalSize,
bool horiz,
+ int leftMargin, int rightMargin, int topMargin, int bottomMargin, int axisDist,
Cairo.Context g, int textHeight)
+ {
+ //show 5 steps positive, 5 negative (if possible)
+ int temp = Convert.ToInt32(Util.DivideSafe(max - min, seps));
+ int step = temp;
+
+ //to have values multiples than 10, 100 ...
+ if(step <= 10)
+ step = temp;
+ else if(step <= 100)
+ step = temp - (temp % 10);
+ else if(step <= 1000)
+ step = temp - (temp % 100);
+ else if(step <= 10000)
+ step = temp - (temp % 1000);
+ else //if(step <= 100000)
+ step = temp - (temp % 10000);
+
+ //fix crash when no force
+ if(step == 0)
+ step = 1;
+
+ List<int> l = new List<int>();
+ g.Save();
+ g.SetDash(new double[]{1, 2}, 0);
+ for(int i = min; i <= max ; i += step)//TODO, start at min+sep
+ {
+ //LogB.Information("i: " + i.ToString());
+ if(horiz)
+ {
+ int ytemp = calculatePaintHeight(i, verticalSize, max, min, topMargin,
bottomMargin + axisDist);
+ g.MoveTo(leftMargin, ytemp);
+ g.LineTo(horizontalSize - rightMargin, ytemp);
+ printText(Convert.ToInt32(leftMargin/2), ytemp, 0, textHeight, i.ToString(),
g, true);
+ } else {
+ int xtemp = calculatePaintWidth(i, horizontalSize, max, min, rightMargin,
leftMargin + axisDist);
+ g.MoveTo(xtemp, verticalSize - bottomMargin);
+ g.LineTo(xtemp, topMargin);
+ printText(xtemp, verticalSize - Convert.ToInt32(bottomMargin/2), 0,
textHeight, i.ToString(), g, true);
+ }
+ }
+ g.Stroke ();
+ g.Restore();
+ }
+
+ private static int calculatePaintWidth(double currentValue, int ancho, double maxValue, double
minValue, int rightMargin, int leftMargin)
+ {
+ return Convert.ToInt32(leftMargin + (currentValue - minValue) * (ancho - rightMargin -
leftMargin) / (maxValue - minValue));
+ }
+
+ private static int calculatePaintHeight(double currentValue, int alto, double maxValue, double
minValue, int topMargin, int bottomMargin)
+ {
+ return Convert.ToInt32(alto - bottomMargin - ((currentValue - minValue) * (alto - topMargin
- bottomMargin) / (maxValue - minValue)));
+ }
+
//TODO: inherit this
- private static Cairo.Color colorFromRGB(int red, int green, int blue) {
+ private static Cairo.Color colorFromRGB(int red, int green, int blue)
+ {
return new Cairo.Color(red/256.0, green/256.0, blue/256.0);
}
diff --git a/src/jumpsDjOptimalFall.cs b/src/jumpsDjOptimalFall.cs
index 1455963e..cc32f40e 100644
--- a/src/jumpsDjOptimalFall.cs
+++ b/src/jumpsDjOptimalFall.cs
@@ -24,6 +24,7 @@ using System.Collections.Generic; //List
public class JumpsDjOptimalFall
{
private List<Point> point_l;
+ LeastSquares ls;
//constructor
public JumpsDjOptimalFall()
@@ -45,7 +46,7 @@ public class JumpsDjOptimalFall
));
//3 get LeastSquares
- LeastSquares ls = new LeastSquares();
+ ls = new LeastSquares();
ls.Calculate(point_l);
//4 print data
@@ -53,22 +54,47 @@ public class JumpsDjOptimalFall
LogB.Information(string.Format("coef = {0} {1} {2}",
ls.Coef[0], ls.Coef[1], ls.Coef[2]));
- if(ls.CalculatedMaxY)
- LogB.Information(string.Format("MaxY = {0}", ls.MaxY));
+ if(ls.CalculatedXatMaxY)
+ LogB.Information(string.Format("XatMaxY = {0}", ls.XatMaxY));
}
- public double GetMaxY()
+ public double GetMaxValue()
{
- double maxY = 0;
+ double maxValue = 0;
foreach(Point p in point_l)
- if(p.Y > maxY)
- maxY = p.Y;
+ {
+ if(p.X > maxValue)
+ maxValue = p.X;
+ if(p.Y > maxValue)
+ maxValue = p.Y;
+ }
- return maxY;
+ return maxValue;
}
public List<Point> Point_l
{
get { return point_l; }
}
+
+ public double[] Coefs
+ {
+ get {
+ if(! ls.CalculatedCoef)
+ return new double[0];
+
+ LogB.Information(string.Format("coef0:{0}", ls.Coef[0]));
+ return ls.Coef;
+ }
+ }
+
+ public double XatMaxY //model
+ {
+ get {
+ if(! ls.CalculatedXatMaxY)
+ return -1;
+
+ return ls.XatMaxY;
+ }
+ }
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]