プログラムが動かなくなる

[戻る]
はれ 2002/01/13(日) 23:49:41
題名をどうつけたらよいかわからなく、言いたいことを捕らえていなくてすみません。
VC++6.0を使っています。しかし、私自身がCを少し経験した程度で、今回のプログラムはCの知識で作っています。
今、多角形に外接する四角形を作り、そのx、y値を配列の番号としてhairetu[t][r]を用意しました。
その配列の多角形内の番号のところを1、外を0とするプログラムです。
まず多角形の頂点を順に左回りにクリックしていき、tyoutenx[0]tyouteny[0]に最初にクリックした
x座標、y座標を、tyoutenx[1]tyouteny[1]...に2回目にクリックしたx座標、y座標を入れます。
4角形を作ったら頂点の座標が順にtyoutenx[3]tyouteny[3]まで入ります。このtyoutenxからx座標の
最大値、最小値、y座標の最大値、最小値を取り出してMinx、Maxx、Miny、Maxyとしました。これを
もとに多角形を囲んでいる四角形を書きました。
クリックした頂点の座標をx,y座標と考えて、y=ax+b(その変形のa=(y-b)/x,b=y-ax)を使って考えています。
配列の番号は整数なので、多少の誤差が出ることは覚悟しています。
今hairetu[t][r]にはすべて1が入っていて、外側の部分に0を入れるだけのプログラムです。
これをforループでtの値かMinxからMaxxまで、rの値がMinyからMaxyまで足して行けば面積が求められると
思って作っています。
その多角形が完成したとき、このプログラムが動くようにしていますが、途中で止まっている(計算しつづ
けている?)ようで、プログラムが止まって、×印を押しても動かなくて、実行させるたびに
いつもパソコンを再起動しています。再起動のときは、「システムがビジー状態です。」と出るので強制的
に終了させています。
ビルドしたときにはエラーはでません。whileのところでおかしくなっているのはわかるのですが・・・
どこが悪いのかわかりません。こんなに長々書いて、うまく伝わらないかもしれませんが、もし少しでも
アドバイスがあれば教えていただきたいです。
よろしくお願いします。

a1,a3,bのみdouble他はintにしています。nがn回目にクリックした点。iは多角形の画数-1の数。

    while(tyouteny[n]!=Miny){//いちばん上の部分の頂点が何番目にクリックされたか調べる。
                n++;
              }
            if(n!=i){//一番上の頂点から、一つ目の辺の左側に0を入れる
                j=tyouteny[n+1];//一本目の直線の終点のy座標
                a1=(-tyouteny[n+1]-(-tyouteny[n]))/(tyoutenx[n+1]-tyoutenx[n]);
                b=-tyouteny[n]-(a1*tyoutenx[n]);
                for(r=Miny;r<=tyouteny[n+1];r++){
                    for(t=Minx;t<(-r-b)/a1;t++){
                        hairetu[t][r]=0;
                    }
                }
            }
            else if(n==i){
                j=tyouteny[0];//一本目の直線の終点のy座標
                a1=(-tyouteny[0]-(-tyouteny[n]))/(tyoutenx[0]-tyoutenx[n]);
                b=-tyouteny[n]-(a1*tyoutenx[n]);
                for(r=Miny;r<=tyouteny[0];r++){
                    for(t=Minx;t<(-r-b)/a1;t++){
                        hairetu[t][r]=0;
                    }
                }n=-1;
            }//ここまでは動いています。

            //ここからが2つめの辺以降。ここから後がうまく動いていません                while(j!=Maxy){//Maxyより左の部分
                if(n=i-1){
                    j=tyouteny[0];
                    a3=(-tyouteny[0]-(-tyouteny[i]))/(tyoutenx[0]-tyoutenx[i]);
                    b=-tyouteny[0]-(a3*tyoutenx[0]);
                    for(r=tyouteny[i];r<=tyouteny[0];r++){
                        for(t=Minx;t<=(-r-b)/a3;t++){
                            hairetu[t][r]=0;
                        }
                    }n=-1;
                }
                else{
                    n=n+1;
                    j=tyouteny[n+1];
                    a3=(-tyouteny[n+1]-(-tyouteny[n]))/(tyoutenx[n+1]-tyoutenx[n]);
                    b=-tyouteny[n]-(a3*tyoutenx[n]);
                    for(r=tyouteny[n];r<=tyouteny[n+1];r++){
                        for(t=Minx;t<=(-r-b)/a3;t++){
                            hairetu[t][r]=0;
                        }
                    }
                }
            }
            while(j!=Miny){//右の部分
                if(n=i-1){
                    j=tyouteny[0];
                    a3=(-tyouteny[0]-(-tyouteny[i]))/(tyoutenx[0]-tyoutenx[i]);
                    b=-tyouteny[0]-(a3*tyoutenx[0]);
                    for(r=tyouteny[i];r>=tyouteny[0];r--){
                        for(t=Maxx;t>=(-r-b)/a3;t--){
                            hairetu[t][r]=0;
                        }
                    }n=-1;
                }
                else{
                    n=n+1;
                    j=tyouteny[n+1];
                    a3=(-tyouteny[n+1]-(-tyouteny[n]))/(tyoutenx[n+1]-tyoutenx[n]);
                    b=-tyouteny[n]-(a3*tyoutenx[n]);
                    for(r=tyouteny[n];r>=tyouteny[n+1];r--){
                        for(t=Maxx;t>=(-r-b)/a3;t--){
                            hairetu[t][r]=0;
                        }
                    }
                }
            }

