今、Chartを使って折れ線グラフを書いているのですが、
どうもなめらかな曲線になりません。
なにか、よい方法はないのでしょうか?
「折れ線」というものは、そもそも「なめらかな曲線」とは違うものでは?
Chartを使用せず、自前で描画ならば方法はいくらでもあるのですが・・・。
TChartは良くわかりませんが、データ数を増やして曲線っぽく見せるのはどうでしょう。
例えば、実際のデータ数が5つだとするグラフのデータ数を50に設定します。実際のデータを10おきに設定してその間に中間データを設定すれば、一応曲線っぽく見えるのではないか思います。
安直な方法かもしれませんが、参考までに...
にしのさん、お返事ありがとうございます。
TChart以外でどういった方法があるのでしょうか?
プログラムで、グラフを曲線にして、TCanvasに表示すればよいでしょう。
理恵さんへ、
解決すればチェックしましょう。
Delphi WorldのMiscellaneous に補間用のコンポーネントがあるので,
これを使って,スプライン補間を行えば曲線がかけると思います。
私も使ったことがありますが,処理は結構高速でした。
HOotaさんお返事ありがとうございます。
グラフを曲線にするにはどのようにすればよいのでしょうか?
理恵さんへ,
失礼ですが,理恵さんには,もう少しグラフや曲線を描くとか
Canvasについても知識が必要なのではないかと思います.
グラフという言葉にはいくつかの意味があります.
棒グラフや円グラフのグラフです.理恵さんが描きたいのは,関数曲線の
ようなものではないかと思います.だと仮定します.
(正確な説明ではないのですが)
実は,コンピュータでは関数などの曲線(関数のグラフとも言いますが,
ここでは棒グラフ等と区別するため)は,基本的に,自在定規や雲型定規を
使用する時のように描けないのです.既にCanvas(FormでもChartのあるいは
Printerのでもいいです)に座標が決められているとします.
つまり,Canvas上に方眼用紙が準備されていると思って下さい.ここに
y=x*x (二次関数)
の曲線を描くことを想像して下さい.以下の2点を計算します.
x y
-2 4
0 0
2 4
この3点を直線で結んだ状況を想像して下さい.とても2次関数の曲線には
見えませんよね.そこで,今度は計算の間隔を変更して,
x y
-2 4
-1.8 3.24
-1.6 2.56
と細かく計算して,また直線で結んだ状況を想像して下さい.今度は
曲線らしく見えてきます.つまり,細かく計算すれば曲線に見えるんで
す.この計算の間隔は,その人の目的により変更する必要があります.
例えば,私はx=0.05から0.10の間を詳しく見たいのだ.と言う場合は,
xの間隔を変更する必要があります.
待って下さい.私の場合関数はわからないのです.実験データを滑らかに
描きたいのです.という場合はFutaさんのようにスブライン関数などを
使用します.そうすると
http://homepage2.nifty.com/Mr_XRAY/PC-9801/SPTest.htm
な感じで曲線を描くことが可能となります.
それから,先程の方眼用紙が設定されていたと仮定したことです.
画面では,コンピュータでは,基本的にピクセル(ドット)単位の座標値
を扱います.例えばCRTの横が1024ドットの画面に先程の2次関数曲線を,
画面いっぱいに描きたいとします.
そんなときは,x=-2の時は画面の一番左がx-0,右か2となるように換算
しながら描画するわけです.Win32 APIにはこれを自動的に行う関数もあ
りますが,基本的には換算です.
少し長くなりましたが,何だか会話がズレているようなので,出しゃばり
ました.
そんなこと分かってますよ!! 失礼な!1 と気を悪くしたらごめんなさい.
しつこいようですが,
>りますが,基本的には換算です.
実は人が方眼用紙などに曲線を描くときも同じような換算をしています.
「x座標の一番左が-2だから,2cm右は-1.5だな...」
とか,でもコンピュータで描く時は,意識的に換算の計算を行う必要が
あるということです.
Delphiのコントロール(コンポーネント)にはCanvasをもつものがあります.
Form,Image,StringGrid等など,Canvasには描画用のいろいろな描画用のメ
ソッドが用意されています.
直線,円,楕円等など.
これらの機能を使用して,人が方眼用紙に座標軸を作成し,曲線を描く
のと同じ作業を,プログラムのコードとして書くことになるわけです.
Mr.XARY さんお返事ありがとうございます。
スプライン補間を使って見たのですが同じような結果になりました。
Chartで滑らかな曲線をかくのは、不可能なのでしょうか?
>スプライン補間を使って見たのですが同じような結果になりました。
>Chartで滑らかな曲線をかくのは、不可能なのでしょうか?
ChartそのものだってCanvasに描いているわけですから,
原理的には可能はなはずだと思いますが...
現実のデータと補間点数をどのくらいにしたのかが不明だと,これ以上
はちょっと何とも...
それとどうしてもChartでやる必要があるのかも検討してみてはいかが
でしょか.
最終目的が一体なんなのかもよくわかりませんので.
私は勝手に,2次元の実験データの測定点など結ぶ曲線を描きたいと思った
んですが(自在定規を使用した場合のように).
理恵さんのいわれる「滑らかな曲線」というのが見えてきません.
Mr.XRAYさんお返事ありがとうございます。
Mr.XRAY産の言われたとうり
2次元の実験データの測定点など結ぶ曲線を描きたいのですが
Chartで描いたほうが、座標で点を決めることができるので
よいかとおもったもですが、以下のようなスプライン補間の
プログラムを書いたのですが、プログラムに問題があるのでしょうか?
Var
NDiv:integer;
XDiv: double;
Q1:double;
H1:double;
P1:double;
E1:double;
Xs,Ys1,Ys2,Ys3: PDArray; // pointer to array of double;
Ns: integer;
begin
Chart1.Series[1].clear;
Chart2.Series[1].clear;
Chart4.Series[1].clear;
Ns:=200; // 節点の個数
GetMem( Xs, Ns*8);
GetMem( Ys1, Ns*8);
GetMem( Ys2, Ns*8);
GetMem( Ys3, Ns*8);
Case ComboBox1.ItemIndex of // 補間法を設定
0: Interpolate1.Method:=Linear;
1: Interpolate1.Method:=Square;
2: Interpolate1.Method:=CSpline;
end;
Case ComboBox2.ItemIndex of // 補間法を設定
0: Interpolate1.Method:=Linear;
1: Interpolate1.Method:=Square;
2: Interpolate1.Method:=CSpline;
end;
Case ComboBox1.ItemIndex of // 補間法を設定
0: Interpolate3.Method:=Linear;
1: Interpolate3.Method:=Square;
2: Interpolate3.Method:=CSpline;
end;
For i:=1 to Ns do
begin
Xs[i]:=i;
Ys1[i]:=(3*Power(Xs[i],3))+(2*Power(Xs[i],2))+(0.2*Xs[i])+6;
Ys2[i]:=(3*Power(Xs[i],3))+(0.45*Power(Xs[i],2))+(0.03*Xs[i])+6;
Ys3[i]:= 16.3 * Xs[i] * Ys1[i] / Ys2[i]*8 ;
end;
Interpolate1.DKnot( Ns, Xs, Ys1 );
Interpolate2.DKnot( Ns, Xs, Ys2 );
Interpolate3.DKnot( Ns, Xs, Ys3 );
NDiv:=StrToInt(Edit1.Text);
XDiv:=(Xs[Ns]-Xs[1])/NDiv;
for i:=0 to NDiv do
begin
Q1:=XDiv*i;
H1:=Interpolate1.Value(Q1) ; //与えられたX値に対する補間値を計算する
P1:=Interpolate2.Value(Q1) ;
E1:=Interpolate3.Value(Q1) ;
Chart1.Series[1].AddXY(Q1,H1);
Chart2.Series[1].AddXY(Q1,P1);
Chart4.Series[1].AddXY(Q1,E1);
end;
end;
親切な助言に全く耳を貸さず、自分の質問をしつづけるあたり・・・
補間用コンポーネントTInterpolateで遊んでみました。
procedure TForm1.Button1Click(Sender: TObject);
var
NDiv,Ns,i: Integer;
XDiv: double;
X,Y: array[1..6] of double;
begin
Chart1.Series[0].Clear;
Chart1.Series[1].Clear;
Interpolate1.Method := CSpline;
Interpolate1.Interval := Regular;
Ns := 6;
for i:=1 to Ns do begin
X[i] := i;
Y[i] := (3*Power(X[i],3))+(0.45*Power(X[i],2))+(0.03*X[i])+6;
Chart1.Series[0].AddXY(X[i],Y[i]);
end;
NDiv := 1000;
XDiv := (X[Ns]-X[1])/NDiv;
Interpolate1.DKnot(Ns,@X,@Y);
for i:=0 to NDiv do
Chart1.Series[1].AddXY(XDiv*i,Interpolate1.Value(XDiv*i));
end;
それらしく「滑らかな曲線」になっていると
わたしなりには思うんですけど。。。
私も通りすがりさんのコードをコピーしてやって見ました.
> Interpolate1.DKnot(Ns,@X,@Y);
> for i:=0 to NDiv do
> Chart1.Series[1].AddXY(XDiv*i,Interpolate1.Value(XDiv*i));
十分滑らかなではないかと思います.
皆さん、考えすぎかもしれませんでした。
今表示させた曲線をきれいに印刷する方法はありますか?
今表示させた曲線をそのままきれいに印刷できません。
ご教授おねがいします。
そのままCanvasに描けばok
ツイート | ![]() |