ZedGraph がすぐに使用できる極グラフをサポートしておらず、オンラインでの例がほとんどないことに驚きました。この guildlineを使用して、C# の ZedGraph で独自の極座標グラフを作成しました。WillKraemer がすでに彼の問題を解決しており (4 年が経過しました)、他の誰かが私の実装が有用であると考えていることを願っています。
まず、ZedGraphControl の初期化です。
myZg = new ZedGraphControl();
GraphPane myPane = myZg.GraphPane;
// Init lists
RadarPointList dseries1 = new RadarPointList();
RadarPointList dseries2 = new RadarPointList();
// Maximize available space in pane
myPane.Legend.Position = LegendPos.InsideTopLeft;
myPane.Title.IsVisible = false;
myPane.XAxis.IsVisible = false;
myPane.YAxis.IsVisible = false;
myPane.Border.IsVisible = false;
myPane.Chart.Border.IsVisible = false;
myPane.Margin.All = 0;
// Create concentric grid with 30 degrees spacing & add corresponding labels
for (double i = 0; i < 36; i+=3.0)
{
TextObj gridlbs = new TextObj((i * 10.0).ToString("0°"), (radius + 10.0) * Math.Cos((i * 10.0 * Math.PI) / 180.0), (radius + 10.0) * Math.Sin((i * 10.0 * Math.PI) / 180.0));
gridlbs.FontSpec.Border.IsVisible = false;
LineObj gridlns = new LineObj(0, 0, radius * Math.Cos((i * 10.0 * Math.PI) / 180.0), radius * Math.Sin((i * 10.0 * Math.PI) / 180.0));
myPane.GraphObjList.Add(gridlbs);
myPane.GraphObjList.Add(gridlns);
}
// Draw circular grid, 5 should look okay
for (double i = (radius / 5.0); i <= radius; i += (radius / 5.0))
{
EllipseObj gridcrl = new EllipseObj(-i, i, 2.0 * i, 2.0 * i);
gridcrl.ZOrder = ZOrder.E_BehindCurves;
myPane.GraphObjList.Add(gridcrl);
}
// Make sure the pane is big enough to fit the labels around the polar plot
myPane.XAxis.Scale.Min = -(radius + 20.0);
myPane.XAxis.Scale.Max = (radius + 20.0);
myPane.YAxis.Scale.Min = -(radius + 20.0);
myPane.YAxis.Scale.Max = (radius + 20.0);
_selectedRadius = radius;
// Keep X & Y axis in the correct ratio to avoid distorting polar circle
myZg_Resize((object)"Startup", EventArgs.Empty);
myZg.Resize += new EventHandler(myZg_Resize);
myZg.ZoomEvent += new ZedGraphControl.ZoomEventHandler(myZg_ZoomEvent2);
// Draw snailly curves (example)
for (int i = 0; i < 360; i++)
{
double r = (double)i/360.0 * radius;
PointPair pt = new PointPair(PointPair.Missing, r, null);
dseries1.Add(pt);
PointPair pt2 = new PointPair(PointPair.Missing, radius - r, null);
dseries2.Add(pt2);
}
// Curves are somple LineItem
FirstCurve = myPane.AddCurve("Snail", dseries1, Color.Blue, SymbolType.None);
SecondCurve = myPane.AddCurve("antiSnail", dseries2, Color.Red, SymbolType.None);
// Rotate the lists to aling with labels
dseries1.Rotation = 0;
dseries2.Rotation = 0;
フォーム/コントロールのサイズが変更されたときにグラフが歪まないようにする必要があったため、これをサイズ変更イベントに追加しました。
protected void myZg_Resize(object sender, EventArgs e)
{
GraphPane pane = myZg.GraphPane;
myZg.AxisChange();
bool IsXMin = ( pane.Rect.Width < pane.Rect.Height ) ? true : false;
if (IsXMin)
{
// Scale based on X (width)
pane.XAxis.Scale.Max = (radius + 20.0); pane.XAxis.Scale.Min = -(radius + 20.0);
double xPixPerUnit = (double)pane.Chart.Rect.Width / (pane.XAxis.Scale.Max - pane.XAxis.Scale.Min);
pane.YAxis.Scale.Max = (double)pane.Chart.Rect.Height / xPixPerUnit / 2.0;
pane.YAxis.Scale.Min = -pane.YAxis.Scale.Max;
myZg.AxisChange();
}
else
{
// Scale based on Y (height)
pane.YAxis.Scale.Max = (radius + 20.0); pane.YAxis.Scale.Min = -(radius + 20.0);
double yPixPerUnit = (double)pane.Chart.Rect.Height / (pane.YAxis.Scale.Max - pane.YAxis.Scale.Min);
pane.XAxis.Scale.Max = (double)pane.Chart.Rect.Width / yPixPerUnit / 2.0;
pane.XAxis.Scale.Min = -pane.XAxis.Scale.Max;
myZg.AxisChange();
}
}
また、ズーム操作からユーザーをブロックすることにしました。
protected void myZg_ZoomEvent2(ZedGraphControl sender, ZoomState oldState, ZoomState newState)
{
myZg_Resize("zoomevent", EventArgs.Empty);
}
出力は次の図のようになります。
提案はいつでも大歓迎です!