はれ 2002/01/14(月) 00:07:12
すみません。説明の追加です。
この多角形とそれを囲む四角形のx座標y座標は
x座標右に行くほど大きくなる
y座標下に行くほど大きくなる
x座標は問題ありませんが、普通のグラフでは
y座標は下に行くほど小さくなるので、y座標
の値には-をつけて考えています。

deck 2002/01/14(月) 02:28:38
プログラムは面倒なので見てません。ごめんなさい。

>面積が求められると思って作っています。
もし、多角形の面積を計算したいだけなら、
こんな、面倒なことをしないでも、点の座標から直接計算できます。

はれ さんの記法にしたがって、

i角形の頂点の座標を、左回りに
(tyoutenx[0],tyouteny[0]) から (tyoutenx[i-1], tyouteny[i-1])
とすると、

double s;
int j;

s=0.0;
for(j=0; j<i; j++) {
  if (j < i-1) {
    s += (tyoutenx[j]*tyouteny[j+1] - tyoutenx[j+1]*tyouteny[j]) / 2.0;
  } else {
    s += (tyoutenx[i-1]*tyouteny[0] - tyoutenx[0]*tyouteny[i-1]) / 2.0;
  }
}

で、s に面積が入ります。

はれ 2002/01/14(月) 15:34:16
deckさん本当にありがとうございます。

しかし、そのhairetu[t][r]のt値をpoint.x、r値をpoint.yとして、
そのx,y点のrgb値を取り出したいんです。だからhairetu[][]に入れてるのです。
そして、その多角形は五角形かもしれないし、途中でへこんでいるかも
しれないんです。ただ、MinnyからMaxyまでは必ずyの変化量は+(下向き)
MaxyからMinyまではyの変化量は-(上向き)にするつもりなのです。
私のプログラムは多角形を囲んでいる四角形の左上から多角形の辺に向かって
順に0を入れているつもりです。多角形の一番下の点にきたら、次は囲んでいる
四角形の右下から多角形の辺に向かって0を入れているつもりです。

TAKA 2002/01/15(火) 10:28:23
質問ですがこんな感じになってませんか?

頂点1=(5,8)、頂点2=(6,9)、頂点3=(10,6)、頂点4=(11,3)
上記を例にすると求められるminx,miny,maxx,maxy
はそれぞれminx=5,miny=3,maxx=11,maxy=9となります。

上記のようになっていたりすると動かなくなる可能性は十分あります。
最小と最大だけではだめです。
全ての頂点の位置を考えて覚えておいてあげないと動かないでしょう。

あくまで頂点1は(5,8)なのですから・・

deck 2002/01/15(火) 14:16:19
>途中でへこんでいるかもしれないんです。
前に書いた方法は、途中でへんこんでいても、面積は求られますが。。。

途中でへこんでいると、はれ さんの方法はうまくいかない場合がある気がします。

例えば、
      ____________
     |   _____    |
     |  |     |   |
     |__|     |___|

こんな図形だと、
「MinnyからMaxyまでは必ずyの変化量は+(下向き)
 MaxyからMinyまではyの変化量は-(上向き)にするつもりなのです。」
は、成り立たないと思います。こういう図形は考えないのでしょうか?

