private void ZoomFit() { GraphPane myPane = zedChart.GraphPane; // Chart setup min/max bounds switch (GlobalSettings.Instance.ChartType) { case ChartType.Cadence: myPane.XAxis.Scale.Max = 140; myPane.YAxis.Scale.Max = 700; myPane.XAxis.Scale.Min = 20; myPane.YAxis.Scale.Min = 0; break; case ChartType.PedalVelocity: myPane.XAxis.Scale.Max = QAActivity.CadenceToVelocity(140); myPane.YAxis.Scale.Max = 700; myPane.XAxis.Scale.Min = QAActivity.CadenceToVelocity(20); myPane.YAxis.Scale.Min = 0; break; } zedChart.Refresh(); zedChart.AxisChange(); //zedChart.ZoomOutAll(zedChart.GraphPane); }
/// <summary> /// Add quadrant analysis of an activity to the zed chart /// </summary> /// <param name="track">Data to be displayed</param> internal void AddQuadAnalysis(QAActivity activity) { // Activity cannot be null if (activity == null || activity.IsTotalsRow) { return; } GraphPane myPane = zedChart.GraphPane; PointPairList quadAnalysis = activity.GetQuadAnalysis(); string refId = activity.ReferenceId; // Quadrant Analysis Scatter plot Color color = Common.GetRandomColor(); activity.Color = color; LineItem quadScatter = myPane.AddCurve(activity.StartTime.Add(activity.Activity.TimeZoneUtcOffset).Date.ToShortDateString(), quadAnalysis, color, SymbolType.Circle); quadScatter.Tag = activity.ReferenceId; if (qActivities.Count > 2) { quadScatter.Symbol.Size = 2; } else { quadScatter.Symbol.Size = 3; } quadScatter.Symbol.IsAntiAlias = true; quadScatter.Line.IsVisible = false; ZoomChartButton_Click(null, null); }
protected override FontStyle GetCellFontStyle(object element, TreeList.Column column) { QAActivity activity = element as QAActivity; // Bold totals row if (activity != null && activity.IsTotalsRow) { return(FontStyle.Bold); } return(base.GetCellFontStyle(element, column)); }
protected override RowDecoration GetRowDecoration(object element) { QAActivity activity = element as QAActivity; // Draw line for totals row if (activity != null && activity.IsTotalsRow) { return(RowDecoration.TopLineSingle); } return(base.GetRowDecoration(element)); }
/// <summary> /// Float a power line on the QA chart. /// </summary> /// <param name="sender">zedChart</param> /// <param name="e">Mouse Location (to be converted to graph points)</param> private void zedChart_MouseMove(object sender, MouseEventArgs e) { ZedGraphControl chart = sender as ZedGraphControl; GraphPane myPane = chart.GraphPane; // Get calculated values double cadence, force; chart.GraphPane.ReverseTransform(e.Location, out cadence, out force); float pedalForce = GlobalSettings.Instance.Power / (float)QAActivity.CadenceToVelocity(GlobalSettings.Instance.Cadence); // Power line at current coordinate float power = (float)(force * QAActivity.CadenceToVelocity(cadence)); // Draw Power Curve PointPairList powerPoints = GetPowerCurve(power); CurveItem powerCurve; Color color = Color.Navy; int index = myPane.CurveList.IndexOfTag("UserPower"); if (index == -1) { // New Line powerCurve = myPane.AddCurve(CommonResources.Text.LabelPower + ": " + power.ToString("#", CultureInfo.CurrentCulture), powerPoints, color, SymbolType.None); powerCurve.Tag = "UserPower"; powerCurve.Label.IsVisible = false; } else { // Update exsiting powerCurve = myPane.CurveList[index]; powerCurve.Points = powerPoints; powerCurve.Label.Text = CommonResources.Text.LabelPower + ": " + power.ToString("#", CultureInfo.CurrentCulture); } chart.Refresh(); }
protected override void DrawCell(Graphics graphics, TreeList.DrawItemState rowState, object element, TreeList.Column column, Rectangle cellRect) { QAActivity activity = element as QAActivity; StringFormat stringFormat = new StringFormat(); stringFormat.Alignment = column.TextAlign; // Draw colored square in column 1 if (column.Id == "id" && activity != null && activity.Color != Color.Empty) { Brush selectedBrush = new SolidBrush(activity.Color); graphics.FillRectangle(selectedBrush, cellRect); } if (column.Id == "Q1Percent" || column.Id == "Q2Percent" || column.Id == "Q3Percent" || column.Id == "Q4Percent" || column.Id == "Q2PercentHigh" || column.Id == "Q2PercentLow" || column.Id == "Q4PercentHigh" || column.Id == "Q4PercentLow") { // Display percentage in appropriate format Type type = typeof(QAActivity); float value = (float)type.GetProperty(column.Id).GetValue(activity, null); graphics.DrawString(value.ToString("P1", CultureInfo.CurrentCulture), base.Font(GetCellFontStyle(element, column)), new SolidBrush(PluginMain.GetApplication().VisualTheme.ControlText), cellRect, stringFormat); } else if (column.Id == "Q1Time" || column.Id == "Q2Time" || column.Id == "Q2TimeHigh" || column.Id == "Q2TimeLow" || column.Id == "Q3Time" || column.Id == "Q4Time" || column.Id == "Q4TimeHigh" || column.Id == "Q4TimeLow") { // Display formatted time Type type = typeof(QAActivity); TimeSpan value = (TimeSpan)type.GetProperty(column.Id).GetValue(activity, null); string display = Util.Utilities.ToTimeString(value); graphics.DrawString(display, base.Font(GetCellFontStyle(element, column)), new SolidBrush(PluginMain.GetApplication().VisualTheme.ControlText), cellRect, stringFormat); } else if (activity.IsTotalsRow && column.Id == "StartTime") { // Displat "Totals" graphics.DrawString(CommonResources.Text.LabelTotal, base.Font(GetCellFontStyle(element, column)), new SolidBrush(PluginMain.GetApplication().VisualTheme.ControlText), cellRect, stringFormat); } else if (activity.IsTotalsRow && column.Id == "check") { // Don't draw checkbox on totals row } else { // Everything else base.DrawCell(graphics, rowState, element, column, cellRect); } }
/// <summary> /// Update the power line, vertical, and horizontal lines /// </summary> private void UpdateReferenceLines() { GraphPane myPane = zedChart.GraphPane; // Remove static lines in order to replace them for (int i = 0; i < zedChart.GraphPane.CurveList.Count;) { string lineId = zedChart.GraphPane.CurveList[i].Tag as string; if (lineId == "Power" || lineId == "horizLine" || lineId == "vertLine") { zedChart.GraphPane.CurveList.RemoveAt(i); } else { // Becasue the length of this list is dynamically changing, only increment the index if an item is not removed. i++; } } // Add Power Curve float bandPercent = (float)GlobalSettings.Instance.PowerBand / 100f; PointPairList powerPoints = GetPowerCurve(GlobalSettings.Instance.Power); PointPairList powerPointsHi = GetPowerCurve((float)GlobalSettings.Instance.Power * (1f + bandPercent)); PointPairList powerPointsLo = GetPowerCurve((float)GlobalSettings.Instance.Power * (1f - bandPercent)); Color color = Color.Blue; LineItem powerCurve = myPane.AddCurve(CommonResources.Text.LabelPower + ": " + GlobalSettings.Instance.Power.ToString("#", CultureInfo.CurrentCulture), powerPoints, color, SymbolType.None); powerCurve.Tag = "Power"; powerCurve.Label.IsVisible = false; powerCurve.Line.IsAntiAlias = true; color = Color.Red; LineItem powerCurveHi = myPane.AddCurve(CommonResources.Text.LabelPower + ": " + (GlobalSettings.Instance.Power * (1 + bandPercent)).ToString("#", CultureInfo.CurrentCulture), powerPointsHi, color, SymbolType.None); powerCurveHi.Tag = "Power"; powerCurveHi.Label.IsVisible = false; powerCurveHi.Line.IsAntiAlias = true; LineItem powerCurveLo = myPane.AddCurve(CommonResources.Text.LabelPower + ": " + (GlobalSettings.Instance.Power * (1 - bandPercent)).ToString("#", CultureInfo.CurrentCulture), powerPointsLo, color, SymbolType.None); powerCurveLo.Tag = "Power"; powerCurveLo.Label.IsVisible = false; powerCurveLo.Line.IsAntiAlias = true; // Add Quadrant Dividers: Vertical, then Horizontal float pedalVelocity = GlobalSettings.Instance.Cadence * (GlobalSettings.Instance.CrankLength / 1000f) * 2f * (float)Math.PI / 60f; float xIntercept, xmin, xmax; switch (GlobalSettings.Instance.ChartType) { case ChartType.PedalVelocity: xIntercept = pedalVelocity; xmin = (float)QAActivity.CadenceToVelocity(20); xmax = (float)QAActivity.CadenceToVelocity(140); break; default: case ChartType.Cadence: xIntercept = GlobalSettings.Instance.Cadence; xmin = 20; xmax = 140; break; } double[] x = new double[2] { xIntercept, xIntercept }; double[] y = new double[2] { 0, 700 }; LineItem vertLine = myPane.AddCurve("Vertical", x, y, Color.DimGray, SymbolType.None); vertLine.Tag = "vertLine"; vertLine.Line.Style = System.Drawing.Drawing2D.DashStyle.Dash; vertLine.Line.Width = 1.9f; vertLine.Label.IsVisible = false; float pedalForce = GlobalSettings.Instance.Power * 60f / (GlobalSettings.Instance.Cadence * 2f * (float)Math.PI * (GlobalSettings.Instance.CrankLength / 1000f)); x = new double[2] { xmin, xmax }; y = new double[2] { pedalForce, pedalForce }; LineItem horizLine = myPane.AddCurve("Horizontal", x, y, Color.DimGray, SymbolType.None); horizLine.Tag = "horizLine"; horizLine.Line.Style = System.Drawing.Drawing2D.DashStyle.Dash; horizLine.Line.Width = 1.9f; horizLine.Label.IsVisible = false; // Update activities to match new lines foreach (QAActivity activity in qActivities) { foreach (CurveItem curve in zedChart.GraphPane.CurveList) { if (curve.Tag as string == activity.ReferenceId) { double q1 = 0, q2h = 0, q2l = 0, q3 = 0, q4h = 0, q4l = 0; for (int i = 0; i < curve.Points.Count; i++) { PointPair point = curve.Points[i]; if (point.X > xIntercept) { if (point.Y > pedalForce) { // Add to quad 1 q1 += point.Z; } else { double temp = powerPoints.InterpolateX(point.X); if (point.Y > temp) { // Add to quad 4 (high) q4h += point.Z; } else { // Add to quad 4 (low) q4l += point.Z; } } } else { if (point.Y > pedalForce) { if (point.Y > powerPoints.InterpolateX(point.X)) { // Add to quad 2 (high) q2h += point.Z; } else { // Add to quad 2 (low) q2l += point.Z; } } else { // Add to quad 3 q3 += point.Z; } } } if (activity.TotalQuadTime != TimeSpan.Zero) { // Assign activity values activity.Q1Percent = (float)(q1 / activity.TotalQuadTime.TotalSeconds); activity.Q2PercentHigh = (float)(q2h / activity.TotalQuadTime.TotalSeconds); activity.Q2PercentLow = (float)(q2l / activity.TotalQuadTime.TotalSeconds); activity.Q3Percent = (float)(q3 / activity.TotalQuadTime.TotalSeconds); activity.Q4PercentHigh = (float)(q4h / activity.TotalQuadTime.TotalSeconds); activity.Q4PercentLow = (float)(q4l / activity.TotalQuadTime.TotalSeconds); } } } } // Calculate 'totals' data QAActivity totalRow = null; double[] totalSeconds = { 0, 0, 0, 0, 0, 0, 0 }; foreach (QAActivity qActivity in qActivities) { if (!qActivity.IsTotalsRow) { totalSeconds[0] += qActivity.TotalQuadTime.TotalSeconds; totalSeconds[1] += qActivity.Q1Time.TotalSeconds; totalSeconds[2] += qActivity.Q2TimeHigh.TotalSeconds; totalSeconds[3] += qActivity.Q2TimeLow.TotalSeconds; totalSeconds[4] += qActivity.Q3Time.TotalSeconds; totalSeconds[5] += qActivity.Q4TimeHigh.TotalSeconds; totalSeconds[6] += qActivity.Q4TimeLow.TotalSeconds; } else { totalRow = qActivity; } } // Add Totals Row to treelist if (totalRow != null && totalSeconds[0] != 0) { totalRow.TotalQuadTime = TimeSpan.FromSeconds(totalSeconds[0]); totalRow.Q1Percent = (float)(totalSeconds[1] / totalSeconds[0]); totalRow.Q2PercentHigh = (float)(totalSeconds[2] / totalSeconds[0]); totalRow.Q2PercentLow = (float)(totalSeconds[3] / totalSeconds[0]); totalRow.Q3Percent = (float)(totalSeconds[4] / totalSeconds[0]); totalRow.Q4PercentHigh = (float)(totalSeconds[5] / totalSeconds[0]); totalRow.Q4PercentLow = (float)(totalSeconds[6] / totalSeconds[0]); string message13 = "{0}\r\n " + CommonResources.Text.LabelTime + ": {2}\r\n " + CommonResources.Text.LabelPercent + ": {1}"; string message24 = "{0}\r\n " + CommonResources.Text.LabelTime + ": {2}\r\n >" + CommonResources.Text.LabelPower + ": {5}\r\n <" + CommonResources.Text.LabelPower + ": {6}\r\n " + CommonResources.Text.LabelPercent + ": {1}\r\n >" + CommonResources.Text.LabelPower + ": {3}\r\n <" + CommonResources.Text.LabelPower + ": {4}"; object[] args1 = { "Quadrant 1" , totalRow.Q1Percent.ToString("P1", CultureInfo.CurrentCulture) , TimeSpan.FromSeconds(totalSeconds[1]) }; object[] args2 = { "Quadrant 2" , totalRow.Q2Percent.ToString("P1", CultureInfo.CurrentCulture) , TimeSpan.FromSeconds(totalSeconds[2] + totalSeconds[3]) , totalRow.Q2PercentHigh.ToString("P1", CultureInfo.CurrentCulture) , totalRow.Q2PercentLow.ToString("P1", CultureInfo.CurrentCulture) , TimeSpan.FromSeconds(totalSeconds[2]) , TimeSpan.FromSeconds(totalSeconds[3]) }; object[] args3 = { "Quadrant 3" , totalRow.Q3Percent.ToString("P1", CultureInfo.CurrentCulture) , TimeSpan.FromSeconds(totalSeconds[4]) }; object[] args4 = { "Quadrant 4" , totalRow.Q4Percent.ToString("P1", CultureInfo.CurrentCulture) , TimeSpan.FromSeconds(totalSeconds[5] + totalSeconds[6]) , totalRow.Q4PercentHigh.ToString("P1", CultureInfo.CurrentCulture) , totalRow.Q4PercentLow.ToString("P1", CultureInfo.CurrentCulture) , TimeSpan.FromSeconds(totalSeconds[5]) , TimeSpan.FromSeconds(totalSeconds[6]) }; lblQ1.Text = String.Format(message13, args1); lblQ2.Text = String.Format(message24, args2); lblQ3.Text = String.Format(message13, args3); lblQ4.Text = String.Format(message24, args4); } else { lblQ1.Text = "Q1"; lblQ2.Text = "Q2"; lblQ3.Text = "Q3"; lblQ4.Text = "Q4"; } treeActivities.Refresh(); zedChart.Refresh(); zedChart.AxisChange(); }