ページ 11

グラデーション作り

Posted: 2011年12月08日(木) 10:18
by oubon
Visual C++ 2008 Express Editionを用いてグラデーションを作りたいのですが、どうすればいいのでしょうか。

Re: グラデーション作り

Posted: 2011年12月08日(木) 10:32
by beatle
これでもかというぐらい質問が大雑把で真意が掴めないのですが、
とりあえずVisual C++ 2008をたくさん起動させて、少しずつウィンドウをずらしておき、
Print Screenキーでスクリーンショットを撮影すれば、なんとなくグラデーションになる
ような気がします。

Re: グラデーション作り

Posted: 2011年12月08日(木) 11:47
by naohiro19
oubon さんが書きました:Visual C++ 2008 Express Editionを用いてグラデーションを作りたいのですが、どうすればいいのでしょうか
フォーラムルールをご覧ください。

Re: グラデーション作り

Posted: 2011年12月08日(木) 12:44
by oubon
説明不足で申し訳ありません。

半無限棒の先端を熱したときの温度分布を、ピクチャーボックスの中でグラデーションを用いて表したいのです。

以下に詳細を示します。

棒の先端から長手方向にX軸をとり、Dを棒の直径[m]、hを熱伝達係数[J/K・m^2・s]、kを熱伝導率[J/K・m・s]、
さらに棒の先端を熱したときの温度をT1[K]、外気温度をT0[K]とすると、半無限棒の温度T[K]は
Xの関数として表され、

T(X) = T0 + (T1 - T0) × exp(-2 × √(h/k×D) × X)       (1)

となり、熱したときのT1[K]は、先端から離れるにしたがって指数関数的に外気温度T0[K]に収束していきます。
さらに、(1)の左辺を無次元化すると、

(T(X) - T0)/(T1 - T0) = exp(-2 × √(h/k×D) × X)       (2)

となります。今回は(2)を用います。

まず、(2)を指数関数のグラフとしてピクチャーボックスに表示させようと作ったプログラムが以下の通りです。

ただし、√(h/k×D) = p1~p3 とおき、この値が変わることによってグラフが変化することを色別に表しています。
また、y1~y6はグラフが見やすくなるようにわざと大きめの数字(ここでは300)を掛けています。
さらに、T1 = 300[K] 、T0 = 20[K]としています。
_____________________________________________________________________________________________
#pragma once

#include<windows.h>
#include<math.h>
#include<stdio.h>

namespace 熱伝導 {

using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;

/// <summary>
/// Form1 の概要
///
/// 警告: このクラスの名前を変更する場合、このクラスが依存するすべての .resx ファイルに関連付けられた
/// マネージ リソース コンパイラ ツールに対して 'Resource File Name' プロパティを
/// 変更する必要があります。この変更を行わないと、
/// デザイナと、このフォームに関連付けられたローカライズ済みリソースとが、
/// 正しく相互に利用できなくなります。
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
//
//TODO: ここにコンストラクタ コードを追加します
//
}

protected:
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
~Form1()
{
if (components)
{
delete components;
}
}
private: System::Windows::Forms::PictureBox^ pictureBox1;
protected:

private:
/// <summary>
/// 必要なデザイナ変数です。
/// </summary>
System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
void InitializeComponent(void)
{
this->pictureBox1 = (gcnew System::Windows::Forms::PictureBox());
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->pictureBox1))->BeginInit();
this->SuspendLayout();
//
// pictureBox1
//
this->pictureBox1->Location = System::Drawing::Point(0, -1);
this->pictureBox1->Name = L"pictureBox1";
this->pictureBox1->Size = System::Drawing::Size(991, 545);
this->pictureBox1->TabIndex = 0;
this->pictureBox1->TabStop = false;
this->pictureBox1->Click += gcnew System::EventHandler(this, &Form1::pictureBox1_Click);
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 12);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(1028, 578);
this->Controls->Add(this->pictureBox1);
this->Name = L"Form1";
this->Text = L"Form1";
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->pictureBox1))->EndInit();
this->ResumeLayout(false);

}
#pragma endregion
private: System::Void pictureBox1_Click(System::Object^ sender, System::EventArgs^ e) {

//ピクチャボックスと同じ大きさのBitmapを作成
Bitmap^ bmp = gcnew Bitmap(pictureBox1->Width, pictureBox1->Height);

pictureBox1->Image = bmp;

//ピクチャボックスからGraphicsの作成
Graphics^ G = Graphics::FromImage(pictureBox1->Image);

//ピクチャボックスの背景色でクリアする。
G->Clear(pictureBox1->BackColor);


//熱した丸棒の温度分布//

int x;
double p=0.1;
double p1=1;
double p2=0.01;
double T0=20; //外気の温度//
double T1=300; //熱したときの温度//
double E=2.71828; //自然対数の底//
int A=1; //xの刻み//


for(x=0;x<=1000;x=x+A){

int Tx1=(T1-T0)*pow(E,-p*x)+T0;
int Tx2=(T1-T0)*pow(E,-(p*x+p*A))+T0;
int y1=300*(Tx1+T0)/(T1-T0);
int y2=300*(Tx2+T0)/(T1-T0);

int Tx3=(T1-T0)*pow(E,-p1*x)+T0;
int Tx4=(T1-T0)*pow(E,-(p1*x+p1*A))+T0;
int y3=300*(Tx3+T0)/(T1-T0);
int y4=300*(Tx4+T0)/(T1-T0);

int Tx5=(T1-T0)*pow(E,-p2*x)+T0;
int Tx6=(T1-T0)*pow(E,-(p2*x+p2*A))+T0;
int y5=300*(Tx5+T0)/(T1-T0);
int y6=300*(Tx6+T0)/(T1-T0);



//グラフの描画
G->DrawLine(Pens::Green, x, y1, x+A, y2);
G->DrawLine(Pens::Red, x, y3, x+A, y4);
G->DrawLine(Pens::Blue, x, y5, x+A, y6);

}

}
};
}
_____________________________________________________________________________________________


これで一応、指数関数のグラフを作ることはできたのですが、今度はこの結果をグラデーションとして
表示させたいのです。(熱せられた先端を赤く、そこから離れるにしたがって指数関数的に青くなっていくような)

いろいろ試してみたのですが、全くやり方がわからず、ここで相談した次第です。
まだC++を初めて間もなく、無知で未熟な点が多々ありますが、ご協力いただけたら幸いです。

Re: グラデーション作り

Posted: 2011年12月08日(木) 12:54
by softya(ソフト屋)
codeタグをご利用下さい。詳しくはフォーラムルールに書いてありますので必ず読んでくださいね。 http://dixq.net/board/board.html
使用環境はVisualC++2010?のウィンドウズ・フォーム(C++/CLI)って事ですね?
とりあえず、フォームの部分が分からないとこちらで実行できませんね。
とりあえずフォーム名は熱伝導で動きましたが、今現在のコードの意味が良く分かりません。グラフに見えますが。

[追記]インデント(字下げ)がでたらめなので、まず整形と描画している物を説明したソース・コメントをお願いします。
つまり、
//グラフの描画
では説明になっていないので、どういうグラフなのかをコメントに書いて下さい。

コード:

#pragma once

#include<windows.h>
#include<math.h>
#include<stdio.h>

namespace 熱伝導 {

	using namespace System;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Drawing;

