반응형
필자는 그래프를 생성하기 위해 아주 가끔 GDI+를 이용하기도 하지만, 주로 ZedGraph를 이용한다. 그런데, 문제는 Log scale로 설정한 X축의 값이 10의 거듭제곱으로 표시되는 Major Tick만 표시가 되고, Minor Tick에는 표시되지 않는다.
이는 아래 그림과 같이 Major Tick이 그래프의 중간에만 표시되거나, 그래프를 확대하여 Major Tick이 그래프의 범위에 있지 않는 경우 X축의 값이 전혀 표시되지 않는 등의 문제를 초래한다.
이에 관한 다른 사용자의 공식 포럼의 질문이 있었고, 개발자는 불가능 하다고 답변 한 바 있다. 이에 궁여지책으로나마 시작, 종료 값만이라도 표시할 수 있는 방법을 공유하고자 한다.
아래와 같이 선언되는 이벤트 핸들러를 이용한다.
public event Axis.Axis.ScaleFormatHandler ScaleFormatEvent
ScaleFormatHandler는 아래와 같이 정의된다.
public delegate string ScaleFormatHandler(
GraphPane pane,
Axis axis,
double val,
int index
)
Parameters
- pane (GraphPane) : The GraphPane for which the label is to be formatted
- axis (Axis) : The Scale of interest.val (Double)The value to be formatted
- index (Int32) : The zero-based index of the label to be formatted
Return Value
A string value representing the label, or null if the ZedGraph should go ahead and generate the label according to the current settings
기존 코드에 아래와 같은 코드를 추가하여 이벤트를 선언하고,
zGraph.GraphPane.XAxis.ScaleFormatEvent += new ZedGraph.Axis.ScaleFormatHandler(ZedGraph_XAxis_ScaleFormatEvent);
이벤트 핸들러는 다음과 같이 구현한다.
string ZedGraph_XAxis_ScaleFormatEvent(ZedGraph.GraphPane pane, ZedGraph.Axis axis, double val, int index)
{
// 시작 주파수를 표시한다.
pane.GraphObjList.Clear();
double x_min = pane.XAxis.Scale.Min;
int x_min_n = Exponentiation_Get(x_min);
string x_min_text = DoubleToPrefix(Convert.ToDouble((x_min / Math.Pow(10, x_min_n)).ToString("0.000")), x_min_n);
var x_min_text_obj = new ZedGraph.TextObj(x_min_text, 0.0, 1.026, ZedGraph.CoordType.ChartFraction, ZedGraph.AlignH.Center, ZedGraph.AlignV.Top);
x_min_text_obj.ZOrder = ZedGraph.ZOrder.A_InFront;
x_min_text_obj.FontSpec.Size = pane.XAxis.Scale.FontSpec.Size;
x_min_text_obj.FontSpec.Border.Color = pane.Fill.Color;
x_min_text_obj.FontSpec.Fill.Color = pane.Fill.Color;
x_min_text_obj.FontSpec.Border.Width = 0;
pane.GraphObjList.Add(x_min_text_obj);
// 종료 주파수를 표시한다.
double x_max = pane.XAxis.Scale.Max;
int x_max_n = Exponentiation_Get(x_max);
string x_max_text = DoubleToPrefix(Convert.ToDouble((x_max / Math.Pow(10, x_max_n)).ToString("0.000")), x_max_n);
var x_max_text_obj = new ZedGraph.TextObj(x_max_text, 1, 1.026, ZedGraph.CoordType.ChartFraction, ZedGraph.AlignH.Center, ZedGraph.AlignV.Top);
x_max_text_obj.ZOrder = ZedGraph.ZOrder.A_InFront;
x_max_text_obj.FontSpec.Size = pane.XAxis.Scale.FontSpec.Size;
x_max_text_obj.FontSpec.Border.Color = pane.Fill.Color;
x_max_text_obj.FontSpec.Fill.Color = pane.Fill.Color;
x_max_text_obj.FontSpec.Border.Width = 0;
pane.GraphObjList.Add(x_max_text_obj);
return DoubleToPrefix(1, val);
}
private int Exponentiation_Get(double val)
{
if (val >= Math.Pow(10, 24)) return 24;
if (val >= Math.Pow(10, 21)) return 21;
if (val >= Math.Pow(10, 18)) return 18;
if (val >= Math.Pow(10, 15)) return 15;
if (val >= Math.Pow(10, 12)) return 12;
if (val >= Math.Pow(10, 9)) return 9;
if (val >= Math.Pow(10, 6)) return 6;
if (val >= Math.Pow(10, 3)) return 3;
return 0;
}
private string DoubleToPrefix(double c, double n)
{
if (n >= 24) return String.Format("{0}Y", c * Math.Pow(10, n) / Math.Pow(10, 24));
if (n >= 21) return String.Format("{0}Z", c * Math.Pow(10, n) / Math.Pow(10, 21));
if (n >= 18) return String.Format("{0}E", c * Math.Pow(10, n) / Math.Pow(10, 18));
if (n >= 15) return String.Format("{0}P", c * Math.Pow(10, n) / Math.Pow(10, 15));
if (n >= 12) return String.Format("{0}T", c * Math.Pow(10, n) / Math.Pow(10, 12));
if (n >= 9) return String.Format("{0}G", c * Math.Pow(10, n) / Math.Pow(10, 9));
if (n >= 6) return String.Format("{0}M", c * Math.Pow(10, n) / Math.Pow(10, 6));
if (n >= 3) return String.Format("{0}K", c * Math.Pow(10, n) / Math.Pow(10, 3));
return String.Format("{0}", c * Math.Pow(10, n) / Math.Pow(10, 1));
}
코드 해석은 각자 해보길 바라며, 위 코드는 Zoom In/Out 및 Pan 등의 이벤트에 모두 대응된다.
반응형
'윈도우프로그래밍' 카테고리의 다른 글
[C#] PictureBox에 이미지 표시하기 (feat. MemoryStream) (3) | 2021.05.23 |
---|---|
[C#] 반복루프를 사용하지 않고 배열 및 리스트의 각 원소를 연산하는 방법 (0) | 2020.08.23 |
[C#] 구조체 리스트 항목 검색하기 (0) | 2020.06.26 |
[VB] 구조체 리스트 항목 검색하기 (0) | 2020.06.26 |
Visual Studio 2017 탐색 모음 표시 (2) | 2018.11.14 |
Visual Studio Installer HRESULT -2147024769 에러 해결방법 (0) | 2018.06.07 |
"Resources" 매개 변수에 두 번 이상 지정했습니다. 오류 (0) | 2018.05.24 |
[C#] DataGridView의 ComboBoxColumn 값이 변경된 후 이벤트 처리하기 (0) | 2018.03.19 |