C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[1]: Chartのグラフ表示領域をセンタリングさせて表示させたい


(過去ログ 169 を表示中)

[トピック内 2 記事 (1 - 2 表示)]  << 0 >>

■97388 / inTopicNo.1)  Chartのグラフ表示領域をセンタリングさせて表示させたい
  
□投稿者/ takka (1回)-(2021/05/06(Thu) 17:29:59)

分類:[C#] 

WindowsフォームアプリのChartコントロールに対して、以下対応を行いたいです。
・X軸またはY軸の最小値と最大値をいずれか変更したときに、グラフ表示領域をセンタリングさせて表示させたい
(このとき、グリッドラインのアスペクト比は常に1:1(グリッドラインがすべて正方形)の状態を維持させたい)

そこで以下サンプルコードを作成してみましたが、センタリングさせることができませんでした。
以下サンプルコードですと、InnerPlotPositionとPositionの座標関係がわからないため、参考となるサイトや、
他に良い方法があれば教えていただけないでしょうか。宜しくお願い致します。


public partial class Main : Form
{
ChartArea ca;
ElementPosition ipp;

public Main()
{
InitializeComponent();

//初期値(固定)
textBox_xMin.Text = "-40";
textBox_xMax.Text = "40";
textBox_yMin.Text = "-10";
textBox_yMax.Text = "190";

// ElementPositionの初期値(特に指定はありません)
textBox_ElementPositionX.Text = "13";
textBox_ElementPositionY.Text = "0";

// Positionの初期値(特に指定はありません)
textBox_PositionX.Text = "10";
textBox_PositionY.Text = "10";
textBox_PositionWidth.Text = "50";
textBox_PositionHeight.Text = "50";

//描画
DrawGraph(double.Parse(textBox_xMin.Text), double.Parse(textBox_xMax.Text),
double.Parse(textBox_yMin.Text), double.Parse(textBox_yMax.Text), 40);

}

private void DrawGraph(double xMin, double xMax, double yMin, double yMax, double cntDist)
{

int Width = chart2.Size.Width;
int Height = chart2.Size.Height;

chart2.Series.Clear();
chart2.ChartAreas.Clear();
chart2.Titles.Clear();

Series Series0 = new Series
{
ChartType = SeriesChartType.Line,
BorderWidth = 2,
MarkerStyle = MarkerStyle.Circle,
MarkerSize = 2
};
chart2.Series.Add(Series0);
chart2.Series[0].Points.Clear();
chart2.Series[0].Points.AddXY(xMin, 60);
chart2.Series[0].Points.AddXY(xMax, 60);


//---------------------------------
// X軸、Y軸のラベル設定
//---------------------------------
ChartArea ChartArea2 = new ChartArea();
ChartArea2.AxisY.IsReversed = false;
ChartArea2.AxisX.TitleForeColor = Color.Black;
chart2.ChartAreas.Add(ChartArea2);

//グラフのアスペクト比調整
//グラフの「縦:横」が、「2.5:1」の場合に、縦の縮尺と横の縮尺がほぼ同一となるため、以下実装した
// Xの長さとYの長さを求める
double xLen = xMax - xMin;
double yLen = yMax - yMin;

// Xの長さが基準の「80」に対して何%の値か
float xp = (float)(xLen / 80);
xp *= 84; // 初期値:84%

// Yの長さが基準の「200」に対して何%の値か
float yp = (float)(yLen / 200);
yp *= 97; // 初期値:97%

// xpまたはypいずれかが上限値超える場合は調整する
// ypはラベル表示が消えないように100以外の値をセットしている
if (xp > 100 || yp > 98)
{
if (xp > yp)
{
yp *= (98 / xp);
xp = 100;
}
else if (yp > xp)
{
xp *= (100 / yp);
yp = 98;
}
else
{
yp *= (98 / xp);
xp = 100;
}
}

ca = chart2.ChartAreas[0];
ipp = ca.InnerPlotPosition;
ipp.Auto = false;
ipp.Height = yp;
ipp.Width = xp;

  //以下コメントアウト部分のセンタリング対応ではダメだった
//float elementPositionX = 0;
//float elementPositionY = 0;

//if (xLen < 100)
//{
// //0〜99の範囲ではy = (n - 1) * (-0.5) + 49.5の等差数列でセンタリング可能
// //ただし、xLenとyLenの値の組み合わせ次第ではラベルの影響?によりセンタリングとならなかった
// elementPositionX = (float)(((-0.5) * xLen) + 50);
//}
//else
//{
// elementPositionX = 0;
//}

//if (yLen < 200)
//{
// //0〜200の範囲ではy = (n - 1) * (0.5) + 45.5の等差数列でセンタリングとならなかった
// //elementPositionY = (float)(((0.5) * yLen) + 45);
//}
//else
//{
// elementPositionY = 0;
//}

//ipp.X = elementPositionX;
//ipp.Y = elementPositionY;
ipp.X = float.Parse(textBox_ElementPositionX.Text); // 初期値:13pxl
ipp.Y = float.Parse(textBox_ElementPositionY.Text); // 初期値: 0pxl

//---------------------------------
// X軸設定
//---------------------------------
chart2.ChartAreas[0].AxisX.Minimum = xMin;
chart2.ChartAreas[0].AxisX.Maximum = xMax;
chart2.ChartAreas[0].AxisX.Interval = 10;
chart2.ChartAreas[0].AxisX.MajorTickMark.LineWidth = 0;
chart2.ChartAreas[0].AxisX.MajorGrid.LineColor = Color.Silver;

// Minor Grid
chart2.ChartAreas[0].AxisX.MinorGrid.Enabled = true;
chart2.ChartAreas[0].AxisX.MinorGrid.Interval = 2;
chart2.ChartAreas[0].AxisX.MinorGrid.LineColor = Color.WhiteSmoke;

//---------------------------------
// Y軸設定
//---------------------------------
chart2.ChartAreas[0].AxisY.Minimum = yMin;
chart2.ChartAreas[0].AxisY.Maximum = yMax;
chart2.ChartAreas[0].AxisY.Interval = 10;
chart2.ChartAreas[0].AxisY.MajorTickMark.LineWidth = 0;
chart2.ChartAreas[0].AxisY.MajorGrid.LineColor = Color.Silver;

// Minor Grid
chart2.ChartAreas[0].AxisY.MinorGrid.Enabled = true;
chart2.ChartAreas[0].AxisY.MinorGrid.Interval = 2;
chart2.ChartAreas[0].AxisY.MinorGrid.LineColor = Color.WhiteSmoke;


  // センタリング対応
// テキストボックスからPositionを変更するだけではセンタリングがうまくいかなかった
chart2.ChartAreas[0].Position.Auto = false;
chart2.ChartAreas[0].Position.X = float.Parse(textBox_PositionX.Text);
chart2.ChartAreas[0].Position.Y = float.Parse(textBox_PositionY.Text);
chart2.ChartAreas[0].Position.Width = float.Parse(textBox_PositionWidth.Text);
chart2.ChartAreas[0].Position.Height = float.Parse(textBox_PositionHeight.Text);


Series Series1 = new Series
{
ChartType = SeriesChartType.Line,
Color = Color.Red
};
chart2.Series.Add(Series1);
chart2.Series[1].Points.Clear();
chart2.Series[1].Points.AddXY(xMin, cntDist);
chart2.Series[1].Points.AddXY(xMax, cntDist);
}
}
引用返信 編集キー/
■97474 / inTopicNo.2)  Re[1]: Chartのグラフ表示領域をセンタリングさせて表示させたい
□投稿者/ takka (2回)-(2021/05/21(Fri) 13:35:49)
自己解決しました。
修正したコードを載せておきます。
宜しくお願い致します。

        private void DrawGraph(double xMin, double xMax, double yMin, double yMax, double cntDist)
        {
            //---------------------------------
            // クリアする前にアスペクト比調整のためグラフのサイズを取得しておく
            //---------------------------------
            int Width = chart1.Size.Width;
            int Height = chart1.Size.Height;

            chart1.Series.Clear();
            chart1.ChartAreas.Clear();
            chart1.Titles.Clear();

            Series Series0 = new Series
            {
                ChartType = SeriesChartType.Point,
                BorderWidth = 2,
                MarkerStyle = MarkerStyle.Circle,
                MarkerSize = 2
            };
            chart1.Series.Add(Series0);

            //---------------------------------
            // X軸、Y軸のラベル設定
            //---------------------------------
            ChartArea ChartArea1 = new ChartArea();
            ChartArea1.AxisY.IsReversed = false;
            ChartArea1.AxisX.TitleForeColor = Color.Black;
            chart1.ChartAreas.Add(ChartArea1);

            //---------------------------------
            // グラフのアスペクト比調整
            //---------------------------------
            // Chartの表示領域の比とX軸、Y軸の比を元にChartAreaのサイズ(比率)を計算する
            double xLen = xMax - xMin;
            double yLen = yMax - yMin;

            // メモリ数値の表示を考慮しX軸の比率の初期値を84%とする。それをもとに、Y軸の比率を算出する
            float xRate = 0.84F;
            // (Chart幅 × 0.84) ÷ X軸 = (Chart高さ × α) ÷ Y軸
            // ※ Chart幅の84%をX軸で割った値(X軸の1メモリ分のピクセル数)と同じになる比率(α)を求める
            float yRate = ((float)Width / (float)Height) * (float)(yLen / xLen) * xRate;

            // Y軸の比率が97%を超える場合(X軸の比率が84%の場合にY軸が表示しきれない状態)
            if (0.97F < yRate)
            {
                // X軸の比率が84%の際にX軸、Y軸のメモリ数が基準値の場合のY軸の比率を用いる
                // ※ X軸、Y軸の基準値:X=80, Y=200
                yRate = ((float)Width / (float)Height) * (200.0F / 80.0F) * 0.84F;
                // 上記で求めた基準値でのY軸の比率からX軸の比率を算出する
                xRate = ((float)Height / (float)Width) * (float)(xLen / yLen) * yRate;
            }

            // 1メモリのピクセル数が基準値の場合より多い場合(拡大表示される状態)
            if (((float)Width * 0.84F / 80.0F) < ((float)Width * xRate / xLen))
            {
                // 基準値でのピクセル数になる比率を算出する
                xRate = ((float)xLen / 80.0F) * 0.84F;
                yRate = ((float)Width / (float)Height) * (float)(yLen / xLen) * xRate;
            }

            //---------------------------------
            // グラフのセンタリング設定
            //---------------------------------
            // グラフ領域外の半分をマージンとして指定(100分率)
            float xMargin = (1.0F - xRate) / 2.0F;
            float yMargin = (1.0F - yRate) / 2.0F;

            // 以下のようにInnerPlotPositionを直接指定することで、グラフの描画エリアを制御できる
            ChartArea ca = chart1.ChartAreas[0];
            ElementPosition ipp = ca.InnerPlotPosition;
            ipp.Auto = false;
            ipp.Height = yRate * 100;   // 初期値:97 %
            ipp.Width = xRate * 100;    // 初期値:84 %
            ipp.X = xMargin * 100;
            ipp.Y = yMargin * 100;

            //---------------------------------
            // Y軸設定
            //---------------------------------
            chart1.ChartAreas[0].AxisY.Minimum = yMin;
            chart1.ChartAreas[0].AxisY.Maximum = yMax;
            chart1.ChartAreas[0].AxisY.Interval = 10;
            chart1.ChartAreas[0].AxisY.MajorTickMark.LineWidth = 0;
            chart1.ChartAreas[0].AxisY.MajorGrid.LineColor = Color.Silver;

            // Minor Grid
            chart1.ChartAreas[0].AxisY.MinorGrid.Enabled = true;
            chart1.ChartAreas[0].AxisY.MinorGrid.Interval = 2;
            chart1.ChartAreas[0].AxisY.MinorGrid.LineColor = Color.WhiteSmoke;

            //---------------------------------
            // X軸設定
            //---------------------------------
            chart1.ChartAreas[0].AxisX.Minimum = xMin;
            chart1.ChartAreas[0].AxisX.Maximum = xMax;
            chart1.ChartAreas[0].AxisX.Interval = 10;
            chart1.ChartAreas[0].AxisX.MajorTickMark.LineWidth = 0;
            chart1.ChartAreas[0].AxisX.MajorGrid.LineColor = Color.Silver;

            // Minor Grid
            chart1.ChartAreas[0].AxisX.MinorGrid.Enabled = true;
            chart1.ChartAreas[0].AxisX.MinorGrid.Interval = 2;
            chart1.ChartAreas[0].AxisX.MinorGrid.LineColor = Color.WhiteSmoke;

            Series Series1 = new Series
            {
                ChartType = SeriesChartType.Line,
                Color = Color.ForestGreen
            };
            chart1.Series.Add(Series1);
            chart1.Series[1].Points.Clear();
            chart1.Series[1].Points.AddXY(xMin, cntDist);
            chart1.Series[1].Points.AddXY(xMax, cntDist);
        }

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -