曲線の描画について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ゆうき

曲線の描画について

#1

投稿記事 by ゆうき » 16年前

初めまして、C言語初心者の「ゆうき」と申します。

お仕事で複数の円弧を接続して描画させるというプログラムを考えています。
既知な値は、1)円弧の長さ 2)円弧の半径 3)描画開始点のみです。

現在「Borand C++」と「BCC developer」でプログラムの練習中です。
いろいろと調べ、「GrWinグラフィックス・ライブラリ」を入れてみたのですが、
半径を指定して描画することができないようで、何か良い方法が無いかと考えております。

詳しくは、添付ファイルを確認して頂きたいのですが、そもそもC言語でこのようなことが可能なのでしょうか?
※実際の数値も記入しましたので、実際にプログラムしていただけると幸いです。

よろしくお願いいたします。

lbfuvab

Re:曲線の描画について

#2

投稿記事 by lbfuvab » 16年前

ん~、手順的には
区間A,Bの開始点をa,bとすると
①a,bから半径分はなれている点を求める(二つ)
②どちらに凸かで中心点を確定
③円が外接する正方形の頂点を出す(二つ)。
④aの角度を出す(x軸方向との)
⑤bの角度を出す(aとの)

でGWarc使って頑張ってください。

ゆうき

Re:曲線の描画について

#3

投稿記事 by ゆうき » 16年前

lbfuvabさん、返信ありがとうございます。

早速GWarcを使って円弧の接続を行いました。
しかしながら、GWarcでは円弧の描画だけで、
後々の両端直線との距離を計算できないことが分かりました。
※勉強にはなりました・・・。

そこで、円弧上の座標を0.1mm刻みで描画していくGWsetpxlを使って
座標の取得と描画を行うことにしました。

1区間中の描画は繰り返し(while ~区間末端まで)を使って、
区間描画が済むと次の区間に移るようにし、
連続した円弧の描画ができるようになったのですが、
変数が常に更新されているので、任意座標の再取得ができませんでした。

そこで、座標が更新される前にどこかにメモ(プログラム中の変数orCSVに書き込み)して
最後に任意座標を読み込むようなロジックを組み込みたいのですが、
そのようなことは可能でしょうか?

アドバイスいただけると幸いです。

lbfuvab

Re:曲線の描画について

#4

投稿記事 by lbfuvab » 16年前

直線距離を出すならΔx^2 + Δy^2 = d^2で(Δxはx座標の距離、Δyはy座標での距離、dは距離)
弧の長さならr * θで出ませんか?(rは半径、θは角度)

ゆうき

Re:曲線の描画について

#5

投稿記事 by ゆうき » 16年前

lbfuvabさん、毎回返信くださりありがとうございます。

ええと、正確に何をしたいのかと言いますと、

1) 円弧が複数連なった曲線があり、
2) その両端(描画開始点と描画終了点)を直線で結びます。
3) 任意に曲線状の点を選び、
4) その点から直線までの距離(垂線)を計算します。

例えば、ファイル中のパラメータの場合50mm×8区間で
全長400mmのクネクネした曲線が描けます。
そこから、描画開始後200mmの点だったり167.5mmの点だったりと任意に選んで
両端を結ぶ直線はどのくらい離れているかを計算したいのです。

任意の点は曲線描画後に選びたいので、全座標(0.1mm刻みで4000点)を
覚えておく必要があるのではと思います。

※実はこないだのGWにC言語の本を買って始めたばかりですので、
どのような命令があって、どのようなことができるか分からない状態です。
こういう命令で外部ファイルに書き込みができるよとか、
外部ファイルからデータを読み込むにはこうしたらいいよとか、
実際のプログラムでお教えいただけると良いのですが・・・。

lbfuvab

Re:曲線の描画について

#6

投稿記事 by lbfuvab » 16年前

円弧の長さは一定なら、
~~~~~~~~~~~~~~~~~
①どの二点間(AB、BC、CD等)にするか乱数で決定する。
②選んだ二点上で(弧の長さ) = (半径) * (角度)を使い、どの点にするか決定する。

で任意の点(すべての点で可能性は等しい)を選べると思いますが、やはりややこしいでしょうか?

ゆうき

Re:曲線の描画について