	/// <summary>
	/// Form1 の概要
	///
	/// 警告: このクラスの名前を変更する場合、このクラスが依存するすべての .resx ファイルに関連付けられた
	///          マネージ リソース コンパイラ ツールに対して 'Resource File Name' プロパティを
	///          変更する必要があります。この変更を行わないと、
	///          デザイナと、このフォームに関連付けられたローカライズ済みリソースとが、
	///          正しく相互に利用できなくなります。
	/// </summary>
	public ref class Form1 : public System::Windows::Forms::Form
	{
	public:
		Form1(void)
		{
			InitializeComponent();
			//
			//TODO: ここにコンストラクタ コードを追加します
			//
		}

	protected:
		/// <summary>
		/// 使用中のリソースをすべてクリーンアップします。
		/// </summary>
		~Form1()
		{
			if (components)
			{
				delete components;
			}
		}
	private: System::Windows::Forms::PictureBox^  pictureBox1;
	protected: 

	private:
		/// <summary>
		/// 必要なデザイナ変数です。
		/// </summary>
		System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
		/// <summary>
		/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
		/// コード エディタで変更しないでください。
		/// </summary>
		void InitializeComponent(void)
		{
			this->pictureBox1 = (gcnew System::Windows::Forms::PictureBox());
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->pictureBox1))->BeginInit();
			this->SuspendLayout();
			// 
			// pictureBox1
			// 
			this->pictureBox1->Location = System::Drawing::Point(0, -1);
			this->pictureBox1->Name = L"pictureBox1";
			this->pictureBox1->Size = System::Drawing::Size(991, 545);
			this->pictureBox1->TabIndex = 0;
			this->pictureBox1->TabStop = false;
			this->pictureBox1->Click += gcnew System::EventHandler(this, &Form1::pictureBox1_Click);
			// 
			// Form1
			// 
			this->AutoScaleDimensions = System::Drawing::SizeF(6, 12);
			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
			this->ClientSize = System::Drawing::Size(1028, 578);
			this->Controls->Add(this->pictureBox1);
			this->Name = L"Form1";
			this->Text = L"Form1";
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->pictureBox1))->EndInit();
			this->ResumeLayout(false);

		}
#pragma endregion
	private: System::Void pictureBox1_Click(System::Object^  sender, System::EventArgs^  e) {

//ピクチャボックスと同じ大きさのBitmapを作成
Bitmap^ bmp = gcnew Bitmap(pictureBox1->Width, pictureBox1->Height);

pictureBox1->Image = bmp;
   
//ピクチャボックスからGraphicsの作成
Graphics^ G = Graphics::FromImage(pictureBox1->Image);

//ピクチャボックスの背景色でクリアする。
G->Clear(pictureBox1->BackColor);


//熱した丸棒の温度分布//

int x;
double p=0.1;
double p1=1;
double p2=0.01;
double T0=20; //外気の温度//
double T1=300; //熱したときの温度//
double E=2.71828; //自然対数の底//
int A=1; //xの刻み//


for(x=0;x<=1000;x=x+A){

	int Tx1=(T1-T0)*pow(E,-p*x)+T0;
	int Tx2=(T1-T0)*pow(E,-(p*x+p*A))+T0;
	int y1=300*(Tx1+T0)/(T1-T0);
	int y2=300*(Tx2+T0)/(T1-T0);

    int Tx3=(T1-T0)*pow(E,-p1*x)+T0;
	int Tx4=(T1-T0)*pow(E,-(p1*x+p1*A))+T0;
	int y3=300*(Tx3+T0)/(T1-T0);
	int y4=300*(Tx4+T0)/(T1-T0);

    int Tx5=(T1-T0)*pow(E,-p2*x)+T0;
	int Tx6=(T1-T0)*pow(E,-(p2*x+p2*A))+T0;
	int y5=300*(Tx5+T0)/(T1-T0);
	int y6=300*(Tx6+T0)/(T1-T0);



//グラフの描画
G->DrawLine(Pens::Green, x, y1, x+A, y2);
G->DrawLine(Pens::Red, x, y3, x+A, y4);
G->DrawLine(Pens::Blue, x, y5, x+A, y6);

}

			 }
	};
}

Re: グラデーション作り

Posted: 2011年12月08日(木) 13:19
by softya(ソフト屋)
とりあえずグラデーションで棒の作り方説明。

DrawLineが使えていますのでこれで棒の形に描画することが出来ますか?
Lineを一定の長さで連続で引いて横にずらしていけば棒の形になります。
この時にPens::BlueやPens::Redを使わずに色を自分で計算すれば良いわけです。

[補足]Penクラスで色を作れば良いのですがやり方は分かりますでしょうか?
私もC++/CLIのフォームには詳しくないのでココが分かりやすというのが紹介できなくてすいません。Win32APIやMFCなら分かるのですが。

ここかな?
「Pen クラス」
http://msdn.microsoft.com/ja-jp/library ... S.80).aspx

Re: グラデーション作り

Posted: 2011年12月08日(木) 13:43
by oubon
すみませんでした。

教えていただいたURLも参考にしつつ、他にも色々漁って、もうちょっとこちらで粘ってみようと思います。

親切な回答、本当にありがとうございます。