- 締切済み
クリックされた地点が2点の線分上かの判定
bool CheckOnline(int x1,int y1,int x2,int y2,int MouseX,int MouseY){ int range = 10; //許容範囲 double a; double b; if(x2 == x1){ if( abs( MouseX -x1)<range ){ if( abs(MouseY -abs(y2-y1)) <range) return true; } }else{ a=(y2-y1)/(x2-x1); b= y1 - a*x1; if( abs(MouseY - (a * MouseX +b)) <range ){ if( abs(MouseX - ((MouseY-b)/a)) <range ) return true; } } return false; } ぴったりでなく少し誤差があっても線上と判定したいです。 上記の方法ではうまく行きませんでした。 一応、y=ax+bのaとbを求めて、マウスのxとマウスのyを代入 その結果がrange以内かどうかでやってみようとした結果です。
- みんなの回答 (4)
- 専門家の回答
みんなの回答
- nag0720
- ベストアンサー率58% (1093/1860)
>この環境ではアルゴリズムは変化するのでしょうか? Nodeとマウスの位置座標とも同じ座標系ならアルゴリズムに変わりはありません。 Edge_eraseでNodeを書き換えていると思いますが、 とりあえずのデバッグ方法としては、Edge_eraseをコメント行にして、代わりに、 i, j, num, Node[i].x, Node[i].y, Node[num].x, Node[num].y, x, y などを画面かファイルに出力して数値を確認してみてはいかがですか? もしそれに異常がなければEdge_eraseのロジックに問題があるかもしれません。
- nag0720
- ベストアンサー率58% (1093/1860)
>a=(y2-y1)/(x2-x1); >この部分が常に0.0000000になっています。 int同士の演算はintになります。 doubleにしたかったらキャストする必要があります。 a = (double)(y2 - y1) / (x2 - x1); ちなみに、書かれている方法では、線分が垂直に近い場合(x1とx2の差が0に近い場合)、 マウスの位置と線分の近くにあったとしても、MouseY と a*MouseX+b の差は大きくなる可能性があります。 abs(MouseY - (a * MouseX +b)) <range と abs(MouseX - ((MouseY-b)/a)) <range の両方をtrue判定するのではなく、どちらか片方がtrueであればOKとすべきでしょう。
- nag0720
- ベストアンサー率58% (1093/1860)
>しかし、チェックが未だに成功していません。 具体的に、どんな値で実行したとき、どんな結果になるんでしょうか? デバッグ機能が使えるなら、どのステップを通ったかを確認しながら実行してみてはいかが。
補足
a=(y2-y1)/(x2-x1); この部分が常に0.0000000になっています。 修正した内容が間違ってるのでしょうか?
- nag0720
- ベストアンサー率58% (1093/1860)
間違いは2点ほど。 (1) x2=x1の場合 if( abs( MouseX -x1)<range ) は問題ないですが、 if( abs(MouseY -abs(y2-y1)) <range) は違います。 正しくは、 y1<y2のとき、 y1-MouseY<range かつ MouseY-y2<range である必要があります。 (y2<y1のときは、y1とy2を逆にして比較) (2) x2≠x1の場合 考え方は合ってますが、その方法だと2点を通る直線上にあるかどうかの判定です。 線分上にあるかどうかなら、さらにMouseXまたはMouseYの範囲チェックが必要です。
補足
bool CheckOnline(int x1,int y1,int x2,int y2,int MouseX,int MouseY){ int range = 10; //許容範囲 double a; double b; if(x2 == x1){ if( abs( MouseX -x1)<range ){ if(y1<y2){ if(y1-MouseY<range && MouseY-y2 <range) return true; }else if(y2<y1){ if(y2-MouseY<range && MouseY-y1 <range) return true; } } }else{ a=(y2-y1)/(x2-x1); b= y1 - a*x1; if( abs(MouseY - (a * MouseX +b)) <range ){ if( abs(MouseX - ((MouseY-b)/a)) <range ){ if(x1<x2){ if(y1<y2){ if(MouseX>x1 && MouseX<x2 && MouseY>y1 && MouseY<y2) return true; }else if(y1>y2){ if(MouseX>x1 && MouseX<x2 && MouseY<y1 && MouseY>y2) return true; } }else{ if(y1<y2){ if(MouseX<x1 && MouseX>x2 && MouseY>y1 && MouseY<y2) return true; }else if(y1>y2){ if(MouseX<x1 && MouseX>x2 && MouseY<y1 && MouseY>y2) return true; } } } } } return false; } 出来る限り直してみました。 しかし、チェックが未だに成功していません。
補足
回答ありがとうございます。 double型でキャストした所、true falseは返すようになりました。 しかし、線をクリックした際に意図していない点を返してきます。 クリックした線を消去するために作っています。 その為以下のような関数で呼び出されています。 引数はマウスの座標です。 Nodeは構造体で自分の位置座標と、どこにつながっているか(edges_to)を格納しています。 bool DeliteLine(int x,int y){ int i,j; int num; for(i=0;i<Node.size();i++){ for(j=0;j<Node[i].edges_to.size();j++){ num=Node[i].edges_to.at(j); if( CheckOnline(Node[i].x,Node[i].y,Node[num].x,Node[num].y,x,y)){ Edge_erase(i,j); return true; } } } return false; } あと一点気になったのですが、私の環境は画面左上を(0,0)として 下に行くとyは増加し右に行くとxが増加します。 この環境ではアルゴリズムは変化するのでしょうか? 何度も質問して申し訳ないのですが、どうしてもわからないいので お力添えお願いします。