Skip to content

Commit b2cbc07

Browse files
author
Nils Haferkemper
committed
Extended polar plot to full plot area, including Examples
1 parent bbc87bb commit b2cbc07

7 files changed

Lines changed: 919 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
All notable changes to this project will be documented in this file.
33

44
## [Unreleased]
5+
### Added
6+
- New PolarPlot filling the full plot area (#1056)
7+
58
### Added
69
- Added Avalonia based renderer and control library (based off OxyPlot.Wpf).
710
- New `InterpolationAlgorithm` property in LineSeries and PolylineAnnotation (#494)

CONTRIBUTORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ Levi Botelho <levi_botelho@hotmail.com>
6969
Linquize
7070
lsowen
7171
Luka B
72+
Nils Haferkemper <nils@haferkemper.de>
7273
Matt Williams
7374
Matthew Leibowitz <mattleibow@live.com>
7475
Memphisch <memphis@machzwo.de>

Source/Examples/ExampleLibrary/Axes/PolarPlotExamples.cs

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,5 +243,76 @@ public static PlotModel EastWestDirections()
243243
model.Series.Add(new FunctionSeries(x => Math.Sin(x / 180 * Math.PI), t => t, 0, 180, 0.01));
244244
return model;
245245
}
246+
247+
[Example("Semi-circle full plot area")]
248+
public static PlotModel SemiCircleFullPlotArea()
249+
{
250+
var model = new PlotModel
251+
{
252+
Title = "Semi-circle polar plot filling the plot area",
253+
Subtitle = "The center can be move using the right mouse button",
254+
PlotType = PlotType.Polar,
255+
PlotAreaBorderThickness = new OxyThickness(1),
256+
PlotMargins = new OxyThickness(60, 20, 4, 40)
257+
};
258+
model.Axes.Add(
259+
new AngleAxisFullPlotArea
260+
{
261+
Minimum = 0,
262+
Maximum = 180,
263+
MajorStep = 45,
264+
MinorStep = 9,
265+
StartAngle = 0,
266+
EndAngle = 180,
267+
MajorGridlineStyle = LineStyle.Solid,
268+
MinorGridlineStyle = LineStyle.Solid
269+
});
270+
model.Axes.Add(new MagnitudeAxisFullPlotArea
271+
{
272+
Minimum = 0,
273+
Maximum = 1,
274+
MidshiftH = 0,
275+
MidshiftV = 0.9d,
276+
MajorGridlineStyle = LineStyle.Solid,
277+
MinorGridlineStyle = LineStyle.Solid
278+
});
279+
model.Series.Add(new FunctionSeries(x => Math.Sin(x / 180 * Math.PI), t => t, 0, 180, 0.01));
280+
return model;
281+
}
282+
283+
[Example("Spiral full plot area")]
284+
public static PlotModel ArchimedeanSpiralFullPlotArea()
285+
{
286+
var model = new PlotModel
287+
{
288+
Title = "Polar plot filling the plot area",
289+
Subtitle = "The center can be move using the right mouse button",
290+
PlotType = PlotType.Polar,
291+
PlotAreaBorderThickness = new OxyThickness(1),
292+
PlotMargins = new OxyThickness(60, 20, 4, 40)
293+
};
294+
model.Axes.Add(
295+
new AngleAxisFullPlotArea
296+
{
297+
MajorStep = Math.PI / 4,
298+
MinorStep = Math.PI / 16,
299+
MajorGridlineStyle = LineStyle.Solid,
300+
MinorGridlineStyle = LineStyle.Solid,
301+
FormatAsFractions = true,
302+
FractionUnit = Math.PI,
303+
FractionUnitSymbol = "π",
304+
Minimum = 0,
305+
Maximum = 2 * Math.PI
306+
});
307+
model.Axes.Add(new MagnitudeAxisFullPlotArea
308+
{
309+
MidshiftH = -0.1d,
310+
MidshiftV = -0.25d,
311+
MajorGridlineStyle = LineStyle.Solid,
312+
MinorGridlineStyle = LineStyle.Solid
313+
});
314+
model.Series.Add(new FunctionSeries(t => t, t => t, 0, Math.PI * 6, 0.01));
315+
return model;
316+
}
246317
}
247-
}
318+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace OxyPlot.Axes
6+
{
7+
public class AngleAxisFullPlotArea : AngleAxis
8+
{
9+
/// <summary>
10+
/// Renders the axis on the specified render context.
11+
/// </summary>
12+
/// <param name="rc">The render context.</param>
13+
/// <param name="pass">The pass.</param>
14+
public override void Render(IRenderContext rc, int pass)
15+
{
16+
var r = new AngleAxisFullPlotAreaRenderer(rc, this.PlotModel);
17+
r.Render(this, pass);
18+
}
19+
}
20+
}
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
// --------------------------------------------------------------------------------------------------------------------
2+
// <copyright file="MagnitudeAxisFullPlotArea.cs" company="OxyPlot">
3+
// Copyright (c) 2014 OxyPlot contributors
4+
// </copyright>
5+
// <summary>
6+
// Represents a magnitude axis for polar plots.
7+
// </summary>
8+
// --------------------------------------------------------------------------------------------------------------------
9+
10+
namespace OxyPlot.Axes
11+
{
12+
using System;
13+
using System.Collections.Generic;
14+
using System.Text;
15+
16+
public class MagnitudeAxisFullPlotArea : MagnitudeAxis
17+
{
18+
private double _midshiftH = 0;
19+
/// <summary>
20+
/// Portion to shift the center in horizontal direction relative to the plot area size (from -0.5 to +0.5 meaning +-50% of the width)
21+
/// </summary>
22+
public double MidshiftH
23+
{
24+
get { return _midshiftH; }
25+
set
26+
{
27+
_midshiftH = value;
28+
_midshiftH = Math.Max(_midshiftH, -0.5d);
29+
_midshiftH = Math.Min(_midshiftH, 0.5d);
30+
}
31+
}
32+
33+
private double _midshiftV = 0d;
34+
/// <summary>
35+
/// Portion to shift the center in vertical direction relative to the plot area size (from -0.5 to +0.5 meaning +-50% of the height)
36+
/// </summary>
37+
public double MidshiftV
38+
{
39+
get { return _midshiftV; }
40+
set
41+
{
42+
_midshiftV = value;
43+
_midshiftV = Math.Max(_midshiftV, -0.5d);
44+
_midshiftV = Math.Min(_midshiftV, 0.5d);
45+
}
46+
}
47+
48+
/// <summary>
49+
/// Initializes a new instance of the <see cref="MagnitudeAxis" /> class.
50+
/// </summary>
51+
public MagnitudeAxisFullPlotArea()
52+
{
53+
this.Position = AxisPosition.None;
54+
this.IsPanEnabled = true;
55+
this.IsZoomEnabled = false;
56+
57+
this.MajorGridlineStyle = LineStyle.Solid;
58+
this.MinorGridlineStyle = LineStyle.Solid;
59+
}
60+
61+
///// <summary>
62+
///// Inverse transform the specified screen point.
63+
///// </summary>
64+
///// <param name="x">The x coordinate.</param>
65+
///// <param name="y">The y coordinate.</param>
66+
///// <param name="yaxis">The y-axis.</param>
67+
///// <returns>The data point.</returns>
68+
//public override DataPoint InverseTransform(double x, double y, Axis yaxis)
69+
//{
70+
// var angleAxis = yaxis as AngleAxis;
71+
// if (angleAxis == null)
72+
// {
73+
// throw new InvalidOperationException("Polar angle axis not defined!");
74+
// }
75+
76+
// x -= this.MidPoint.x;
77+
// y -= this.MidPoint.y;
78+
// y *= -1;
79+
// double th = Math.Atan2(y, x);
80+
// double r = Math.Sqrt((x * x) + (y * y));
81+
// x = (r / this.Scale) + this.Offset;
82+
// y = (th / angleAxis.Scale) + angleAxis.Offset;
83+
// return new DataPoint(x, y);
84+
//}
85+
86+
/// <summary>
87+
/// Renders the axis on the specified render context.
88+
/// </summary>
89+
/// <param name="rc">The render context.</param>
90+
/// <param name="pass">The rendering pass.</param>
91+
public override void Render(IRenderContext rc, int pass)
92+
{
93+
var r = new MagnitudeAxisFullPlotAreaRenderer(rc, this.PlotModel);
94+
r.Render(this, pass);
95+
}
96+
97+
///// <summary>
98+
///// Transforms the specified point to screen coordinates.
99+
///// </summary>
100+
///// <param name="x">The x value (for the current axis).</param>
101+
///// <param name="y">The y value.</param>
102+
///// <param name="yaxis">The y axis.</param>
103+
///// <returns>The transformed point.</returns>
104+
//public override ScreenPoint Transform(double x, double y, Axis yaxis)
105+
//{
106+
// var angleAxis = yaxis as AngleAxis;
107+
// if (angleAxis == null)
108+
// {
109+
// throw new InvalidOperationException("Polar angle axis not defined!");
110+
// }
111+
112+
// var r = (x - this.Offset) * this.Scale;
113+
// var theta = (y - angleAxis.Offset) * angleAxis.Scale;
114+
115+
// return new ScreenPoint(this.MidPoint.x + (r * Math.Cos(theta / 180 * Math.PI)), this.MidPoint.y - (r * Math.Sin(theta / 180 * Math.PI)));
116+
//}
117+
118+
/// <summary>
119+
/// Updates the scale and offset properties of the transform from the specified boundary rectangle.
120+
/// </summary>
121+
/// <param name="bounds">The bounds.</param>
122+
internal override void UpdateTransform(OxyRect bounds)
123+
{
124+
double x0 = bounds.Left;
125+
double x1 = bounds.Right;
126+
double y0 = bounds.Bottom;
127+
double y1 = bounds.Top;
128+
129+
this.ScreenMin = new ScreenPoint(x0, y1);
130+
this.ScreenMax = new ScreenPoint(x1, y0);
131+
132+
this.MidPoint = new ScreenPoint((x0 + x1) / 2 + this.MidshiftH * bounds.Width, (y0 + y1) / 2 + this.MidshiftV * bounds.Height); //new ScreenPoint((x0 + x1) / 2, (y0 + y1) / 2);
133+
//this.ShiftedMidPoint = new ScreenPoint((x0 + x1) / 2 + this.MidshiftH * bounds.Width, (y0 + y1) / 2 + this.MidshiftV * bounds.Height);
134+
135+
// this.ActualMinimum = 0;
136+
double r = Math.Min(Math.Abs(x1 - x0), Math.Abs(y1 - y0));
137+
this.SetTransform(0.5 * r / (this.ActualMaximum - this.ActualMinimum), this.ActualMinimum);
138+
}
139+
140+
/// <summary>
141+
/// Pans the specified axis.
142+
/// </summary>
143+
/// <param name="ppt">The previous point (screen coordinates).</param>
144+
/// <param name="cpt">The current point (screen coordinates).</param>
145+
public override void Pan(ScreenPoint ppt, ScreenPoint cpt)
146+
{
147+
if (!this.IsPanEnabled)
148+
{
149+
return;
150+
}
151+
152+
bool isHorizontal = this.IsHorizontal();
153+
154+
double dsx = cpt.X - ppt.X;
155+
double dsy = cpt.Y - ppt.Y;
156+
157+
double dsxp = dsx / this.PlotModel.PlotArea.Width;
158+
double dsyp = dsy / this.PlotModel.PlotArea.Height;
159+
160+
this.MidshiftH += dsxp;
161+
this.MidshiftV += dsyp;
162+
163+
//double d = isHorizontal ? cpt.X - ppt.X : cpt.Y - ppt.Y;
164+
//this.Pan(d);
165+
166+
this.OnAxisChanged(new AxisChangedEventArgs(AxisChangeTypes.Pan, 0, 0));
167+
}
168+
169+
/// <summary>
170+
/// Zooms the axis at the specified coordinate.
171+
/// </summary>
172+
/// <param name="factor">The zoom factor.</param>
173+
/// <param name="x">The coordinate to zoom at.</param>
174+
public override void ZoomAt(double factor, double x)
175+
{
176+
if (!this.IsZoomEnabled)
177+
{
178+
return;
179+
}
180+
181+
base.ZoomAt(factor, 0);
182+
return;
183+
}
184+
}
185+
}

0 commit comments

Comments
 (0)