多角形の塗りつぶしは、scan conversion がよく使われます。
http://www.people.or.jp/~fussy/argo6-1.htm
で丁寧に説明されています。

はれ 2002/01/17(木) 00:02:18
>TAKAさん
どちら回りにクリックするか指定しておいて、
頂点1〜4の中のどのyがMaxyか(どの頂点が一番
上か)調べるなら、簡単にできるということでしょうか。

>deckさん
本当はdeckさんがおっしゃっている形も考えたか
ったのですが、私の考えがついていかなかったので
妥協しました。
その多角形はユーザーの入力によってつくるので、
MinnyからMaxyまでは必ずyの変化量は+(下向き)
MaxyからMinyまではyの変化量は-(上向き)にす
るよう指定しようと思っていたのです。

  /\
 / |←へこんでいるときでも
 \ | こんなかんじ
 / |
  ̄ ̄ ̄
しかし、deckさんから教えてもらったHPを見て
スキャンコン・バージョンの考え方を勉強できま
した。

お二人ともどうもありがとうございました。

TAKA 2002/01/17(木) 12:55:45
すみません。
前回のコメントは思い違いみたいです。
よく読んで発言してなかったことをおわびします。
混乱させる発言申し訳ありませんでしたm(_ _)m
 
後、ソースを見て思ったことは、
2回あるこれは代入ですが間違いでは?

 if(n=i-1){
 if(n=i-1){

if(n==i-1) { でなないのでしょうか?

はれ 2002/01/18(金) 00:31:54
「プログラムが動かなくなる」という題名なんですが、実は他の
PCを使うと動きました。エラーがでたり、値がおかしいのは変わ
りませんでしたが…(以前はエラーも出ずに止まっていたので)
そのときに他の方から宣言の型が大きすぎるのでは?と言われ、
0か1しか入れないhairetu[][]をintからcharに変えたりしまし
た。

>TAKAさん
そのとおりですね!何日も考えていたのに気づかなかったです。
しかし、そこを直しても今度は面積が約2倍に・・・
いろいろやってみて、一番上の頂点から必ずクリックするように
指定しました。そして、Maxy(一番下)は何回目のクリックか探し
て、そこまでは多角形の左側に0を入れるように、そこから後は
右側に0を入れるようにforループで計算するようにしました。
一応はできたので解決・・・と言いたいのですがこの方法でもク
リックする位置によって(3回に1回くらいの確率で)エラーが
出るのです。

「例外unknown software exception(0x0000094)がアプリケーション
の0x00402abaで発生しました。」や、「アプリケーションエラー、
命令****は命令****を呼び出しましたが命令****はwritten
になることができませんでした。」

などです。やはり私の計算式に無理があるのでしょうか・・・

(deckさん、せっかくスキャンコン・バージョンの方法を教えて
頂いたのに活用していなくてすみません)

TAKA 2002/01/18(金) 10:42:25
今どうなってるかわからませんが
for ないで r,t の値を全てファイルにおとしてみましょう。
ついでに b, a1 等の値もファイルにしMaxx,Minx Maxy,Miny
の値を超えた値になっていないか確認しましょう。

もちろんプログラムが正常に終了するときのパターンでもしましょう。

それで値の変化がおかしい for文を修正すればいいとおもいます。
後は地道にがんばってください。

EIJI 2002/01/18(金) 11:14:51
デバッグの手法になりますが、「いたるところにassert埋め込む」のはどうでしょうか?
上記のようなコードの場合に注意する点としては、
・配列の範囲外を使っていないか(これが一番怪しい)
・ゼロで除算してないか(doubleの場合、発見しにくい)
といった感じでしょうか。

たとえば
>j=tyouteny[n+1];
というのがあったら、その前の行に
 assert( n+1>=0 && n+1<=要素の最大値 );
てな具合で。

はれ 2002/02/02(土) 11:32:22
おそくなってすみません。
deckさんTAKAさんEIJIさんみなさんありがとうございます。

きちんと解決してから返事を書きたかったのですが、まだで
きていません。
結局締め切りに間に合わず何回かに1回はエラーがで
るまま次のステップに進んでしまいました。この掲示板には
社会人の方も多いようで、エラーが出るままあきらめること
ができない方が大半だと思います。そんな中でせっかくアド
バイスを頂いたのにこういう結果にして申し訳ありません。
今後エラーがなくなり次第報告します。

古いスレッドには追加発言できません。