DOBON.NET DOBON.NETプログラミング掲示板過去ログ

極座標系の線描画

環境/言語:[C#.NET2003]
分類:[.NET]

初めまして。
不躾ながら質問させて頂きます。

現在作成中のプログラム
で、極座標でのcos曲線描画が必要になったのですが、どうにも方法が見つからずに行き詰っております。

要求としましては、
a+b*cos(θ)のa,bをパラメータとして与え、0<=θ<2πの範囲での極座標表示をしたい、というものなのですが…

何方かお知恵をお貸し願えませんでしょうか?
2006/09/29(Fri) 18:08:43 編集(投稿者)
2006/09/21(Thu) 06:46:34 編集(投稿者)
2006/09/20(Wed) 17:28:37 編集(投稿者)
2006/09/20(Wed) 12:20:41 編集(投稿者)

曲線の式が r = a+b*cos(θ) (a>b) であるものとしてお答えします。
以下、考えている平面上の直交座標を(x,y),それをビットマップに移した座標を(X,Y)とします。

もし、ある程度計算時間がかかっていいのなら、次の方法があります(私が似たようなことをしたときには、数百ピクセル四方で数分の1秒かかりました)。

1. xとyの最大値と最小値を求め(xの最小値は-a+b,最大値はa+b,yは計算して求めてもよいが、ごくおおざっぱに±(a+b)としてもよい)、それらをXとYに変換

↑ここ、間違っていました。No17737をご覧下さい。

2. Xの最小値から最大値までループ

  2-1. Yの最小値から最大値に向かってループ

    2-1-1. (X,Y)から(x,y)に逆変換、それからcos(θ)を求め(cos(θ) = x / sqrt(x^2 + y^2))、r = a+b*cos(θ)を計算

    2-1-2. sqrt(x^2 + y^2) ≦ rとなったとき(曲線の外側から中側に入ったとき)(X,Y)に点を打ち、ループ2-1を抜ける

  2-2. Yの最大値から最小値に向かってループ

    2-1-1, 2-1-2と同様

3. XとYを入れ替えて2と同様の処理を行う

別法として、次のような手順もあるかと思います。このほうが計算量は減りますが、多少煩雑な面があるかもしれません(実際にコードしてみないとわかりませんが)。

1. θ=0の点(a+b,0)に対応する(X,Y)に点を打つ

2. ビットマップ上でその点に隣接する8点から、θが増加する点を選ぶ

3. それらの点を逆変換した(x,y)について、新しいcos(θ)からrを計算し、(sqrt(x^2 + y^2) - r)が0以下で最大(または0以上で最小、あるいは絶対値が最小)の点を選び、対応する(X,Y)に点を打つ

4. θ=2πになるまで繰り返す

(5. 全体をチェックして、型に並んだ3点から角の点を取り除く)

5は、必要かどうか今のところわかりません。
2006/09/20(Wed) 17:29:48 編集(投稿者)
2006/09/20(Wed) 12:23:12 編集(投稿者)

補足です。

外のループを単純に端から端まで回すのではなく、真ん中から始めて端に向かい、チェック開始点のY(X)座標に前回の終了点のY(X)座標を使えば計算量が減るので、別法を使う必要はなさそうです。また、曲線が上下対称であることを用いると、ループ2-2は不要になります。

「真ん中」の選びかたは、yについては単純に0でいいですが、xについては非対称性を考慮しなければならないので多少の工夫が要ります。

もし、yが最大/最小となるxを直接求めるとするならば、

cos(θ) = (-a + sqrt(a^2 + 8*b^2)) / (4*b)  (この点でdy/dθ=0となる)

を用い、これからr,xを計算します(x=r*cos(θ))。

あるいは、常に外から中へ攻めるのではなく、「チェック開始点が中なら外へ、外なら中へ進む」という方法をとれば、yがどこで最小になるかを最初に求める必要がなくなります。この場合は、外のループを端から端まで回すことになります。

----------

さらに補足です。

XとYを入れ替えて処理を繰り返すよりも、次のようにしたほうがよさそうです。

外側のループはYにして、y=0に対応するYから始めます。
その中で、たとえば、(X,Y)=(100,100)の次の点が(105,101)になったとします。
このとき、前の点が(100,100)であったことを記憶しておき、(101,100)から(104,100)まで直線を引きます。

この方法では、上に書いた最小/最大値の計算が不要になります。
Xを右から(x=0に対応するX)まで動かしても曲線の内側の点がみつからなくなったところで、Yのループを終了します。
そして最後に、終端の2点を直線で結びます
■No17621に返信(千八巧者さんの記事)

ちょっと興味深く見ていたのですが、全く返信がありませんが
どうなったのでしょうか?

>極座標でのcos曲線描画が必要になったのですが、どうにも方法が見つからずに行き詰っております。

私は頭が悪いので、質問の意味がよく理解できなかったので回答できなかったのですが
普通なら
極座標なら原点に円グラフで、a、bに応じて円の大きさが変わる、または原点から離れるかと思っていました。またcos曲線なら振幅がかわる、原点からy方向に移動するかと思っていたのですが、質問の意味が良く解らないので様子をみていました。

千八巧者さんが回答していますので、掲示板をご覧になっていましたら、理解できる出来ないはべつとして、何らかのコメントを返して頂きたいと思います。
返信が遅くなりまして申し訳有りません。

回答頂いた千八巧者さん、有難う御座いました。
様々調べてみたりしたのですが、ツールに頼らない限りはやはりおっしゃるとおりのやり方が一番早い様です。

なんとか一つ問題が解決しそうです。
  • 題名: Re[5]: 極座標系の線描画
  • 著者: 千八巧者
  • 日時: 2006/09/29 18:07:02
  • ID: 17737
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
2006/09/30(Sat) 06:31:07 編集(投稿者)

大事な点を見落としていました。
b>a/2のときは、左側に凹んだ部分ができるんですね。
でも、すでにそのことも含め十分検討されてると思いますので、詳細は省略します。

xの最小値が-a+bと書いたのも間違っており、申し訳ありませんでした。

DOBON.NET | プログラミング道 | プログラミング掲示板