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

わんくま同盟

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

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


(過去ログ 164 を表示中)
■94971 / )  対数グラフをリニアに戻すとエラーとなる
□投稿者/ 還暦おやじkuma (1回)-(2020/06/07(Sun) 22:06:20)

分類:[C#] 

C#を始めて3年目の初心者(還暦おやじkuma)です。長文すみません。

**環境:Windows10 ver.1909, Intel Core i5, RAM 8GB,x64,
Visual Studio Express 2013 for Windows Desktop, C# 5.0, NetFramework 4.5
(Community2017,2019系は会社の都合で入れることができませんので古い環境でやっています)

**疑問点:アプリを実行してChartType=Lineでリニアグラフが描かれ、チェックボックスでX軸を対数表示にすることまではできますが、もう1度チェックボックスをクリックしてグラフを再描画してリニアに戻そうとするとエラーとなります。描画ルーチンのtry-catchでは引っ掛かりません。
原因と解決方法がお分かりでしたらご教示いただけますでしょうか?。

**補足:
・デザイナーではlog_checkBoxという名前のCheckBoxを1つ追加してあるだけで、他はデフォルトのままです。

・X軸のデータmydataXの[0]に意図的に0.00を入れてありますが、対数グラフを描画する際には飛ばすようにしています。もっとも、元データの0.00を1.10とかにしても結果は同じエラーとなりますが。

**エラーメッセージ:
「追加情報:軸オブジェクト - 対数グラフでは、負の値または 0 を正しくプロットできません。対数スケールで解釈できるのは正の値だけです。」
と出ますが、もともと負の値は無く、0も回避するようにしているのと、1度目は対数で描画できているので、意味が分かりません。

・dobon.netさんの「捕捉されなかった例外がスローされたことを知る」
http://dobon.net/vb/dotnet/programing/unhandledexception.html
を参考に、MainにThreadExceptionイベントハンドラを入れてみましたが、
Message = 軸オブジェクト - 対数グラフでは、負の値または 0 を正しくプロットできません。対数スケールで解釈できるのは正の値だけです。
パラメーター名:minimumValue
Source = System.Windows.Forms.DataVisualization
TypeName = ArgumentOutOfRangeException
StackTrace =    場所 System.Windows.Forms.DataVisualization.Charting.Axis.EstimateLogarithmicAxis(Double& minimumValue, Double& maximumValue, Double crossingValue, Boolean autoMaximum, Boolean autoMinimum)
 以下、場所がずらずらと。
と出るため、私には原因が分かりませんでした。

パラメーター名:minimumValueは
「this.chart1.ChartAreas[0].AxisX.Minimum = 1.0;//対数表示にはこれが必要」
としてあるのですが、どうもこれのことではないような・・・。

= = = = = = = = = = = = Form1ソース= = = = = = = = = = = = = = = = 
using はデフォルトのままなので省略
namespace LogGraphTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        //以下は、もともとは別のクラスで読み込むデータだが質問のサンプルとしてここに書いているだけ。
        static public double[] mydataX = new double[] { 0.00, 3.02, 3.91, 32.66, 141.51, 251.45, 461.08, 771.34, 801.49, 911.34, 1000.00 };//意図的に[0]に0を入れてある。
        static public double[] mydataY1 = new double[] { 102.14, 92.08, 53.44, 46.56, 78.27, 49.20, 103.60, 48.33, 29.83, 71.15, 7.22 };

        drawGraph form_graph = new drawGraph();//もともとは別のクラスからも呼び出しているがサンプルとしてここにこう書いているだけ。


        private void Form1_Load(object sender, EventArgs e)
        {
            form_graph.Left = this.Right;
            form_graph.Top = this.Top;
            form_graph.StartPosition = FormStartPosition.Manual;
            form_graph.Show();

        }
    }
}
= = = = = = = = = = = = drawGraphソース= = = = = = = = = = = = = = = = 
using はデフォルトのものは省略
using System.Windows.Forms.DataVisualization.Charting;//追加した
using System.Diagnostics;//try-catchの結果を出力に出すために追加した

namespace LogGraphTest
{
    public partial class drawGraph : Form
    {
        public drawGraph()
        {
            InitializeComponent();
        }

        static bool isGraphLog = false;//テスト用に初期値を入れ替えるためにここに記載

        private void drawGraph_Load(object sender, EventArgs e)
        {
            chart1.ChartAreas[0].CursorX.IsUserEnabled = true;
            chart1.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
            chart1.ChartAreas[0].AxisX.ScaleView.Zoomable = true;

            drawDataGraph();
            log_checkBox.Checked = isGraphLog;
        }

        public void drawDataGraph()
        {
            try
            {
                chart1.Series.Clear();//log_checkBoxをクリックしたときにdrawDataGraph()を再描画するために過去のSeriesをクリアする
                if (isGraphLog)
                {
                    this.chart1.ChartAreas[0].AxisX.Minimum = 1.0;//対数表示にはこれが必要
                }
                else
                {
                    this.chart1.ChartAreas[0].AxisX.Minimum = 0.0;//リニア表示にはこれが必要
                }

                if (isGraphLog)
                {
                    chart1.ChartAreas[0].AxisX.IsStartedFromZero = false;//対数表示にはこれが必要か?、データも0を含んでいてはいけないが
                    chart1.ChartAreas[0].AxisX.IsLogarithmic = true;
                }

                Series[] dseries = new Series[2];//もともと複数のデータ系列があったため配列として[2]としてあるが、このサンプルでは1つなので意味は無い。
                dseries[0] = new Series();
                dseries[0].ChartType = SeriesChartType.Line;
                dseries[0].Name = "DataY1";
                dseries[0].Color = Color.Black;
                this.chart1.Series.Add(dseries[0]);

                int startData = 0;
                if (isGraphLog) { startData = 1; }//Logの時はデータがx=0である[0]を飛ばしている。このためLogのグラフが描ける、のでは?
                for (int i = startData; i < 11; i++)
                {
                    chart1.Series[dseries[0].Name].Points.AddXY(Form1.mydataX[i], Form1.mydataY1[i]);
                }
            }
            catch (System.Exception ex)
            {
                Debug.WriteLine("Message = " + ex.Message);
                Debug.WriteLine("Source = " + ex.Source);
                Debug.WriteLine("StackTrace = " + ex.StackTrace);
                throw;//例外を再スローする
            }
        }

        private void log_checkBox_CheckedChanged(object sender, EventArgs e)
        {
            if (log_checkBox.Checked)// isGraphLog = log_checkBox.Checkedとも書けると思うが念のために細かく書いた。
            {
                isGraphLog = true;
            }
            else
            {
                isGraphLog = false;
            }
            drawDataGraph();
        }
    }
}
= = = = = = = = = = = = ソースはここまで= = = = = = = = = = = = = = = = 
すみませんが、ご教示よろしくお願いいたします。

返信 編集キー/


管理者用

- Child Tree -