#7

投稿記事 by ゆうき » 16年前

lbfuvabさん、すみません、アドバイスの内容が理解できませんでした。
円弧の描画後、特定の必要座標のみを再度求め直すということでしょうか?

今のところ考えているのは以下の方法で、任意座標の取得が必須となります。

曲線を描画した時点で変数内に残っているのは
1)描画開始点 Xs=0, Ys=0
2)描画終了点 Xe, Ye
のみ。

そこから、2点を結ぶ直線の式を求め、それに直交する傾き(逆数×-1)を持つ
任意座標(Xc,Yc)を通る直線式との連立方程式で、交点座標(Xa,Ya)を求め、
(Xc,Yc)と(Xa,Ya)から距離を求めるという方法です。

そもそも問題そのものがややこしいぞ、というご指摘を受けそうですね・・・。

たいちう

Re:曲線の描画について

#8

投稿記事 by たいちう » 16年前

仕事でやっているのにプログラムしてくれ、というのはどうかと思うよ。
面白そうだったので作ったけど、見ての通りGrWinは使っていないし、色々手抜き。
動作確認は「猫でもわかる…」のSDKの部分とかを参考にしてほしい。
void Draw(HDC hdc)
{
	int data[/url] = { -93, -61, 71, 80, 77, 78, -43, -69 };
	double x0 = 0, y0 = 0, angle = 0; // 初期値(原点、右向き)
	const double pi = 3; // 若さをアピール

	for (int i = 0; i < sizeof(data) / sizeof(data[0]); i++) {
		// データの分解
		int flag = (data) > 0 ? 1 : -1;
		int r = abs(data);

		// 円の中心座標
		double cx = x0 + flag * r * cos(angle + pi / 2);
		double cy = y0 + flag * r * sin(angle + pi / 2);

		// 中心から見た始点と終点の角度
		double d0 = angle - flag * pi / 2;
		double d1 = d0 + flag * 50. / r;

		// 座標変換
		int cx_ = (int)(200 + cx + 0.5);
		int cy_ = (int)(300 - cy + 0.5);
		int sx_ = (int)(cx_ + r * cos(d0) + 0.5);
		int sy_ = (int)(cy_ - r * sin(d0) + 0.5);
		int ex_ = (int)(cx_ + r * cos(d1) + 0.5);
		int ey_ = (int)(cy_ - r * sin(d1) + 0.5);

		// 描画
		if (flag > 0)
			::Arc(hdc, cx_ - r, cy_ - r, cx_ + r, cy_ + r, sx_, sy_, ex_, ey_);
		else
			::Arc(hdc, cx_ - r, cy_ - r, cx_ + r, cy_ + r, ex_, ey_, sx_, sy_);

		// 始点の更新
		x0 = cx + r * cos(d1);
		y0 = cy + r * sin(d1);
		angle += d1 - d0;
	}
}


# 今日やっと時間と気力とノンアルコールの条件が整った。
# 所要時間1時間。30分位で作りたいんだけどな。

ゆうき

Re:曲線の描画について

#9

投稿記事 by ゆうき » 16年前

初めまして、たいちうさん。
実際のプログラムありがとうございました。
あと、(お仕事の件)ご指摘ごもっともです。

早速動作確認と考察をしてみます。
※設定をいじりましたが「外部シンボル 'WinMain' が未解決」とエラーが出て、
 すぐにはできませんでした。

各座標の記録は、もう少し自分で考えてやってみます。

lbfuvabさん、たいちうさん
ありがとうございました。

たいちう

Re:曲線の描画について

#10

投稿記事 by たいちう » 16年前

http://homepage2.nifty.com/c_lang/sdk/sdk_00.htm
のサンプルを次のように変更すれば呼び出せるのではないかな。
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	switch (msg)
	{
		case WM_PAINT:
			hdc = BeginPaint(hWnd, &ps);
			Draw(hdc);
			EndPaint(hWnd, &ps);
			break;
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		default:
			return(DefWindowProc(hWnd, msg, wParam, lParam));
	}
	return (0L);
}
同じサイトの↓も参考になるかも。
http://homepage2.nifty.com/c_lang/bcc/index.html

閉鎖

“C言語何でも質問掲示板” へ戻る