Skip to content

Commit 42aaad6

Browse files
committed
Fix #794 axis alignment with MinimumRange or MaximumRange with Absolute limits
1 parent 2cbee7f commit 42aaad6

File tree

5 files changed

+286
-4
lines changed

5 files changed

+286
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ All notable changes to this project will be documented in this file.
168168
- LogarithmicAxis sometimes places major ticks outside of the axis range (#850)
169169
- LineSeries with smoothing raises exception (#72)
170170
- Exception when legend is outside and plot area is small (#880)
171+
- Axis alignment with MinimumRange (#794)
171172

172173
## [2014.1.546] - 2014-10-22
173174
### Added

CONTRIBUTORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Carlos Anderson <carlosjanderson@gmail.com>
2323
Carlos Teixeira <karlmtc@gmail.com>
2424
Choden Konigsmark <choden.konigsmark@gmail.com>
2525
classicboss302
26+
csabar <rumancsabi@gmail.com>
2627
Cyril Martin <cyril.martin.cm@gmail.com>
2728
darrelbrown
2829
David Laundav <davelaundav@gmail.com>

Source/Examples/ExampleLibrary/Issues/Issues.cs

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1500,7 +1500,7 @@ public static PlotModel AutoPlotMarginAndAxisLabelWidths()
15001500
}
15011501

15021502
/// <summary>
1503-
/// Creates a demo PlotModel with MinimumRange defined
1503+
/// Creates a demo PlotModel with MinimumRange defined
15041504
/// and with series with values which are within this range.
15051505
/// </summary>
15061506
/// <returns>The created PlotModel</returns>
@@ -1571,6 +1571,65 @@ public static PlotModel TooMuchTitlePadding()
15711571
return model;
15721572
}
15731573

1574+
/// <summary>
1575+
/// Creates a demo PlotModel with MinimumRange defined
1576+
/// and with series with values which are within this range.
1577+
/// </summary>
1578+
/// <returns>The created PlotModel</returns>
1579+
[Example("#794: Axis alignment when MinimumRange is set with AbsoluteMaximum")]
1580+
public static PlotModel MinimumRangeAbsoluteMaximumTest()
1581+
{
1582+
var model = new PlotModel();
1583+
var yaxis = new LinearAxis()
1584+
{
1585+
Position = AxisPosition.Left,
1586+
MinimumRange = 1,
1587+
AbsoluteMaximum = 10.5
1588+
};
1589+
1590+
model.Axes.Add(yaxis);
1591+
1592+
var series = new LineSeries();
1593+
series.Points.Add(new DataPoint(0, 10.1));
1594+
series.Points.Add(new DataPoint(1, 10.15));
1595+
series.Points.Add(new DataPoint(2, 10.3));
1596+
series.Points.Add(new DataPoint(3, 10.25));
1597+
series.Points.Add(new DataPoint(4, 10.1));
1598+
1599+
model.Series.Add(series);
1600+
1601+
return model;
1602+
}
1603+
1604+
/// <summary>
1605+
/// Creates a demo PlotModel with MinimumRange defined
1606+
/// and with series with values which are within this range.
1607+
/// </summary>
1608+
/// <returns>The created PlotModel</returns>
1609+
[Example("#794: Axis alignment when MinimumRange is set with AbsoluteMinimum")]
1610+
public static PlotModel MinimumRangeAbsoluteMinimumTest()
1611+
{
1612+
var model = new PlotModel();
1613+
var yaxis = new LinearAxis()
1614+
{
1615+
Position = AxisPosition.Left,
1616+
MinimumRange = 1,
1617+
AbsoluteMinimum = 10,
1618+
};
1619+
1620+
model.Axes.Add(yaxis);
1621+
1622+
var series = new LineSeries();
1623+
series.Points.Add(new DataPoint(0, 10.1));
1624+
series.Points.Add(new DataPoint(1, 10.15));
1625+
series.Points.Add(new DataPoint(2, 10.3));
1626+
series.Points.Add(new DataPoint(3, 10.25));
1627+
series.Points.Add(new DataPoint(4, 10.1));
1628+
1629+
model.Series.Add(series);
1630+
1631+
return model;
1632+
}
15741633

15751634
/* NEW ISSUE TEMPLATE
15761635
[Example("#123: Issue Description")]

Source/OxyPlot.Tests/Axes/AxisTests.cs

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,5 +464,203 @@ public void Axis_DesiredSize()
464464
Assert.That(yaxis.DesiredSize.Width, Is.EqualTo(50.0).Within(0.5), "y-axis width");
465465
Assert.That(yaxis.DesiredSize.Height, Is.EqualTo(0.0).Within(1e-6), "y-axis height");
466466
}
467+
468+
/// <summary>
469+
/// Tests the alignment of the series, if minimum range is set
470+
/// </summary>
471+
[Test]
472+
public void Axis_VerticalAlignment_MinimumRange()
473+
{
474+
var plot = new PlotModel();
475+
var yaxis = new LinearAxis()
476+
{
477+
Position = AxisPosition.Left,
478+
MinimumRange = 1,
479+
};
480+
481+
plot.Axes.Add(yaxis);
482+
483+
var series = new LineSeries();
484+
series.Points.Add(new DataPoint(0, 10.1));
485+
series.Points.Add(new DataPoint(1, 10.15));
486+
series.Points.Add(new DataPoint(2, 10.3));
487+
series.Points.Add(new DataPoint(3, 10.25));
488+
489+
plot.Series.Add(series);
490+
491+
((IPlotModel)plot).Update(true);
492+
493+
double dataMin = 10.1;
494+
double dataMax = 10.3;
495+
double dataCenter = (dataMax + dataMin) / 2;
496+
497+
// Center should be the between data min and max
498+
Assert.AreEqual(dataCenter, (plot.Axes[0].ActualMaximum + plot.Axes[0].ActualMinimum) / 2, 1e-5, "center");
499+
Assert.AreEqual(dataCenter - 0.5, plot.Axes[0].ActualMinimum, 1e-5, "minimum");
500+
Assert.AreEqual(dataCenter + 0.5, plot.Axes[0].ActualMaximum, 1e-5, "maximum");
501+
}
502+
503+
/// <summary>
504+
/// Tests the alignment of the series, if MinimumRange and the AbsoluteMaximum are set
505+
/// </summary>
506+
[Test]
507+
public void Axis_VerticalAlignment_MinimumRange_AbsoluteMaximum()
508+
{
509+
var plot = new PlotModel();
510+
var yaxis = new LinearAxis()
511+
{
512+
Position = AxisPosition.Left,
513+
MinimumRange = 1,
514+
AbsoluteMaximum = 10.5,
515+
};
516+
517+
plot.Axes.Add(yaxis);
518+
519+
var series = new LineSeries();
520+
series.Points.Add(new DataPoint(0, 10.1));
521+
series.Points.Add(new DataPoint(1, 10.15));
522+
series.Points.Add(new DataPoint(2, 10.3));
523+
series.Points.Add(new DataPoint(3, 10.25));
524+
525+
plot.Series.Add(series);
526+
527+
((IPlotModel)plot).Update(true);
528+
529+
// Center should be the between AbsoluteMaximum and the (AboluteMaximum - MinimumRange)
530+
Assert.AreEqual(yaxis.AbsoluteMaximum, plot.Axes[0].ActualMaximum, 0, "absolute maximum");
531+
Assert.AreEqual(yaxis.AbsoluteMaximum - (yaxis.MinimumRange / 2), (plot.Axes[0].ActualMaximum + plot.Axes[0].ActualMinimum) / 2, 1e-5, "center");
532+
Assert.AreEqual(yaxis.AbsoluteMaximum - yaxis.MinimumRange, plot.Axes[0].ActualMinimum, 1e-5, "minimum");
533+
}
534+
535+
/// <summary>
536+
/// Tests the alignment of the series, if MinimumRange and the AbsoluteMaximum are set
537+
/// </summary>
538+
[Test]
539+
public void Axis_VerticalAlignment_MinimumRange_AbsoluteMinimum()
540+
{
541+
var plot = new PlotModel();
542+
var yaxis = new LinearAxis()
543+
{
544+
Position = AxisPosition.Left,
545+
MinimumRange = 1,
546+
AbsoluteMinimum = 10,
547+
};
548+
549+
plot.Axes.Add(yaxis);
550+
551+
var series = new LineSeries();
552+
series.Points.Add(new DataPoint(0, 10.1));
553+
series.Points.Add(new DataPoint(1, 10.15));
554+
series.Points.Add(new DataPoint(2, 10.3));
555+
series.Points.Add(new DataPoint(3, 10.25));
556+
557+
plot.Series.Add(series);
558+
559+
((IPlotModel)plot).Update(true);
560+
561+
// Center should be the between AbsoluteMinimum and the (AboluteMinimum + MinimumRange)
562+
Assert.AreEqual(yaxis.AbsoluteMinimum, plot.Axes[0].ActualMinimum, 0, "absolute minimum");
563+
Assert.AreEqual(yaxis.AbsoluteMinimum + (yaxis.MinimumRange / 2), (plot.Axes[0].ActualMaximum + plot.Axes[0].ActualMinimum) / 2, 1e-5, "center");
564+
Assert.AreEqual(yaxis.AbsoluteMinimum + yaxis.MinimumRange, plot.Axes[0].ActualMaximum, 1e-5, "maximum");
565+
}
566+
567+
/// <summary>
568+
/// Tests the alignment of the series, if maximum range is set.
569+
/// </summary>
570+
[Test]
571+
public void Axis_VerticalAlignment_MaximumRange()
572+
{
573+
var plot = new PlotModel();
574+
var yaxis = new LinearAxis()
575+
{
576+
Position = AxisPosition.Left,
577+
MaximumRange = 0.1,
578+
};
579+
580+
plot.Axes.Add(yaxis);
581+
582+
var series = new LineSeries();
583+
series.Points.Add(new DataPoint(0, 10.1));
584+
series.Points.Add(new DataPoint(1, 10.15));
585+
series.Points.Add(new DataPoint(2, 10.3));
586+
series.Points.Add(new DataPoint(3, 10.25));
587+
588+
plot.Series.Add(series);
589+
590+
((IPlotModel)plot).Update(true);
591+
592+
double dataMin = 10.1;
593+
double dataMax = 10.3;
594+
double dataCenter = (dataMax + dataMin) / 2;
595+
596+
// Center should be the between data min and max
597+
Assert.AreEqual(dataCenter, (plot.Axes[0].ActualMaximum + plot.Axes[0].ActualMinimum) / 2, 1e-5, "center");
598+
Assert.AreEqual(dataCenter - 0.05, plot.Axes[0].ActualMinimum, 1e-5, "minimum");
599+
Assert.AreEqual(dataCenter + 0.05, plot.Axes[0].ActualMaximum, 1e-5, "maximum");
600+
}
601+
602+
/// <summary>
603+
/// Tests the alignment of the series, if MaximumRange and the AbsoluteMaximum are set.
604+
/// </summary>
605+
[Test]
606+
public void Axis_VerticalAlignment_MaximumRange_AbsoluteMaximum()
607+
{
608+
var plot = new PlotModel();
609+
var yaxis = new LinearAxis()
610+
{
611+
Position = AxisPosition.Left,
612+
MaximumRange = 0.1,
613+
AbsoluteMaximum = 10.22,
614+
};
615+
616+
plot.Axes.Add(yaxis);
617+
618+
var series = new LineSeries();
619+
series.Points.Add(new DataPoint(0, 10.1));
620+
series.Points.Add(new DataPoint(1, 10.15));
621+
series.Points.Add(new DataPoint(2, 10.3));
622+
series.Points.Add(new DataPoint(3, 10.25));
623+
624+
plot.Series.Add(series);
625+
626+
((IPlotModel)plot).Update(true);
627+
628+
// Range is between AbsoluteMaximum and the (AboluteMaximum - MaximumRange)
629+
Assert.AreEqual(yaxis.AbsoluteMaximum, plot.Axes[0].ActualMaximum, 0, "absolute maximum");
630+
Assert.AreEqual(yaxis.AbsoluteMaximum - (yaxis.MaximumRange / 2), (plot.Axes[0].ActualMaximum + plot.Axes[0].ActualMinimum) / 2, 1e-6, "center");
631+
Assert.AreEqual(yaxis.AbsoluteMaximum - yaxis.MaximumRange, plot.Axes[0].ActualMinimum, 1e-6, "minimum");
632+
}
633+
634+
/// <summary>
635+
/// Tests the alignment of the series, if MaximumRange and the AbsoluteMinimum are set.
636+
/// </summary>
637+
[Test]
638+
public void Axis_VerticalAlignment_MaximumRange_AbsoluteMinimum()
639+
{
640+
var plot = new PlotModel();
641+
var yaxis = new LinearAxis()
642+
{
643+
Position = AxisPosition.Left,
644+
MaximumRange = 0.1,
645+
AbsoluteMinimum = 10.16,
646+
};
647+
648+
plot.Axes.Add(yaxis);
649+
650+
var series = new LineSeries();
651+
series.Points.Add(new DataPoint(0, 10.1));
652+
series.Points.Add(new DataPoint(1, 10.15));
653+
series.Points.Add(new DataPoint(2, 10.3));
654+
series.Points.Add(new DataPoint(3, 10.25));
655+
656+
plot.Series.Add(series);
657+
658+
((IPlotModel)plot).Update(true);
659+
660+
// Range is between AbsoluteMinimum and the (AboluteMinimum + MaximumRange)
661+
Assert.AreEqual(yaxis.AbsoluteMinimum, plot.Axes[0].ActualMinimum, 0, "absolute minimum");
662+
Assert.AreEqual(yaxis.AbsoluteMinimum + (yaxis.MaximumRange / 2), (plot.Axes[0].ActualMaximum + plot.Axes[0].ActualMinimum) / 2, 1e-6, "center");
663+
Assert.AreEqual(yaxis.AbsoluteMinimum + yaxis.MaximumRange, plot.Axes[0].ActualMaximum, 1e-6, "maximum");
664+
}
467665
}
468666
}

Source/OxyPlot/Axes/Axis.cs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,12 +1402,24 @@ protected virtual void CoerceActualMaxMin()
14021402
{
14031403
if (this.ActualMinimum + this.MinimumRange < this.AbsoluteMaximum)
14041404
{
1405+
var average = (this.ActualMaximum + this.ActualMinimum) * 0.5;
1406+
var delta = this.MinimumRange / 2;
1407+
this.ActualMinimum = average - delta;
1408+
this.ActualMaximum = average + delta;
1409+
14051410
if (this.ActualMinimum < this.AbsoluteMinimum)
14061411
{
1412+
var diff = this.AbsoluteMinimum - this.ActualMinimum;
14071413
this.ActualMinimum = this.AbsoluteMinimum;
1414+
this.ActualMaximum += diff;
14081415
}
14091416

1410-
this.ActualMaximum = this.ActualMinimum + this.MinimumRange;
1417+
if (this.ActualMaximum > this.AbsoluteMaximum)
1418+
{
1419+
var diff = this.AbsoluteMaximum - this.ActualMaximum;
1420+
this.ActualMaximum = this.AbsoluteMaximum;
1421+
this.ActualMinimum += diff;
1422+
}
14111423
}
14121424
else
14131425
{
@@ -1429,13 +1441,24 @@ protected virtual void CoerceActualMaxMin()
14291441
{
14301442
if (this.ActualMinimum + this.MaximumRange < this.AbsoluteMaximum)
14311443
{
1444+
var average = (this.ActualMaximum + this.ActualMinimum) * 0.5;
1445+
var delta = this.MaximumRange / 2;
1446+
this.ActualMinimum = average - delta;
1447+
this.ActualMaximum = average + delta;
1448+
14321449
if (this.ActualMinimum < this.AbsoluteMinimum)
14331450
{
1451+
var diff = this.AbsoluteMinimum - this.ActualMinimum;
14341452
this.ActualMinimum = this.AbsoluteMinimum;
1453+
this.ActualMaximum += diff;
14351454
}
14361455

1437-
// Adjust the actual maximum only
1438-
this.ActualMaximum = this.ActualMinimum + this.MaximumRange;
1456+
if (this.ActualMaximum > this.AbsoluteMaximum)
1457+
{
1458+
var diff = this.AbsoluteMaximum - this.ActualMaximum;
1459+
this.ActualMaximum = this.AbsoluteMaximum;
1460+
this.ActualMinimum += diff;
1461+
}
14391462
}
14401463
else
14411464
{

0 commit comments

Comments
 (0)