- Timestamp:
- 05/30/11 18:07:32 (13 years ago)
- Location:
- trunk/sources
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources
- Property svn:mergeinfo changed
/branches/histogram (added) merged: 5959,5961,5970,5994-5996,5999,6007,6010-6016,6020,6022,6027-6028,6032,6046,6055-6056,6081-6082,6086-6087,6089,6115,6176,6194-6195,6338-6341
- Property svn:mergeinfo changed
-
trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableView.cs
r5445 r6342 36 36 [View("DataTable View")] 37 37 [Content(typeof(DataTable), true)] 38 public partial class DataTableView : NamedItemView {38 public partial class DataTableView : NamedItemView, IConfigureableView { 39 39 protected List<Series> invisibleSeries; 40 40 protected Dictionary<IObservableList<double>, DataRow> valuesRowsTable; … … 60 60 } 61 61 62 #region Event Handler Registration 62 63 /// <summary> 63 64 /// Removes the eventhandlers from the underlying <see cref="Variable"/>. … … 89 90 RegisterDataRowEvents(row); 90 91 } 92 93 /// <summary> 94 /// Automatically called for every existing data row and whenever a data row is added 95 /// to the data table. Do not call this method directly. 96 /// </summary> 97 /// <param name="row">The DataRow that was added.</param> 98 protected virtual void RegisterDataRowEvents(DataRow row) { 99 row.NameChanged += new EventHandler(Row_NameChanged); 100 row.VisualPropertiesChanged += new EventHandler(Row_VisualPropertiesChanged); 101 valuesRowsTable.Add(row.Values, row); 102 row.Values.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsAdded); 103 row.Values.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved); 104 row.Values.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced); 105 row.Values.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved); 106 row.Values.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_CollectionReset); 107 } 108 109 /// <summary> 110 /// Automatically called for every data row that is removed from the DataTable. Do 111 /// not directly call this method. 112 /// </summary> 113 /// <param name="row">The DataRow that was removed.</param> 114 protected virtual void DeregisterDataRowEvents(DataRow row) { 115 row.Values.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsAdded); 116 row.Values.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved); 117 row.Values.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced); 118 row.Values.ItemsMoved -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved); 119 row.Values.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_CollectionReset); 120 valuesRowsTable.Remove(row.Values); 121 row.VisualPropertiesChanged -= new EventHandler(Row_VisualPropertiesChanged); 122 row.NameChanged -= new EventHandler(Row_NameChanged); 123 } 124 #endregion 91 125 92 126 protected override void OnContentChanged() { … … 102 136 foreach (DataRow row in Content.Rows) 103 137 AddDataRow(row); 104 chart.ChartAreas[0].AxisX.Title = Content.VisualProperties.XAxisTitle; 105 chart.ChartAreas[0].AxisY.Title = Content.VisualProperties.YAxisTitle; 106 chart.ChartAreas[0].AxisY2.Title = Content.VisualProperties.SecondYAxisTitle; 138 ConfigureChartArea(chart.ChartAreas[0]); 139 RecalculateAxesScale(chart.ChartAreas[0]); 107 140 } 108 141 } … … 113 146 } 114 147 148 public void ShowConfiguration() { 149 if (Content != null) { 150 DataTableVisualPropertiesDialog dialog = new DataTableVisualPropertiesDialog(Content); 151 dialog.ShowDialog(); 152 } else MessageBox.Show("Nothing to configure."); 153 } 115 154 116 155 /// <summary> … … 120 159 protected virtual void AddDataRow(DataRow row) { 121 160 Series series = new Series(row.Name); 161 ConfigureSeries(series, row); 162 FillSeriesWithRowValues(series, row); 163 164 chart.Series.Add(series); 165 ConfigureChartArea(chart.ChartAreas[0]); 166 RecalculateAxesScale(chart.ChartAreas[0]); 167 UpdateYCursorInterval(); 168 } 169 170 private void ConfigureSeries(Series series, DataRow row) { 171 RemoveCustomPropertyIfExists(series, "PointWidth"); 172 series.BorderWidth = 1; 173 series.BorderDashStyle = ChartDashStyle.Solid; 174 series.BorderColor = Color.Empty; 175 176 if (row.VisualProperties.Color != Color.Empty) 177 series.Color = row.VisualProperties.Color; 178 else series.Color = Color.Empty; 179 122 180 switch (row.VisualProperties.ChartType) { 123 181 case DataRowVisualProperties.DataRowChartType.Line: 124 182 series.ChartType = SeriesChartType.FastLine; 183 series.BorderWidth = row.VisualProperties.LineWidth; 184 series.BorderDashStyle = ConvertLineStyle(row.VisualProperties.LineStyle); 125 185 break; 126 186 case DataRowVisualProperties.DataRowChartType.Bars: 127 series.ChartType = SeriesChartType.Bar; 187 // Bar is incompatible with anything but Bar and StackedBar* 188 if (!chart.Series.Any(x => x.ChartType != SeriesChartType.Bar && x.ChartType != SeriesChartType.StackedBar && x.ChartType != SeriesChartType.StackedBar100)) 189 series.ChartType = SeriesChartType.Bar; 190 else { 191 series.ChartType = SeriesChartType.FastPoint; //default 192 row.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points; 193 } 128 194 break; 129 195 case DataRowVisualProperties.DataRowChartType.Columns: … … 133 199 series.ChartType = SeriesChartType.FastPoint; 134 200 break; 201 case DataRowVisualProperties.DataRowChartType.Histogram: 202 series.ChartType = SeriesChartType.Column; 203 series.SetCustomProperty("PointWidth", "1"); 204 if (!series.Color.IsEmpty && series.Color.GetBrightness() < 0.25) 205 series.BorderColor = Color.White; 206 else series.BorderColor = Color.Black; 207 break; 135 208 default: 136 209 series.ChartType = SeriesChartType.FastPoint; … … 138 211 } 139 212 series.YAxisType = row.VisualProperties.SecondYAxis ? AxisType.Secondary : AxisType.Primary; 140 if (row.VisualProperties.Color != Color.Empty) series.Color = row.VisualProperties.Color;213 series.XAxisType = row.VisualProperties.SecondXAxis ? AxisType.Secondary : AxisType.Primary; 141 214 series.ToolTip = row.Name + " X = #INDEX, Y = #VAL"; 142 FillSeriesWithRowValues(series, row); 143 chart.Series.Add(series); 144 chart.ChartAreas[0].RecalculateAxesScale(); 145 UpdateYCursorInterval(); 146 } 147 215 } 216 217 private void ConfigureChartArea(ChartArea area) { 218 if (Content.VisualProperties.TitleFont != null) chart.Titles[0].Font = Content.VisualProperties.TitleFont; 219 if (!Content.VisualProperties.TitleColor.IsEmpty) chart.Titles[0].ForeColor = Content.VisualProperties.TitleColor; 220 221 if (Content.VisualProperties.AxisTitleFont != null) area.AxisX.TitleFont = Content.VisualProperties.AxisTitleFont; 222 if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisX.TitleForeColor = Content.VisualProperties.AxisTitleColor; 223 area.AxisX.Title = Content.VisualProperties.XAxisTitle; 224 225 if (Content.VisualProperties.AxisTitleFont != null) area.AxisX2.TitleFont = Content.VisualProperties.AxisTitleFont; 226 if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisX2.TitleForeColor = Content.VisualProperties.AxisTitleColor; 227 area.AxisX2.Title = Content.VisualProperties.SecondXAxisTitle; 228 229 if (Content.VisualProperties.AxisTitleFont != null) area.AxisY.TitleFont = Content.VisualProperties.AxisTitleFont; 230 if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisY.TitleForeColor = Content.VisualProperties.AxisTitleColor; 231 area.AxisY.Title = Content.VisualProperties.YAxisTitle; 232 233 if (Content.VisualProperties.AxisTitleFont != null) area.AxisY2.TitleFont = Content.VisualProperties.AxisTitleFont; 234 if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisY2.TitleForeColor = Content.VisualProperties.AxisTitleColor; 235 area.AxisY2.Title = Content.VisualProperties.SecondYAxisTitle; 236 } 237 238 private void RecalculateAxesScale(ChartArea area) { 239 // Reset the axes bounds so that RecalculateAxesScale() will assign new bounds 240 foreach (Axis a in area.Axes) { 241 a.Minimum = double.NaN; 242 a.Maximum = double.NaN; 243 } 244 area.RecalculateAxesScale(); 245 area.AxisX.IsMarginVisible = false; 246 area.AxisX2.IsMarginVisible = false; 247 248 if (!Content.VisualProperties.XAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.XAxisMinimumFixedValue)) area.AxisX.Minimum = Content.VisualProperties.XAxisMinimumFixedValue; 249 if (!Content.VisualProperties.XAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.XAxisMaximumFixedValue)) area.AxisX.Maximum = Content.VisualProperties.XAxisMaximumFixedValue; 250 if (!Content.VisualProperties.SecondXAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.SecondXAxisMinimumFixedValue)) area.AxisX2.Minimum = Content.VisualProperties.SecondXAxisMinimumFixedValue; 251 if (!Content.VisualProperties.SecondXAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.SecondXAxisMaximumFixedValue)) area.AxisX2.Maximum = Content.VisualProperties.SecondXAxisMaximumFixedValue; 252 if (!Content.VisualProperties.YAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.YAxisMinimumFixedValue)) area.AxisY.Minimum = Content.VisualProperties.YAxisMinimumFixedValue; 253 if (!Content.VisualProperties.YAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.YAxisMaximumFixedValue)) area.AxisY.Maximum = Content.VisualProperties.YAxisMaximumFixedValue; 254 if (!Content.VisualProperties.SecondYAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.SecondYAxisMinimumFixedValue)) area.AxisY2.Minimum = Content.VisualProperties.SecondYAxisMinimumFixedValue; 255 if (!Content.VisualProperties.SecondYAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.SecondYAxisMaximumFixedValue)) area.AxisY2.Maximum = Content.VisualProperties.SecondYAxisMaximumFixedValue; 256 if (area.AxisX.Minimum > area.AxisX.Maximum) area.AxisX.Maximum = area.AxisX.Minimum + 1; 257 if (area.AxisX2.Minimum > area.AxisX2.Maximum) area.AxisX2.Maximum = area.AxisX2.Minimum + 1; 258 if (area.AxisY.Minimum > area.AxisY.Maximum) area.AxisY.Maximum = area.AxisY.Minimum + 1; 259 if (area.AxisY2.Minimum > area.AxisY2.Maximum) area.AxisY2.Maximum = area.AxisY2.Minimum + 1; 260 } 148 261 149 262 /// <summary> … … 151 264 /// </summary> 152 265 protected virtual void UpdateYCursorInterval() { 153 double interestingValuesRange = (from series in chart.Series 154 where series.Enabled 155 let values = (from point in series.Points 156 where !point.IsEmpty 157 select point.YValues[0]) 158 .DefaultIfEmpty(1.0) 159 let range = values.Max() - values.Min() 160 where range > 0.0 161 select range) 162 .DefaultIfEmpty(1.0) 163 .Min(); 266 double interestingValuesRange = ( 267 from series in chart.Series 268 where series.Enabled 269 let values = (from point in series.Points 270 where !point.IsEmpty 271 select point.YValues[0]).DefaultIfEmpty(1.0) 272 let range = values.Max() - values.Min() 273 where range > 0.0 274 select range 275 ).DefaultIfEmpty(1.0).Min(); 164 276 165 277 double digits = (int)Math.Log10(interestingValuesRange) - 3; … … 178 290 if (invisibleSeries.Contains(series)) 179 291 invisibleSeries.Remove(series); 180 chart.ChartAreas[0].RecalculateAxesScale(); 181 } 182 183 #region Content Events 184 /// <summary> 185 /// Automatically called for every existing data row and whenever a data row is added 186 /// to the data table. Do not call this method directly. 187 /// </summary> 188 /// <param name="row">The DataRow that was added.</param> 189 protected virtual void RegisterDataRowEvents(DataRow row) { 190 row.NameChanged += new EventHandler(Row_NameChanged); 191 row.VisualPropertiesChanged += new EventHandler(Row_VisualPropertiesChanged); 192 valuesRowsTable.Add(row.Values, row); 193 row.Values.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsAdded); 194 row.Values.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved); 195 row.Values.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced); 196 row.Values.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved); 197 row.Values.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_CollectionReset); 198 } 199 200 /// <summary> 201 /// Automatically called for every data row that is removed from the DataTable. Do 202 /// not directly call this method. 203 /// </summary> 204 /// <param name="row">The DataRow that was removed.</param> 205 protected virtual void DeregisterDataRowEvents(DataRow row) { 206 row.Values.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsAdded); 207 row.Values.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved); 208 row.Values.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced); 209 row.Values.ItemsMoved -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved); 210 row.Values.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_CollectionReset); 211 valuesRowsTable.Remove(row.Values); 212 row.VisualPropertiesChanged -= new EventHandler(Row_VisualPropertiesChanged); 213 row.NameChanged -= new EventHandler(Row_NameChanged); 214 } 292 RecalculateAxesScale(chart.ChartAreas[0]); 293 } 294 295 #region Event Handlers 296 #region Content Event Handlers 215 297 protected override void Content_NameChanged(object sender, EventArgs e) { 216 298 if (InvokeRequired) … … 225 307 Invoke(new EventHandler(Content_VisualPropertiesChanged), sender, e); 226 308 else { 227 chart.ChartAreas[0].AxisX.Title = Content.VisualProperties.XAxisTitle; 228 chart.ChartAreas[0].AxisY.Title = Content.VisualProperties.YAxisTitle; 229 chart.ChartAreas[0].AxisY2.Title = Content.VisualProperties.SecondYAxisTitle; 230 } 231 } 309 ConfigureChartArea(chart.ChartAreas[0]); 310 RecalculateAxesScale(chart.ChartAreas[0]); // axes min/max could have changed 311 } 312 } 313 #endregion 314 #region Rows Event Handlers 232 315 private void Rows_ItemsAdded(object sender, CollectionItemsChangedEventArgs<DataRow> e) { 233 316 if (InvokeRequired) … … 278 361 } 279 362 } 363 #endregion 364 #region Row Event Handlers 280 365 private void Row_VisualPropertiesChanged(object sender, EventArgs e) { 281 366 if (InvokeRequired) … … 283 368 else { 284 369 DataRow row = (DataRow)sender; 285 switch (row.VisualProperties.ChartType) { 286 case DataRowVisualProperties.DataRowChartType.Line: 287 chart.Series[row.Name].ChartType = SeriesChartType.FastLine; 288 break; 289 case DataRowVisualProperties.DataRowChartType.Bars: 290 chart.Series[row.Name].ChartType = SeriesChartType.Bar; 291 break; 292 case DataRowVisualProperties.DataRowChartType.Columns: 293 chart.Series[row.Name].ChartType = SeriesChartType.Column; 294 break; 295 case DataRowVisualProperties.DataRowChartType.Points: 296 chart.Series[row.Name].ChartType = SeriesChartType.FastPoint; 297 break; 298 default: 299 chart.Series[row.Name].ChartType = SeriesChartType.FastPoint; 300 break; 301 } 302 chart.Series[row.Name].YAxisType = row.VisualProperties.SecondYAxis ? AxisType.Secondary : AxisType.Primary; 303 if (row.VisualProperties.Color != Color.Empty) chart.Series[row.Name].Color = row.VisualProperties.Color; 304 chart.ChartAreas[0].RecalculateAxesScale(); 370 Series series = chart.Series[row.Name]; 371 series.Points.Clear(); 372 ConfigureSeries(series, row); 373 FillSeriesWithRowValues(series, row); 374 RecalculateAxesScale(chart.ChartAreas[0]); 305 375 } 306 376 } … … 313 383 } 314 384 } 385 #endregion 386 #region Values Event Handlers 315 387 private void Values_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<double>> e) { 316 388 if (InvokeRequired) … … 324 396 rowSeries.Points.Clear(); 325 397 FillSeriesWithRowValues(rowSeries, row); 398 RecalculateAxesScale(chart.ChartAreas[0]); 326 399 UpdateYCursorInterval(); 327 400 } … … 340 413 rowSeries.Points.Clear(); 341 414 FillSeriesWithRowValues(rowSeries, row); 415 RecalculateAxesScale(chart.ChartAreas[0]); 342 416 UpdateYCursorInterval(); 343 417 } … … 354 428 Series rowSeries = chart.Series[row.Name]; 355 429 if (!invisibleSeries.Contains(rowSeries)) { 356 foreach (IndexedItem<double> item in e.Items) { 357 if (IsInvalidValue(item.Value)) 358 rowSeries.Points[item.Index].IsEmpty = true; 359 else { 360 rowSeries.Points[item.Index].YValues = new double[] { item.Value }; 361 rowSeries.Points[item.Index].IsEmpty = false; 430 if (row.VisualProperties.ChartType == DataRowVisualProperties.DataRowChartType.Histogram) { 431 rowSeries.Points.Clear(); 432 FillSeriesWithRowValues(rowSeries, row); 433 } else { 434 foreach (IndexedItem<double> item in e.Items) { 435 if (IsInvalidValue(item.Value)) 436 rowSeries.Points[item.Index].IsEmpty = true; 437 else { 438 rowSeries.Points[item.Index].YValues = new double[] { item.Value }; 439 rowSeries.Points[item.Index].IsEmpty = false; 440 } 362 441 } 363 442 } 443 RecalculateAxesScale(chart.ChartAreas[0]); 364 444 UpdateYCursorInterval(); 365 445 } … … 378 458 rowSeries.Points.Clear(); 379 459 FillSeriesWithRowValues(rowSeries, row); 460 RecalculateAxesScale(chart.ChartAreas[0]); 380 461 UpdateYCursorInterval(); 381 462 } … … 395 476 rowSeries.Points.Clear(); 396 477 FillSeriesWithRowValues(rowSeries, row); 478 RecalculateAxesScale(chart.ChartAreas[0]); 397 479 UpdateYCursorInterval(); 398 480 } … … 401 483 } 402 484 #endregion 403 404 #region Chart Events 485 #endregion 486 487 #region Chart Event Handlers 405 488 private void chart_MouseDown(object sender, MouseEventArgs e) { 406 489 HitTestResult result = chart.HitTest(e.X, e.Y); … … 409 492 } 410 493 } 494 private void chart_MouseMove(object sender, MouseEventArgs e) { 495 HitTestResult result = chart.HitTest(e.X, e.Y); 496 if (result.ChartElementType == ChartElementType.LegendItem) 497 this.Cursor = Cursors.Hand; 498 else 499 this.Cursor = Cursors.Default; 500 } 501 private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) { 502 foreach (LegendItem legendItem in e.LegendItems) { 503 var series = chart.Series[legendItem.SeriesName]; 504 if (series != null) { 505 bool seriesIsInvisible = invisibleSeries.Contains(series); 506 foreach (LegendCell cell in legendItem.Cells) { 507 cell.ForeColor = seriesIsInvisible ? Color.Gray : Color.Black; 508 } 509 } 510 } 511 } 512 #endregion 411 513 412 514 private void ToggleSeriesVisible(Series series) { … … 423 525 FillSeriesWithRowValues(series, row); 424 526 this.chart.Legends[series.Legend].ForeColor = Color.Black; 527 RecalculateAxesScale(chart.ChartAreas[0]); 425 528 UpdateYCursorInterval(); 426 529 } … … 429 532 430 533 private void FillSeriesWithRowValues(Series series, DataRow row) { 431 for (int i = 0; i < row.Values.Count; i++) { 432 var value = row.Values[i]; 433 DataPoint point = new DataPoint(); 434 point.XValue = row.VisualProperties.StartIndexZero ? i : i + 1; 435 if (IsInvalidValue(value)) 436 point.IsEmpty = true; 437 else 438 point.YValues = new double[] { value }; 439 series.Points.Add(point); 440 } 441 } 442 443 private void chart_MouseMove(object sender, MouseEventArgs e) { 444 HitTestResult result = chart.HitTest(e.X, e.Y); 445 if (result.ChartElementType == ChartElementType.LegendItem) 446 this.Cursor = Cursors.Hand; 447 else 448 this.Cursor = Cursors.Default; 449 } 450 private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) { 451 foreach (LegendItem legendItem in e.LegendItems) { 452 var series = chart.Series[legendItem.SeriesName]; 453 if (series != null) { 454 bool seriesIsInvisible = invisibleSeries.Contains(series); 455 foreach (LegendCell cell in legendItem.Cells) { 456 cell.ForeColor = seriesIsInvisible ? Color.Gray : Color.Black; 457 } 458 } 459 } 460 } 461 #endregion 462 534 switch (row.VisualProperties.ChartType) { 535 case DataRowVisualProperties.DataRowChartType.Histogram: 536 CalculateHistogram(series, row); 537 break; 538 default: { 539 for (int i = 0; i < row.Values.Count; i++) { 540 var value = row.Values[i]; 541 DataPoint point = new DataPoint(); 542 point.XValue = row.VisualProperties.StartIndexZero ? i : i + 1; 543 if (IsInvalidValue(value)) 544 point.IsEmpty = true; 545 else 546 point.YValues = new double[] { value }; 547 series.Points.Add(point); 548 } 549 } 550 break; 551 } 552 } 553 554 protected virtual void CalculateHistogram(Series series, DataRow row) { 555 series.Points.Clear(); 556 if (!row.Values.Any()) return; 557 int bins = row.VisualProperties.Bins; 558 559 double minValue = row.Values.Min(); 560 double maxValue = row.Values.Max(); 561 double intervalWidth = (maxValue - minValue) / bins; 562 if (intervalWidth < 0) return; 563 if (intervalWidth == 0) { 564 series.Points.AddXY(minValue, row.Values.Count); 565 return; 566 } 567 568 if (!row.VisualProperties.ExactBins) { 569 intervalWidth = HumanRoundRange(intervalWidth); 570 minValue = Math.Floor(minValue / intervalWidth) * intervalWidth; 571 maxValue = Math.Ceiling(maxValue / intervalWidth) * intervalWidth; 572 } 573 574 double current = minValue, intervalCenter = intervalWidth / 2.0; 575 int frequency = 0; 576 series.Points.AddXY(current - intervalCenter, 0); // so that the first column is not visually truncated 577 foreach (double v in row.Values.Where(x => !IsInvalidValue(x)).OrderBy(x => x)) { 578 while (v > current + intervalWidth) { 579 series.Points.AddXY(current + intervalCenter, frequency); 580 current += intervalWidth; 581 frequency = 0; 582 } 583 frequency++; 584 } 585 series.Points.AddXY(current + intervalCenter, frequency); 586 series.Points.AddXY(current + 3 * intervalCenter, 0); // so that the last column is not visually truncated 587 } 588 589 #region Helpers 590 protected void RemoveCustomPropertyIfExists(Series series, string property) { 591 if (series.IsCustomPropertySet(property)) series.DeleteCustomProperty(property); 592 } 593 594 private double HumanRoundRange(double range) { 595 double base10 = Math.Pow(10.0, Math.Floor(Math.Log10(range))); 596 double rounding = range / base10; 597 if (rounding <= 1.5) rounding = 1; 598 else if (rounding <= 2.25) rounding = 2; 599 else if (rounding <= 3.75) rounding = 2.5; 600 else if (rounding <= 7.5) rounding = 5; 601 else rounding = 10; 602 return rounding * base10; 603 } 604 605 private double HumanRoundMax(double max) { 606 double base10; 607 if (max > 0) base10 = Math.Pow(10.0, Math.Floor(Math.Log10(max))); 608 else base10 = Math.Pow(10.0, Math.Ceiling(Math.Log10(-max))); 609 double rounding = (max > 0) ? base10 : -base10; 610 while (rounding < max) rounding += base10; 611 return rounding; 612 } 613 614 private ChartDashStyle ConvertLineStyle(DataRowVisualProperties.DataRowLineStyle dataRowLineStyle) { 615 switch (dataRowLineStyle) { 616 case DataRowVisualProperties.DataRowLineStyle.Dash: 617 return ChartDashStyle.Dash; 618 case DataRowVisualProperties.DataRowLineStyle.DashDot: 619 return ChartDashStyle.DashDot; 620 case DataRowVisualProperties.DataRowLineStyle.DashDotDot: 621 return ChartDashStyle.DashDotDot; 622 case DataRowVisualProperties.DataRowLineStyle.Dot: 623 return ChartDashStyle.Dot; 624 case DataRowVisualProperties.DataRowLineStyle.NotSet: 625 return ChartDashStyle.NotSet; 626 case DataRowVisualProperties.DataRowLineStyle.Solid: 627 return ChartDashStyle.Solid; 628 default: 629 return ChartDashStyle.NotSet; 630 } 631 } 463 632 464 633 /// <summary> … … 471 640 return double.IsNaN(x) || x < (double)decimal.MinValue || x > (double)decimal.MaxValue; 472 641 } 642 #endregion 473 643 } 474 644 }
Note: See TracChangeset
for help on using the changeset viewer.